コード例 #1
0
    def GetLocalTraction(self, function_space, material, LagrangeElemCoords, EulerElemCoords, fem_solver, elem=0):
        """Get traction vector of the system"""

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        # ALLOCATE
        tractionforce = np.zeros((nodeperelem*nvar,1),dtype=np.float64)
        B = np.zeros((nodeperelem*nvar,material.H_VoigtSize),dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerElemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # UPDATE/NO-UPDATE GEOMETRY
        if fem_solver.requires_geometry_update:
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientx = np.einsum('ijk,jl->kil',Jm, EulerElemCoords)
            # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
            SpatialGradient = np.einsum('ijk,kli->ilj',inv(ParentGradientx),Jm)
            # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
            detJ = np.einsum('i,i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)),np.abs(StrainTensors['J']))
        else:
            # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
            SpatialGradient = np.einsum('ikj',MaterialGradient)
            # COMPUTE ONCE detJ
            detJ = np.einsum('i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)))


        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):

            # COMPUTE CAUCHY STRESS TENSOR
            CauchyStressTensor = []
            if fem_solver.requires_geometry_update:
                CauchyStressTensor = material.CauchyStress(StrainTensors,None,elem,counter)

            # COMPUTE THE TANGENT STIFFNESS MATRIX
            t = self.TractionIntegrand(B, SpatialGradient[counter,:,:],
                CauchyStressTensor, requires_geometry_update=fem_solver.requires_geometry_update)

            if fem_solver.requires_geometry_update:
                # INTEGRATE TRACTION FORCE
                tractionforce += t*detJ[counter]


        return tractionforce
コード例 #2
0
    def GetLinearMomentum(self,
                          function_space,
                          material,
                          LagrangeElemCoords,
                          EulerELemCoords,
                          VelocityElem,
                          fem_solver,
                          elem=0):
        """Get linear momentum or virtual power of the system. For dynamic analysis this is handy for computing conservation of linear momentum.
            The routine computes the global form of virtual power i.e. integral of "P:Grad_0(V)"" where P is first Piola-Kirchhoff
            stress tensor and Grad_0(V) is the material gradient of velocity. Alternatively in update Lagrangian format this could be
            computed using "Sigma: Grad(V) J" where Sigma is the Cauchy stress tensor and Grad(V) is the spatial gradient of velocity.
            The latter approach is followed here
        """

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        internal_power = 0.

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)
        # TIME DERIVATIVE OF F
        Fdot = np.einsum('ij,kli->kjl', VelocityElem, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientx = np.einsum('ijk,jl->kil', Jm, EulerELemCoords)
        # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
        SpatialGradient = np.einsum('ijk,kli->ilj', inv(ParentGradientx), Jm)
        # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
        detJ = np.einsum('i,i,i->i', AllGauss[:, 0],
                         np.abs(det(ParentGradientX)),
                         np.abs(StrainTensors['J']))

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):
            GradV = np.dot(Fdot[counter, :, :],
                           np.linalg.inv(F[counter, :, :]))
            # COMPUTE CAUCHY
            CauchyStressTensor = material.CauchyStress(StrainTensors, None,
                                                       elem, counter)
            # INTEGRATE INTERNAL VIRTUAL POWER
            internal_power += np.einsum('ij,ij', CauchyStressTensor,
                                        GradV) * detJ[counter]

        return internal_power
コード例 #3
0
    def GetEnergy(self, function_space, material, LagrangeElemCoords,
        EulerELemCoords, ElectricPotentialElem, fem_solver, elem=0):
        """Get virtual energy of the system. For dynamic analysis this is handy for computing conservation of energy.
            The routine computes the global form of virtual internal energy i.e. integral of "W(C,G,C)"". This can be
            computed purely in a Lagrangian configuration.
        """

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        internal_energy = 0.

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
        SpatialGradient = np.einsum('ikj',MaterialGradient)
        # COMPUTE ONCE detJ
        detJ = np.einsum('i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)))

        # GET ELECTRIC FIELD
        ElectricFieldx = - np.einsum('ijk,j',SpatialGradient,ElectricPotentialElem)

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):
            if material.energy_type == "enthalpy":
                # COMPUTE THE INTERNAL ENERGY AT THIS GAUSS POINT
                energy = material.InternalEnergy(StrainTensors,ElectricFieldx[counter,:],0,elem,counter)
            elif material.energy_type == "internal_energy":
                # COMPUTE ELECTRIC DISPLACEMENT IMPLICITLY
                ElectricDisplacementx = material.ElectricDisplacementx(StrainTensors, ElectricFieldx[counter,:], elem, counter)
                # COMPUTE THE INTERNAL ENERGY AT THIS GAUSS POINT
                energy = material.InternalEnergy(StrainTensors,ElectricDisplacementx[counter,:],elem,counter)

            # INTEGRATE INTERNAL ENERGY
            internal_energy += energy*detJ[counter]

        return internal_energy
コード例 #4
0
    def GetEnergy(self,
                  function_space,
                  material,
                  LagrangeElemCoords,
                  EulerELemCoords,
                  fem_solver,
                  elem=0):
        """Get virtual energy of the system. For dynamic analysis this is handy for computing conservation of energy.
            The routine computes the global form of virtual internal energy i.e. integral of "W(C,G,C)"". This can be
            computed purely in a Lagrangian configuration.
        """

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        internal_energy = 0.

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientx = np.einsum('ijk,jl->kil', Jm, EulerELemCoords)
        # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
        SpatialGradient = np.einsum('ijk,kli->ilj', inv(ParentGradientx), Jm)
        # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
        detJ = np.einsum('i,i,i->i', AllGauss[:, 0],
                         np.abs(det(ParentGradientX)),
                         np.abs(StrainTensors['J']))

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):
            # COMPUTE THE INTERNAL ENERGY AT THIS GAUSS POINT
            energy = material.InternalEnergy(StrainTensors, elem, counter)
            # INTEGRATE INTERNAL ENERGY
            internal_energy += energy * detJ[counter]

        return internal_energy
