Exemple #1
0
def get_nodes_and_elements(gmsh_session, fem, fem_set_name="all_elements"):
    nodes = list(gmsh_session.model.mesh.getNodes(-1, -1))
    # Get nodes
    fem._nodes = Nodes(
        [
            Node(
                [roundoff(x) for x in gmsh_session.model.mesh.getNode(n)[0]],
                n,
                parent=fem,
            ) for n in nodes[0]
        ],
        parent=fem,
    )

    # Get elements
    elemTypes, elemTags, elemNodeTags = gmsh_session.model.mesh.getElements(
        2, -1)
    elements = []
    for k, element_list in enumerate(elemTags):
        face, dim, morder, numv, parv, _ = gmsh_session.model.mesh.getElementProperties(
            elemTypes[k])
        elem_type = gmsh_map[face]
        for j, eltag in enumerate(element_list):
            nodes = []
            for i in range(numv):
                idtag = numv * j + i
                p1 = elemNodeTags[k][idtag]
                nodes.append(fem.nodes.from_id(p1))

            el = Elem(eltag, nodes, elem_type, parent=fem)
            elements.append(el)
    fem._elements = FemElements(elements, fem_obj=fem)
    femset = FemSet(fem_set_name, elements, "elset")
    fem.sets.add(femset)
Exemple #2
0
def meshio_read_fem(fem_file, fem_name=None):
    """Import a FEM file using the meshio package"""

    mesh = meshio.read(fem_file)
    name = fem_name if fem_name is not None else "Part-1"
    fem = FEM(name)

    def to_node(data):
        return Node(data[1], data[0])

    point_ids = mesh.points_id if "points_id" in mesh.__dict__.keys() else [
        i + 1 for i, x in enumerate(mesh.points)
    ]
    elem_counter = Counter(1)

    cell_ids = (mesh.cells_id if "cells_id" in mesh.__dict__.keys() else
                [[next(elem_counter) for cell in cellblock.data]
                 for cellblock in mesh.cells])
    fem.nodes = Nodes([to_node(p) for p in zip(point_ids, mesh.points)])

    cell_block_counter = Counter(0)

    def to_elem(cellblock):
        block_id = next(cell_block_counter)
        return [
            Elem(
                cell_ids[block_id][i],
                [fem.nodes.from_id(point_ids[c]) for c in cell],
                cellblock.type,
            ) for i, cell in enumerate(cellblock.data)
        ]

    fem.elements = FemElements(chain.from_iterable(map(to_elem, mesh.cells)))
    return Assembly("TempAssembly") / Part(name, fem=fem)
Exemple #3
0
    def get_elements(cls, bulk_str, parent):
        """
        Import elements from Sesam Bulk str


        :param bulk_str:
        :param parent:
        :type parent: ada.fem.FEM
        :return: FemElementsCollections
        :rtype: ada.fem.containers.FemElements
        """
        from ada.fem.containers import FemElements

        def grab_elements(match):
            d = match.groupdict()
            nodes = [
                parent.nodes.from_id(x)
                for x in filter(
                    lambda x: x != 0,
                    map(str_to_int, d["nids"].replace("\n", "").split()),
                )
            ]
            eltyp = d["eltyp"]
            el_type = cls.sesam_eltype_2_general(eltyp)
            metadata = dict(eltyad=str_to_int(d["eltyad"]), eltyp=eltyp)
            return Elem(
                str_to_int(d["elno"]),
                nodes,
                el_type,
                None,
                parent=parent,
                metadata=metadata,
            )

        return FemElements(list(map(grab_elements, cls.re_gelmnt.finditer(bulk_str))), fem_obj=parent)
Exemple #4
0
    def get_fem(self, name="AdaFEM") -> FEM:
        from .utils import (
            add_fem_sections,
            get_elements_from_entities,
            get_nodes_from_gmsh,
        )

        fem = FEM(name)
        gmsh_nodes = get_nodes_from_gmsh(self.model, fem)
        fem.nodes = Nodes(gmsh_nodes, parent=fem)

        def add_obj_to_elem_ref(el: Elem, obj: Union[Shape, Beam, Plate,
                                                     Pipe]):
            el.refs.append(obj)

        # Get Elements
        elements = []
        for gmsh_data in self.model_map.values():
            entity_elements = get_elements_from_entities(
                self.model, gmsh_data.entities, fem)
            gmsh_data.obj.elem_refs = entity_elements
            [add_obj_to_elem_ref(el, gmsh_data.obj) for el in entity_elements]
            elements += entity_elements

        fem.elements = FemElements(elements, fem_obj=fem)

        # Add FEM sections
        for model_obj, gmsh_data in self.model_map.items():
            add_fem_sections(self.model, fem, model_obj, gmsh_data)

        fem.nodes.renumber()
        fem.elements.renumber()
        return fem
