Exemple #1
0
def line_mesh(xmin, xblocks):
    """ create evenly spaced mesh given endpoints and number of elements

    """
    coords = np.array([xmin])
    for i, (xlen, xint) in enumerate(xblocks):
        xl = coords[-1]
        xr = xl + xlen
        n = xint + 1

        # check for bad inputs
        if xl >= xr:
            raise UserInputError("BLOCK {0}: xl > xr".format(i))

        if n <= 0:
            raise UserInputError("XBLOCK {0}: negative interval".format(i))

        # find element seperation
        block_coords = np.linspace(xl, xr, n)

        #force location of endpoints
        block_coords[0] = xl
        block_coords[-1] = xr
        coords = np.append(coords, block_coords[1:])
        continue
    nel = coords.size - 1
    conn = np.array([[i, i + 1] for i in range(nel)])
    return coords, conn
Exemple #2
0
    def check_coords_and_conn(dim, coords, connect):
        """Check the coordinates and connectivity arrays

        """
        # coords
        if not np.any(coords):
            raise UserInputError("No coords given")
        coords = np.array(coords)
        if coords.shape[1] == 2:
            coords = np.hstack((coords, np.zeros((coords.shape[0], 1))))
        nnodes = coords.shape[0]

        # connectivity
        if not np.any(connect):
            raise UserInputError("No nodal connectivity given")
        conn = []
        for lmn, nodes in enumerate(connect):
            if max(nodes) > nnodes:
                raise UserInputError(
                    "Node number {0} in connect exceeds number "
                    "of nodes in coords".format(max(nodes)))
            conn.append(nodes)
            continue
        connect = np.array(conn)
        return coords, connect
Exemple #3
0
    def pBoundary(self, element_list):
        """Parse a boundary element

        """
        boundary = {}
        if not element_list:
            raise UserInputError("Boundary: input not found")
        if len(element_list) > 1:
            raise UserInputError(
                "Boundary: expected 1 block, found: {0}".format(
                    len(element_list)))
        element = element_list[0]

        prdisps = self.parse_prescribed_displacement_block(
            element.getElementsByTagName("PrescribedDisplacement"))
        boundary["PrescribedDisplacement"] = prdisps

        prforces = self.parse_prescribed_force_block(
            element.getElementsByTagName("PrescribedForce"))
        boundary["PrescribedForce"] = prforces

        tractions = self.parse_traction_block(
            element.getElementsByTagName("Traction"))
        boundary["Traction"] = tractions

        return boundary
Exemple #4
0
    def get_node_sets(node_sets_element):
        """Parse Mesh.Set.Nodeset element trees

        Three options for specifying nodeset: sub_domain, nodes, point
        """
        node_sets = []
        for node_set in node_sets_element:
            nsid = node_set.attributes.get("id")
            if nsid is None:
                raise UserInputError("Set: Nodeset: 'id' not found")
            nsid = int(nsid.value.strip())

            dom = node_set.attributes.get("sub_domain")
            if dom is not None:
                dom = dom.value.strip().upper()

            nodes = node_set.attributes.get("nodes")
            if nodes is not None:
                nodes = str2list(nodes.value.strip())

            point = node_set.attributes.get("atpoint")
            if point is not None:
                point = str2list(point.value.strip(), dtype=float)
                point += [0.] * (3 - len(point))
                point = dict(zip(("X", "Y", "Z"), point))

            spec = [x for x in (dom, nodes, point) if x is not None]
            if not spec:
                raise UserInputError("Set: Nodeset: expected one of "
                                     "{sub_domain, nodes, atpoint}")
            elif len(spec) > 1:
                raise UserInputError("Set: Nodeset: specify only one of "
                                     "{sub_domain, nodes, atpoint}")
            node_sets.append([nsid, spec[0]])
        return node_sets
Exemple #5
0
    def pBlocks(self, element_list):
        """Parse the Blocks block

        """
        if not element_list:
            raise UserInputError("Blocks: input not found")
        if len(element_list) > 1:
            raise UserInputError("Blocks: expected 1 block, found: {0}".format(
                len(element_list)))
        element = element_list[0]

        blocks = {}
        for block in element.getElementsByTagName("Block"):
            blkid = block.attributes.get("id")
            if blkid is None:
                raise UserInputError("Blocks.Block: id not found")
            blkid = int(blkid.value)

            material = block.attributes.get("material")
            if material is None:
                raise UserInputError("Blocks.Block({0}): material not "
                                     "found".format(blkid))
            material = int(material.value)

            blocks[blkid] = (material, )

        return blocks
