예제 #1
0
 def add_section(self, section: FemSection) -> FemSection:
     section.parent = self
     if section.elset.parent is None:
         if section.elset.name in self.elsets.keys():
             fs = self.elsets[section.elset.name]
         else:
             fs = self.sets.add(section.elset)
         if fs != section.elset:
             logging.info(
                 f'Element set "{section.elset}" is replaced by {fs}')
             section.elset = fs
     if section.material.parent is None and self.parent is not None:
         self.parent.add_material(section.material)
     self.sections.add(section)
     return section
예제 #2
0
def get_shell_section(m, sh_name, fem: "FEM", a: "Assembly"):
    d = m.groupdict()
    name = next(sh_name)
    elset = fem.sets.get_elset_from_name(d["elset"])

    material = d["material"]
    mat = a.materials.get_by_name(material)
    thickness = float(d["t"])
    offset = d["offset"]
    if offset is not None:
        # TODO: update this with the latest eccentricity class
        logging.warning("Offset for Shell elements is not yet evaluated")
        for el in elset.members:
            el.eccentricity = Eccentricity(sh_ecc_vector=offset)
    int_points = d["int_points"]
    metadata = dict(controls=d["controls"])

    return FemSection(
        name=name,
        sec_type=ElemType.SHELL,
        thickness=thickness,
        elset=elset,
        material=mat,
        int_points=int_points,
        parent=fem,
        metadata=metadata,
    )
예제 #3
0
    def create_fem_elem_from_obj(self, obj, el_type=None) -> Elem:
        """Converts structural object to FEM elements. Currently only BEAM is supported"""
        from ada.fem.shapes import ElemType

        if type(obj) is not Beam:
            raise NotImplementedError(
                f'Object type "{type(obj)}" is not yet supported')

        el_type = ElemType.LINE if el_type is None else el_type

        res = self.nodes.add(obj.n1)
        if res is not None:
            obj.n1 = res
        res = self.nodes.add(obj.n2)
        if res is not None:
            obj.n2 = res

        elem = self.add_elem(Elem(None, [obj.n1, obj.n2], el_type))
        femset = self.add_set(
            FemSet(f"{obj.name}_set", [elem], FemSet.TYPES.ELSET))
        self.add_section(
            FemSection(
                f"d{obj.name}_sec",
                ElemType.LINE,
                femset,
                obj.material,
                obj.section,
                obj.ori[1],
            ))
        return elem
예제 #4
0
 def grab_beam(match):
     d = match.groupdict()
     elset = fem.elsets[d["elset"]]
     name = d["sec_name"] if d["sec_name"] is not None else elset.name
     profile = d["profile_name"] if d[
         "profile_name"] is not None else elset.name
     ass = fem.parent.get_assembly()
     material = ass.materials.get_by_name(d["material"])
     # material = parent.parent.materials.get_by_name(d['material'])
     temperature = d["temperature"]
     section_type = d["sec_type"]
     geo_props = d["line1"]
     sec = interpret_section(profile, section_type, geo_props)
     beam_y = [
         float(x.strip()) for x in d["line2"].split(",") if x.strip() != ""
     ]
     metadata = dict(
         temperature=temperature,
         profile=profile.strip(),
         section_type=section_type,
         line1=geo_props,
     )
     res = fem.parent.sections.add(sec)
     if res is not None:
         sec = res
     return FemSection(
         name.strip(),
         sec_type="beam",
         elset=elset,
         section=sec,
         local_y=beam_y,
         material=material,
         metadata=metadata,
         parent=fem,
     )
