Пример #1
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
Пример #2
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
Пример #3
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
Пример #4
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()[:3] != el_block[1][:3]:
                    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
Пример #5
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])
Пример #6
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]
            i, etype, els, elopts = el_block
            elopts["RUNID"] = runid
            mtl_name, mtl_params = materials.get(mtlid, (None, None))

            # Check if element is an RVE
            if mtl_name.lower() == "rve":
                etype = "RVE"
                elopts.update(mtl_params)
                # give default elastic material
                mtl_name = "elastic"
                mtl_params = {"E": 10.0E+09, "NU": .333333333}

            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, nodes, nodal_coords, material,
                                     matparams, p, **elopts)

        del matparams
        del perturbed
        return elements
Пример #7
0
    def __init__(self, runid, dim, coords, connect, el_blocks, ssets, nsets,
                 prdisps, prforces, tractions, block_options, materials,
                 periodic_masters_slaves):

        self.dim = dim
        self._sidesets = {}
        self._elem_blocks = {}
        self._nodesets = {}
        self._displacement_bcs = []
        self._nodal_forces = []
        self._traction_bcs = []
        self._elements = None
        self._coords = []
        self._conn = []

        coords, connect = self.check_coords_and_conn(dim, coords, connect)

        # assign element blocks
        # Do this first because element ordering changes
        formatted_el_blocks = self.format_el_blocks(coords, connect, el_blocks)

        # elements are put in to the exodus output by element set. As a
        # result, the element numbering in the exodus file will differ from
        # the element numbering in the fea code. exo_emap maps the number
        # in the exodus file to the number in the fea code as
        #        exodus_element_number = exo_map[i]
        # where i is the internal element number
        i = 0
        self.exo_emap = np.empty(len(connect), dtype=int)
        for (ielset, eltype, els, elopts) in formatted_el_blocks:
            for el in els:
                self.exo_emap[el] = i
                i += 1

        # instantiate element classes
        elements = self.form_elements(runid, formatted_el_blocks, connect,
                                      coords, block_options, materials)

        # assign sets
        # Sidesets are a dict made up of ID: DOMAIN pairs, where ID is the
        # integer for the sideset and DOMAIN is the domain - one of {ILO, IHI,
        # JLO, JHI}. We first get the nodes that lie on the DOMAIN and the
        # connected elements
        sidesets = self.format_sidesets(coords, connect, elements, ssets)
        nodesets = self.format_nodesets(coords, connect, nsets)

        # Now that sets have been assigned, assign the displacement and
        # traction boundary conditions to appropriate sets.
        displacement_bcs = self.parse_displacement_bc(prdisps, nodesets)

        # Nodal forces
        nodal_forces = self.parse_nodal_forces(prforces, nodesets)

        # tractions
        tractions = self.parse_traction_bc(tractions, sidesets, coords,
                                           connect, elements)

        # assign class members
        self._coords = coords
        self._conn = connect

        self.assign_sidesets(sidesets)
        self.assign_nodesets(nodesets)
        self.assign_elem_blocks(formatted_el_blocks)

        self.assign_displacement_bcs(displacement_bcs)
        self.assign_nodal_forces(nodal_forces)
        self.assign_traction_bcs(tractions)

        self._elements = np.array(elements)

        self._node_el_map = self.generate_node_el_map(self._coords.shape[0],
                                                      self._conn)

        if periodic_masters_slaves and len(periodic_masters_slaves) > 1:
            raise UserInputError("Only one periodic bc currently supported")

        pass
Пример #8
0
    def __init__(self, lmnid, nodes, coords, material, mat_params, perturbed,
                 *args, **kwargs):

        import src.fem.core.fe_model as fem

        # Find parent and child elements
        parent = kwargs.get("ParentElement")
        if parent is None:
            raise UserInputError("RVE element expected a parent element")
        parent = DEFAULT_ELEMENTS.get(parent.upper())
        if parent not in (Quad4, ):
            raise WasatchError("RVE requires Quad4 parent element")
        self.name = parent.name

        # The analysis driver
        analysis_driver = kwargs.get("AnalysisDriver")
        if analysis_driver is None:
            raise UserInputError("No rve driver specified for RVE")
        analysis_driver = analysis_driver.upper()
        if analysis_driver not in ("WASATCH", ):
            raise UserInputError("{0}: unsupported rve driver")
        self.analysis_driver = analysis_driver

        ki = kwargs.get("KeepIntermediateResults")
        if ki is not None:
            ki = {"FALSE": 0, "TRUE": 1}.get(ki.upper(), 1)
        self.wipe_intermediate = not bool(ki)

        template = kwargs.get("InputTemplate")
        if template is None:
            raise UserInputError("RVE element expected an input template")
        if not os.path.isfile(template):
            raise UserInputError("{0}: no such template file".format(template))
        self.input_template_file = template
        self.template = open(template, "r").read()

        # RVE inherits from parent.  Is there a better way to do this?
        self.parent = parent(lmnid, nodes, coords, material, mat_params,
                             perturbed, *args, **kwargs)
        self.bndry = self.parent.bndry
        self.nnodes = self.parent.nnodes
        self.ncoord = self.parent.ncoord
        self.ndof = self.parent.ndof
        self.dim = self.parent.dim
        self.ngauss = self.parent.ngauss
        self.cornernodes = self.parent.cornernodes
        self.facenodes = self.parent.facenodes
        self.gauss_coords = self.parent.gauss_coords
        self.gauss_weights = self.parent.gauss_weights

        # Find the refinement level and form the child mesh
        self.refinement = kwargs.get("Refinement", 10)
        self.generate_child_mesh_info(coords)

        self.end_state = None

        super(RVE, self).__init__(lmnid, nodes, coords, material, mat_params,
                                  perturbed, *args, **kwargs)

        # setup FEModel object for the entire RVE simulation
        wasatch_input = self.generate_wasatch_input(0.,
                                                    np.zeros((self.nnodes, 3)))
        runid = "{0}_EID={1}_RVE".format(kwargs["RUNID"], lmnid)
        self.rve_model = fem.FEModel.from_input_string(runid,
                                                       wasatch_input,
                                                       rundir=os.getcwd())
Пример #9
0
    def __init__(self, lmnid, 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.rve_model = None
        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.lmnid = lmnid
        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
Пример #10
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
Пример #11
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
Пример #12
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
Пример #13
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
Пример #14
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])
Пример #15
0
def create_material(matname):
    model = models.get(matname.upper())
    if model is None:
        raise UserInputError("model {0} not recognized".format(matname))
    return model()