예제 #1
0
 def test_csys(self):
     from spyfe.csys import CSys
     from numpy import linalg
     assert CSys().isconstant
     assert CSys().isidentity
     q, r = linalg.qr(numpy.random.rand(3, 3))
     assert CSys(matrix=q).isidentity == False
예제 #2
0
 def __init__(self,
              fes=None,
              integration_rule=None,
              material_csys=CSys(),
              assoc_geom=None):
     self.fes = None
     self.fes = fes
     self.integration_rule = integration_rule
     self.material_csys = material_csys
     self.assoc_geom = assoc_geom
예제 #3
0
    def __init__(self, fes=None, integration_rule=None, material_csys=CSys(), assoc_geom=None,
                 material=None):
        """Constructor.

        :param material: Material object.
        :param fes: Finite element set object.
        :param integration_rule: Integration rule object.
        """
        super().__init__(fes=fes, integration_rule=integration_rule,
                         material_csys=material_csys, assoc_geom=assoc_geom)
        self.material = material
예제 #4
0
def plot_stress(model_data):
    """Algorithm for plotting stress results.

    :param model_data: Model data dictionary.

    model_data['fens'] = finite element node set (mandatory)

    For each region (connected piece of the domain made of a particular material), mandatory:
    model_data['regions']= list of dictionaries, one for each region
        Each region:
        region['femm'] = finite element set that covers the region (mandatory)
        
    For essential boundary conditions (optional):
    model_data['boundary_conditions']['essential']=list of dictionaries, one for each 
        application of an essential boundary condition.
        For each EBC dictionary ebc:
            ebc['node_list'] =  node list,
            ebc['comp'] = displacement component (zero-based),
            ebc['value'] = function to supply the prescribed value, default is lambda x: 0.0
      

    :return: Success?  True or false.  The model_data object is modified.
    model_data['geom'] =the nodal field that is the geometry
    model_data['temp'] =the nodal field that is the computed temperature
    model_data['timings'] = timing of the individual operations
    """
    file = 'stresses'
    if 'postprocessing' in model_data:
        if 'file' in model_data['postprocessing']:
            file = model_data['postprocessing']['file']
        outcs = model_data['postprocessing']['outcs'] if 'outcs' in model_data['postprocessing']\
            else CSys()

    geom = model_data['geom']
    u = model_data['u']
    dtemp = model_data['dtemp'] if 'dtemp' in model_data else None
    for r in range(len(model_data['regions'])):
        region = model_data['regions'][r]
        femm = region['femm']
        stresses = femm.nodal_field_from_integr_points(
            geom,
            u,
            u,
            dtempn1=dtemp,
            output=OUTPUT_CAUCHY,
            component=[0, 1, 2, 3, 4, 5],
            outcs=outcs)
        vtkexport(file + str(r), femm.fes, model_data['geom'], {
            'displacement': u,
            'stresses': stresses
        })
    return True
    def __init__(self, material=None, fes=None, integration_rule=None,
                 material_csys=CSys(), assoc_geom=None):
        """Constructor.

        :param material: Material object.
        :param fes: Finite element set object.
        :param integration_rule: Integration rule object.
        """
        integration_rule = TetRule(npts=4) if integration_rule is None else integration_rule
        super().__init__(fes=fes, material=material, integration_rule=integration_rule,
                         material_csys=material_csys, assoc_geom=assoc_geom)
        self._gamma = 2.6 #one of the stabilization parameters
        self._C = 1.e4 #the other stabilization parameter
