B3M
B3M is a command-line interface (CLI) tool for blade modeling, integrating functionalities from sub-projects: geometry processing (b3_geo), meshing (b3_msh), and draping (b3_drp).
Features
- Geometry Processing: Handle airfoils and lofting steps.
- Meshing: Generate meshes for blade models.
- Draping: Assign plies to blade structures.
- Modular CLI: Organized subgroups for different functionalities.
- Example Workflow: Includes a sample script for building blades from configuration files.
Installation
Ensure you have Python 3.8+ and uv installed. Clone the repository and install dependencies:
git clone https://github.com/wr1/b3m.git
cd b3m
uv sync --devFor local development with sub-projects, ensure the paths in pyproject.toml point to your local copies of b3_geo, b3_msh, and b3_drp.
Usage
CLI
Run the CLI with:
uv run b3mThis will display the help for the main CLI, with subgroups:
build: Blade build commands.
Use uv run b3m build --help for details on build commands.
Example: Build Blade
Use the provided example script to build a blade from a YAML config file:
python examples/build_blade.py -c path/to/config.yaml --forceThe config file should specify the workdir and other parameters.
Main Workflow
The B3M workflow consists of several steps to model and analyze wind turbine blades:
- Airfoils Processing (B3 Geo): Load and resample airfoils.
- Lofting (B3 Geo): Create LM1 blade model and export to VTP.
- Meshing (B3 Msh): Generate structured meshes.
- Draping (B3 Drp): Assign composite material plies.
- 2D Meshing (B3 2D): Process sections for FEA.
- Analysis (ANBA): Run ANBA4 for structural analysis.
Input File Format
B3M uses YAML configuration files to define the blade model, materials, and analysis parameters.
Example structure (see config/data/blade_test.yml for full example):
workdir: temp_blade
geometry:
planform:
npchord: 200
# offset in prebend direction, negative is upwind
dx: [[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [1.0, -5.0]]
# offset in chord direction
dy: [[0.0, 0.0], [0.01, 0], [0.3, 0.586], [0.43, 0.529],
[0.56, 0.498], [0.69, 0.4355],
[0.82, 0.329], [0.95, 0.33]]
z: [[0, 3], [1, 126]]
chord: [[0.0, 5], [0.03, 5.06], [0.2, 6.5], [0.4, 4.4], [0.6, 2.8], [0.75, 2.0], [
0.94, 1.4], [0.985, 0.8], [1, 0.1]]
thickness: [[0.0, 1.0], [0.05, 0.97], [0.2, 0.53], [0.31, 0.39], [1.0, 0.17]]
twist: [[0.0, 10], [0.2, 2], [0.4, 1], [0.6, 0], [0.8, -0.5], [0.9, -1], [1.0, 0]]
airfoils:
- path: airfoils/DU93-W-210_smoothed_dero_0.210.dat
name: DU93-W-210
thickness: 0.21
- path: airfoils/du_91_w2_250_smoothed_dero_0.250.dat
name: DU91-W-250
thickness: 0.25
- path: airfoils/circ_m32.dat
name: Circ M32
thickness: 1.0
- path: airfoils/naca633418_te.dat
name: NACA 633418 TE
thickness: 0.179928
- path: airfoils/naca0017.dat
name: NACA 0017
thickness: 0.17
bem:
rated_power: 10000000
polars:
- key: 1.0
name: Cylinder
file: polars/Cylinder1.dat
- key: 0.21
name: DU21
file: polars/DU21_A17.dat
- key: 0.25
name: DU25
file: polars/DU25_A17.dat
- key: 0.30
name: DU30
file: polars/DU30_A17.dat
- key: 0.35
name: DU35
file: polars/DU35_A17.dat
- key: 0.40
name: DU40
file: polars/DU40_A17.dat
- key: 0.17
name: NACA64
file: polars/NACA64_A17.dat
B: 3
rho: 1.225
mu: 0.0000181
precone: 0
tilt: 0
yaw: 0
shearExp: 0.2
hubHt: 90
max_tipspeed: 95
uinf: [4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26]
structure:
webs:
- name: web0
type: plane
origin: [0, 0, 0]
orientation: [0.02, 1, 0]
z_range: [1,100]
element_size: 0.10
mesh: false
- name: web1
type: plane
origin: [0, 0.2, 0]
orientation: [0.02, 1, 0]
z_range: [1, 110]
element_size: 0.10
mesh: true
- name: web2
type: plane
origin: [0, -0.2, 0]
orientation: [0.02, 1, 0]
z_range: [1, 100]
element_size: 0.10
mesh: true
mesh:
z:
- type: "plain"
values: [4,20.25,50,80]
- type: "linspace"
values: [3,100]
num: 50
chordwise:
default:
# number of elements per panel where panel between 2 hard points, hard points being the start or end of the airfoil line, or a web intersection
n_elem: 40
element_size: 0.10
panels:
- id: 0
element_size: 0.05
- id: 1
element_size: 0.10
matdb:
carbon:
id: 1
type: orthotropic
E1: 100000000000.0
E2: 10000000000.0
E3: 10000000000.0
G12: 5000000000.0
G13: 5000000000.0
G23: 5000000000.0
nu12: 0.3
nu13: 0.3
nu23: 0.3
rho: 1600.0
glass:
id: 2
type: isotropic
E: 50000000000.0
nu: 0.3
rho: 2000.0
foam:
id: 3
type: isotropic
E: 100000000.0
nu: 0.4
rho: 100.0
laminates:
datums:
thickness_taper:
base: z
values: [[5,0],[30,0.008], [100,0.008], [101,0.0]]
# [[-101, 0.0], [-100, 0.008], [-30, 0.008],[-8,0.0]]
glass_taper:
base: z
values: [[0, 0.1],[3,0.02], [20,0.008], [200,0.004]]
# [[-200, 0.004], [-20, 0.008], [-3, 0.02],[0,0.1]]
plies:
- mat: glass
angle: 0
thickness: glass_taper * 0.6
parent: plate
conditions: []
key: 99
- mat: carbon
angle: 0
thickness: thickness_taper
parent: plate
conditions:
- field: z
operator: in_range
operand: [-1e3, 1e3]
- field: abs_dist_web1_hp0
operator: in_range
operand: [0, 0.4]
- field: panel_id
operator: in_range
operand: [1,12]
key: 100
- mat: glass
angle: 0
thickness: glass_taper
parent: plate
conditions: []
key: 102This YAML defines the work directory, geometry parameters, BEM settings, material database, and laminate plans.
Development
- Linting and Formatting: Use
rufffor code quality. - Testing: Run tests with
pytest. - Local Admin Script: Use
admin.shfor automated checks and commits.
To contribute:
- Fork the repo.
- Create a feature branch.
- Make changes, ensuring tests pass.
- Submit a PR.
License
MIT