예제 #5
0
    def get_beam_elements(self, li, order):
        """

        :param li:
        :param order:
        :return:
        """
        import gmsh

        from ada.core.utils import make_name_fem_ready

        model = gmsh.model
        bm = self._bm_map[li]
        segments = model.mesh.getElements(1, li)[1][0]
        fem_nodes = model.mesh.getElements(1, li)[2][0]
        elem_types, elem_tags, elem_node_tags = gmsh.model.mesh.getElements(
            1, li)
        face, dim, morder, numv, parv, _ = gmsh.model.mesh.getElementProperties(
            elem_types[0])

        set_name = make_name_fem_ready(f"el{bm.name}_set")
        fem = self._part.fem

        def make_elem(j):
            no = []
            for i in range(numv):
                p1 = fem_nodes[numv * j + i]
                p1_co = gmsh.model.mesh.getNode(p1)[0]
                no.append(Node(p1_co, p1))
            if len(no) == 3:
                myorder = [0, 2, 1]
                no = [no[i] for i in myorder]
            bm_el_type = "B31" if order == 1 else "B32"

            return Elem(segments[j], no, bm_el_type, parent=self._part.fem)

        elements = list(map(make_elem, range(len(segments))))
        fem_sec_name = make_name_fem_ready(f"d{bm.name}_sec")

        if set_name in fem.elsets.keys():
            fem_set = fem.elsets[set_name]
            for el in elements:
                el.fem_sec = fem_set.members[0].fem_sec
            fem_set.add_members(elements)
        else:
            fem_set = FemSet(set_name, elements, "elset", parent=fem)
            fem.sets.add(fem_set)
            fem.add_section(
                FemSection(
                    fem_sec_name,
                    "beam",
                    fem_set,
                    bm.material,
                    bm.section,
                    bm.ori[2],
                    metadata=dict(beam=bm, numel=len(elements)),
                ))
        return elements
예제 #6
0
 def grab_solid(m_in):
     name = m_in.group(1) if m_in.group(1) is not None else next(secnames)
     elset = m_in.group(2)
     material = m_in.group(3)
     return FemSection(
         name=name,
         sec_type="solid",
         elset=elset,
         material=material,
         parent=fem,
     )
예제 #7
0
 def grab_solid(m_in):
     name = m_in.group(1) if m_in.group(1) is not None else next(secnames)
     elset = m_in.group(2)
     material = m_in.group(3)
     mat = a.materials.get_by_name(material)
     return FemSection(
         name=name,
         sec_type=ElemType.SOLID,
         elset=elset,
         material=mat,
         parent=fem,
     )
예제 #8
0
    def test_negative_sec_contained(self):
        # A minor change in section box thickness
        sec = Section("myBG", from_str="BG800x400x20x40")
        mat = Material("my_mat")

        bm = Beam("my_beam", (0, 0, 0), (1, 0, 0), sec, mat)
        elem = Elem(1, [bm.n1, bm.n2], "B31")
        fem_set = FemSet("my_set", [elem], "elset")
        fem_sec = FemSection("my_sec", "beam", fem_set, mat, sec)
        p = get_fsec_bm_collection()

        self.assertFalse(fem_sec in p.fem.sections)
예제 #9
0
    def test_negative_sec_contained(self):
        # A minor change in section box thickness
        sec = Section('myBG', from_str='BG800x400x20x40')
        mat = Material('my_mat')

        bm = Beam('my_beam', (0, 0, 0), (1, 0, 0), sec, mat)
        elem = Elem(1, [bm.n1, bm.n2], 'B31')
        fem_set = FemSet('my_set', [elem], 'elset')
        fem_sec = FemSection('my_sec', 'beam', fem_set, mat, sec)
        p = get_fsec_bm_collection()

        self.assertFalse(fem_sec in p.fem.sections)
예제 #10
0
    def get_shell_elements(self, sh, order):
        """

        :param sh:
        :param order:
        :return:
        """
        import gmsh

        pl = self._pl_map[sh]
        assert isinstance(pl, Plate)
        try:
            get_elems = gmsh.model.mesh.getElements(2, sh)
            segments = get_elems[1][0]
        except BaseException as e:
            logging.debug(e)
            return []
        fem_nodes = gmsh.model.mesh.getElements(2, sh)[2][0]
        elemTypes, elemTags, elemNodeTags = gmsh.model.mesh.getElements(2, sh)
        face, dim, morder, numv, parv, _ = gmsh.model.mesh.getElementProperties(
            elemTypes[0])

        elem_type = gmsh_map[face]

        def make_elem(j):
            el_id = segments[j]
            nonlocal elem_type
            nonlocal numv
            nonlocal fem_nodes
            no = []
            for i in range(numv):
                p1 = fem_nodes[numv * j + i]
                p1_co = gmsh.model.mesh.getNode(p1)[0]
                no.append(Node(p1_co, p1))

            return Elem(el_id, no, elem_type, parent=self._part.fem)

        elements = list(map(make_elem, range(len(segments))))

        femset = FemSet(f"el{pl.name}_set", elements, "elset")
        self._part.fem.add_set(femset)
        self._part.fem.add_section(
            FemSection(
                f"sh{pl.name}_sec",
                "shell",
                femset,
                pl.material,
                local_z=pl.n,
                thickness=pl.t,
                int_points=5,
                metadata=dict(beam=pl, numel=len(elements)),
            ))
        return elements