예제 #6
0
    def __init__(self,
                 material=None,
                 fes=None,
                 integration_rule=None,
                 material_csys=CSys(),
                 assoc_geom=None):
        """Constructor.

        :param material: Material object.
        :param fes: Finite element set object.
        :param integration_rule: Integration rule object.
        """
        super().__init__(fes=fes,
                         integration_rule=integration_rule,
                         material_csys=material_csys,
                         assoc_geom=assoc_geom)
        self.material = material
        self._phis = None
        e = getattr(self.material, 'e', None)
        if e is not None:
            e = self.material.e
            if self.material.nu < 0.3:
                nu = self.material.nu
            else:
                nu = 0.3 + (self.material.nu - 0.3) / 2.0
        else:
            e1 = getattr(self.material, 'e1', None)
            if e1 is not None:
                e = min(self.material.e1, self.material.e2, self.material.e3)
                nu = min(self.material.nu12, self.material.nu13,
                         self.material.nu23)
            else:
                raise Exception(
                    'No clues on how to construct the stabilization material')
        self.stabilization_material = MatDeforTriaxLinearIso(e=e, nu=nu)
        # Now try to figure out which Poisson ratio to use in the optimal scaling
        # factor(to account for geometry)
        nu = getattr(self.material, "nu", None)
        if nu is not None:
            self.nu = self.material.nu
        else:
            nu12 = getattr(self.material, "nu12", None)
            if nu12 is not None:
                self.nu = max(self.material.nu12, self.material.nu13,
                              self.material.nu23)
            else:
                raise Exception(
                    'No clues on how to construct the stabilization material')
예제 #7
0
    def nodal_field_from_integr_points(self, geom, un1, un, dt=0.0, dtempn1=None,
                                       outcs=CSys(), output=OUTPUT_CAUCHY, component=(0,)):
        """Create a nodal field from quantities at integration points.

        The procedure is the universe-distance interpolation.
        :param geom: Geometry field.
        :param un1: Displacement field at the time t_n+1.
        :param un: Displacement field at time t_n.
        :param dt: Time step from t_n to t_n+1.
        :param dtempn1: Temperature increment field or None.
        :param outcs: Output coordinate system.
        :param output: Output quantity (enumeration).
        :param component: Which component of the output quantity?
        :return: nodal field
        """
        # Container of intermediate results
        sum_inv_dist = numpy.zeros((geom.nfens,))
        sum_quant_inv_dist = numpy.zeros((geom.nfens, len(component)))
        fld = NodalField(nfens=geom.nfens, dim=len(component))

        # This is an inverse-distance interpolation inspector.
        def idi(idat, out, xyz, u, pc):
            x, conn = idat
            da = x - numpy.ones((x.shape[0], 1)) * xyz
            d = numpy.sum(da ** 2, axis=1)
            zi = d == 0
            d[zi] = min(d[~zi]) / 1.e9
            invd = numpy.reshape(1. / d, (x.shape[0], 1))
            quant = numpy.reshape(out[component], (1, len(component)))
            sum_quant_inv_dist[conn, :] += invd * quant
            sum_inv_dist[conn] += invd.ravel()
            return

        # Loop over cells to interpolate to nodes
        for i in range(self.fes.conn.shape[0]):
            x1 = geom.values[self.fes.conn[i, :], :]
            idat1 = (x1, self.fes.conn[i, :])
            self.inspect_integration_points([i], idi, idat1,
                                            geom, un1, un, dt, dtempn1,
                                            outcs, output)

        # compute the field data array
        nzi = ~(sum_inv_dist == 0)
        for j in range(len(component)):
            fld.values[nzi, j] = sum_quant_inv_dist[nzi, j] / sum_inv_dist[nzi]
        return fld
    def __init__(self,
                 material=None,
                 fes=None,
                 integration_rule=None,
                 material_csys=CSys(),
                 assoc_geom=None):
        """Constructor.

        :param material: Material object.
        :param fes: Finite element set object.
        :param integration_rule: Integration rule object.
        """
        integration_rule = GaussRule(
            dim=3, order=2) if integration_rule is None else integration_rule
        super().__init__(fes=fes,
                         material=material,
                         integration_rule=integration_rule,
                         material_csys=material_csys,
                         assoc_geom=assoc_geom)
