beamme.four_c.model_importer

This module contains functions to load and parse existing 4C input files.

  1# The MIT License (MIT)
  2#
  3# Copyright (c) 2018-2026 BeamMe Authors
  4#
  5# Permission is hereby granted, free of charge, to any person obtaining a copy
  6# of this software and associated documentation files (the "Software"), to deal
  7# in the Software without restriction, including without limitation the rights
  8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9# copies of the Software, and to permit persons to whom the Software is
 10# furnished to do so, subject to the following conditions:
 11#
 12# The above copyright notice and this permission notice shall be included in
 13# all copies or substantial portions of the Software.
 14#
 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 21# THE SOFTWARE.
 22"""This module contains functions to load and parse existing 4C input files."""
 23
 24from collections import defaultdict as _defaultdict
 25from pathlib import Path as _Path
 26from typing import Tuple as _Tuple
 27
 28import numpy as _np
 29
 30from beamme.core.boundary_condition import BoundaryCondition as _BoundaryCondition
 31from beamme.core.boundary_condition import (
 32    BoundaryConditionBase as _BoundaryConditionBase,
 33)
 34from beamme.core.conf import Geometry as _Geometry
 35from beamme.core.conf import bme as _bme
 36from beamme.core.coupling import Coupling as _Coupling
 37from beamme.core.geometry_set import GeometrySetNodes as _GeometrySetNodes
 38from beamme.core.mesh import Mesh as _Mesh
 39from beamme.core.mesh_representation import (
 40    MESH_REPRESENTATION_MAPPINGS as _MESH_REPRESENTATION_MAPPINGS,
 41)
 42from beamme.core.mesh_representation import GeometrySetInfo as _GeometrySetInfo
 43from beamme.core.mesh_representation import MeshRepresentation as _MeshRepresentation
 44from beamme.core.mesh_representation import (
 45    string_to_geometry_set_info as _string_to_geometry_set_info,
 46)
 47from beamme.core.node import Node as _Node
 48from beamme.four_c.element_data import FourCElementData as _FourCElementData
 49from beamme.four_c.element_data import (
 50    four_c_element_data_from_legacy_dict as _four_c_element_data_from_legacy_dict,
 51)
 52from beamme.four_c.element_solid import get_four_c_solid as _get_four_c_solid
 53from beamme.four_c.input_file import InputFile as _InputFile
 54from beamme.four_c.input_file_mappings import (
 55    INPUT_FILE_MAPPINGS as _INPUT_FILE_MAPPINGS,
 56)
 57from beamme.four_c.material import MaterialSolid as _MaterialSolid
 58from beamme.utils.environment import cubitpy_is_available as _cubitpy_is_available
 59
 60if _cubitpy_is_available():
 61    from cubitpy.cubit_to_fourc_input import (
 62        get_input_file_with_mesh as _get_input_file_with_mesh,
 63    )
 64
 65
 66class UniqueDataTracker:
 67    """Helper class to track unique data dictionaries and assign IDs to them.
 68
 69    When importing input files, we need to identify elements of the same
 70    type. The type information is given in dictionaries. This class
 71    provides a tracker that can be queried with a given element data and
 72    return an already matching element type ID or create a new one.
 73    """
 74
 75    def __init__(self) -> None:
 76        self.unique_id_to_data: dict[int, _FourCElementData] = {}
 77
 78    def get_unique_id(self, data: _FourCElementData) -> int:
 79        """Get the unique ID for the given data. If the data has not been seen
 80        before, a new ID will be assigned to it.
 81
 82        Args:
 83            data: The data dictionary to get the ID for.
 84
 85        Returns:
 86            The unique ID for the given data.
 87        """
 88        for unique_id, seen_data in self.unique_id_to_data.items():
 89            if data == seen_data:
 90                return unique_id
 91
 92        # If we reach this point, the data has not been seen before. We assign a new ID to it.
 93        new_unique_id = len(self.unique_id_to_data)
 94        self.unique_id_to_data[new_unique_id] = data
 95        return new_unique_id
 96
 97
 98def import_cubitpy_model(
 99    cubit, convert_input_to_mesh: bool = False
100) -> _Tuple[_InputFile, _Mesh]:
101    """Convert a CubitPy instance to a BeamMe InputFile.
102
103    Args:
104        cubit (CubitPy): An instance of a cubit model.
105        convert_input_to_mesh: If this is false, the cubit model will be
106            converted to plain FourCIPP input data. If this is true, an input
107            file with all the parameters will be returned and a mesh which
108            contains the mesh information from cubit converted to BeamMe
109            objects.
110
111    Returns:
112        A tuple with the input file and the mesh. If convert_input_to_mesh is
113        False, the mesh will be empty. Note that the input sections which are
114        converted to a BeamMe mesh are removed from the input file object.
115    """
116
117    input_file = _InputFile()
118    input_file.add(_get_input_file_with_mesh(cubit).sections)
119
120    if convert_input_to_mesh:
121        return _extract_mesh_from_input_file(input_file)
122    else:
123        return input_file, _Mesh()
124
125
126def import_four_c_model(
127    input_file_path: _Path, convert_input_to_mesh: bool = False
128) -> _Tuple[_InputFile, _Mesh]:
129    """Import an existing 4C input file and optionally convert it into a BeamMe
130    mesh.
131
132    Args:
133        input_file_path: A file path to an existing 4C input file that will be
134            imported.
135        convert_input_to_mesh: If True, the input file will be converted to a
136            BeamMe mesh.
137
138    Returns:
139        A tuple with the input file and the mesh. If convert_input_to_mesh is
140        False, the mesh will be empty. Note that the input sections which are
141        converted to a BeamMe mesh are removed from the input file object.
142    """
143
144    input_file = _InputFile().from_4C_yaml(input_file_path=input_file_path)
145
146    if convert_input_to_mesh:
147        return _extract_mesh_from_input_file(input_file)
148    else:
149        return input_file, _Mesh()
150
151
152def _extract_mesh_from_input_file(input_file: _InputFile) -> tuple[_InputFile, _Mesh]:
153    """Convert an InputFile into a native mesh by translating sections like
154    materials, nodes, elements, geometry sets, and boundary conditions.
155
156    Args:
157        input_file: The input file containing 4C sections.
158    Returns:
159        A tuple (input_file, mesh). The input_file is modified in place to remove
160        sections converted into BeamMe objects.
161    """
162    if input_file.contains_external_mesh_based_geometry():
163        raise NotImplementedError(
164            "Importing external mesh-based geometry from 4C input files "
165            "is not yet implemented."
166        )
167    else:
168        (
169            mesh_representation,
170            element_type_id_to_data,
171            node_set_id_mesh_representation_to_input_file,
172        ) = _extract_mesh_representation(input_file)
173    return _create_mesh_from_mesh_representation(
174        input_file,
175        mesh_representation,
176        element_type_id_to_data,
177        node_set_id_mesh_representation_to_input_file,
178    )
179
180
181def _extract_mesh_representation(
182    input_file: _InputFile,
183) -> tuple[_MeshRepresentation, dict[int, _FourCElementData], dict[int, int]]:
184    """Extract the mesh representation from mesh data directly contained in the
185    input file.
186
187    This will do an inplace removal of the mesh data from the provided input file.
188
189    Args:
190        input_file: The input file containing the mesh data, will be modified in place.
191
192    Returns:
193        A tuple containing:
194        - `mesh_representation`: Contains the mesh data extracted from the input file.
195        - `element_type_id_to_data`: A mapping between the element type ID and the
196            element data.
197        - `node_set_id_mesh_representation_to_input_file`: A mapping that can be used
198            to map the IDs in the mesh representation to the IDs in the input file.
199    """
200
201    # extract nodes
202    nodes = input_file.pop("NODE COORDS", [])
203    n_nodes = len(nodes)
204    points = _np.zeros((n_nodes, 3))
205    point_types = _np.full(n_nodes, -1)
206    control_point_weights = _np.full(n_nodes, -1.0)
207    for i, node in enumerate(nodes):
208        four_c_node_type = node["data"]["type"]
209        node_id = node["id"]
210        try:
211            node_type = _INPUT_FILE_MAPPINGS["four_c_node_type_to_beamme_node_type"][
212                four_c_node_type
213            ]
214        except KeyError:
215            raise ValueError(
216                f"Unknown node type `{four_c_node_type}` for node {node_id}."
217            )
218        points[i] = node["COORD"]
219        point_types[i] = node_type.value
220        if node_type == _bme.node_type.control_point:
221            control_point_weights[i] = node["data"]["weight"]
222
223    # extract elements
224    element_type_tracker = UniqueDataTracker()
225    elements = input_file.pop("STRUCTURE ELEMENTS", [])
226    n_elements = len(elements)
227    cell_connectivity = []
228    cell_types = _np.full(n_elements, -1)
229    cell_element_type_ids = _np.full(n_elements, -1)
230    cell_material_ids = _np.full(n_elements, -1)
231    for i_element, input_element in enumerate(elements):
232        four_c_element_data, element_id, connectivity, material_id = (
233            _four_c_element_data_from_legacy_dict(input_element)
234        )
235        element_type_id = element_type_tracker.get_unique_id(four_c_element_data)
236
237        # Check if connectivity has to be reordered
238        reorder_indices = _INPUT_FILE_MAPPINGS[
239            "four_c_cell_to_vtk_connectivity_mapping"
240        ].get(four_c_element_data.four_c_cell, None)
241        if reorder_indices is not None:
242            connectivity = connectivity[reorder_indices]
243
244        cell_connectivity.extend([len(connectivity), *connectivity.tolist()])
245
246        try:
247            vtk_cell_type = _INPUT_FILE_MAPPINGS["four_c_cell_to_vtk_cell_type"][
248                four_c_element_data.four_c_cell
249            ]
250        except KeyError:
251            raise ValueError(
252                f"Unknown cell type `{four_c_element_data.four_c_cell}` for element {element_id}."
253            )
254
255        cell_types[i_element] = vtk_cell_type
256        cell_element_type_ids[i_element] = element_type_id
257        cell_material_ids[i_element] = material_id
258
259    # extract geometry sets
260    node_sets: list[_GeometrySetInfo] = []
261    node_set_id_mesh_representation_to_input_file: dict[int, int] = {}
262    for section_name in input_file.sections:
263        if not section_name.endswith("TOPOLOGY"):
264            continue
265
266        items = input_file.pop(section_name, [])
267        if not items:
268            continue
269
270        # Find geometry type for this section
271        try:
272            geometry_type = _INPUT_FILE_MAPPINGS[
273                "geometry_sets_condition_to_geometry_name"
274            ][section_name]
275        except KeyError as e:
276            raise ValueError(f"Unknown geometry section: {section_name}") from e
277
278        # Extract geometry set indices
279        geom_dict: dict[int, set[int]] = _defaultdict(set)
280        for entry in items:
281            geom_dict[entry["d_id"]].add(entry["node_id"] - 1)
282
283        for input_file_node_set_id, node_ids in geom_dict.items():
284            node_set_id = len(node_sets)
285
286            node_set_flag = _np.zeros(n_nodes, dtype=int)
287            node_set_flag[list(node_ids)] = 1
288
289            node_sets.append(
290                _GeometrySetInfo(
291                    geometry_type=geometry_type,
292                    i_global=node_set_id,
293                    point_flag_vector=node_set_flag,
294                )
295            )
296
297            node_set_id_mesh_representation_to_input_file[node_set_id] = (
298                input_file_node_set_id
299            )
300
301    # Create the mesh representation and add the extracted data to it.
302    mesh_representation = _MeshRepresentation(
303        cell_connectivity=cell_connectivity,
304        cell_types=cell_types,
305        points=points,
306        geometry_sets=node_sets,
307        point_data={
308            "point_type": point_types,
309            "control_point_weight": control_point_weights,
310        },
311        cell_data={
312            "element_type_id": cell_element_type_ids,
313            "material_id": cell_material_ids,
314        },
315    )
316
317    return (
318        mesh_representation,
319        element_type_tracker.unique_id_to_data,
320        node_set_id_mesh_representation_to_input_file,
321    )
322
323
324def _create_mesh_from_mesh_representation(
325    input_file,
326    mesh_representation,
327    element_type_id_to_data,
328    node_set_id_mesh_representation_to_input_file,
329) -> tuple[_InputFile, _Mesh]:
330    """Extract a BeamMe mesh from a mesh representation.
331
332    Args:
333        input_file: The input file containing general data.
334        mesh_representation: The mesh representation to convert.
335        node_set_id_mesh_representation_to_input_file: A mapping of the mesh
336            representation node set IDs to input file IDs, which can be used to link
337            the geometry sets in the input file to the node sets in the mesh
338            representation.
339
340    Returns:
341        A tuple (input_file, mesh). The input_file is modified in place to remove
342        sections converted into the BeamMe mesh.
343    """
344
345    # convert all sections to native objects and add to a new mesh
346    mesh = _Mesh()
347
348    # extract materials
349    material_id_map = _extract_materials_from_input_file(input_file)
350    mesh.materials.extend(material_id_map.values())
351
352    # extract nodes
353    for node_coordinates, node_type in zip(
354        mesh_representation.points, mesh_representation.point_data["point_type"]
355    ):
356        if node_type == _bme.node_type.node.value:
357            mesh.nodes.append(_Node(node_coordinates))
358        else:
359            raise ValueError(
360                f"Mesh conversion for node type {_bme.node_type(node_type).name} is not implemented!"
361            )
362
363    # extract element types
364    element_type_id_to_element_type: dict[int, type] = {}
365    for (
366        element_type_id,
367        element_data,
368    ) in element_type_id_to_data.items():
369        element_type, n_nodes = _INPUT_FILE_MAPPINGS[
370            "four_c_cell_to_element_type_and_n_nodes"
371        ][element_data.four_c_cell]
372        if not element_type == _bme.element_type.solid:
373            raise ValueError(
374                f"Mesh conversion for element type {element_type} is not implemented!"
375            )
376        element_type_id_to_element_type[element_type_id] = _get_four_c_solid(
377            element_type,
378            element_data.four_c_type,
379            n_nodes=n_nodes,
380            element_technology=element_data.element_technology,
381        )
382
383    # loop over the elements and create the mesh elements with the correct type, connectivity and material.
384    for connectivity, cell_element_type_id_, material_id in zip(
385        mesh_representation.connectivity_iterator(),
386        mesh_representation.cell_data["element_type_id"],
387        mesh_representation.cell_data["material_id"],
388    ):
389        element_type = element_type_id_to_element_type[cell_element_type_id_]
390
391        reorder_indices = _MESH_REPRESENTATION_MAPPINGS[
392            "element_type_and_n_nodes_to_connectivity_mapping_vtk_to_beamme"
393        ].get((element_type.element_type, len(connectivity)), None)
394        if reorder_indices is not None:
395            nodes = [mesh.nodes[connectivity[i]] for i in reorder_indices]
396        else:
397            nodes = [mesh.nodes[i] for i in connectivity]
398
399        element = element_type(nodes=nodes)
400
401        if not material_id == -1:
402            element.material = material_id_map[material_id]
403        mesh.elements.append(element)
404
405    # extract geometry sets
406    geometry_sets_in_sections: dict[_Geometry, dict[int, _GeometrySetNodes]] = (
407        _defaultdict(dict)
408    )
409    for name in mesh_representation.point_data.keys():
410        info = _string_to_geometry_set_info(name)
411        if info is not None:
412            node_indices = _np.nonzero(mesh_representation.point_data[name])[0]
413            geometry_type = info.geometry_type
414            geometry_set = _GeometrySetNodes(
415                geometry_type, nodes=[mesh.nodes[i] for i in node_indices]
416            )
417            input_file_id = node_set_id_mesh_representation_to_input_file[info.i_global]
418            geometry_sets_in_sections[geometry_type][input_file_id] = geometry_set
419            mesh.add(geometry_set)
420
421    # extract boundary conditions
422    _standard_bc_types = (
423        _bme.bc.dirichlet,
424        _bme.bc.neumann,
425        _bme.bc.locsys,
426        _bme.bc.beam_to_solid_surface_meshtying,
427        _bme.bc.beam_to_solid_surface_contact,
428        _bme.bc.beam_to_solid_volume_meshtying,
429    )
430
431    for (bc_key, geometry_type), section_name in _INPUT_FILE_MAPPINGS[
432        "boundary_conditions"
433    ].items():
434        for bc_data in input_file.pop(section_name, []):
435            geometry_set = geometry_sets_in_sections[geometry_type][bc_data.pop("E")]
436
437            bc_obj: _BoundaryConditionBase
438
439            if bc_key in _standard_bc_types or isinstance(bc_key, str):
440                bc_obj = _BoundaryCondition(geometry_set, bc_data, bc_type=bc_key)
441            elif bc_key is _bme.bc.point_coupling:
442                bc_obj = _Coupling(
443                    geometry_set, bc_key, bc_data, check_overlapping_nodes=False
444                )
445            else:
446                raise ValueError(f"Unexpected boundary condition: {bc_key}")
447
448            mesh.boundary_conditions.append((bc_key, geometry_type), bc_obj)
449
450    return input_file, mesh
451
452
453def _extract_materials_from_input_file(
454    input_file: _InputFile,
455) -> dict[int, _MaterialSolid]:
456    """Extract all materials from the input file and convert them to BeamMe
457    materials.
458
459    Args:
460        input_file: The input file containing the material sections.
461
462    Returns:
463        A mapping of material IDs to BeamMe material objects.
464    """
465
466    material_id_map_all = {}
467
468    for mat in input_file.pop("MATERIALS", []):
469        mat_id = mat.pop("MAT") - 1
470        if len(mat) != 1:
471            raise ValueError(
472                f"Could not convert the material data `{mat}` to a BeamMe material!"
473            )
474        mat_name, mat_data = list(mat.items())[0]
475        material = _MaterialSolid(material_string=mat_name, data=mat_data)
476        material_id_map_all[mat_id] = material
477
478    nested_materials = set()
479    for material in material_id_map_all.values():
480        # Replace the integer IDs in the "MATIDS" list of the material with the actual
481        # material objects.
482        sub_materials = material.data.get("MATIDS", [])
483        sub_material_ids = _np.array(sub_materials) - 1
484        for i_sub_material, sub_material_id in enumerate(sub_material_ids):
485            try:
486                sub_materials[i_sub_material] = material_id_map_all[sub_material_id]
487            except KeyError as key_exception:
488                raise KeyError(
489                    f"Material ID {sub_material_id} not in material_id_map_all (available "
490                    f"IDs: {list(material_id_map_all.keys())})."
491                ) from key_exception
492            nested_materials.add(sub_material_id)
493
494    # Get a map of all non-nested materials. We assume that only those are used as
495    # materials for elements. Also, add the non-nested materials to the mesh.
496    material_id_map = {
497        key: val
498        for key, val in material_id_map_all.items()
499        if key not in nested_materials
500    }
501
502    return material_id_map
class UniqueDataTracker:
67class UniqueDataTracker:
68    """Helper class to track unique data dictionaries and assign IDs to them.
69
70    When importing input files, we need to identify elements of the same
71    type. The type information is given in dictionaries. This class
72    provides a tracker that can be queried with a given element data and
73    return an already matching element type ID or create a new one.
74    """
75
76    def __init__(self) -> None:
77        self.unique_id_to_data: dict[int, _FourCElementData] = {}
78
79    def get_unique_id(self, data: _FourCElementData) -> int:
80        """Get the unique ID for the given data. If the data has not been seen
81        before, a new ID will be assigned to it.
82
83        Args:
84            data: The data dictionary to get the ID for.
85
86        Returns:
87            The unique ID for the given data.
88        """
89        for unique_id, seen_data in self.unique_id_to_data.items():
90            if data == seen_data:
91                return unique_id
92
93        # If we reach this point, the data has not been seen before. We assign a new ID to it.
94        new_unique_id = len(self.unique_id_to_data)
95        self.unique_id_to_data[new_unique_id] = data
96        return new_unique_id