Exemple #5
0
    def test_from_iterables(self):
        el1, el2, el3, el4 = get_elems()

        def geniter():
            yield el1
            yield el2
            yield el3

        g = geniter()
        n = FemElements(g)
Exemple #6
0
def get_fem_from_cache(cache_fem):
    node_groups = cache_fem["NODES"]
    fem = FEM(cache_fem.attrs["NAME"])
    fem.nodes = get_nodes_from_cache(node_groups, fem)
    elements = []
    for eltype, mesh in cache_fem["MESH"].items():
        el_ids = mesh["ELEMENTS"][()]
        elements += [Elem(el_id[0], [fem.nodes.from_id(eli) for eli in el_id[1:]], eltype) for el_id in el_ids]
    fem.elements = FemElements(elements, fem)

    return fem
Exemple #7
0
def get_elem_from_bulk_str(bulk_str, fem: "FEM") -> FemElements:
    """Read and import all *Element flags"""
    elements = FemElements(
        chain.from_iterable(
            filter(lambda x: x is not None,
                   (grab_elements(m, fem)
                    for m in cards.re_el.finditer(bulk_str)))),
        fem_obj=fem,
    )

    return elements
Exemple #8
0
def test_from_iterables(elems):
    el1, el2, el3, el4 = elems

    def geniter():
        yield el1
        yield el2
        yield el3

    g = geniter()
    n = FemElements(g)

    assert len(n) == 3
Exemple #9
0
def get_nodes_and_elements(gmsh, fem=None, fem_set_name="all_elements"):
    """

    :param gmsh:
    :type gmsh: gmsh
    :param fem:
    :type fem: ada.fem.FEM
    :param fem_set_name:
    :type fem_set_name: str
    """
    from ada.fem import FEM

    fem = FEM("AdaFEM") if fem is None else fem

    nodes = list(gmsh.model.mesh.getNodes(-1, -1))
    # Get nodes
    fem._nodes = Nodes(
        [
            Node(
                [roundoff(x) for x in gmsh.model.mesh.getNode(n)[0]],
                n,
                parent=fem,
            ) for n in nodes[0]
        ],
        parent=fem,
    )

    # Get elements
    elemTypes, elemTags, elemNodeTags = gmsh.model.mesh.getElements(2, -1)
    elements = []
    for k, element_list in enumerate(elemTags):
        face, dim, morder, numv, parv, _ = gmsh.model.mesh.getElementProperties(
            elemTypes[k])
        elem_type = gmsh_map[face]
        for j, eltag in enumerate(element_list):
            nodes = []
            for i in range(numv):
                idtag = numv * j + i
                p1 = elemNodeTags[k][idtag]
                nodes.append(fem.nodes.from_id(p1))

            el = Elem(eltag, nodes, elem_type, parent=fem)
            elements.append(el)
    fem._elements = FemElements(elements, fem_obj=fem)
    femset = FemSet(fem_set_name, elements, "elset")
    fem.sets.add(femset)