예제 #11
0
def test_negative_contained_shell_(part_with_shell):
    # Testing equal operator for change in element type
    mat = Material("my_mat")
    elem = Elem(
        1,
        [Node((0, 0, 0)),
         Node((1, 0, 0)),
         Node((1, 1, 0)),
         Node((0, 1, 0))], "quad")
    fem_set = FemSet("my_set", [elem], "elset")
    fem_sec = FemSection("my_sec", "shell", fem_set, mat, thickness=0.01)

    assert fem_sec not in part_with_shell.fem.sections
예제 #12
0
    def test_negative_mat_contained(self):
        # A minor change in material property (S420 instead of S355)
        sec = Section("myBG", from_str="BG800x400x30x40")

        mat = Material("my_mat", CarbonSteel("S420"))

        bm = Beam("my_beam", (0, 0, 0), (1, 0, 0), sec, mat)
        elem = Elem(1, [bm.n1, bm.n2], "B31")
        fem_set = FemSet("my_set", [elem], "elset")
        fem_sec = FemSection("my_sec", "beam", fem_set, mat, sec)
        p = get_fsec_bm_collection()

        self.assertFalse(fem_sec in p.fem.sections)
예제 #13
0
    def test_negative_mat_contained(self):
        # A minor change in material property (S420 instead of S355)
        sec = Section('myBG', from_str='BG800x400x30x40')

        mat = Material('my_mat', CarbonSteel('S420'))

        bm = Beam('my_beam', (0, 0, 0), (1, 0, 0), sec, mat)
        elem = Elem(1, [bm.n1, bm.n2], 'B31')
        fem_set = FemSet('my_set', [elem], 'elset')
        fem_sec = FemSection('my_sec', 'beam', fem_set, mat, sec)
        p = get_fsec_bm_collection()

        self.assertFalse(fem_sec in p.fem.sections)
예제 #14
0
파일: conftest.py 프로젝트: Krande/adapy
def part_with_beam():
    sec = Section("myIPE", from_str="BG800x400x30x40")
    mat = Material("my_mat")

    bm = Beam("my_beam", (0, 0, 0), (1, 0, 0), sec, mat)
    elem = Elem(1, [bm.n1, bm.n2], "line")
    p = Part("my_part") / bm
    fem_set = p.fem.sets.add(FemSet("my_set", [elem]))
    p.fem.sections.add(
        FemSection("my_sec", "line", fem_set, mat, sec, local_z=(0, 0, 1)))
    p.fem.elements.add(elem)

    return p
예제 #15
0
    def test_negative_contained_shell(self):
        # Testing equal operator for different shell thickness
        mat = Material('my_mat')
        elem = Elem(1, [
            Node((0, 0, 0)),
            Node((1, 0, 0)),
            Node((1, 1, 0)),
            Node((0, 1, 0))
        ], 'S4R')
        fem_set = FemSet('my_set', [elem], 'elset')
        fem_sec = FemSection('my_sec', 'shell', fem_set, mat, thickness=0.02)

        p = get_fsec_sh_collection()

        self.assertFalse(fem_sec in p.fem.sections)
예제 #16
0
    def test_negative_contained_shell_(self):
        # Testing equal operator for change in element type
        mat = Material("my_mat")
        elem = Elem(1, [
            Node((0, 0, 0)),
            Node((1, 0, 0)),
            Node((1, 1, 0)),
            Node((0, 1, 0))
        ], "S4")
        fem_set = FemSet("my_set", [elem], "elset")
        fem_sec = FemSection("my_sec", "shell", fem_set, mat, thickness=0.01)

        p = get_fsec_sh_collection()

        self.assertFalse(fem_sec in p.fem.sections)