예제 #9
0
    def inspect_integration_points(self, fe_list, inspector, idat,
                                   geom, un1, un, dt=0.0, dtempn1=None,
                                   outcs=CSys(), output=OUTPUT_CAUCHY):
        """Inspect integration point quantities.

        :param fe_list: indexes of the finite elements that are to be inspected:
               The fes to be included are: fes.conn[fe_list, :].
        :param inspector: inspector function,
        :param idat: data for inspector function,
        :param geom: Geometry field.
        :param un1: Displacement field at the time t_n+1.
        :param un: Displacement field at time t_n.
        :param dt: Time step from t_n to t_n+1.
        :param dtempn1: Temperature increment field or None.
        :param outcs: output coordinate system
        :param output: type of output
        :return: idat: data for inspector function
        """
        raise Exception(
            'This method needs to be overridden in the derived class')  # need to override in the child class
예제 #10
0
    def __init__(self,
                 material=None,
                 fes=None,
                 integration_rule=None,
                 material_csys=CSys(),
                 assoc_geom=None,
                 surface_normal_spring_coefficient=1.0,
                 surface_normal=None):
        """Constructor.

        :param material: Material object.
        :param fes: Finite element set object.
        :param integration_rule: Integration rule object.
        """
        super().__init__(fes=fes,
                         integration_rule=integration_rule,
                         material_csys=material_csys,
                         assoc_geom=assoc_geom)
        self.surface_normal_spring_coefficient = surface_normal_spring_coefficient
        self.surface_normal = surface_normal
예제 #11
0
    def elemental_field_from_integr_points(self, geom, un1, un, dt=0.0, dtempn1=None,
                                           outcs=CSys(), output=OUTPUT_CAUCHY, component=(0,)):
        """Create a elemental field from quantities at integration points.

        :param geom: Geometry field.
        :param un1: Displacement field at the time t_n+1.
        :param un: Displacement field at time t_n.
        :param dt: Time step from t_n to t_n+1.
        :param dtempn1: Temperature increment field or None.
        :param outcs: Output coordinate system.
        :param output: Output quantity (enumeration).
        :param component: Which component of the output quantity?
        :return: nodal field
        """
        # Container of intermediate results
        nelems = self.fes.conn.shape[0]
        n_q = numpy.zeros((nelems,))
        sum_q = numpy.zeros((nelems, len(component)))
        fld = ElementalField(nelems=nelems, dim=len(component))

        # This is an inverse-distance interpolation inspector.
        def idi(idat, out, xyz, u, pc):
            i = idat
            quant = numpy.reshape(out[component], (1, len(component)))
            sum_q[i, :] += quant.ravel()
            n_q[i] += 1
            return

        # Loop over cells to interpolate to nodes
        for i in range(self.fes.conn.shape[0]):
            x1 = geom.values[self.fes.conn[i, :], :]
            idat1 = i
            self.inspect_integration_points([i], idi, idat1,
                                            geom, un1, un, dt, dtempn1,
                                            outcs, output)

        # compute the field data array
        for i in range(self.fes.conn.shape[0]):
            for j in range(len(component)):
                fld.values[i, j] = sum_q[i, j] / n_q[i]
        return fld
예제 #12
0
def elem_dep_data_qt10ms(na, nb, nts):
    print(na, nb, nts)
    # fens, fes = t4_block(a, b, t, na, nb, nt, orientation='a')
    fens, fes = t4_composite_plate(a, b, ts, na, nb, nts)
    fens, fes = t4_to_t10(fens, fes)
    bfes = mesh_boundary(fes)
    t = sum(ts)
    fesel = fe_select(fens, bfes, box=[0, a, 0, b, t, t], inflate=htol)
    tsfes = bfes.subset(fesel)
    femms = []
    for layer in range(len(nts)):
        aangle = angles[layer] / 180. * math.pi
        print(aangle)
        mcsys = CSys(matrix=rotmat(numpy.array([0.0, 0.0, aangle])))
        el = fe_select(fens, fes, bylabel=True, label=layer)
        femms.append(
            FEMMDeforLinearQT10MS(material=m,
                                  material_csys=mcsys,
                                  fes=fes.subset(el)))
    sfemm = FEMMDeforLinear(fes=tsfes, integration_rule=TriRule(npts=3))
    return fens, femms, sfemm