Exemple #10
0
def meshio_read_fem(assembly, fem_file, fem_name=None):
    """
    Import a FEM file using the meshio package.


    :param assembly: Assembly object
    :param fem_file: Path to fem file
    :param fem_name: Name of FEM model
    :type assembly: ada.Assembly
    """
    from ada import Node, Part

    from . import meshio_to_ada_type

    mesh = meshio.read(fem_file)
    name = fem_name if fem_name is not None else "Part-1"
    fem = FEM(name)

    def to_node(data):
        return Node(data[1], data[0])

    point_ids = mesh.points_id if "points_id" in mesh.__dict__.keys() else [
        i + 1 for i, x in enumerate(mesh.points)
    ]
    elem_counter = Counter(0)

    cell_ids = (mesh.cells_id if "cells_id" in mesh.__dict__.keys() else
                [[next(elem_counter) for cell in cellblock.data]
                 for cellblock in mesh.cells])
    fem._nodes = Nodes([to_node(p) for p in zip(point_ids, mesh.points)])

    cell_block_counter = Counter(-1)

    def to_elem(cellblock):
        block_id = next(cell_block_counter)
        return [
            Elem(
                cell_ids[block_id][i],
                [fem.nodes.from_id(point_ids[c]) for c in cell],
                meshio_to_ada_type[cellblock.type],
            ) for i, cell in enumerate(cellblock.data)
        ]

    fem._elements = FemElements(chain.from_iterable(map(to_elem, mesh.cells)))
    assembly.add_part(Part(name, fem=fem))
Exemple #11
0
def get_mass_from_bulk(bulk_str, parent: "FEM") -> FemElements:
    """

    *MASS,ELSET=MASS3001
    2.00000000E+03,

    :return:
    """
    mass_ids = Counter(int(parent.elements.max_el_id + 1))

    re_masses = re.compile(
        r"\*(?P<mass_type>Nonstructural Mass|Mass|Rotary Inertia),\s*elset=(?P<elset>.*?)"
        r"(?:,\s*type=(?P<ptype>.*?)\s*|\s*)(?:, units=(?P<units>.*?)|\s*)\n\s*(?P<mass>.*?)$",
        _re_in,
    )
    return FemElements(
        (get_mass(m, parent, mass_ids) for m in re_masses.finditer(bulk_str)),
        fem_obj=parent)
Exemple #12
0
def get_elements(bulk_str: str,
                 fem: FEM) -> Tuple[FemElements, dict, dict, dict]:
    """Import elements from Sesam Bulk str"""

    mass_elem = dict()
    spring_elem = dict()
    internal_external_element_map = dict()

    def grab_elements(match):
        d = match.groupdict()
        el_no = str_to_int(d["elno"])
        el_nox = str_to_int(d["elnox"])
        internal_external_element_map[el_no] = el_nox
        nodes = [
            fem.nodes.from_id(x) for x in filter(
                lambda x: x != 0,
                map(str_to_int, d["nids"].replace("\n", "").split()),
            )
        ]
        eltyp = d["eltyp"]
        el_type = sesam_eltype_2_general(str_to_int(eltyp))

        if el_type in ("SPRING1", "SPRING2"):
            spring_elem[el_no] = dict(gelmnt=d)
            return None

        metadata = dict(eltyad=str_to_int(d["eltyad"]), eltyp=eltyp)
        elem = Elem(el_no, nodes, el_type, None, parent=fem, metadata=metadata)

        if el_type == Elem.EL_TYPES.MASS_SHAPES.MASS:
            logging.warning(
                "Mass element interpretation in sesam is undergoing changes. Results should be checked"
            )
            mass_elem[el_no] = dict(gelmnt=d)
            fem.sets.add(
                FemSet(f"m{el_no}", [elem], FemSet.TYPES.ELSET, parent=fem))

        return elem

    elements = FemElements(filter(
        lambda x: x is not None,
        map(grab_elements, cards.re_gelmnt.finditer(bulk_str))),
                           fem_obj=fem)
    return elements, mass_elem, spring_elem, internal_external_element_map
Exemple #13
0
def test_empty():
    n = FemElements([])
    assert len(n) == 0
