diff --git a/src/meshpy/core/boundary_condition.py b/src/meshpy/core/boundary_condition.py index 3bbcc4b1..581bffa3 100644 --- a/src/meshpy/core/boundary_condition.py +++ b/src/meshpy/core/boundary_condition.py @@ -48,12 +48,10 @@ def __init__(self, geometry_set, bc_type=None, **kwargs): self.geometry_set = geometry_set @classmethod - def from_dict(cls, geometry_sets, bc_key, bc_dict): + def from_dict(cls, geometry_set, bc_key, bc_dict): """This function acts as a factory and creates the correct boundary condition object from a dictionary parsed from an input file.""" - geometry_set_id = int(bc_dict["E"]) - 1 - geometry_set = geometry_sets[geometry_set_id] del bc_dict["E"] if bc_key in ( diff --git a/src/meshpy/four_c/input_file.py b/src/meshpy/four_c/input_file.py index 778ce706..067aed8d 100644 --- a/src/meshpy/four_c/input_file.py +++ b/src/meshpy/four_c/input_file.py @@ -74,30 +74,28 @@ def _get_geometry_set_indices_from_section( geometry_set_dict: _Dict[int, _List[int]] = {} for line in section_list: - index_geometry_set = int(line.split()[-1]) + id_geometry_set = int(line.split()[-1]) index_node = int(line.split()[1]) - 1 - if index_geometry_set not in geometry_set_dict: - geometry_set_dict[index_geometry_set] = [] + if id_geometry_set not in geometry_set_dict: + geometry_set_dict[id_geometry_set] = [] if append_node_ids: - geometry_set_dict[index_geometry_set].append(index_node) + geometry_set_dict[id_geometry_set].append(index_node) return geometry_set_dict def _get_yaml_geometry_sets( nodes: _List[_Node], geometry_key: _conf.Geometry, section_list: _List -): +) -> _Dict[int, _GeometrySetNodes]: """Add sets of points, lines, surfaces or volumes to the object.""" # Create the individual geometry sets. The nodes are still integers at this # point. They have to be converted to links to the actual nodes later on. geometry_set_dict = _get_geometry_set_indices_from_section(section_list) - geometry_sets_in_this_section = [] - for node_ids in geometry_set_dict.values(): - geometry_sets_in_this_section.append( - _GeometrySetNodes( - geometry_key, nodes=[nodes[node_id] for node_id in node_ids] - ) + geometry_sets_in_this_section = {} + for geometry_set_id, node_ids in geometry_set_dict.items(): + geometry_sets_in_this_section[geometry_set_id] = _GeometrySetNodes( + geometry_key, nodes=[nodes[node_id] for node_id in node_ids] ) return geometry_sets_in_this_section @@ -219,6 +217,10 @@ def sections_to_mesh(self): """Convert mesh items, e.g., nodes, elements, element sets, node sets, boundary conditions, materials, ... + Note: In the current implementation we cannibalize the mesh sections in + the self.sections dictionary. This should be reconsidered and be done + in a better way when this function is generalized. + to "true" MeshPy objects. """ @@ -266,6 +268,7 @@ def _get_section_items(section_name): mesh.elements.append(_Element.from_legacy_string(element_nodes, item)) # Add geometry sets + geometry_sets_in_sections = {key: None for key in _mpy.geo} for section_name in self.sections.keys(): if section_name.endswith("TOPOLOGY"): section_items = _get_section_items(section_name) @@ -277,10 +280,13 @@ def _get_section_items(section_name): break else: raise ValueError(f"Could not find the set {section_name}") - geometry_sets_in_this_section = _get_yaml_geometry_sets( + geometry_sets_in_section = _get_yaml_geometry_sets( mesh.nodes, geometry_key, section_items ) - mesh.geometry_sets[geometry_key] = geometry_sets_in_this_section + geometry_sets_in_sections[geometry_key] = geometry_sets_in_section + mesh.geometry_sets[geometry_key] = list( + geometry_sets_in_section.values() + ) # Add boundary conditions for ( @@ -288,11 +294,11 @@ def _get_section_items(section_name): geometry_key, ), section_name in self.boundary_condition_names.items(): for item in _get_section_items(section_name): + geometry_set_id = item["E"] + geometry_set = geometry_sets_in_sections[geometry_key][geometry_set_id] mesh.boundary_conditions.append( (bc_key, geometry_key), - _BoundaryConditionBase.from_dict( - mesh.geometry_sets[geometry_key], bc_key, item - ), + _BoundaryConditionBase.from_dict(geometry_set, bc_key, item), ) self.add(mesh) diff --git a/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_dict_import.4C.yaml b/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_dict_import.4C.yaml new file mode 100644 index 00000000..3a64962e --- /dev/null +++ b/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_dict_import.4C.yaml @@ -0,0 +1,93 @@ +DLINE-NODE TOPOLOGY: + - NODE 1 DLINE 2 + - NODE 2 DLINE 2 + - NODE 3 DLINE 2 + - NODE 4 DLINE 2 + - NODE 5 DLINE 2 + - NODE 6 DLINE 4 + - NODE 7 DLINE 4 + - NODE 8 DLINE 4 + - NODE 9 DLINE 4 + - NODE 10 DLINE 4 + - NODE 11 DLINE 7 + - NODE 12 DLINE 7 + - NODE 13 DLINE 7 + - NODE 14 DLINE 7 + - NODE 15 DLINE 7 + - NODE 16 DLINE 8 + - NODE 17 DLINE 8 + - NODE 18 DLINE 8 + - NODE 19 DLINE 8 + - NODE 20 DLINE 8 + - NODE 21 DLINE 9 + - NODE 22 DLINE 9 + - NODE 23 DLINE 9 + - NODE 24 DLINE 9 + - NODE 25 DLINE 9 + - NODE 26 DLINE 10 + - NODE 27 DLINE 10 + - NODE 28 DLINE 10 + - NODE 29 DLINE 10 + - NODE 30 DLINE 10 +DNODE-NODE TOPOLOGY: + - NODE 5 DNODE 2 + - NODE 1 DNODE 4 + - NODE 10 DNODE 7 + - NODE 6 DNODE 11 + - NODE 15 DNODE 13 + - NODE 11 DNODE 17 + - NODE 20 DNODE 18 + - NODE 16 DNODE 19 + - NODE 25 DNODE 20 + - NODE 21 DNODE 21 + - NODE 30 DNODE 22 + - NODE 26 DNODE 23 +MATERIALS: + - MAT: 1 + MAT_BeamReissnerElastHyper: + CROSSAREA: 3.141592653589793 + DENS: 0.0 + MOMIN2: 0.7853981633974483 + MOMIN3: 0.7853981633974483 + MOMINPOL: 1.5707963267948966 + POISSONRATIO: 0.0 + SHEARCORR: 1 + YOUNG: -1.0 +NODE COORDS: + - NODE 1 COORD 0 0 0 + - NODE 2 COORD 0 0 1 + - NODE 3 COORD 0 0 2 + - NODE 4 COORD 0 0 3 + - NODE 5 COORD 0 0 4 + - NODE 6 COORD 1 0 0 + - NODE 7 COORD 1 0 1 + - NODE 8 COORD 1 0 2 + - NODE 9 COORD 1 0 3 + - NODE 10 COORD 1 0 4 + - NODE 11 COORD 2 0 0 + - NODE 12 COORD 2 0 1 + - NODE 13 COORD 2 0 2 + - NODE 14 COORD 2 0 3 + - NODE 15 COORD 2 0 4 + - NODE 16 COORD 3 0 0 + - NODE 17 COORD 3 0 1 + - NODE 18 COORD 3 0 2 + - NODE 19 COORD 3 0 3 + - NODE 20 COORD 3 0 4 + - NODE 21 COORD 4 0 0 + - NODE 22 COORD 4 0 1 + - NODE 23 COORD 4 0 2 + - NODE 24 COORD 4 0 3 + - NODE 25 COORD 4 0 4 + - NODE 26 COORD 5 0 0 + - NODE 27 COORD 5 0 1 + - NODE 28 COORD 5 0 2 + - NODE 29 COORD 5 0 3 + - NODE 30 COORD 5 0 4 +STRUCTURE ELEMENTS: + - 1 BEAM3R HERM2LINE3 16 18 17 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 2 BEAM3R HERM2LINE3 18 20 19 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 3 BEAM3R HERM2LINE3 21 23 22 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 4 BEAM3R HERM2LINE3 23 25 24 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 5 BEAM3R HERM2LINE3 26 28 27 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 6 BEAM3R HERM2LINE3 28 30 29 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 diff --git a/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_full_import.4C.yaml b/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_full_import.4C.yaml new file mode 100644 index 00000000..b1dcee99 --- /dev/null +++ b/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_full_import.4C.yaml @@ -0,0 +1,93 @@ +DLINE-NODE TOPOLOGY: + - NODE 1 DLINE 1 + - NODE 2 DLINE 1 + - NODE 3 DLINE 1 + - NODE 4 DLINE 1 + - NODE 5 DLINE 1 + - NODE 6 DLINE 2 + - NODE 7 DLINE 2 + - NODE 8 DLINE 2 + - NODE 9 DLINE 2 + - NODE 10 DLINE 2 + - NODE 11 DLINE 3 + - NODE 12 DLINE 3 + - NODE 13 DLINE 3 + - NODE 14 DLINE 3 + - NODE 15 DLINE 3 + - NODE 16 DLINE 4 + - NODE 17 DLINE 4 + - NODE 18 DLINE 4 + - NODE 19 DLINE 4 + - NODE 20 DLINE 4 + - NODE 21 DLINE 5 + - NODE 22 DLINE 5 + - NODE 23 DLINE 5 + - NODE 24 DLINE 5 + - NODE 25 DLINE 5 + - NODE 26 DLINE 6 + - NODE 27 DLINE 6 + - NODE 28 DLINE 6 + - NODE 29 DLINE 6 + - NODE 30 DLINE 6 +DNODE-NODE TOPOLOGY: + - NODE 5 DNODE 1 + - NODE 1 DNODE 2 + - NODE 10 DNODE 3 + - NODE 6 DNODE 4 + - NODE 15 DNODE 5 + - NODE 11 DNODE 6 + - NODE 20 DNODE 7 + - NODE 16 DNODE 8 + - NODE 25 DNODE 9 + - NODE 21 DNODE 10 + - NODE 30 DNODE 11 + - NODE 26 DNODE 12 +MATERIALS: + - MAT: 1 + MAT_BeamReissnerElastHyper: + CROSSAREA: 3.141592653589793 + DENS: 0.0 + MOMIN2: 0.7853981633974483 + MOMIN3: 0.7853981633974483 + MOMINPOL: 1.5707963267948966 + POISSONRATIO: 0.0 + SHEARCORR: 1 + YOUNG: -1.0 +NODE COORDS: + - NODE 1 COORD 0 0 0 + - NODE 2 COORD 0 0 1 + - NODE 3 COORD 0 0 2 + - NODE 4 COORD 0 0 3 + - NODE 5 COORD 0 0 4 + - NODE 6 COORD 1 0 0 + - NODE 7 COORD 1 0 1 + - NODE 8 COORD 1 0 2 + - NODE 9 COORD 1 0 3 + - NODE 10 COORD 1 0 4 + - NODE 11 COORD 2 0 0 + - NODE 12 COORD 2 0 1 + - NODE 13 COORD 2 0 2 + - NODE 14 COORD 2 0 3 + - NODE 15 COORD 2 0 4 + - NODE 16 COORD 3 0 0 + - NODE 17 COORD 3 0 1 + - NODE 18 COORD 3 0 2 + - NODE 19 COORD 3 0 3 + - NODE 20 COORD 3 0 4 + - NODE 21 COORD 4 0 0 + - NODE 22 COORD 4 0 1 + - NODE 23 COORD 4 0 2 + - NODE 24 COORD 4 0 3 + - NODE 25 COORD 4 0 4 + - NODE 26 COORD 5 0 0 + - NODE 27 COORD 5 0 1 + - NODE 28 COORD 5 0 2 + - NODE 29 COORD 5 0 3 + - NODE 30 COORD 5 0 4 +STRUCTURE ELEMENTS: + - 1 BEAM3R HERM2LINE3 16 18 17 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 2 BEAM3R HERM2LINE3 18 20 19 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 3 BEAM3R HERM2LINE3 21 23 22 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 4 BEAM3R HERM2LINE3 23 25 24 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 5 BEAM3R HERM2LINE3 26 28 27 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 + - 6 BEAM3R HERM2LINE3 28 30 29 MAT 1 TRIADS 0 -1.57079632679 0 0 -1.57079632679 0 0 -1.57079632679 0 diff --git a/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_input.4C.yaml b/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_input.4C.yaml new file mode 100644 index 00000000..1cc012dd --- /dev/null +++ b/tests/reference-files/test_four_c_import_non_consecutive_geometry_sets_input.4C.yaml @@ -0,0 +1,39 @@ +DLINE-NODE TOPOLOGY: + - NODE 1 DLINE 2 + - NODE 2 DLINE 2 + - NODE 3 DLINE 2 + - NODE 4 DLINE 2 + - NODE 5 DLINE 2 + - NODE 6 DLINE 4 + - NODE 7 DLINE 4 + - NODE 8 DLINE 4 + - NODE 9 DLINE 4 + - NODE 10 DLINE 4 + - NODE 11 DLINE 7 + - NODE 12 DLINE 7 + - NODE 13 DLINE 7 + - NODE 14 DLINE 7 + - NODE 15 DLINE 7 +DNODE-NODE TOPOLOGY: + - NODE 5 DNODE 2 + - NODE 1 DNODE 4 + - NODE 10 DNODE 7 + - NODE 6 DNODE 11 + - NODE 15 DNODE 13 + - NODE 11 DNODE 17 +NODE COORDS: + - NODE 1 COORD 0 0 0 + - NODE 2 COORD 0 0 1 + - NODE 3 COORD 0 0 2 + - NODE 4 COORD 0 0 3 + - NODE 5 COORD 0 0 4 + - NODE 6 COORD 1 0 0 + - NODE 7 COORD 1 0 1 + - NODE 8 COORD 1 0 2 + - NODE 9 COORD 1 0 3 + - NODE 10 COORD 1 0 4 + - NODE 11 COORD 2 0 0 + - NODE 12 COORD 2 0 1 + - NODE 13 COORD 2 0 2 + - NODE 14 COORD 2 0 3 + - NODE 15 COORD 2 0 4 diff --git a/tests/test_four_c.py b/tests/test_four_c.py index e75d6dc1..cb262992 100644 --- a/tests/test_four_c.py +++ b/tests/test_four_c.py @@ -709,3 +709,35 @@ def test_four_c_beam_to_solid( mpy.bc.beam_to_solid_surface_contact, ) assert_results_equal(get_corresponding_reference_file_path(), input_file) + + +@pytest.mark.parametrize( + ("full_import", "additional_identifier"), + [(False, "dict_import"), (True, "full_import")], +) +def test_four_c_import_non_consecutive_geometry_sets( + full_import, + additional_identifier, + get_corresponding_reference_file_path, + assert_results_equal, +): + """Test that we can import non-consecutively numbered geometry sets.""" + + mpy.import_mesh_full = full_import + input_file = InputFile( + yaml_file=get_corresponding_reference_file_path(additional_identifier="input") + ) + + material = MaterialReissner() + for i in range(3): + beam_set = create_beam_mesh_line( + input_file, Beam3rHerm2Line3, material, [i + 3, 0, 0], [i + 3, 0, 4], n_el=2 + ) + input_file.add(beam_set) + + assert_results_equal( + get_corresponding_reference_file_path( + additional_identifier=additional_identifier + ), + input_file, + )