예제 #13
0
aangle = 45.0 / 180. * math.pi
uz_ref = -1.202059060799316e-06 * SI.m
a, b, t = 90.0 * SI.mm, 100.0 * SI.mm, 20.0 * SI.mm
na, nb, nt = 6, 6, 2
htol = min(a, b, t) / 1000
q0 = -1. * SI.psi
m = MatDeforTriaxLinearOrtho(e1=e1,
                             e2=e2,
                             e3=e3,
                             g12=g12,
                             g13=g13,
                             g23=g23,
                             nu12=nu12,
                             nu13=nu13,
                             nu23=nu23)
mcsys = CSys(matrix=rotmat(numpy.array([0.0, 0.0, aangle])))


def elem_dep_data_t10(na, nb, nt):
    fens, fes = t4_block(a, b, t, na, nb, nt, orientation='a')
    fens, fes = t4_to_t10(fens, fes)
    femm = FEMMDeforLinear(material=m,
                           material_csys=mcsys,
                           fes=fes,
                           integration_rule=TetRule(npts=4))
    bfes = mesh_boundary(femm.fes)
    fesel = fe_select(fens, bfes, box=[a, a, 0, b, 0, t], inflate=htol)
    tsfes = bfes.subset(fesel)
    sfemm = FEMMDeforLinear(fes=tsfes, integration_rule=TriRule(npts=3))
    return fens, femm, sfemm
예제 #14
0
        model_data['boundary_conditions']['essential'] = essential

        # Traction on the free end
        fi = ForceIntensity(magn=lambda x, J: numpy.array([0, 0, q0]))
        traction = [{'femm': sfemm, 'force_intensity': fi}]
        model_data['boundary_conditions']['traction'] = traction

        # Call the solver
        algo_defor_linear.statics(model_data)
        # for action, time in model_data['timings']:
        #     print(action, time, ' sec')

        geom = model_data['geom']
        u = model_data['u']

        bottom_edge = fenode_select(
            fens, box=[a / 2.0, a / 2.0, b / 2.0, b / 2.0, 0, t], inflate=htol)
        uv = u.values[bottom_edge, :]
        uz = numpy.mean(abs(uv[:, 2]))
        print('Center displacement uz =', uz, ', ',
              (uz / abs(wc_analytical) * 100), ' %')

        algo_defor_linear.plot_displacement(model_data)

        model_data['postprocessing'] = {
            'file': 'Z_laminate_u_ss_' + k + '_results',
            'outcs': CSys()
        }
        # algo_defor.plot_stress(model_data)
        algo_defor.plot_elemental_stress(model_data)