コード例 #5
0
    def K_ww(self, material, fem_solver, Eulerw, Eulerp=None, elem=0):
        """Get stiffness matrix of the system"""

        meshes = self.meshes
        mesh = self.meshes[1]

        function_spaces = self.function_spaces
        function_space = self.function_spaces[1]

        ndim = self.ndim
        nvar = ndim
        nodeperelem = meshes[1].elements.shape[1]

        # GET THE FIELDS AT THE ELEMENT LEVEL
        LagrangeElemCoords = mesh.points[mesh.elements[elem,:],:]
        EulerELemCoords = Eulerw[mesh.elements[elem,:],:]

        Jm = function_spaces[1].Jm
        AllGauss = function_space.AllGauss

        # # GET LOCAL KINEMATICS
        # SpatialGradient, F, detJ = _KinematicMeasures_(Jm, AllGauss[:,0],
        #     LagrangeElemCoords, EulerELemCoords, fem_solver.requires_geometry_update)
        # # COMPUTE WORK-CONJUGATES AND HESSIAN AT THIS GAUSS POINT
        # CauchyStressTensor, _, H_Voigt = material.KineticMeasures(F,elem=elem)


        # ALLOCATE
        stiffness = np.zeros((nodeperelem*nvar,nodeperelem*nvar),dtype=np.float64)
        tractionforce = np.zeros((nodeperelem*nvar,1),dtype=np.float64)
        B = np.zeros((nodeperelem*nvar,material.gradient_elasticity_tensor_size),dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # UPDATE/NO-UPDATE GEOMETRY
        if fem_solver.requires_geometry_update:
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientx = np.einsum('ijk,jl->kil',Jm,EulerELemCoords)
            # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
            SpatialGradient = np.einsum('ijk,kli->ilj',inv(ParentGradientx),Jm)
            # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
            detJ = np.einsum('i,i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)),np.abs(StrainTensors['J']))
        else:
            # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
            SpatialGradient = np.einsum('ikj',MaterialGradient)
            # COMPUTE ONCE detJ
            detJ = np.einsum('i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)))


        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):

            # COMPUTE THE HESSIAN AT THIS GAUSS POINT
            material.Hessian(StrainTensors,None, elem, counter)
            H_Voigt = material.gradient_elasticity_tensor

            # COMPUTE CAUCHY STRESS TENSOR
            CoupleStressVector = []
            if fem_solver.requires_geometry_update:
                CoupleStressVector = material.CoupleStress(StrainTensors,None,elem,counter).reshape(self.ndim,1)


            # COMPUTE THE TANGENT STIFFNESS MATRIX
            BDB_1, t = self.K_ww_Integrand(B, SpatialGradient[counter,:,:],
                None, CoupleStressVector, H_Voigt, analysis_nature=fem_solver.analysis_nature,
                has_prestress=fem_solver.has_prestress)

            # COMPUTE GEOMETRIC STIFFNESS MATRIX
            if fem_solver.requires_geometry_update:
                # INTEGRATE TRACTION FORCE
                tractionforce += t*detJ[counter]

            # INTEGRATE STIFFNESS
            stiffness += BDB_1*detJ[counter]


        # # SAVE AT THIS GAUSS POINT
        # self.SpatialGradient = SpatialGradient
        # self.detJ = detJ

        return stiffness, tractionforce
コード例 #6
0
    def GetLocalStiffness(self,
                          function_space,
                          material,
                          VolumesX,
                          Volumesx,
                          LagrangeElemCoords,
                          EulerELemCoords,
                          fem_solver,
                          elem=0):
        """Compute stiffness matrix of an element"""

        nvar = self.nvar
        ndim = self.ndim
        Domain = function_space

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = Domain.Jm
        AllGauss = Domain.AllGauss

        material.kappa = material.lamb + 2.0 * material.mu / 3.0
        material.pressure = (Volumesx - VolumesX) / VolumesX

        # ALLOCATE
        stiffness = np.zeros(
            (Domain.Bases.shape[0] * nvar, Domain.Bases.shape[0] * nvar),
            dtype=np.float64)
        stiffness_XP = np.zeros(Domain.Bases.shape[0] * nvar, dtype=np.float64)
        stiffness_JJ = 0
        tractionforce = np.zeros((Domain.Bases.shape[0] * nvar, 1),
                                 dtype=np.float64)
        B = np.zeros((Domain.Bases.shape[0] * nvar, material.H_VoigtSize),
                     dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)
        # COFACTOR OF DEFORMATION GRADIENT TENSOR
        H = np.einsum('ijk,k->ijk', np.linalg.inv(F).T, StrainTensors['J'])
        # COMPUTE H:\nabla_{\delta\vec{v}} - TRANSPOSE IS NECESSARY TO FORCE F-CONTIGUOUS
        B_XP = np.einsum('ijk,kjl->il', H, MaterialGradient).T.ravel()

        # UPDATE/NO-UPDATE GEOMETRY
        if fem_solver.requires_geometry_update:
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientx = np.einsum('ijk,jl->kil', Domain.Jm,
                                        EulerELemCoords)
            # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
            SpatialGradient = np.einsum('ijk,kli->ilj', inv(ParentGradientx),
                                        Jm)
            # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
            detJ = np.einsum('i,i,i->i', AllGauss[:, 0],
                             np.abs(det(ParentGradientX)),
                             np.abs(StrainTensors['J']))
        else:
            # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
            SpatialGradient = np.einsum('ikj', MaterialGradient)
            # COMPUTE ONCE detJ
            detJ = np.einsum('i,i->i', AllGauss[:, 0],
                             np.abs(det(ParentGradientX)))

        # print(MaterialGradient.shape)
        # exit()
        stiffness_x = np.zeros((12, 12))
        dN = np.zeros((6, 2))

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):

            # for a in range(6):
            #     for b in range(6):
            #         dNa = SpatialGradient[counter,a,:]
            #         dNb = SpatialGradient[counter,b,:]
            # stiffness_x[2*a:2*(a+1),2*b:2*(b+1)] += dNa[:,None].dot(dNb[None,:])*detJ[counter]

            dN[:] += 1. / Volumesx[elem] * SpatialGradient[
                counter, :, :] * detJ[counter]

            # COMPUTE THE HESSIAN AT THIS GAUSS POINT
            H_Voigt = material.Hessian(StrainTensors, None, elem, counter)

            # COMPUTE CAUCHY STRESS TENSOR
            CauchyStressTensor = []
            if fem_solver.requires_geometry_update:
                CauchyStressTensor = material.CauchyStress(
                    StrainTensors, None, elem, counter)

            # COMPUTE THE TANGENT STIFFNESS MATRIX
            BDB_1, t = self.ConstitutiveStiffnessIntegrand(
                B,
                SpatialGradient[counter, :, :],
                CauchyStressTensor,
                H_Voigt,
                analysis_nature=fem_solver.analysis_nature,
                has_prestress=fem_solver.has_prestress)

            # COMPUTE GEOMETRIC STIFFNESS MATRIX
            if fem_solver.requires_geometry_update:
                BDB_1 += self.GeometricStiffnessIntegrand(
                    SpatialGradient[counter, :, :], CauchyStressTensor)
                # INTEGRATE TRACTION FORCE
                tractionforce += t * detJ[counter]

            # INTEGRATE STIFFNESS
            stiffness += BDB_1 * detJ[counter]

            # K_JP, K_PJ
            # detJ_XP = np.einsum('i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)))
            # stiffness_XP[:] = B_XP*detJ_XP[counter]

            # K_JJ
            # stiffness_JJ += detJ_XP[counter]

        # stiffness_JP = np.copy(stiffness_JJ)
        # stiffness_JJ *= material.kappa

        # b1 = np.concatenate((stiffness,np.zeros((12,1)),stiffness_XP[:,None]),axis=1)
        # b2 = np.concatenate((np.zeros((1,12)),stiffness_XP[:,None].T),axis=0)
        # b3 = np.array([[stiffness_JJ, - stiffness_JP], [-stiffness_JP, 0]])
        # b4 = np.concatenate((b2,b3),axis=1)
        # bf = np.concatenate((b1,b4),axis=0)
        # stiffness = bf

        # stiffness = stiffness+stiffness_x*material.kappa/VolumesX[elem]

        # print dN[0,:,None].dot(dN[0,:,None].T)
        # exit()
        for a in range(6):
            for b in range(6):
                stiffness_x[2 * a:2 * (a + 1),
                            2 * b:2 * (b + 1)] += dN[a, :,
                                                     None].dot(dN[b, :,
                                                                  None].T)

        kappa_bar = material.kappa * Volumesx[elem] / VolumesX[elem]
        stiffness_x *= (kappa_bar * Volumesx[elem])
        stiffness = stiffness + stiffness_x

        return stiffness, tractionforce
コード例 #7
0
    def GetLocalStiffness(self,
                          function_space,
                          material,
                          LagrangeElemCoords,
                          EulerElemCoords,
                          fem_solver,
                          elem=0):
        """Get stiffness matrix of the system"""

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        # ALLOCATE
        stiffness = np.zeros((nodeperelem * nvar, nodeperelem * nvar),
                             dtype=np.float64)
        tractionforce = np.zeros((nodeperelem * nvar, 1), dtype=np.float64)
        B = np.zeros((nodeperelem * nvar, material.H_VoigtSize),
                     dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # ParentGradientX = [np.eye(3,3)]
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerElemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
        SpatialGradient = np.einsum('ikj', MaterialGradient)
        # COMPUTE ONCE detJ
        detJ = np.einsum('i,i->i', AllGauss[:, 0], det(ParentGradientX))
        # detJ = np.einsum('i,i,i->i', AllGauss[:,0], det(ParentGradientX), StrainTensors['J'])

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):

            # COMPUTE THE HESSIAN AT THIS GAUSS POINT
            H_Voigt = material.Hessian(StrainTensors, None, elem, counter)

            # COMPUTE CAUCHY STRESS TENSOR
            CauchyStressTensor = []
            if fem_solver.requires_geometry_update:
                CauchyStressTensor = material.CauchyStress(
                    StrainTensors, None, elem, counter)

            # COMPUTE THE TANGENT STIFFNESS MATRIX
            BDB_1, t = self.ConstitutiveStiffnessIntegrand(
                B,
                SpatialGradient[counter, :, :],
                StrainTensors['F'][counter],
                CauchyStressTensor,
                H_Voigt,
                requires_geometry_update=fem_solver.requires_geometry_update)

            # INTEGRATE TRACTION FORCE
            if fem_solver.requires_geometry_update:
                tractionforce += t * detJ[counter]

            # INTEGRATE STIFFNESS
            stiffness += BDB_1 * detJ[counter]

        makezero(stiffness, 1e-12)
        # print(stiffness)
        # print(tractionforce)
        # exit()
        return stiffness, tractionforce
コード例 #8
0
    def GetLocalTraction(self,
                         function_space,
                         material,
                         LagrangeElemCoords,
                         EulerELemCoords,
                         ElectricPotentialElem,
                         fem_solver,
                         elem=0):
        """Get traction vector of the system"""

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        # ALLOCATE
        tractionforce = np.zeros((nodeperelem * nvar, 1), dtype=np.float64)
        B = np.zeros((nodeperelem * nvar, material.H_VoigtSize),
                     dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # UPDATE/NO-UPDATE GEOMETRY
        if fem_solver.requires_geometry_update:
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientx = np.einsum('ijk,jl->kil', Jm, EulerELemCoords)
            # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
            SpatialGradient = np.einsum('ijk,kli->ilj', inv(ParentGradientx),
                                        Jm)
            # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
            detJ = np.einsum('i,i,i->i', AllGauss[:, 0],
                             np.abs(det(ParentGradientX)),
                             np.abs(StrainTensors['J']))
        else:
            # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
            SpatialGradient = np.einsum('ikj', MaterialGradient)
            # COMPUTE ONCE detJ
            detJ = np.einsum('i,i->i', AllGauss[:, 0],
                             np.abs(det(ParentGradientX)))

        # GET ELECTRIC FIELD
        ElectricFieldx = -np.einsum('ijk,j', SpatialGradient,
                                    ElectricPotentialElem)

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):

            if material.energy_type == "enthalpy":

                # COMPUTE ELECTRIC DISPLACEMENT
                ElectricDisplacementx = material.ElectricDisplacementx(
                    StrainTensors, ElectricFieldx[counter, :], elem, counter)

            elif material.energy_type == "internal_energy":
                # THIS REQUIRES LEGENDRE TRANSFORM

                # COMPUTE ELECTRIC DISPLACEMENT IMPLICITLY
                ElectricDisplacementx = material.ElectricDisplacementx(
                    StrainTensors, ElectricFieldx[counter, :], elem, counter)

            # COMPUTE THE TANGENT STIFFNESS MATRIX
            t = self.TractionIntegrand(
                B,
                SpatialGradient[counter, :, :],
                ElectricDisplacementx,
                analysis_nature=fem_solver.analysis_nature,
                has_prestress=fem_solver.has_prestress)

            # INTEGRATE TRACTION FORCE
            tractionforce += t * detJ[counter]

        return tractionforce
コード例 #9
0
ファイル: ComputeErrorNorms.py プロジェクト: xyuan/florence
def ComputeErrorNorms(MainData,mesh,nmesh,AnalyticalSolution,Domain,Quadrature,MaterialArgs):

    # AT THE MOMENT THE ERROR NORMS ARE COMPUTED FOR LINEAR PROBLEMS ONLY
    if MainData.GeometryUpdate:
        raise ValueError('The error norms are computed for linear problems only.')

    # INITIATE/ALLOCATE
    C = MainData.C 
    ndim = MainData.ndim
    nvar = MainData.nvar
    elements = nmesh.elements
    points = nmesh.points
    nelem = elements.shape[0]
    nodeperelem = elements.shape[1]
    w = Quadrature.weights

    # TotalDisp & TotalPot ARE BOTH THIRD ORDER TENSOR (3RD DIMENSION FOR INCREMENTS) - TRANCATE THEM UNLESS REQUIRED
    TotalDisp = MainData.TotalDisp[:,:,-1]
    TotalPot  = MainData.TotalPot[:,:,-1]

    # # print TotalDisp
    # TotalDispa = np.zeros(TotalDisp.shape)
    # uxa = (points[:,1]*np.cos(points[:,0])); uxa=np.zeros(uxa.shape)
    # uya = (points[:,0]*np.sin(points[:,1]))
    # TotalDispa[:,0]=uxa
    # TotalDispa[:,1]=uya
    # # print TotalDispa
    # # print TotalDisp
    # print np.concatenate((TotalDispa,TotalDisp),axis=1)
    # # print points


    # ALLOCATE
    B = np.zeros((Domain.Bases.shape[0]*nvar,MaterialArgs.H_VoigtSize))
    E_nom = 0; E_denom = 0; L2_nom = 0; L2_denom = 0
    # LOOP OVER ELEMENTS
    for elem in range(0,nelem):
        xycoord = points[elements[elem,:],:]    
        # GET THE NUMERICAL SOLUTION WITHIN THE ELEMENT (AT NODES)
        ElementalSol = np.zeros((nodeperelem,nvar))
        ElementalSol[:,:ndim] = TotalDisp[elements[elem,:],:]
        ElementalSol[:,ndim]  = TotalPot[elements[elem,:],:].reshape(nodeperelem)
        # GET THE ANALYTICAL SOLUTION WITHIN THE ELEMENT (AT NODES)
        AnalyticalSolution.Args.node = xycoord
        AnalyticalSol = AnalyticalSolution().Get(AnalyticalSolution.Args)

        # AnalyticalSol[:,0] = ElementalSol[:,0]
        # print np.concatenate((AnalyticalSol[:,:2], ElementalSol[:,:2]),axis=1)
        # print

        # print points
        # print points[elements[elem,:],:]
        # print AnalyticalSol

        # ALLOCATE
        nvarBasis = np.zeros((Domain.Bases.shape[0],nvar))
        ElementalSolGauss  = np.zeros((Domain.AllGauss.shape[0],nvar)); AnalyticalSolGauss  = np.copy(ElementalSolGauss)
        dElementalSolGauss = np.zeros((Domain.AllGauss.shape[0],nvar)); dAnalyticalSolGauss = np.copy(ElementalSolGauss)
        # LOOP OVER GAUSS POINTS
        for counter in range(0,Domain.AllGauss.shape[0]):
            # GET THE NUMERICAL SOLUTION WITHIN THE ELEMENT (AT QUADRATURE POINTS)
            ElementalSolGauss[counter,:] = np.dot(Domain.Bases[:,counter].reshape(1,nodeperelem),ElementalSol)
            # GET THE ANALYTICAL SOLUTION WITHIN THE ELEMENT (AT QUADRATURE POINTS)
            AnalyticalSolution.Args.node = np.dot(Domain.Bases[:,counter],xycoord)
            AnalyticalSolGauss[counter,:] = AnalyticalSolution().Get(AnalyticalSolution.Args)

            # print AnalyticalSolGauss, ElementalSolGauss[:,0]
            # AnalyticalSolGauss[:,0] = ElementalSolGauss[:,0] # REMOVE
            # AnalyticalSolGauss[:,1] = ElementalSolGauss[:,1] # REMOVE
            # print np.concatenate((AnalyticalSolGauss[:,:2], ElementalSolGauss[:,:2]),axis=1)#, AnalyticalSolution.Args.node
            # print 
            # GRADIENT TENSOR IN PARENT ELEMENT [\nabla_\varepsilon (N)]
            Jm = Domain.Jm[:,:,counter]
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientX=np.dot(Jm,xycoord) #
            # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
            MaterialGradient = np.dot(la.inv(ParentGradientX),Jm)
            # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
            # F = np.dot(EulerELemCoords.T,MaterialGradient.T)
            F = np.eye(ndim,ndim)
            # COMPUTE REMAINING KINEMATIC MEASURES
            StrainTensors = KinematicMeasures(F).Compute()
            # UPDATE/NO-UPDATE GEOMETRY
            if MainData.GeometryUpdate:
                # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
                ParentGradientx=np.dot(Jm,EulerELemCoords)
                # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
                SpatialGradient = np.dot(la.inv(ParentGradientx),Jm).T
            else:
                SpatialGradient = MaterialGradient.T

            # SPATIAL ELECTRIC FIELD
            ElectricFieldx = - np.dot(SpatialGradient.T,ElementalSol[:,ndim])
            # COMPUTE SPATIAL ELECTRIC DISPLACEMENT
            ElectricDisplacementx = MainData.ElectricDisplacementx(MaterialArgs,StrainTensors,ElectricFieldx)
            # COMPUTE CAUCHY STRESS TENSOR
            CauchyStressTensor = MainData.CauchyStress(MaterialArgs,StrainTensors,ElectricFieldx)
            # COMPUTE THE HESSIAN AT THIS GAUSS POINT
            H_Voigt = MainData.Hessian(MaterialArgs,ndim,StrainTensors,ElectricFieldx)
            # COMPUTE THE TANGENT STIFFNESS MATRIX
            BDB_1, t = MainData().ConstitutiveStiffnessIntegrand(Domain,B,MaterialGradient,nvar,SpatialGradient,
                ndim,CauchyStressTensor,ElectricDisplacementx,MaterialArgs,H_Voigt)

            # L2 NORM
            L2_nom   += np.linalg.norm((AnalyticalSolGauss - ElementalSolGauss)**2)*Domain.AllGauss[counter,0]
            L2_denom += np.linalg.norm((AnalyticalSolGauss)**2)*Domain.AllGauss[counter,0]

            # ENERGY NORM
            DiffSol = (AnalyticalSol - ElementalSol).reshape(ElementalSol.shape[0]*ElementalSol.shape[1],1)
            E_nom   += np.linalg.norm(DiffSol**2)*Domain.AllGauss[counter,0]
            E_denom += np.linalg.norm(AnalyticalSol.reshape(AnalyticalSol.shape[0]*AnalyticalSol.shape[1],1)**2)*Domain.AllGauss[counter,0]

    L2Norm = np.sqrt(L2_nom)/np.sqrt(L2_denom)
    EnergyNorm = np.sqrt(E_nom)/np.sqrt(E_denom)
    print(L2Norm, EnergyNorm)
    return L2Norm, EnergyNorm
コード例 #10
0
    def GetLocalStiffness(self,
                          function_space,
                          material,
                          LagrangeElemCoords,
                          EulerELemCoords,
                          fem_solver,
                          elem=0):
        """Get stiffness matrix of the system"""

        nvar = self.nvar
        ndim = self.ndim
        nodeperelem = function_space.Bases.shape[0]

        det = np.linalg.det
        inv = np.linalg.inv
        Jm = function_space.Jm
        AllGauss = function_space.AllGauss

        # ALLOCATE
        stiffness = np.zeros((nodeperelem * nvar, nodeperelem * nvar),
                             dtype=np.float64)
        tractionforce = np.zeros((nodeperelem * nvar, 1), dtype=np.float64)
        B = np.zeros((nodeperelem * nvar, material.H_VoigtSize),
                     dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # UPDATE/NO-UPDATE GEOMETRY
        if fem_solver.requires_geometry_update:
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientx = np.einsum('ijk,jl->kil', Jm, EulerELemCoords)
            # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
            SpatialGradient = np.einsum('ijk,kli->ilj', inv(ParentGradientx),
                                        Jm)
            # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
            detJ = np.einsum('i,i,i->i', AllGauss[:, 0],
                             np.abs(det(ParentGradientX)),
                             np.abs(StrainTensors['J']))
        else:
            # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
            SpatialGradient = np.einsum('ikj', MaterialGradient)
            # COMPUTE ONCE detJ
            detJ = np.einsum('i,i->i', AllGauss[:, 0],
                             np.abs(det(ParentGradientX)))

        # COMPUTE PARAMETERS FOR MEAN DILATATION METHOD, IT NEEDS TO BE BEFORE COMPUTE HESSIAN AND STRESS
        if material.is_nearly_incompressible:
            dV = np.einsum('i,i->i', AllGauss[:, 0],
                           np.abs(det(ParentGradientX)))
            stiffness_k = self.VolumetricStiffnessIntegrand(
                material, SpatialGradient, detJ, dV)
            stiffness += stiffness_k

        # LOOP OVER GAUSS POINTS
        for counter in range(AllGauss.shape[0]):

            # COMPUTE THE HESSIAN AT THIS GAUSS POINT
            H_Voigt = material.Hessian(StrainTensors, None, elem, counter)

            # COMPUTE CAUCHY STRESS TENSOR
            CauchyStressTensor = []
            if fem_solver.requires_geometry_update:
                CauchyStressTensor = material.CauchyStress(
                    StrainTensors, None, elem, counter)

            # COMPUTE THE TANGENT STIFFNESS MATRIX
            BDB_1, t = self.ConstitutiveStiffnessIntegrand(
                B,
                SpatialGradient[counter, :, :],
                CauchyStressTensor,
                H_Voigt,
                requires_geometry_update=fem_solver.requires_geometry_update)

            # COMPUTE GEOMETRIC STIFFNESS MATRIX
            if material.nature != "linear":
                BDB_1 += self.GeometricStiffnessIntegrand(
                    SpatialGradient[counter, :, :], CauchyStressTensor)
            # INTEGRATE TRACTION FORCE
            if fem_solver.requires_geometry_update:
                tractionforce += t * detJ[counter]

            # INTEGRATE STIFFNESS
            stiffness += BDB_1 * detJ[counter]

        return stiffness, tractionforce
コード例 #11
0
        AllGauss = function_space.AllGauss

        # ALLOCATE
        tractionforce = np.zeros((nodeperelem*nvar,1),dtype=np.float64)
        B = np.zeros((nodeperelem*nvar,material.H_VoigtSize),dtype=np.float64)

        # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP)
        # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
        ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords)
        # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)]
        MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm)
        # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)]
        F = np.einsum('ij,kli->kjl', EulerELemCoords, MaterialGradient)

        # COMPUTE REMAINING KINEMATIC MEASURES
        StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature)

        # UPDATE/NO-UPDATE GEOMETRY
        if fem_solver.requires_geometry_update:
            # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)]
            ParentGradientx = np.einsum('ijk,jl->kil',Jm,EulerELemCoords)
            # SPATIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla (N)]
            SpatialGradient = np.einsum('ijk,kli->ilj',inv(ParentGradientx),Jm)
            # COMPUTE ONCE detJ (GOOD SPEEDUP COMPARED TO COMPUTING TWICE)
            detJ = np.einsum('i,i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)),np.abs(StrainTensors['J']))
        else:
            # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL
            SpatialGradient = np.einsum('ikj',MaterialGradient)
            # COMPUTE ONCE detJ
            detJ = np.einsum('i,i->i',AllGauss[:,0],np.abs(det(ParentGradientX)))