Exemple #14
0
def get_elem_from_inp(bulk_str, fem):
    """
    Extract elements from abaqus input file

    :param bulk_str:
    :param fem:
    :type fem: ada.fem.FEM

    :return:
    :rtype: ada.fem.containers.FemElements
    """

    from ada import Node, Part

    re_el = re.compile(
        r"^\*Element,\s*type=(?P<eltype>.*?)(?:\n|,\s*elset=(?P<elset>.*?)\s*\n)(?<=)(?P<members>(?:.*?)(?=\*|\Z))",
        _re_in,
    )

    def grab_elements(match):
        d = match.groupdict()
        eltype = d["eltype"]
        elset = d["elset"]
        members = d["members"]
        res = re.search("[a-zA-Z]", members)
        if eltype.upper(
        ) in ElemShapes.cube20 + ElemShapes.cube27 or res is None:
            if eltype.upper() in ElemShapes.cube20 + ElemShapes.cube27:
                temp = members.splitlines()
                ntext = "".join([
                    l1.strip() + "    " + l2.strip() + "\n"
                    for l1, l2 in zip(temp[:-1:2], temp[1::2])
                ])
            else:
                ntext = d["members"]
            res = np.fromstring(ntext.replace("\n", ","), sep=",", dtype=int)
            n = ElemShapes.num_nodes(eltype) + 1
            res_ = res.reshape(int(res.size / n), n)
            return [
                Elem(e[0], [fem.nodes.from_id(n) for n in e[1:]],
                     eltype,
                     elset,
                     parent=fem) for e in res_
            ]
        else:

            # TODO: This code needs to be re-worked!
            elems = []
            for li in members.splitlines():
                new_mem = []
                temp = li.split(",")
                elid = str_to_int(temp[0])
                for d in temp[1:]:
                    temp2 = [x.strip() for x in d.split(".")]
                    par_ = None
                    if len(temp2) == 2:
                        par, setr = temp2
                        pfems = []
                        parents = fem.parent.get_all_parts_in_assembly()
                        for p in parents:
                            assert isinstance(p, Part)
                            pfems.append(p.fem.name)
                            if p.fem.name == par:
                                par_ = p
                                break
                        if par_ is None:
                            raise ValueError(
                                f'Unable to find parent for "{par}"')
                        r = par_.fem.nodes.from_id(str_to_int(setr))
                        if type(r) != Node:
                            raise ValueError("Node ID not found")
                        new_mem.append(r)
                    else:
                        r = fem.nodes.from_id(str_to_int(d))
                        if type(r) != Node:
                            raise ValueError("Node ID not found")
                        new_mem.append(r)
                elems.append(Elem(elid, new_mem, eltype, elset, parent=fem))
            return elems

    return FemElements(
        chain.from_iterable(map(grab_elements, re_el.finditer(bulk_str))),
        fem_obj=fem,
    )
Exemple #15
0
    def test_from_sequence(self):
        all_elemes = get_elems()
        n = FemElements(all_elemes[:3])

        assert len(n) == 3
Exemple #16
0
    def test_with_duplicates(self):
        el1, el2, el3, el4 = get_elems()
        n = FemElements([el1, el2, el1])

        assert len(n) == 3
Exemple #17
0
def test_with_duplicates(elems):
    el1, el2, el3, el4 = elems

    with pytest.raises(ValueError):
        FemElements([el1, el2, el1])
Exemple #18
0
def test_from_sequence(elems):
    n = FemElements(elems[:3])

    assert len(n) == 3
Exemple #19
0
    def mesh(
        self,
        size=0.1,
        order=1,
        max_dim=2,
        interactive=False,
        mesh_algo=8,
        sh_int_points=5,
    ):
        """

        :param size:
        :param order:
        :param max_dim:
        :param interactive:
        :param mesh_algo:
        :param sh_int_points:
        :return:
        """

        part = self._part
        pl_in = [pl_ for p in part.get_all_subparts()
                 for pl_ in p.plates] + [pl for pl in part.plates]
        bm_in = [bm_ for p in part.get_all_subparts()
                 for bm_ in p.beams] + [bm for bm in part.beams]
        try:
            gmsh.finalize()
        except BaseException as e:
            logging.debug(e)
        gmsh.initialize()
        gmsh.option.setNumber("General.Terminal", 1)
        gmsh.option.setNumber("Mesh.SecondOrderIncomplete", 1)
        gmsh.option.setNumber("Mesh.Algorithm", mesh_algo)
        gmsh.option.setNumber("Mesh.ElementOrder", order)

        list(
            map(
                functools.partial(
                    self._create_plate_geom,
                    beams=bm_in,
                    size=size,
                    interactive=interactive,
                ),
                pl_in,
            ))
        gmsh.model.geo.synchronize()

        list(
            map(
                functools.partial(self._create_bm_geom, size=size),
                filter(lambda x: x not in [b for b in self._bm_map.values()],
                       bm_in),
            ))
        gmsh.model.geo.synchronize()

        if len(pl_in) > 0:
            gmsh.model.mesh.setRecombine(2, 1)

        gmsh.model.mesh.generate(max_dim)
        gmsh.model.mesh.removeDuplicateNodes()

        if interactive:
            gmsh.fltk.run()

        nodes = list(gmsh.model.mesh.getNodes(-1, -1))

        # Extract Gmsh model information and import the data into a FEM model
        self._part.fem._nodes = Nodes(list(map(self.get_mesh_nodes, nodes[0])),
                                      parent=self._part.fem)
        bm_elems = map(functools.partial(self.get_beam_elements, order=order),
                       self._bm_map.keys())
        pl_elems = map(functools.partial(self.get_shell_elements, order=order),
                       self._pl_map.keys())
        self._part.fem._elements = FemElements(
            chain.from_iterable(list(bm_elems) + list(pl_elems)),
            fem_obj=self._part.fem)
        self._part.fem.elements.renumber()

        gmsh.finalize()