Helper class to track unique data dictionaries and assign IDs to them.

When importing input files, we need to identify elements of the same type. The type information is given in dictionaries. This class provides a tracker that can be queried with a given element data and return an already matching element type ID or create a new one.

unique_id_to_data: dict[int, beamme.four_c.element_data.FourCElementData]
def get_unique_id(self, data: beamme.four_c.element_data.FourCElementData) -> int:
79    def get_unique_id(self, data: _FourCElementData) -> int:
80        """Get the unique ID for the given data. If the data has not been seen
81        before, a new ID will be assigned to it.
82
83        Args:
84            data: The data dictionary to get the ID for.
85
86        Returns:
87            The unique ID for the given data.
88        """
89        for unique_id, seen_data in self.unique_id_to_data.items():
90            if data == seen_data:
91                return unique_id
92
93        # If we reach this point, the data has not been seen before. We assign a new ID to it.
94        new_unique_id = len(self.unique_id_to_data)
95        self.unique_id_to_data[new_unique_id] = data
96        return new_unique_id

Get the unique ID for the given data. If the data has not been seen before, a new ID will be assigned to it.

Arguments:
  • data: The data dictionary to get the ID for.
Returns:

The unique ID for the given data.

def import_cubitpy_model( cubit, convert_input_to_mesh: bool = False) -> Tuple[beamme.four_c.input_file.InputFile, beamme.core.mesh.Mesh]:
 99def import_cubitpy_model(
100    cubit, convert_input_to_mesh: bool = False
101) -> _Tuple[_InputFile, _Mesh]:
102    """Convert a CubitPy instance to a BeamMe InputFile.
103
104    Args:
105        cubit (CubitPy): An instance of a cubit model.
106        convert_input_to_mesh: If this is false, the cubit model will be
107            converted to plain FourCIPP input data. If this is true, an input
108            file with all the parameters will be returned and a mesh which
109            contains the mesh information from cubit converted to BeamMe
110            objects.
111
112    Returns:
113        A tuple with the input file and the mesh. If convert_input_to_mesh is
114        False, the mesh will be empty. Note that the input sections which are
115        converted to a BeamMe mesh are removed from the input file object.
116    """
117
118    input_file = _InputFile()
119    input_file.add(_get_input_file_with_mesh(cubit).sections)
120
121    if convert_input_to_mesh:
122        return _extract_mesh_from_input_file(input_file)
123    else:
124        return input_file, _Mesh()