Exemple #6
0
    def parse_prescribed_displacement_block(elements):
        prescribed_displacements = []
        attributes = ("constant", "function", "dof", "scale", "nodeset")
        for (i, element) in enumerate(elements):
            const = element.attributes.get("constant")
            func = element.attributes.get("function")
            scale = element.attributes.get("scale")
            dof = element.attributes.get("dof")
            nodeset = element.attributes.get("nodeset")

            # check for required arguments and conflicts
            if dof is None:
                raise UserInputError("Boundary.PrescribedDisplacement: dof "
                                     "not specified")
            dof = dof.value.strip()

            if nodeset is None:
                raise UserInputError(
                    "Boundary.PrescribedDisplacement: nodeset "
                    "not specified")
            nodeset = int(nodeset.value)

            # either const or func must be specified
            if const is None:
                # func must be given
                if func is None:
                    raise UserInputError(
                        "Boundary.PrescribedDisplacement: "
                        "expected either constant or function "
                        "attribute")
                func = int(func.value)
                if scale is None:
                    scale = 1.
                else:
                    scale = float(scale.value)

            else:
                const = float(const.value)
                if func is not None:
                    raise UserInputError("Boundary.PrescribedDisplacement: "
                                         "incompatible attributes: 'function, "
                                         "constant'")
                if scale is not None:
                    raise UserInputError("Boundary.PrescribedDisplacement: "
                                         "incompatible attributes: 'scale, "
                                         "constant'")
                func = W_CONST_FCN
                scale = const

            assert func is not None, "func is None"
            assert scale is not None, "scale is None"
            assert nodeset is not None, "nodeset is None"
            assert dof is not None, "dof is None"
            prescribed_displacements.append([func, scale, nodeset, dof])

            continue

        return prescribed_displacements
Exemple #7
0
    def format_sidesets(coords, conn, elements, ssets):
        """Format sidesets

        Parameters
        ----------

        Returns
        -------

        """
        sidesets = []

        lims = []
        for col in coords.T:
            lims.append([np.amin(col), np.amax(col)])
        lims = np.array(lims)

        for i, members in ssets:
            try:
                dom = members.upper()
            except AttributeError:
                dom = None

            if dom is not None:
                # user specified as ID, DOM
                if dom not in ("IHI", "ILO", "JHI", "JLO", "KHI", "KLO"):
                    raise UserInputError(
                        "Domain {0} not recognized".format(dom))
                axis = ({
                    "I": 0,
                    "J": 1,
                    "K": 2
                }[dom[0]], {
                    "LO": 0,
                    "HI": 1
                }[dom[1:]])
                nodes, els = Mesh.nodes_elements_at_pos(
                    coords, conn, axis[0], lims[axis])

                # Now get the face numbers for the elements in the sideset
                faces = [elements[el].topomap(dom) for el in els]
                ef = [[el, faces[n]] for n, el in enumerate(els)]
                sidesets.append(Mesh.format_sideset(i, ef))

            else:
                # given as ID, [EL, FACE]
                # Collect all from a given set and hold for next lines down
                for member in members:
                    if len(member) != 2:
                        raise UserInputError(
                            "Sidesets must be defined as [el, face], got {0}".
                            format(repr(member)))

                sidesets.append(Mesh.format_sideset(i, members))

            continue

        return sidesets
Exemple #8
0
def gen_coords_conn_from_inline(etype, mins, blocks):
    """Generate nodal coordinates and element connectivity from inline
    specification

    Parameters
    ----------
    mins : ndarray
        List of minimums
    blocks : tuple of ndarray
        blocks[i] -> [[length, interval]_0, [length, interval]_1, ...]

    Returns
    -------
    dim : int
        Dimension
    coords : ndarray
        Nodal coordinates
    connect : ndarray
        Nodal connectivity

    """
    # Initialize local variables
    lohi = [(None, None)] * 3

    if "bar" in etype.lower(): etype = "BAR"
    elif "quad" in etype.lower(): etype = "QUAD"
    elif "hex" in etype.lower(): etype = "HEX"
    else:
        raise UserInputError(
            "{0}: unrecognized inline mesh type".format(etype))

    dim = {"BAR": 1, "QUAD": 2, "HEX": 3}[etype.upper()]

    points = []
    for i in range(dim):

        if not blocks[i]:
            raise UserInputError("No {0}Block specified for inline "
                                 "mesh".format(("X", "Y", "Z")[i]))

        # Generate the 1d bar mesh in this coordinate
        line_points, line_conn = line_mesh(mins[i], blocks[i])
        lohi[i] = (line_points[0], line_points[-1])
        points.append(line_points)

        continue

    if dim == 1:
        # Mesh already created
        coords = np.array(points[0])
        connect = np.array(line_conn)

    else:
        coords, connect = brick_mesh(*points)

    return dim, coords, connect
Exemple #9
0
 def from_input_file(cls, fpath, verbosity=None):
     if not os.path.isfile(fpath):
         raise UserInputError("{0}: no such file".format(fpath))
     fdir, fbase = os.path.split(fpath)
     fnam, fext = os.path.splitext(fpath)
     runid = fnam
     return cls.from_input_string(runid, open(fpath, "r").read(), fdir,
                                  verbosity=verbosity)
Exemple #10
0
    def distributed_loads(self):
        if self._distloads is None:
            return [lambda x: 0.]
        if len(self._distloads) > 1:
            raise UserInputError("Only one distributed load for now")
        distloads = []
        for n, distload in self._distloads.items():
            func_id = distload["FUNCTION"]
            scale = distload["SCALE"]
            blocks = distload["BLOCKS"]

            # get the function
            func = self.functions(func_id)
            if func is None:
                raise UserInputError("Function {0} not defined".format(func_id))
            distloads.append(lambda x, scale=scale: scale * func(x))
            continue
        return distloads
