Examples
Cantilever
Examples
Examples
Cantilever
from generative.core import generative_function, FileAsset, Asset, GenerativeType
import trimesh
from pydantic import Field
import shapely
class CantileverGeometricProperties(GenerativeType):
length_m: float = Field(default=1, gt=0)
depth_m: float = Field(default=0.1, gt=0)
width_m: float = Field(default=0.2, gt=0)
wall_thickness_m: float = Field(default=0.02, gt=0)
class PointLoadScenario(GenerativeType):
force_newtons: float = Field(default=10)
force_location_proportion: float = Field(
default=1,
ge=0,
le=1,
)
class CantileverInputs(GenerativeType):
geometry: CantileverGeometricProperties
material_idx: int = Field(default=0, ge=0, le=1)
load_case: PointLoadScenario
class CantileverAnalysisOutputs(GenerativeType):
slope_radians: float
deflection_m: float
class MaterialProperties(GenerativeType):
material_name: str
modulus_pascals: float = Field(gt=0)
cost_gbp_per_kg: float = Field(gt=0)
density_kg_per_m3: float = Field(gt=0)
class CantileverCostOutputs(GenerativeType):
total_cost_gbp: float
material_cost_gbp: float
fabrication_cost_gbp: float
class CantileverOutputs(GenerativeType):
cost: CantileverCostOutputs
structural: CantileverAnalysisOutputs
model: Asset
@generative_function
def cantilever(inputs: CantileverInputs) -> CantileverOutputs:
validate_inputs(inputs)
material = material_database(inputs.material_idx)
cost = cantilever_cost_model(inputs.geometry, material)
analysis = cantilever_point_load_analysis(inputs.geometry, inputs.load_case, material)
model = cantilever_3d_model(inputs.geometry)
return CantileverOutputs(cost=cost, structural=analysis, model=model)
def validate_inputs(inputs: CantileverInputs) -> None:
max_possible_wall_thickness = 0.5 * min(inputs.geometry.width_m, inputs.geometry.depth_m)
if inputs.geometry.wall_thickness_m >= max_possible_wall_thickness:
raise ValueError("Total wall thickness larger than width or depth")
def cantilever_point_load_analysis(
geom: CantileverGeometricProperties,
load: PointLoadScenario,
material: MaterialProperties,
) -> CantileverAnalysisOutputs:
"""Calculate cantilever performance using standard formulas: https://w.wiki/D2ue"""
second_mom_area_m4 = second_moment_of_area(geom.width_m, geom.depth_m, geom.wall_thickness_m)
load_location = load.force_location_proportion * geom.length_m
slope_numerator = load.force_newtons * load_location**2
slope = slope_numerator / (2 * material.modulus_pascals * second_mom_area_m4)
def_numerator = load.force_newtons * load_location**2 * (3 * geom.length_m - load_location)
deflection = def_numerator / (6 * material.modulus_pascals * second_mom_area_m4)
return CantileverAnalysisOutputs(slope_radians=slope, deflection_m=deflection)
def second_moment_of_area(outer_width: float, outer_depth: float, wall_thickness: float) -> float:
inner_width = outer_width - 2 * wall_thickness
inner_depth = outer_depth - 2 * wall_thickness
return (outer_width * outer_depth**3 - inner_width * inner_depth**3) / 12
MATERIAL_DATA = {
0: MaterialProperties(
material_name="steel", modulus_pascals=210e9, cost_gbp_per_kg=10, density_kg_per_m3=78500
),
1: MaterialProperties(
material_name="aluminium",
modulus_pascals=70e9,
cost_gbp_per_kg=100,
density_kg_per_m3=2700,
),
}
def material_database(material_idx: int) -> MaterialProperties:
try:
return MATERIAL_DATA[material_idx]
except KeyError as e:
raise ValueError(
f"Unknown material index '{material_idx}', try {list(MATERIAL_DATA.keys())}"
) from e
def cantilever_cost_model(
geometry: CantileverGeometricProperties,
material: MaterialProperties,
) -> CantileverCostOutputs:
outer_cross_section = geometry.width_m * geometry.depth_m
inner_cross_section = (geometry.width_m - 2 * geometry.wall_thickness_m) * (
geometry.depth_m - 2 * geometry.wall_thickness_m
)
volume = geometry.length_m * (outer_cross_section - inner_cross_section)
material_cost = material.cost_gbp_per_kg * volume * material.density_kg_per_m3
fabrication_cost = 10_000 + 100 * volume
return CantileverCostOutputs(
total_cost_gbp=fabrication_cost + material_cost,
fabrication_cost_gbp=fabrication_cost,
material_cost_gbp=material_cost,
)
def cantilever_3d_model(geometry: CantileverGeometricProperties) -> Asset:
half_width, half_depth = geometry.width_m / 2, geometry.depth_m / 2
wall_offset = geometry.wall_thickness_m
polygon = shapely.Polygon(
shell=[
(-half_width, -half_depth),
(half_width, -half_depth),
(half_width, half_depth),
(-half_width, half_depth),
],
holes=[
[
(-half_width + wall_offset, -half_depth + wall_offset),
(half_width - wall_offset, -half_depth + wall_offset),
(half_width - wall_offset, half_depth - wall_offset),
(-half_width + wall_offset, half_depth - wall_offset),
]
],
)
cantilever_mesh = trimesh.creation.extrude_polygon(
polygon, height=geometry.length_m, engine="triangle"
)
asset = FileAsset()
cantilever_mesh.export(str(asset.path), file_type="glb")
return asset