예제 #15
0
    def inspect_integration_points(self,
                                   fe_list,
                                   inspector,
                                   idat,
                                   geom,
                                   un1,
                                   un,
                                   dt=0.0,
                                   dtempn1=None,
                                   outcs=CSys(),
                                   output=OUTPUT_CAUCHY):
        """Inspect integration point quantities.

        :param fe_list: indexes of the finite elements that are to be inspected:
               The fes to be included are: fes.conn[fe_list, :].
        :param inspector: inspector function,
        :param idat: data for inspector function,
        :param geom: Geometry field.
        :param un1: Displacement field at the time t_n+1.
        :param un: Displacement field at time t_n.
        :param dt: Time step from t_n to t_n+1.
        :param dtempn1: Temperature increment field or None.
        :return: idat: data for inspector function
        """
        fes = self.fes
        bfuns, gradbfunpars, npts, pc, w = self.integration_data()
        mcs = self.material_csys
        if mcs.isconstant:
            mcsmtx = mcs.eval_matrix()  # constant
        if outcs is not None and outcs.isconstant:
            outcsmtx = outcs.eval_matrix()  # constant
        if dtempn1 is None:
            dtemps = numpy.zeros((geom.nfens, 1))
        else:
            dtemps = dtempn1.values
        bmatfun, bbar = self.fes.bmatdata(self.fes.nfens)
        elemu = numpy.zeros((fes.nfens * un1.dim, ))
        gradbfun = list()
        jac = list()
        gradbfunmean = numpy.zeros((fes.nfens, geom.dim))
        for j in range(npts):
            gradbfun.append(numpy.zeros((fes.nfens, geom.dim)))
            jac.append(0.0)
        quantityout = None
        vout = None
        for i in fe_list:
            x = geom.values[fes.conn[i, :], :]
            # Calculate mean basis function gradient + volume of the element
            vol = 0
            gradbfunmean.fill(0.0)
            for j in range(npts):
                jacmat = dot(x.T, gradbfunpars[j])
                jac[j] = fes.jac_volume(fes.conn[i, :], bfuns[j], jacmat, x)
                fes.gradbfun(gradbfun[j], gradbfunpars[j], jacmat)
                dvol = jac[j] * w[j]
                gradbfunmean += gradbfun[j] * dvol
                vol = vol + dvol
            gradbfunmean /= vol
            bmatfun(bbar, None, gradbfunmean, None)
            un1.gather_values_vec(fes.conn[i, :], elemu)
            c = dot(bfuns[j].T, x)  # Model location of the quadrature point
            u_c = dot(bfuns[j].T, un1.values[fes.conn[
                i, :], :])  # Displacement of the quad point
            strain = dot(bbar,
                         elemu)  # strain in global Cartesian coordinate system
            mstrain = numpy.copy(strain)  #strain in material coordinate
            # If necessary, transform the strain from the global CS to the material CS
            if not mcs.isidentity:  # Transformation is required
                if not mcs.isconstant:  # Do I need to evaluate the local mat orient?
                    mcsmtx = mcs.eval_matrix(c, jacmat, fes.label[i])
                self.material.rotate_strain_vector(mstrain, mcsmtx, strain)
            dtemp = dot(bfuns[j].T, dtemps[fes.conn[i, :]])
            quantityout = self.material.state(None,
                                              strain=strain,
                                              dtemp=dtemp,
                                              output=output,
                                              quantityout=quantityout)
            if output == OUTPUT_CAUCHY:  # vector quantity: transformation may be required
                if vout is None:
                    vout = numpy.zeros_like(quantityout)
                if not mcs.isidentity:  # Transformation is required
                    self.material.rotate_stress_vector(vout, mcsmtx.T,
                                                       quantityout)
                    quantityout[:] = vout[:]
                if not outcs.isidentity:  # Transformation is required
                    if not outcs.isconstant:  # Do I need to evaluate the local mat orient?
                        outcsmtx = outcs.eval_matrix(c, jacmat, fes.label[i])
                    self.material.rotate_stress_vector(vout, outcsmtx,
                                                       quantityout)
                    quantityout[:] = vout[:]
            else:  #
                pass
            if inspector is not None:
                inspector(idat, quantityout, c, u_c, pc[j, :])
        return idat