Exemple #11
0
    def format_traction_bc(sideset, fcn, scale, conn, coords, elements):
        """Format a traction boundary condition

        Parameters
        ----------
        sideset : array_like
            Formatted sideset list

        fcn : function
            The function to apply

        scale : float
            Scale factor for function

        Returns
        -------
        trax : array_like
            Formatted traction BC
        """
        # sideset[i, j] -> jth face of element i in the sideset
        tractions = []
        for (element, face) in sideset:

            traction = [element, face]

            if hasattr(fcn, "__call__"):
                # tjfulle: hard coded for 2D quad
                ecls = elements[element]
                en = ecls.facenodes[face]
                nodes = conn[element, en]
                xyz = coords[nodes]
                # x = (x1, x2), dx = x2 - x1
                # y = (y1, y2), dy = y2 - y1
                # normal = (-dy, dx), (dy, -dx)
                dx = np.diff(xyz, axis=0)[0]
                normal = np.array([dx[1], -dx[0], 0.])
                normal = normal / np.sqrt(np.dot(normal, normal))
                # Assign components of the traction
                traction.extend([
                    lambda x, scale=scale, N=N: fcn(x) * scale * N
                    for N in normal
                ])

            elif isinstance(fcn, list):
                # All three components of traction force given
                traction.extend([
                    lambda x, scale=scale[i]: fcn[i](x) * scale
                    for i in range(3)
                ])

            else:
                raise UserInputError("Unrecognized traction function type")

            tractions.append(traction)
            continue

        return tractions
Exemple #12
0
    def pSolutionControl(self, element_list):
        """Parse the SolutionControl block and set defaults

        """
        if not element_list:
            raise UserInputError("SolutionControl: input not found")
        if len(element_list) > 1:
            raise UserInputError("SolutionControl: expected 1 block, found: "
                                 " {0}".format(len(element_list)))
        control = []
        lowstr = lambda x: str(x).lower()
        gt = lambda x: x > 0
        gte = lambda x: x >= 0
        # keyword, default, type, test
        keywords = (("TimeIntegrator", 0, lambda x: {
            "implicit": 0,
            "explicit": 1
        }.get(x.lower()), lambda x: x in
                     (0, 1)), ("NumberOfSteps", 10, int,
                               gt), ("Tolerance", 1.e-4, float,
                                     gt), ("MaximumIterations", 30, int, gt),
                    ("Relax", 1., float, gt), ("StartTime", 0., float, gte),
                    ("TerminationTime", 10., float,
                     gte), ("TimeStepMultiplier", 1., float,
                            gt), ("Verbosity", 1., int, lambda x: True))

        for i, (key, default, dtype, test) in enumerate(keywords):
            tag = element_list[0].getElementsByTagName(key)
            if not tag:
                control.append(default)
                continue
            tag = tag[-1].firstChild.data.strip()
            try:
                value = dtype(tag)
            except:
                raise UserInputError(
                    "SolutionControl: {0}: expected {1}, got {2}".format(
                        key, repr(dtype), tag))
            if not test(value):
                raise UserInputError(
                    "SolutionControl: {0}: invalid value {1}".format(
                        key, value))
            control.append(value)
        return np.array(control)
Exemple #13
0
def fill_in_includes(lines):
    """Look for 'include' commands in lines and insert then contents in place

    Parameters
    ----------
    lines : str
        User input

    Returns
    -------
    lines : str
        User input, modified in place, with inserts inserted

    """
    regex = r"<include\s(?P<include>.*)/>"
    _lines = []
    for line in lines.split("\n"):
        if not line.split():
            _lines.append(line.strip())
            continue
        include = re.search(regex, line)
        if include is None:
            _lines.append(line)
            continue

        href = re.search(r"""href=["'](?P<href>.*?)["']""",
                         include.group("include"))
        if not href:
            raise UserInputError("expected href='...'")
        name = href.group("href").strip()
        fpath = os.path.realpath(os.path.expanduser(name))
        try:
            fill = open(fpath, "r").read()
        except IOError:
            raise UserInputError("{0}: include not found".format(repr(name)))
        _lines.extend(fill_in_includes(fill).split("\n"))
        continue
    return "\n".join(_lines)
Exemple #14
0
    def get_side_sets(side_sets_element):
        """Parse Mesh.Set.Sideset element trees

        """
        side_sets = []
        for side_set in side_sets_element:
            ssid = side_set.attributes.get("id")
            if ssid is None:
                raise UserInputError("Set: Sideset: 'id' not found")
            ssid = int(ssid.value.strip())

            dom = side_set.attributes.get("sub_domain")
            if dom is not None:
                dom = dom.value.strip().upper()

            members = side_set.attributes.get("members")
            if members is not None:
                # given as element:face pairs
                matches = re.findall(r"[0-9]+\s*?:\s*?[0-9]+", members.value)
                members = [[int(i) for i in x.split(":")] for x in matches]
                for member in members:
                    if len(member) != 2:
                        raise UserInputError("Sidesets must be defined as "
                                             "EL:FACE")
            spec = [x for x in (dom, members) if x is not None]
            if not spec:
                raise UserInputError(
                    "Mesh.AssignGroups.Sideset({0}): expected "
                    "one of {sub_domain, members}".foramt(ssid))
            if len(spec) > 1:
                raise UserInputError(
                    "Mesh.AssignGroups.Sideset({0}): expected "
                    "only one of {sub_domain, "
                    "members}".foramt(ssid))
            side_sets.append([ssid, spec[0]])
        return side_sets