예제 #17
0
파일: common.py 프로젝트: Caladeux/adapy
    def get_beam_elements(self, li, order):
        """

        :param li:
        :param order:
        :return:
        """

        model = gmsh.model
        bm = self._bm_map[li]
        segments = model.mesh.getElements(1, li)[1][0]
        fem_nodes = model.mesh.getElements(1, li)[2][0]
        elem_types, elem_tags, elem_node_tags = gmsh.model.mesh.getElements(
            1, li)
        face, dim, morder, numv, parv, _ = gmsh.model.mesh.getElementProperties(
            elem_types[0])

        def make_elem(j):
            no = []
            for i in range(numv):
                p1 = fem_nodes[numv * j + i]
                p1_co = gmsh.model.mesh.getNode(p1)[0]
                no.append(Node(p1_co, p1))
            if len(no) == 3:
                myorder = [0, 2, 1]
                no = [no[i] for i in myorder]
            bm_el_type = "B31" if order == 1 else "B32"

            return Elem(segments[j], no, bm_el_type, parent=self._part.fem)

        elements = list(map(make_elem, range(len(segments))))

        femset = FemSet(f"el{bm.name}_set",
                        elements,
                        "elset",
                        parent=self._part.fem)
        self._part.fem.sets.add(femset)
        self._part.fem.add_section(
            FemSection(
                f"d{bm.name}_sec",
                "beam",
                femset,
                bm.material,
                bm.section,
                bm.ori[2],
                metadata=dict(beam=bm, numel=len(elements)),
            ))
        return elements
예제 #18
0
def test_negative_sec_contained(part_with_beam):
    # A minor change in section box thickness
    sec = Section("myBG", from_str="BG800x400x20x40")
    mat = Material("my_mat")

    bm = Beam("my_beam", (0, 0, 0), (1, 0, 0), sec, mat)
    elem = Elem(1, [bm.n1, bm.n2], "line")
    fem_set = FemSet("my_set", [elem], "elset")
    fem_sec = FemSection("my_sec",
                         "line",
                         fem_set,
                         mat,
                         sec,
                         local_z=(0, 0, 1))

    assert fem_sec not in part_with_beam.fem.sections
예제 #19
0
def read_line_section(elem: Elem, fem: FEM, mat: Material, geono, d, lcsysd,
                      hinges_global, eccentricities):
    transno = str_to_int(d["transno"])
    sec = fem.parent.sections.get_by_id(geono)
    n1, n2 = elem.nodes
    v = n2.p - n1.p
    if vector_length(v) == 0.0:
        xvec = [1, 0, 0]
    else:
        xvec = unit_vector(v)
    zvec = lcsysd[transno]
    crossed = np.cross(zvec, xvec)
    ma = max(abs(crossed))
    yvec = tuple([roundoff(x / ma, 3) for x in crossed])

    fix_data = str_to_int(d["fixno"])
    ecc_data = str_to_int(d["eccno"])

    members = None
    if d["members"] is not None:
        members = [
            str_to_int(x) for x in d["members"].replace("\n", " ").split()
        ]

    if fix_data == -1:
        add_hinge_prop_to_elem(elem, members, hinges_global, xvec, yvec)

    if ecc_data == -1:
        add_ecc_to_elem(elem, members, eccentricities, fix_data)

    fem_set = FemSet(sec.name, [elem],
                     "elset",
                     metadata=dict(internal=True),
                     parent=fem)
    fem.sets.add(fem_set, append_suffix_on_exist=True)
    fem_sec = FemSection(
        sec_id=geono,
        name=sec.name,
        sec_type=ElemType.LINE,
        elset=fem_set,
        section=sec,
        local_z=zvec,
        local_y=yvec,
        material=mat,
        parent=fem,
    )
    return fem_sec
예제 #20
0
def read_shell_section(elem: Elem, fem: FEM, mat: Material, elno, thicknesses,
                       geono):
    sec_name = f"sh{elno}"
    fem_set = FemSet(sec_name, [elem],
                     "elset",
                     parent=fem,
                     metadata=dict(internal=True))
    fem.sets.add(fem_set)
    fem_sec = FemSection(
        name=sec_name,
        sec_type=ElemType.SHELL,
        thickness=roundoff(thicknesses[geono]),
        elset=fem_set,
        material=mat,
        parent=fem,
    )
    return fem_sec
예제 #21
0
파일: conftest.py 프로젝트: Krande/adapy
def part_with_shell():
    p = Part("my_part")
    mat = Material("my_mat")
    elem = Elem(
        1,
        [Node((0, 0, 0)),
         Node((1, 0, 0)),
         Node((1, 1, 0)),
         Node((0, 1, 0))], "quad")
    fem_set = FemSet("my_set", [elem], "elset")
    fem_sec = FemSection("my_sec", "shell", fem_set, mat, thickness=0.01)
    for n in elem.nodes:
        p.fem.nodes.add(n)
    p.fem.elements.add(elem)
    p.fem.sets.add(fem_set)
    p.fem.sections.add(fem_sec)
    return p