Convert a CubitPy instance to a BeamMe InputFile.

Arguments:
  • cubit (CubitPy): An instance of a cubit model.
  • convert_input_to_mesh: If this is false, the cubit model will be converted to plain FourCIPP input data. If this is true, an input file with all the parameters will be returned and a mesh which contains the mesh information from cubit converted to BeamMe objects.
Returns:

A tuple with the input file and the mesh. If convert_input_to_mesh is False, the mesh will be empty. Note that the input sections which are converted to a BeamMe mesh are removed from the input file object.

def import_four_c_model( input_file_path: pathlib._local.Path, convert_input_to_mesh: bool = False) -> Tuple[beamme.four_c.input_file.InputFile, beamme.core.mesh.Mesh]:
127def import_four_c_model(
128    input_file_path: _Path, convert_input_to_mesh: bool = False
129) -> _Tuple[_InputFile, _Mesh]:
130    """Import an existing 4C input file and optionally convert it into a BeamMe
131    mesh.
132
133    Args:
134        input_file_path: A file path to an existing 4C input file that will be
135            imported.
136        convert_input_to_mesh: If True, the input file will be converted to a
137            BeamMe mesh.
138
139    Returns:
140        A tuple with the input file and the mesh. If convert_input_to_mesh is
141        False, the mesh will be empty. Note that the input sections which are
142        converted to a BeamMe mesh are removed from the input file object.
143    """
144
145    input_file = _InputFile().from_4C_yaml(input_file_path=input_file_path)
146
147    if convert_input_to_mesh:
148        return _extract_mesh_from_input_file(input_file)
149    else:
150        return input_file, _Mesh()

Import an existing 4C input file and optionally convert it into a BeamMe mesh.

Arguments:
  • input_file_path: A file path to an existing 4C input file that will be imported.
  • convert_input_to_mesh: If True, the input file will be converted to a BeamMe mesh.
Returns:

A tuple with the input file and the mesh. If convert_input_to_mesh is False, the mesh will be empty. Note that the input sections which are converted to a BeamMe mesh are removed from the input file object.