Exemple #15
0
    def pMaterials(self, element_list):
        """Parse the materials block

        """
        if not element_list:
            raise UserInputError("Materials: input not found")
        if len(element_list) > 1:
            raise UserInputError(
                "Materials: expected 1 block, found: {0}".format(
                    len(element_list)))
        element = element_list[0]

        materials = {}
        for material in element.getElementsByTagName("Material"):
            mtlid = material.attributes.get("id")
            if mtlid is None:
                raise UserInputError("Materials.Material: id not found")
            mtlid = int(mtlid.value)

            model = material.attributes.get("model")
            if model is None:
                raise UserInputError("Materials.Material: model not found")
            model = model.value.strip()

            params = {}
            for node in material.childNodes:
                if node.nodeType != material.ELEMENT_NODE:
                    continue
                val = " ".join(node.firstChild.data.split())
                try:
                    params[node.nodeName] = float(val)
                except ValueError:
                    params[node.nodeName] = str(val)
            materials[mtlid] = (model, params)

        return materials
Exemple #16
0
    def parse_ascii_mesh(ascii_mesh_element):

        # check for dim, Vertices, and Connectivity definitions
        vertices = ascii_mesh_element.getElementsByTagName("Vertices")
        if not vertices:
            raise UserInputError("Mesh.ascii: no Vertices found")
        if len(vertices) > 1:
            lv = len(vertices)
            raise UserInputError("Mesh.ascii: expected 1 Vertices block, "
                                 "got {0}".format(lv))
        connect = ascii_mesh_element.getElementsByTagName("Connectivity")
        if not connect:
            raise UserInputError("Mesh.ascii: no Connectivity found")
        if len(connect) > 1:
            lc = len(connect)
            raise UserInputError("Mesh.ascii: expected 1 Connectivity block, "
                                 "got {0}".format(lc))
        dim = connect[0].attributes.get("dim")
        if dim is None:
            raise UserInputError("Mesh.ascii.Connectivity: dim attribute not "
                                 "found")
        dim = int(dim.value)
        if dim not in (2, 3):
            raise UserInputError("Mesh.ascii.Connectivity: {0}: invalid "
                                 "dim".format(dim))

        # Vertices
        data = []
        for line in vertices[0].firstChild.data.split("\n"):
            line = [float(x) for x in line.split()]
            if not line:
                continue
            if len(line) > 3:
                ll = len(line)
                raise UserInputError(
                    "Mesh.ascii: expected 3 vertex coordinates, "
                    "got {0}".format(ll))
            data.append(line + [0.] * (3 - len(line)))
        vertices = np.array(data)

        # Connectivity
        data = []
        for line in connect[0].firstChild.data.split("\n"):
            line = [int(x) for x in line.split()]
            if not line:
                continue
            data.append(line)
        connect = np.array(data)

        return dim, vertices, connect
Exemple #17
0
    def parse_traction_bc(tractions, ssets, coords, connect, elements):
        """Parse the traction bc.

        """
        trax = []
        for (func, scale, sideset_id) in tractions:

            # now get the actual sideset
            try:
                sideset = [x[1] for x in ssets if sideset_id == x[0]][0]
            except IndexError:
                raise UserInputError(
                    "Sideset {0} not defined".format(sideset_id))

            trax.extend(
                Mesh.format_traction_bc(sideset, func, scale, connect, coords,
                                        elements))
            continue
        return trax
Exemple #18
0
    def parse_nodal_forces(self, prforces, nsets):
        nfrcs = []
        for prforce in prforces:
            fcn = prforce[0]
            scale = prforce[1]
            nodeset = prforce[2]
            key = prforce[3].upper()
            dofs = default_dofs(self.dim, key)

            # get the nodes in the nodeset
            try:
                nodes = [x[1] for x in nsets if nodeset == x[0]][0]
            except IndexError:
                raise UserInputError("Nodeset {0} not defined".format(nodeset))

            for dof in dofs:
                nfrcs.extend(Mesh.format_nodal_force(nodes, dof, fcn, scale))
            continue
        return nfrcs
Exemple #19
0
    def parse_displacement_bc(self, prdisps, nsets):
        dbcs = []
        for prdisp in prdisps:
            fcn = prdisp[0]
            scale = prdisp[1]
            nodeset = prdisp[2]
            key = prdisp[3].upper()
            dofs = default_dofs(self.dim, key)

            # get the nodes in the nodeset
            try:
                nodes = [x[1] for x in nsets if nodeset == x[0]][0]
            except IndexError:
                raise UserInputError("Nodeset {0} not defined".format(nodeset))

            for dof in dofs:
                dbcs.extend(Mesh.format_displacement_bc(
                    nodes, dof, fcn, scale))
            continue
        return dbcs