Exemple #20
0
def get_mass(bulk_str: str, fem: FEM, mass_elem: dict) -> FemElements:
    def checkEqual2(iterator):
        return len(set(iterator)) <= 1

    def find_bnmass(match) -> Mass:
        d = match.groupdict()

        nodeno = str_to_int(d["nodeno"])
        mass_in = [
            roundoff(d["m1"]),
            roundoff(d["m2"]),
            roundoff(d["m3"]),
            roundoff(d["m4"]),
            roundoff(d["m5"]),
            roundoff(d["m6"]),
        ]
        masses = [m for m in mass_in if m != 0.0]
        if checkEqual2(masses):
            mass_type = Mass.PTYPES.ISOTROPIC
            masses = [masses[0]] if len(masses) > 0 else [0.0]
        else:
            mass_type = Mass.PTYPES.ANISOTROPIC

        no = fem.nodes.from_id(nodeno)
        fem_set = fem.sets.add(
            FemSet(f"m{nodeno}", [no], FemSet.TYPES.NSET, parent=fem))
        el_id = fem.elements.max_el_id + 1
        elem = fem.elements.add(
            Elem(el_id, [no], Elem.EL_TYPES.MASS_SHAPES.MASS, None,
                 parent=fem))
        mass = Mass(f"m{nodeno}",
                    fem_set,
                    masses,
                    Mass.TYPES.MASS,
                    ptype=mass_type,
                    parent=fem,
                    mass_id=el_id)

        elset = fem.sets.add(
            FemSet(f"m{nodeno}", [elem], FemSet.TYPES.ELSET, parent=fem))
        elem.mass_props = mass
        elem.elset = elset
        return mass

    def find_mgmass(match) -> Mass:
        d = match.groupdict()
        matno = str_to_int(d["matno"])
        mat_mass_map = {
            str_to_int(val["section_data"]["matno"]): val
            for key, val in mass_elem.items()
        }
        mass_el: dict = mat_mass_map.get(matno, None)
        if mass_el is None:
            raise ValueError()
        ndof = str_to_int(d["ndof"])
        if ndof != 6:
            raise NotImplementedError(
                "Only mass matrices with 6 DOF are currently supported for reading"
            )

        r = [float(x) for x in d["bulk"].split()]
        A = np.matrix([
            [r[0], 0.0, 0.0, 0.0, 0.0, 0.0],
            [r[1], r[6], 0.0, 0.0, 0.0, 0.0],
            [r[2], r[7], r[11], 0.0, 0.0, 0.0],
            [r[3], r[8], r[12], r[15], 0.0, 0.0],
            [r[4], r[9], r[13], r[16], r[18], 0.0],
            [r[5], r[10], r[14], r[17], r[19], r[20]],
        ])
        # use symmetry to complete the 6x6 matrix
        mass_matrix_6x6 = np.tril(A) + np.triu(A.T, 1)
        nodeno = str_to_int(mass_el["gelmnt"].get("nids"))
        elno = str_to_int(mass_el["gelmnt"].get("elno"))
        no = fem.nodes.from_id(nodeno)
        fem_set = fem.sets.add(
            FemSet(f"m{nodeno}", [no], FemSet.TYPES.NSET, parent=fem))

        mass_type = Mass.PTYPES.ANISOTROPIC
        mass = Mass(f"m{nodeno}",
                    fem_set,
                    mass_matrix_6x6,
                    Mass.TYPES.MASS,
                    ptype=mass_type,
                    parent=fem,
                    mass_id=elno)
        mass_el["el"] = mass
        return mass

    bn_masses = map(find_bnmass, cards.re_bnmass.finditer(bulk_str))
    mg_masses = map(find_mgmass, cards.re_mgmass.finditer(bulk_str))
    return FemElements(chain(bn_masses, mg_masses), fem_obj=fem)
