def test_beam_offset(ifc_roundtrip_test_dir): bm1 = ada.Beam( "bm1", n1=[0, 0, 0], n2=[2, 0, 0], sec="IPE300", colour="red", up=(0, 0, 1), e1=(0, 0, -0.1), e2=(0, 0, -0.1), ) bm2 = ada.Beam( "bm2", n1=[0, 0, 0], n2=[2, 0, 0], sec="IPE300", colour="blue", up=(0, 0, -1), e1=(0, 0, -0.1), e2=(0, 0, -0.1), ) a = ada.Assembly("Toplevel") / [ada.Part("MyPart") / [bm1, bm2]] _ = a.to_ifc(ifc_roundtrip_test_dir / "beams_offset.ifc", return_file_obj=True)
def build_box_model(geom_repr, use_hex_quad): # Build Model box = ada.PrimBox("MyBoxShape", (0, 0, 0), (1, 1, 1)) a = ada.Assembly() / (ada.Part("MyBoxPart") / [box]) # Create FEM mesh p = a.get_part("MyBoxPart") if geom_repr.upper() == ada.fem.Elem.EL_TYPES.SOLID: props = dict(use_hex=use_hex_quad) surf_props = dict() else: # geom_repr is ada.fem.Elem.EL_TYPES.SHELL: props = dict(use_quads=use_hex_quad) surf_props = dict(surf_positive=True) p.fem = p.to_fem_obj(0.5, shp_repr=geom_repr, interactive=False, **props) # Add Step step = a.fem.add_step(ada.fem.StepImplicit("MyStep")) # Add Boundary condition btn_nodes = box.bbox.sides.bottom(return_fem_nodes=True) p.fem.add_bc( ada.fem.Bc("fix", ada.fem.FemSet("BottomNodes", btn_nodes), [1, 2, 3])) # Add surface load surface = p.fem.add_surface( box.bbox.sides.front(return_surface=True, surface_name="FrontSurface", **surf_props)) step.add_load(ada.fem.LoadPressure("PressureFront", 200, surface)) return a
def test_surface_beam(surfaces_test_dir): from ada.fem.meshing import GmshOptions # Build Model bm = ada.Beam("MyBeam", (0, 0, 0), (0, 0, 1), "BG200x150x6x6") p = ada.Part("MyBmPart") / [bm] a = ada.Assembly() / p # Create FEM mesh p.fem = p.to_fem_obj(0.10, "solid", interactive=False, options=GmshOptions(Mesh_ElementOrder=2)) # Add Step step = a.fem.add_step(ada.fem.StepImplicit("MyStep")) # Add Boundary Condition start_of_beam = bm.bbox.sides.back(return_fem_nodes=True) p.fem.add_bc( ada.fem.Bc("fix", ada.fem.FemSet("bc_fix", start_of_beam), [1, 2, 3])) # Add Surface Load surface_top = p.fem.add_surface( bm.bbox.sides.top(return_surface=True, surf_name="TopSurface")) step.add_load(ada.fem.LoadPressure("PressureTop", 1e6, surface_top)) a.to_fem("MyFemBeam_100mm_2nd_order", "abaqus", overwrite=True, execute=False, scratch_dir=surfaces_test_dir)
def part(): p = ada.Part("MyPart") p.add_material(ada.Material("S355")) p.fem.add_set(ada.fem.FemSet("MAT", [], "elset")) p.fem.add_set(ada.fem.FemSet("BSEC8", [], "elset")) p.fem.add_set(ada.fem.FemSet("BSEC9", [], "elset")) p.fem.add_set(ada.fem.FemSet("BG500X", [], "elset")) return p
def test_basic_plate(pl1, test_meshing_dir): p = ada.Part("MyFem") / pl1 p.fem = pl1.to_fem_obj(5, "shell") el_types = {el_type: list(group) for el_type, group in p.fem.elements.group_by_type()} assert len(el_types.keys()) == 1 # TODO: should investigate the root cause why osx calculates 6 elements and not 8 like linux and win assert len(el_types["TRIANGLE"]) == pytest.approx(8, abs=2)
def test_ifc_instancing(test_instancing_dir): a = ada.Assembly("my_test_assembly") p = ada.Part("MyBoxes") box = p.add_shape(ada.PrimBox("Cube_original", (0, 0, 0), (1, 1, 1))) for x in range(1, 10): for y in range(1, 10): for z in range(1, 10): origin = np.array([x, y, z]) * 1.1 + box.placement.origin p.add_instance(box, ada.Placement(origin)) _ = (a / p).to_ifc(test_instancing_dir / "my_test.ifc", return_file_obj=True)
def test_beam_directions(ifc_roundtrip_test_dir): sec = "HP200x10" beams = [ ada.Beam("bm_test2X0", n1=[0, 0, 0], n2=[5, 0, 0], angle=0, sec=sec), ada.Beam("bm_test2X90", n1=[0, 0, 1], n2=[5, 0, 1], angle=90, sec=sec), ada.Beam("bm_test2Y0", n1=[0, 0, 2], n2=[0, 5, 2], angle=0, sec=sec), ada.Beam("bm_test2Y90", n1=[0, 0, 3], n2=[0, 5, 3], angle=90, sec=sec), ] a = ada.Assembly("AdaRotatedProfiles") / (ada.Part("Part") / beams) _ = a.to_ifc(ifc_roundtrip_test_dir / "my_angled_profiles.ifc", return_file_obj=True)
def test_beam_mesh_with_hole(test_meshing_dir): bm = ada.Beam("bm1", n1=[0, 0, 0], n2=[1, 0, 0], sec="IPE220") p = ada.Part("MyFem") / bm bm.add_penetration(ada.PrimCyl("Cylinder", (0.5, -0.5, 0), (0.5, 0.5, 0), 0.05)) p.fem = bm.to_fem_obj(0.5, "line", interactive=False) el_types = {el_type: list(group) for el_type, group in p.fem.elements.group_by_type()} assert len(el_types.keys()) == 1 assert len(el_types["LINE"]) == 2 assert len(p.fem.nodes) == 3
def test_roundtrip_plate(plate1, ifc_test_dir): ifc_beam_file = ifc_test_dir / "plate1.ifc" fp = (ada.Assembly() / (ada.Part("MyPart") / plate1)).to_ifc( ifc_beam_file, return_file_obj=True) a = ada.from_ifc(fp) pl: ada.Plate = a.get_by_name("MyPlate") p = pl.parent assert p.name == "MyPart" p.fem = pl.to_fem_obj(0.1, "shell") a.to_fem("MyFEM_plate_from_ifc_file", "usfos", overwrite=True)
def test_roundtrip_fillets(place1, place2): a = ada.Assembly("ExportedPlates") p = ada.Part("MyPart") a.add_part(p) pl1 = ada.Plate("MyPl", [(0, 0, 0.2), (5, 0), (5, 5), (0, 5)], 20e-3, **place1) p.add_plate(pl1) pl2 = ada.Plate("MyPl2", [(0, 0, 0.2), (5, 0, 0.2), (5, 5), (0, 5)], 20e-3, **place2) p.add_plate(pl2) fp = a.to_ifc(test_dir / "my_plate_simple.ifc", return_file_obj=True) b = ada.from_ifc(fp) _ = b.to_ifc(test_dir / "my_plate_simple_re_exported.ifc", return_file_obj=True)
def test_roundtrip_ipe_beam(bm_ipe300, ifc_roundtrip_test_dir): ifc_beam_file = ifc_roundtrip_test_dir / "ipe300.ifc" fp = (ada.Assembly() / (ada.Part("MyPart") / bm_ipe300)).to_ifc( ifc_beam_file, return_file_obj=True) a = ada.from_ifc(fp) bm: ada.Beam = a.get_by_name("MyIPE300") p = bm.parent sec = bm.section assert p.name == "MyPart" assert bm.name == "MyIPE300" assert sec.type == "I" assert tuple(bm.n1.p) == tuple(bm_ipe300.n1.p) assert tuple(bm.n2.p) == tuple(bm_ipe300.n2.p)
def test_beam_orientation(ifc_roundtrip_test_dir): props = dict(n1=[0, 0, 0], n2=[2, 0, 0], sec="HP200x10") bm1 = ada.Beam("bm_up", **props, up=(0, 0, 1)) bm2 = ada.Beam("bm_down", **props, up=(0, 0, -1)) fp = (ada.Assembly("MyAssembly") / (ada.Part("MyPart") / [bm1, bm2])).to_ifc(ifc_roundtrip_test_dir / "up_down", return_file_obj=True) a = ada.from_ifc(fp) bm_d: ada.Beam = a.get_by_name("bm_down") bm_u: ada.Beam = a.get_by_name("bm_up") assert tuple(bm_u.up) == tuple(bm1.up) assert tuple(bm_d.up) == tuple(bm2.up)
def test_plate_mesh_from_2_fem(pl1, pl2): points = [(1, 1, 0.2), (2, 1, 0.2), (2, 2, 0.2), (1, 2, 0.2)] pl1.add_penetration( ada.PrimExtrude("poly_extrude", points, **align_to_plate(pl1))) pl1.add_penetration( ada.PrimExtrude("poly_extrude2", points, **align_to_plate(pl2))) p = ada.Part("MyFem") / [pl1, pl2] p.fem = pl1.to_fem_obj(1, "shell") p.fem += pl2.to_fem_obj(1, "shell") el_types = { el_type: list(group) for el_type, group in p.fem.elements.group_by_type() } assert len(el_types.keys()) == 1 assert len(el_types["TRIANGLE"]) == pytest.approx(236, abs=15) assert len(p.fem.nodes) == pytest.approx(153, abs=10)
def test_edges_intersect(test_meshing_dir): bm_name = Counter(1, "bm") pl = ada.Plate("pl1", [(0, 0), (1, 0), (1, 1), (0, 1)], 10e-3) points = pl.poly.points3d objects = [pl] # Beams along 3 of 4 along circumference for p1, p2 in zip(points[:-1], points[1:]): objects.append(ada.Beam(next(bm_name), p1, p2, "IPE100")) # Beam along middle in x-dir objects.append( ada.Beam(next(bm_name), (0, 0.5, 0.0), (1, 0.5, 0), "IPE100")) # Beam along diagonal objects.append(ada.Beam(next(bm_name), (0, 0, 0.0), (1, 1, 0), "IPE100")) a = ada.Assembly() / (ada.Part("MyPart") / objects) p = a.get_part("MyPart") # p.connections.find() p.fem = p.to_fem_obj(0.1, interactive=False)
def test_merge_fem_sections(test_merge_sections_dir): bm1 = ada.Beam("Bm1", (0, 0, 0), (10, 0, 0), "IPE300") bm2 = ada.Beam("Bm2", (10, 0, 0), (10, 10, 0), "IPE400") a = ada.Assembly() / (ada.Part("MyPart") / [bm1, bm2]) p = a.get_part("MyPart") p.fem = p.to_fem_obj(2, "line") assert len(p.fem.sections) == 2 name = "Merges_Sections" fem_format = "sesam" a.to_fem(name, fem_format, overwrite=True, scratch_dir=test_merge_sections_dir) inp_path = default_fem_inp_path(name, test_merge_sections_dir)[fem_format] b = ada.from_fem(inp_path) pb = b.get_part("T1") assert len(pb.fem.sections) == 10 pb.fem.sections.merge_by_properties() assert len(pb.fem.sections) == 2
def test_shell_elem_to_plate(): p = ada.Part("MyPart") nodes1 = [ Node([-15.0001154, -6.0, 24.5], 799), Node([-16.0, -6.0, 24.5], 571), Node([-16.0, -7.0, 24.5], 570), Node([-15.0015383, -7.0, 24.5], 802), ] nodes2 = [ Node([-15.0015383, -7.0, 24.5], 802), Node([-16.0, -7.0, 24.5], 570), Node([-16.0, -8.0, 24.5], 529), Node([-15.0, -8.0, 24.5], 651), ] create_shell_elem(999, nodes1, p.fem) create_shell_elem(1003, nodes2, p.fem) a = ada.Assembly() / p p.fem.sections.merge_by_properties() a.create_objects_from_fem() pl: ada.Plate = a.get_by_name("sh999") nodes_eval = nodes1 assert tuple(pl.nodes[0].p) == tuple(nodes_eval[0].p) assert tuple(pl.poly.seg_global_points[0]) == tuple(nodes_eval[-1].p) assert tuple(pl.poly.seg_global_points[1]) == tuple(nodes_eval[0].p) assert tuple(pl.poly.seg_global_points[2]) == tuple(nodes_eval[1].p) assert tuple(pl.poly.seg_global_points[3]) == tuple(nodes_eval[2].p) pl: ada.Plate = a.get_by_name("sh1003") nodes_eval = nodes2 assert tuple(pl.nodes[0].p) == tuple(nodes_eval[0].p) assert tuple(pl.poly.seg_global_points[0]) == tuple(nodes_eval[-1].p) assert tuple(pl.poly.seg_global_points[1]) == tuple(nodes_eval[0].p) assert tuple(pl.poly.seg_global_points[2]) == tuple(nodes_eval[1].p) assert tuple(pl.poly.seg_global_points[3]) == tuple(nodes_eval[2].p)
def test_fem_static( beam_fixture, fem_format, geom_repr, elem_order, use_hex_quad, overwrite=True, execute=True, name=None, ): geom_repr = geom_repr.upper() if name is None: name = f"cantilever_static_{fem_format}_{geom_repr}_o{elem_order}_hq{use_hex_quad}" p = ada.Part("MyPart") a = ada.Assembly("MyAssembly") / [p / beam_fixture] if geom_repr == "LINE" and use_hex_quad is True: return None props = dict(use_hex=use_hex_quad) if geom_repr == "SOLID" else dict( use_quads=use_hex_quad) step = a.fem.add_step( ada.fem.StepImplicit("gravity", nl_geom=True, init_incr=100.0, total_time=100.0)) step.add_load(ada.fem.LoadGravity("grav", -9.81 * 80)) if overwrite is False: if is_conditions_unsupported(fem_format, geom_repr, elem_order): return None res_path = default_fem_res_path(name, scratch_dir=test_dir, fem_format=fem_format) return Results(res_path, name, fem_format, a, import_mesh=False) else: p.fem = beam_fixture.to_fem_obj( 0.05, geom_repr, options=GmshOptions(Mesh_ElementOrder=elem_order), **props) fix_set = p.fem.add_set( ada.fem.FemSet( "bc_nodes", beam_fixture.bbox.sides.back(return_fem_nodes=True, fem=p.fem))) a.fem.add_bc(ada.fem.Bc("Fixed", fix_set, [1, 2, 3, 4, 5, 6])) try: res = a.to_fem(name, fem_format, overwrite=overwrite, execute=execute, scratch_dir=test_dir) except IncompatibleElements as e: if is_conditions_unsupported(fem_format, geom_repr, elem_order): logging.error(e) return None raise e if res.output is not None: with open(test_dir / name / "run.log", "w") as f: f.write(res.output.stdout) if pathlib.Path(res.results_file_path).exists() is False: raise FileNotFoundError( f'FEM analysis was not successful. Result file "{res.results_file_path}" not found.' ) return res
def test_shell_beam() -> ada.Assembly: bm = ada.Beam("Bm", (0, 0, 0), (1, 0, 0), "IPE300") return ada.Assembly("MyAssembly") / ( ada.Part("MyPart", fem=bm.to_fem_obj(0.1, "shell")) / bm)
def test_export_ifc_plate(plate1, ifc_test_dir): _ = (ada.Assembly() / (ada.Part("MyPart") / plate1)).to_ifc( ifc_test_dir / "exported_plate.ifc", return_file_obj=True )