Exemple #20
0
    def pMesh(self, element_list):
        """Parse the Mesh block and set defaults

        """
        if not element_list:
            raise UserInputError("Mesh: input not found")
        if len(element_list) > 1:
            raise UserInputError("Mesh: expected 1 block, found: {0}".format(
                len(element_list)))

        mesh = element_list[0]
        mesh_type = mesh.attributes.get("type")
        if mesh_type is None:
            raise UserInputError("Mesh: mesh type not found")
        mesh_type = mesh_type.value.strip().lower()

        node_sets = []
        side_sets = []
        el_blocks = []
        for s in mesh.getElementsByTagName("AssignGroups"):
            node_sets.extend(
                self.get_node_sets(s.getElementsByTagName("Nodeset")))
            side_sets.extend(
                self.get_side_sets(s.getElementsByTagName("Sideset")))
            el_blocks.extend(
                self.get_el_blocks(s.getElementsByTagName("Block")))

        if not el_blocks:
            raise UserInputError(
                "Mesh.AssignGroups: no element block assignments "
                "found")

        if mesh_type == "inline":
            eltype, dim, coords, connect = self.parse_inline_mesh(mesh)
            for el_block in el_blocks:
                if eltype.lower()[0] != el_block[1][2]:
                    raise UserInputError(
                        "Mesh.inline: {0}: inconsistent element "
                        "type for assigned block {1}".format(
                            el_block[1], el_block[0]))

        elif mesh_type == "ascii":
            dim, coords, connect = self.parse_ascii_mesh(mesh)

        else:
            raise UserInputError("{0}: invalid mesh type".format(mesh_type))

        return dim, coords, connect, el_blocks, side_sets, node_sets
Exemple #21
0
    def form_elements(runid, el_blocks, connect, coords, block_options,
                      materials):
        elements = [None] * len(connect)

        for key, val in block_options.items():
            mtlid = val[0]
            el_block = [x for x in el_blocks if x[0] == key][0]
            elem_blk_id, etype, els, elopts = el_block
            elopts["RUNID"] = runid
            mtl_name, mtl_params = materials.get(mtlid, (None, None))

            if mtl_name is None:
                raise UserInputError(
                    "Material {0} not defined in input file".format(mtlid))

            # instantiate the material model for element
            material = create_material(mtl_name)

            # get the element class for elements in this block
            ecls = element_class_from_name(etype)

            # determine volumes of each element
            v_els = None

            # Check for any perturbed parameters
            matparams, perturbed = {}, {}
            seed(12)
            for key, val in mtl_params.items():
                idx = material.parameter_index(key)
                if idx is None:
                    recognized = ", ".join(material.param_map)
                    raise UserInputError(
                        "{0}: {1}: unrecognized parameter. "
                        "Recognized parameters are: {2}".format(
                            material.name, key, recognized))

                weibull = False
                if not weibull:
                    matparams[key] = val
                    continue

                # weibull perturbation requested
                if v_els is None:
                    v_els = np.array(
                        [ecls.volume(coords[connect[eid]]) for eid in els])
                    v_ave = np.average(v_els)

                p0 = val.get("MEDIAN")
                if p0 is None:
                    raise UserInputError(
                        "{0}: no median value given".format(key))
                k = float(val.get("VOLUME EXPONENT", 1.))
                m = float(val.get("WEIBULL MODULUS", 10.))
                msf = float(val.get("MODULUS SCALE FACTOR", 1.))
                p = [
                    p0 * (v_ave / v_els[i])**(k / m) *
                    (np.log(rand()) / np.log(.5))**(1. / (m * msf))
                    for i, el in enumerate(els)
                ]
                perturbed[key] = (idx, np.array(p))

            # Fill parameter array
            for iel, eid in enumerate(els):
                p = {}
                for key, (i, val) in perturbed.items():
                    p[key] = (i, val[iel])
                nodes = connect[eid]
                nodal_coords = coords[nodes]
                elements[eid] = ecls(eid, (iel, elem_blk_id), nodes,
                                     nodal_coords, material, matparams, p,
                                     **elopts)

        del matparams
        del perturbed
        return elements
Exemple #22
0
    def get_el_blocks(el_blocks_element):
        """Parse Mesh.Blocks.Block element trees

        """
        el_blocks = []
        unassigned, allassigned = 0, 0
        for el_block in el_blocks_element:
            el_block_id = el_block.attributes.get("id")
            if el_block_id is None:
                raise UserInputError("Blocks: Block: 'id' not found")
            el_block_id = int(el_block_id.value.strip())

            # element block elements
            elements = el_block.attributes.get("elements")
            if elements is None:
                raise UserInputError("AssignGroups.Block({0}): no elements "
                                     "assigned".format(el_block_id))
            elements = elements.value.strip().lower()

            # check special cases first
            if elements == "all":
                allassigned += 1
            elif elements == "unassigned":
                unassigned += 1

            if elements not in ("all", "unassigned"):
                elements = str2list(elements, dtype=int)

            # element type for block
            eltype = el_block.attributes.get("eltype")
            if eltype is None:
                raise UserInputError("AssignGroups.Block({0}): no eltype "
                                     "assigned".format(el_block_id))
            eltype = eltype.value.strip().lower()

            # element options for block
            elopts = el_block.attributes.get("elopts", {})
            if elopts:
                S = re.findall(r".*?=\s*[\w\.]+.*?", elopts.value)
                for (i, item) in enumerate(S):
                    item = item.split("=")
                    if len(item) != 2:
                        raise UserInputError("elopts must be of form key=val")
                    try:
                        val = int(item[1])
                    except ValueError:
                        val = str(item[1])
                    key = str("_".join(item[0].split()).upper())
                    S[i] = (key, val)
                elopts = dict(S)

            el_blocks.append([el_block_id, eltype, elements, elopts])

        if unassigned and allassigned:
            raise UserInputError(
                "AssignGroups: elements='all' inconsistent with "
                "elements='unassigned'")

        if allassigned and len(el_blocks) > 1:
            raise UserInputError(
                "AssignGroups: elements='all' inconsistent with "
                "mutliple assigned blocks")

        if unassigned and len(el_blocks) == 1:
            el_blocks[0][2] = "all"

        return el_blocks