예제 #22
0
def get_fsec_sh_collection():
    p = Part('my_part')
    mat = Material('my_mat')
    elem = Elem(
        1,
        [Node((0, 0, 0)),
         Node((1, 0, 0)),
         Node((1, 1, 0)),
         Node((0, 1, 0))], 'S4R')
    fem_set = FemSet('my_set', [elem], 'elset')
    fem_sec = FemSection('my_sec', 'shell', fem_set, mat, thickness=0.01)
    for n in elem.nodes:
        p.fem.nodes.add(n)
    p.fem.elements.add(elem)
    p.fem.sets.add(fem_set)
    p.fem.sections.add(fem_sec)
    return p
예제 #23
0
def test_negative_mat_contained(part_with_beam):
    # A minor change in material property (S420 instead of S355)
    sec = Section("myBG", from_str="BG800x400x30x40")

    mat = Material("my_mat", CarbonSteel("S420"))

    bm = Beam("my_beam", (0, 0, 0), (1, 0, 0), sec, mat)
    elem = Elem(1, [bm.n1, bm.n2], "line")
    fem_set = FemSet("my_set", [elem], "elset")
    fem_sec = FemSection("my_sec",
                         "line",
                         fem_set,
                         mat,
                         sec,
                         local_z=(0, 0, 1))

    assert fem_sec not in part_with_beam.fem.sections
예제 #24
0
파일: utils.py 프로젝트: Krande/adapy
def add_shell_section(
    set_name,
    fem_sec_name,
    normal,
    thickness,
    elements,
    model_obj: Union[Beam, Plate, Pipe, Shape],
    fem: FEM,
    is_rigid=False,
):
    fem_set = FemSet(set_name, elements, FemSet.TYPES.ELSET)
    props = dict(local_z=normal,
                 thickness=thickness,
                 int_points=5,
                 is_rigid=is_rigid)
    fem_sec = FemSection(fem_sec_name, ElemType.SHELL, fem_set,
                         model_obj.material, **props)
    add_sec_to_fem(fem, fem_sec, fem_set)
예제 #25
0
파일: utils.py 프로젝트: Krande/adapy
def get_so_sections(model: gmsh.model, solid_object: Beam, gmsh_data: GmshData,
                    fem: FEM):
    tags = []
    for dim, ent in gmsh_data.entities:
        _, tag, _ = model.mesh.getElements(3, ent)
        tags += tag

    elements = [
        fem.elements.from_id(elid) for elid in chain.from_iterable(tags)
    ]

    set_name = make_name_fem_ready(f"el{solid_object.name}_so")
    fem_sec_name = make_name_fem_ready(f"d{solid_object.name}_so")

    fem_set = FemSet(set_name, elements, FemSet.TYPES.ELSET, parent=fem)
    fem_sec = FemSection(fem_sec_name, ElemType.SOLID, fem_set,
                         solid_object.material)

    add_sec_to_fem(fem, fem_sec, fem_set)
예제 #26
0
def get_fsec_bm_collection():
    sec = Section("myIPE", from_str="BG800x400x30x40")
    mat = Material("my_mat")
    p = Part("my_part")
    bm = Beam("my_beam", (0, 0, 0), (1, 0, 0), sec, mat)
    elem = Elem(1, [bm.n1, bm.n2], "B31")
    fem_set = FemSet("my_set", [elem], "elset")
    fem_sec = FemSection("my_sec",
                         "beam",
                         fem_set,
                         mat,
                         sec,
                         local_z=(0, 0, 1))

    p.add_beam(bm)
    p.fem.elements.add(elem)
    p.fem.sets.add(fem_set)
    p.fem.sections.add(fem_sec)
    return p