Exemple #21
0
def read_fem(assembly, fem_file, fem_name=None):
    """

    :param assembly:
    :param fem_file:
    :param fem_name:
    :return:
    """
    from ada import Node, Part

    f = h5py.File(fem_file, "r")

    # Mesh ensemble
    mesh_ensemble = f["ENS_MAA"]
    meshes = mesh_ensemble.keys()
    if len(meshes) != 1:
        raise ValueError("Must only contain exactly 1 mesh, found {}.".format(len(meshes)))
    mesh_name = list(meshes)[0]
    mesh = mesh_ensemble[mesh_name]

    dim = mesh.attrs["ESP"]

    fem_name = fem_name if fem_name is not None else mesh_name

    # Initialize FEM object
    fem = FEM(mesh_name)

    # Possible time-stepping
    if "NOE" not in mesh:
        # One needs NOE (node) and MAI (French maillage, meshing) data. If they
        # are not available in the mesh, check for time-steppings.
        time_step = mesh.keys()
        if len(time_step) != 1:
            raise ValueError(f"Must only contain exactly 1 time-step, found {len(time_step)}.")
        mesh = mesh[list(time_step)[0]]

    # Points
    pts_dataset = mesh["NOE"]["COO"]
    n_points = pts_dataset.attrs["NBR"]
    points = pts_dataset[()].reshape((n_points, dim), order="F")

    if "NUM" in mesh["NOE"]:
        point_num = list(mesh["NOE"]["NUM"])
    else:
        logging.warning("No node information is found on MED file")
        point_num = np.arange(1, len(points) + 1)

    fem._nodes = Nodes([Node(p, point_num[i]) for i, p in enumerate(points)], parent=fem)

    # Point tags
    tags = None
    if "FAM" in mesh["NOE"]:
        tags = mesh["NOE"]["FAM"][()]

    # Information for point tags
    point_tags = {}
    fas = mesh["FAS"] if "FAS" in mesh else f["FAS"][mesh_name]
    if "NOEUD" in fas:
        point_tags = _read_families(fas["NOEUD"])

    point_sets = _point_tags_to_sets(tags, point_tags, fem) if tags is not None else []

    # Information for cell tags
    cell_tags = {}
    if "ELEME" in fas:
        cell_tags = _read_families(fas["ELEME"])

    # CellBlock
    cell_types = []
    med_cells = mesh["MAI"]

    elements = []
    element_sets = dict()
    for med_cell_type, med_cell_type_group in med_cells.items():
        if med_cell_type == "PO1":
            logging.warning("Point elements are still not supported")
            continue

        cell_type = med_to_abaqus_type(med_cell_type)
        cell_types.append(cell_type)

        nod = med_cell_type_group["NOD"]
        n_cells = nod.attrs["NBR"]
        nodes_in = nod[()].reshape(n_cells, -1, order="F")

        if "NUM" in med_cell_type_group.keys():
            num = list(med_cell_type_group["NUM"])
        else:
            num = np.arange(0, len(nodes_in))

        element_block = [
            Elem(num[i], [fem.nodes.from_id(e) for e in c], cell_type, parent=fem) for i, c in enumerate(nodes_in)
        ]
        elements += element_block
        # Cell tags
        if "FAM" in med_cell_type_group:
            cell_data = med_cell_type_group["FAM"][()]
            cell_type_sets = _cell_tag_to_set(cell_data, cell_tags)
            for key, val in cell_type_sets.items():
                if key not in element_sets.keys():
                    element_sets[key] = []
                element_sets[key] += [element_block[i] for i in val]

    fem._elements = FemElements(elements, fem)

    elsets = []
    for name, values in element_sets.items():
        elsets.append(FemSet(name, values, "elset", parent=fem))

    fem._sets = FemSets(elsets + point_sets, fem_obj=fem)

    assembly.add_part(Part(fem_name, fem=fem))
    return
Exemple #22
0
 def test_empty(self):
     n = FemElements([])