Exemple #23
0
    def parse_traction_block(elements):
        """Parse the Boundary.Traction element

        Tractions are given as either constant or function. Alternatively each
        force component can be specified as components="x=xval y=yval z=zval"

        """
        tractions = []
        attributes = ("components", "constant", "sideset", "function", "scale")
        for (i, element) in enumerate(elements):
            components = element.attributes.get("components")
            sideset = element.attributes.get("sideset")
            const = element.attributes.get("constant")
            function = element.attributes.get("function")
            scale = element.attributes.get("scale")

            # check for required arguments and conflicts
            if sideset is None:
                raise UserInputError(
                    "Boundary.Traction: sideset not specified")
            sideset = int(sideset.value)

            one_rqd = [
                x for x in (const, function, components) if x is not None
            ]
            if not one_rqd:
                raise UserInputError(
                    "Boundary.Traction: expected one of "
                    "(constant, function, components) attribute")
            if len(one_rqd) > 1:
                raise UserInputError(
                    "Boundary.Traction: expected only one of "
                    "(constant, function, components) attribute")

            if components is not None:
                # components specified, find out which
                scale = np.zeros(3)
                components = " ".join(components.value.upper().split())
                for i, label in enumerate("XYZ"):
                    S = re.search(
                        "{0}\s*=\s*(?P<val>{1})".format(label, NUMREGEX),
                        components)
                    if S is not None:
                        scale[i] = float(S.group("val"))
                # assign the constant function
                function = [W_CONST_FCN] * 3

            elif const is not None:
                const = float(const.value)
                if scale is not None:
                    raise UserInputError(
                        "Boundary.PrescribedForce: incompatible "
                        "attributes: 'scale, constant'")
                function = W_CONST_FCN
                scale = const

            else:
                function = int(function.value)
                if scale is None:
                    scale = 1.
                else:
                    scale = float(scale.value)

            assert sideset is not None, "sideset is None"
            tractions.append([function, scale, sideset])

            continue

        return tractions
Exemple #24
0
    def parse_inline_mesh(inline_mesh_element):
        lmn_types = ("Quad", )
        lmn = {}
        for lmn_type in lmn_types:
            tags = inline_mesh_element.getElementsByTagName(lmn_type)
            if not tags:
                continue
            if len(tags) > 1:
                raise UserInputError(
                    "Mesh.inline: expected 1 {0}, got {1}".format(
                        lmn_type, len(tags)))
            lmn.setdefault(lmn_type, []).append(tags[0])

        if not lmn:
            raise UserInputError(
                "Mesh.inline: expected one of {0} block types".format(
                    ", ".join(lmn_types)))

        if len(lmn) > 1:
            raise UserInputError(
                "Mesh.inline: expected only one of {0} block types".format(
                    ", ".join(lmn_types)))

        lmn_type = lmn.keys()[0]
        lmn = lmn[lmn_type][0]

        # get [xyz]mins
        mins = []
        for item in ("xmin", "ymin", "zmin"):
            val = lmn.attributes.get("xmin", 0.)
            if val:
                val = float(val.value.strip())
            mins.append(val)

        xyzblocks = [None] * 3
        attributes = ("order", "length", "interval")
        blk_types = ("XBlock", "YBlock", "ZBlock")
        for i, tag in enumerate(blk_types):
            o = 0
            blks = []
            for xyzblock in lmn.getElementsByTagName(tag):
                blk = []
                for item in attributes:
                    attr = xyzblock.attributes.get(item)
                    if not attr:
                        raise UserInputError(
                            "Mesh.inline.{0}: expected {1} attribute".format(
                                tag, item))
                    attr = float(attr.value.strip())
                    if item == "order":
                        o += 1
                        if attr != o:
                            raise UserInputError(
                                "Mesh.inline.{0}s must be ordered "
                                "contiguously".format(tag))
                        continue
                    blk.append(attr)
                blks.append(blk)
            xyzblocks[i] = blks

        mesh = gen_coords_conn_from_inline(lmn_type, mins, xyzblocks)
        dim, coords, connect = mesh
        return lmn_type, dim, coords, connect