예제 #16
0
    def nodal_field_from_integr_points_spr(self, geom, un1, un, dt=0.0, dtempn1=None,
                                           outcs=CSys(), output=OUTPUT_CAUCHY, component=(0,)):
        """Create a nodal field from quantities at integration points.

        The procedure is the Super-convergent Patch Recovery.
        :param geom: Geometry field.
        :param un1: Displacement field at the time t_n+1.
        :param un: Displacement field at time t_n.
        :param dt: Time step from t_n to t_n+1.
        :param dtempn1: Temperature increment field or None.
        :param outcs: Output coordinate system.
        :param output: Output quantity (enumeration).
        :param component: Which component of the output quantity?
        :return: nodal field
        """
        fes = self.fes
        # Make the inverse map from finite element nodes to finite elements
        femap = fenode_to_fe_map(geom.nfens, fes.conn)
        fld = NodalField(nfens=geom.nfens, dim=len(component))

        # This is an inverse-distance interpolation inspector.
        def idi(idat, out, xyz, u, pc):
            idat.append((numpy.array(out), xyz))

        def spr(idat, xc):
            """Super-convergent Patch Recovery.

            :param idat: List of integration point data.
            :param xc: Location at which the quantities to be recovered.
            :return: Recovered quantity.
            """

            n = len(idat)
            if n == 0:  # nothing can be done
                raise Exception('No data for SPR')
            elif n == 1:  # we got a single value: return it
                out, xyz = idat[0]
                sproutput = out.ravel() / n
            else:  # attempt to solve the least-squares problem
                out, xyz = idat[0]
                dim = xyz.size  # the number of modeling dimensions (1, 2, 3)
                nc = out.size
                na = dim + 1
                if (n >= na):
                    A = numpy.zeros((na, na))
                    b = numpy.zeros((na, nc))
                    pk = numpy.zeros((na, 1))
                    pk[0] = 1.0
                    for k in range(n):
                        out, xyz = idat[k]
                        out.shape = (1, nc)
                        xk = xyz - xc
                        pk[1:] = xk[:].reshape(dim, 1)
                        A += pk * pk.T
                        b += pk * out
                    try:
                        a = numpy.linalg.solve(A, b)
                        # xk = xc - xc
                        # p = [1, xk]
                        sproutput = a[0, :].ravel()
                    except:  # not enough to solve the least-squares problem: compute simple average
                        out, xyz = idat[0]
                        sproutput = out / n
                        for k in range(1, n):
                            out, xyz = idat[k]
                            sproutput += out / n
                        sproutput = sproutput.ravel()
                else:  # not enough to solve the least-squares problem: compute simple average
                    out, xyz = idat[0]
                    sproutput = out / n
                    for k in range(1, n):
                        out, xyz = idat[k]
                        sproutput += out / n
                    sproutput = sproutput.ravel()
            return sproutput

        # Loop over nodes, and for each visit the connected FEs
        for i in range(geom.nfens):
            idat = []
            xc = geom.values[i, :]  # location of the current node
            # construct the list of the relevant integr points
            # and the values at these points
            idat = self.inspect_integration_points(femap[i], idi, idat,
                                                   geom, un1, un, dt, dtempn1,
                                                   outcs, output)
            out1 = spr(idat, xc)
            fld.values[i, :] = out1[:]

        return fld
aangle = 30.0 / 180. * math.pi
uz_ref = -1.054995121951226e-02 * SI.mm  #millimeters
a, b, t = 90.0 * SI.mm, 10.0 * SI.mm, 20.0 * SI.mm  #millimeters
# na, nb, nt = 16, 4,4
htol = min(a, b, t) / 1000
magn = -1000. * SI.Pa  # Pascal
m = MatDeforTriaxLinearOrtho(e1=e1,
                             e2=e2,
                             e3=e3,
                             g12=g12,
                             g13=g13,
                             g23=g23,
                             nu12=nu12,
                             nu13=nu13,
                             nu23=nu23)
mcsys = CSys(matrix=rotmat(numpy.array([aangle, aangle, aangle])))


def elem_dep_data_t10(na, nb, nt):
    fens, fes = t4_block(a, b, t, na, nb, nt, orientation='a')
    fens, fes = t4_to_t10(fens, fes)
    femm = FEMMDeforLinear(material=m,
                           material_csys=mcsys,
                           fes=fes,
                           integration_rule=TetRule(npts=4))
    bfes = mesh_boundary(femm.fes)
    fesel = fe_select(fens, bfes, box=[a, a, 0, b, 0, t], inflate=htol)
    tsfes = bfes.subset(fesel)
    sfemm = FEMMDeforLinear(fes=tsfes, integration_rule=TriRule(npts=3))
    return fens, femm, sfemm