예제 #27
0
def get_fsec_bm_collection():
    sec = Section('myIPE', from_str='BG800x400x30x40')
    mat = Material('my_mat')
    p = Part('my_part')
    bm = Beam('my_beam', (0, 0, 0), (1, 0, 0), sec, mat)
    elem = Elem(1, [bm.n1, bm.n2], 'B31')
    fem_set = FemSet('my_set', [elem], 'elset')
    fem_sec = FemSection('my_sec',
                         'beam',
                         fem_set,
                         mat,
                         sec,
                         local_z=(0, 0, 1))

    p.add_beam(bm)
    p.fem.elements.add(elem)
    p.fem.sets.add(fem_set)
    p.fem.sections.add(fem_sec)
    return p
예제 #28
0
 def grab_shell(m):
     d = m.groupdict()
     name = d["name"] if d["name"] is not None else next(shname)
     elset = fem.sets.get_elset_from_name(d["elset"])
     material = d["material"]
     thickness = float(d["t"])
     offset = d["offset"]
     int_points = d["int_points"]
     metadata = dict(controls=d["controls"])
     return FemSection(
         name=name,
         sec_type="shell",
         thickness=thickness,
         elset=elset,
         material=material,
         int_points=int_points,
         offset=offset,
         parent=fem,
         metadata=metadata,
     )
예제 #29
0
파일: utils.py 프로젝트: Krande/adapy
def get_bm_sections(model: gmsh.model, beam: Beam, gmsh_data, fem: FEM):
    from ada.core.vector_utils import vector_length

    tags = []
    for dim, ent in gmsh_data.entities:
        _, tag, _ = model.mesh.getElements(1, ent)
        tags += tag

    elements = [
        fem.elements.from_id(elid) for elid in chain.from_iterable(tags)
    ]

    set_name = make_name_fem_ready(f"el{beam.name}_set_bm")
    fem_sec_name = make_name_fem_ready(f"d{beam.name}_sec_bm")
    fem_set = FemSet(set_name, elements, FemSet.TYPES.ELSET, parent=fem)
    fem_sec = FemSection(fem_sec_name,
                         ElemType.LINE,
                         fem_set,
                         beam.material,
                         beam.section,
                         beam.ori[2],
                         refs=[beam])

    add_sec_to_fem(fem, fem_sec, fem_set)
    if beam.hinge_prop is None:
        return
    end1_p = beam.hinge_prop.end1.concept_node.p if beam.hinge_prop.end1 is not None else None
    end2_p = beam.hinge_prop.end2.concept_node.p if beam.hinge_prop.end2 is not None else None
    if beam.hinge_prop is not None:
        for el in elements:
            n1 = el.nodes[0]
            n2 = el.nodes[-1]
            el.hinge_prop = beam.hinge_prop
            if beam.hinge_prop.end1 is not None and vector_length(end1_p -
                                                                  n1.p) == 0.0:
                el.hinge_prop.end1.fem_node = n1

            if beam.hinge_prop.end2 is not None and vector_length(end2_p -
                                                                  n2.p) == 0.0:
                el.hinge_prop.end2.fem_node = n2
예제 #30
0
def create_sconcept_str(fem_sec: FemSection) -> Tuple[str, str, str]:
    sconcept_str = ""
    # Give concept relationship based on inputted values

    beams = [x for x in fem_sec.refs if type(x) is Beam]
    if len(beams) != 1:
        raise ValueError("A FemSection cannot be sourced from multiple beams")
    beam = beams[0]

    fem_sec.metadata["ircon"] = next(concept_ircon)
    bm_name = make_name_fem_ready(beam.name, no_dot=True)
    tdsconc_str = write_ff(
        "TDSCONC",
        [(4, fem_sec.metadata["ircon"], 100 + len(bm_name), 0), (bm_name, )],
    )
    sconcept_str += write_ff("SCONCEPT", [(8, next(concept), 7, 0),
                                          (0, 1, 0, 2)])
    sconc_ref = next(concept)
    sconcept_str += write_ff("SCONCEPT", [(5, sconc_ref, 2, 4), (1, )])
    elids: List[tuple] = []
    i = 0

    numel = len(beam.elem_refs)
    elid_bulk = [numel]
    for el in fem_sec.elset.members:
        if i == 3:
            elids.append(tuple(elid_bulk))
            elid_bulk = []
            i = -1
        elid_bulk.append(el.id)
        i += 1
    if len(elid_bulk) != 0:
        elids.append(tuple(elid_bulk))

    mesh_args = [(5 + numel, sconc_ref, 1, 2)] + elids
    scon_mesh = write_ff("SCONMESH", mesh_args)
    return tdsconc_str, sconcept_str, scon_mesh