Exemple #25
0
    def pFunctions(self, element_list):
        """Parse the functions block

        """
        if len(element_list) > 1:
            raise UserInputError(
                "Functions: expected 1 block, found: {0}".format(
                    len(element_list)))

        functions = {W_CONST_FCN: lambda x: 1.}
        if not element_list:
            return functions

        for function in element_list[0].getElementsByTagName("Function"):
            fid = function.attributes.get("id")
            if fid is None:
                raise UserInputError("Functions.Function: id not found")
            fid = int(fid.value)

            if fid == W_CONST_FCN:
                raise UserInputError("Function id {0} is reserved".format(fid))
            if fid in functions:
                raise UserInputError(
                    "{0}: function already defined".format(fid))

            ftype = function.attributes.get("type")
            if ftype is None:
                raise UserInputError("Functions.Function: type not found")
            ftype = " ".join(ftype.value.split()).upper()

            if ftype not in (AE, PWL):
                raise UserInputError(
                    "{0}: invalid function type".format(ftype))
            expr = function.firstChild.data.strip()

            if ftype == AE:
                func, err = build_lambda(expr, disp=1)
                if err:
                    raise UserInputError("{0}: in analytic expression in "
                                         "function {1}".format(err, fid))

            elif ftype == PWL:
                # parse the table in expr
                try:
                    columns = str2list(
                        function.attributes.get("columns").value, dtype=str)
                except AttributeError:
                    columns = ["x", "y"]
                except TypeError:
                    columns = ["x", "y"]

                table = []
                ncol = len(columns)
                for line in expr.split("\n"):
                    line = [float(x) for x in line.split()]
                    if not line:
                        continue
                    if len(line) != ncol:
                        nl = len(line)
                        raise UserInputError(
                            "Expected {0} columns in function "
                            "{1}, got {2}".format(ncol, fid, nl))
                    table.append(line)

                func, err = build_interpolating_function(np.array(table),
                                                         disp=1)
                if err:
                    raise UserInputError("{0}: in piecwise linear table in "
                                         "function {1}".format(err, fid))
            functions[fid] = func
            continue

        return functions
Exemple #26
0
    def __init__(self, elid, elem_blk_ids, nodes, coords, material, mat_params,
                 perturbed, *args, **kwargs):
        if len(nodes) != self.nnodes:
            raise UserInputError("{0}: {1} nodes required, got {2}".format(
                self.name, self.nnodes, len(nodes)))

        # set up the model, perturbing parameters if necessary
        self.material = material
        for key, (i, val) in perturbed.items():
            mat_params[key] = val
        self.material.setup(mat_params)
        self.material.initialize_state()

        self._variables = []
        self.reducedint = "REDUCED_INTEGRATION" in kwargs
        self.planestress = "PLANE_STRESS" in kwargs
        if self.reducedint and not self.canreduce:
            raise UserInputError(
                "Element {0} cannot use reduced integration".format(self.name))
        if self.planestress and not self.hasplanestress:
            raise UserInputError(
                "Element {0} not plane stress compatible".format(self.name))
        ro.reducedint = self.reducedint
        self.elid = elid
        self.elid_this_blk, self.elem_blk_id = elem_blk_ids
        self.ievar = 0

        self.register_variable("CAUCHY-STRESS", vtype="SYMTENS")
        self.register_variable("LEFT-STRETCH", vtype="SYMTENS")
        self.register_variable("ROTATION", vtype="TENS")
        self.register_variable("SYMM-L", vtype="SYMTENS")
        self.register_variable("SKEW-L", vtype="SKEWTENS")
        self.register_variable("GREEN-STRAIN", vtype="SYMTENS")

        for var in self.material.variables():
            self.register_variable(var, vtype="SCALAR")

        # Element data array.  See comments above.
        self.nxtra = self.material.nxtra
        self.ndat = XTRA + self.nxtra + len(perturbed)
        self._p = XTRA + self.nxtra
        self.data = np.zeros((2, self.ngauss + 1, self.ndat))

        # register perturbed parameters as variables
        self._pidx = []
        for i, (key, (idx, val)) in enumerate(perturbed.items()):
            self._pidx.append(idx)
            self.register_variable("{0}_STAT".format(key))
            self.data[:, :, self._p + i] = val

        # Element volume
        self._volume = self.volume(coords)

        # initialize nonzero data
        self.data[:, :, LEFTV:LEFTV + NSYMM] = I6
        self.data[:, :, ROTATE:ROTATE + NTENS] = I9
        self.data[:, :, XTRA:XTRA + self.nxtra] = self.material.initial_state()

        # Initialize the stiffness
        self.kel = np.zeros((self.ndof * self.nnodes, self.ndof * self.nnodes))

        pass
Exemple #27
0
    def __init__(self, user_input):
        """Parse the xml input file

        Parameters
        ----------
        file_name : str
          path to input file

        """
        user_input = fill_in_includes(user_input)
        dom = xdom.parseString(user_input)

        # Get the root element (Should always be "MaterialModel")
        model_input = dom.getElementsByTagName("WasatchModel")
        if not model_input:
            raise UserInputError("Expected Root Element 'WasatchModel'")

        # ------------------------------------------ get and parse blocks --- #
        input_blocks = {}
        recognized_blocks = ("SolutionControl", "Mesh", "Boundary",
                             "Materials", "Functions", "Blocks")
        for block in recognized_blocks:
            elements = model_input[0].getElementsByTagName(block)
            try:
                parse_function = getattr(self, "p{0}".format(block))

            except AttributeError:
                sys.exit("{0}: not finished parsing".format(block))

            input_blocks[block] = parse_function(elements)

            for element in elements:
                p = element.parentNode
                p.removeChild(element)

        # --------------------------------------------------- check input --- #
        #   0) pop needed data from input_blocks dict and save
        #   1) check that functions are defined for entities requiring function
        #   2) replace function ids with actual function
        self.control = input_blocks.pop("SolutionControl")
        self.materials = input_blocks.pop("Materials")
        self.blk_options = input_blocks.pop("Blocks")
        self.periodic_masters_slaves = None

        boundary = input_blocks.pop("Boundary")
        functions = input_blocks.pop("Functions")
        (self.dim, self.coords, self.connect, self.el_blocks, self.ssets,
         self.nsets) = input_blocks.pop("Mesh")

        # element blocks
        for blk, items in self.blk_options.items():
            # make sure block is defined in mesh
            if blk not in [x[0] for x in self.el_blocks]:
                raise UserInputError("Blocks.Block: Block {0} not defined in "
                                     "mesh".format(blk))
            material = items[0]
            try:
                self.materials[material]
            except KeyError:
                raise UserInputError("Blocks.Block({0}): material {1} "
                                     "not defined".format(blk, material))

        # --- boundary
        self.prdisps = []
        for prdisp in boundary.get("PrescribedDisplacement", []):
            (fid, scale, nodeset, dof) = prdisp
            func = functions.get(fid)
            if func is None:
                raise UserInputError(
                    "Boundary.PrescribedDisplacement function "
                    "{0} not defined".format(fid))
            if nodeset not in [x[0] for x in self.nsets]:
                raise UserInputError("Boundary.PrescribedDisplacement nodeset "
                                     "{0} not defined".format(nodeset))

            self.prdisps.append([func, scale, nodeset, dof])

        self.prforces = []
        for (fid, scale, nodeset, dof) in boundary.get("PrescribedForce", []):
            func = functions.get(fid)
            if func is None:
                raise UserInputError("Boundary.PrescribedForce function {0} "
                                     "not defined".format(fid))
            self.prforces.append([func, scale, nodeset, dof])

        self.tractions = []
        for (fid, scale, sideset) in boundary.get("Traction", []):
            # test if fid is a function ID or IDs
            func = None
            try:
                func = [functions[x] for x in fid]
            except TypeError:
                # must be an integer
                func = functions.get(fid)
            if func is None:
                raise UserInputError("Boundary.Traction function {0} not "
                                     "defined".format(fid))

            self.tractions.append([func, scale, sideset])

        self.distloads = []
        for (fid, scale, blx) in boundary.get("DistributedLoad", []):
            func = functions.get(fid)
            if func is None:
                raise UserInputError("Boundary.DistributedLoad function {0} "
                                     "not defined".format(fid))
            self.distloads.append([func, scale, blx])
Exemple #28
0
    def format_el_blocks(coords, conn, el_blocks):
        """Format element sets to be passed to exodusii

        Parameters
        ----------
        coords : ndarray
            Nodal coordinates

        conn : ndarray
            Element connectivity

        el_blocks : array_like
            User given element sets ***

        Returns
        -------
        formatted_el_blocks :array_like
            Sorted list of element sets
            formatted_el_blocks[i][j] -> jth element of the ith set

        Notes
        -----
        el_blocks can be given in one of two ways:

          1) Explicitly give each element of a set.
             [[1, [23, 24, 25]]] would assign element 23, 24, 25 to element set 1

          2) Define ranges to find elements
             [[1, ((xi, xl), (yi, yl), (zi, zl))]] would assign to element set 1
             all elements in the ranges.

        """
        formatted_el_blocks, explicit, used = [], [], []
        unassigned = None

        for i, (j, eltype, members, elopts) in enumerate(el_blocks):

            if members == "all":
                members = range(len(conn))

            if members == "unassigned":
                unassigned = j
                continue

            fromrange = len(members) == 3 and all(
                [len(x) == 2 for x in members])

            # find all element sets that are given explicitly
            if not fromrange:
                members = np.array(members, dtype=np.int)
                formatted_el_blocks.append([j, eltype, members, elopts])
                used.extend(members)
                explicit.append(j)
                continue

        # now find elements within given ranges
        hold = {}
        for (iel, el) in enumerate(conn):

            ecoords = coords[el]

            for i, eltype, members, elopts in el_blocks:
                if i in explicit or i == unassigned:
                    continue

                # look for all elements in the given range
                if all([
                        np.amin(ecoords[:, 0]) >= members[0][0],
                        np.amax(ecoords[:, 0]) <= members[0][1],
                        np.amin(ecoords[:, 1]) >= members[1][0],
                        np.amax(ecoords[:, 1]) <= members[1][1],
                        np.amin(ecoords[:, 2]) >= members[2][0],
                        np.amax(ecoords[:, 2]) <= members[2][1]
                ]):

                    hold.setdefault(i, []).append(iel)

        for iset, members in hold.items():
            # get eltype for this set
            el_block = [x for x in el_blocks if x[0] == iset][0]
            eltype = el_block[1]
            elopts = el_block[3]
            formatted_el_blocks.append([iset, eltype, members, elopts])
            used.extend(iset)

        # put all elements not already assigned in set 'unassigned'
        used = np.unique(used)
        orphans = [x for x in range(len(conn)) if x not in used]
        if orphans:
            if unassigned is None:
                raise UserInputError("nothing to do for unassigned elements")
            el_block = [x for x in el_blocks if x[0] == unassigned][0]
            eltype = el_block[1]
            elopts = el_block[3]
            formatted_el_blocks.append([unassigned, eltype, orphans, elopts])
        return sorted(formatted_el_blocks, key=lambda x: x[0])
Exemple #29
0
def create_material(matname):
    model = models.get(matname.upper())
    if model is None:
        raise UserInputError("model {0} not recognized".format(matname))
    return model()