def __GetResultGaussPoints( mesh, operator, U, list_elementType, list_nb_pg=None): #return the results at GaussPoints res = 0 nvar = [ mesh._GetSpecificNumberOfVariables(idmesh) for idmesh in range(mesh.GetDimension()) ] if list_nb_pg is None: list_nb_pg = [ GetDefaultNbPG(self.__listElementType[dd], self.__Mesh.GetListMesh()[dd]) for dd in range(len(self.__listElementType)) ] for ii in range(len(operator.op)): if isinstance(operator.coef[ii], Number): coef_PG = operator.coef[ii] else: coef_PG = [] res_add = [] for dd, subMesh in enumerate(mesh.GetListMesh()): var = [mesh._GetSpecificVariableRank(dd, operator.op[ii].u)] coef = [1] if 'X' in subMesh.GetCoordinateID( ): #test if the subMesh is related to the spatial coordinates if not (Variable.GetDerivative(operator.op[ii].u) is None): var.append( mesh._GetSpecificVariableRank( dd, Variable.GetDerivative(operator.op[ii].u)[0])) coef.append( Variable.GetDerivative(operator.op[ii].u)[1]) assert operator.op_vir[ ii] == 1, "Operator virtual are only required to build FE operators, but not to get element results" if isinstance(coef_PG, list): coef_PG.append( AssemblyPGD._Assembly__ConvertToGaussPoints( subMesh, operator.coef[ii].data[dd], list_elementType[dd], list_nb_pg[dd])) MatrixChangeOfBasis = AssemblyPGD._Assembly__GetChangeOfBasisMatrix( subMesh, list_elementType[dd], list_nb_pg[dd]) res_add.append( RowBlocMatrix( AssemblyPGD._Assembly__GetElementaryOp( subMesh, operator.op[ii], list_elementType[dd], list_nb_pg[dd]), nvar[dd], var, coef) * MatrixChangeOfBasis * U.data[dd]) if isinstance(coef_PG, list): coef_PG = SeparatedArray(Coef_PG) res = res + coef_PG * SeparatedArray(res_add) return res
def __init__(self, Density, ID = ""): if ID == "": ID = "Inertia" WeakForm.__init__(self,ID) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == "3D": Variable("DispZ") self.__Density = Density
def __init__(self, CurrentConstitutiveLaw, ID=""): if isinstance(CurrentConstitutiveLaw, str): CurrentConstitutiveLaw = ConstitutiveLaw.GetAll( )[CurrentConstitutiveLaw] if ID == "": ID = CurrentConstitutiveLaw.GetID() WeakForm.__init__(self, ID) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == "3D": Variable("DispZ") self.__ConstitutiveLaw = CurrentConstitutiveLaw self.__InitialStressVector = 0
def GetExternalForces(self, U, NumberOfVariable=None): """ Not a static method. Return the nodal Forces and moments in global coordinates related to a specific assembly considering the DOF solution given in U The resulting forces are the sum of : - External forces (associated to Neumann boundary conditions) - Nodal reaction (associated to Dirichelet boundary conditions) - Inertia forces Return a list of separated array [Fx, Fy, Fz, Mx, My, Mz]. example : S = SpecificAssembly.GetNodalForces(PGD.Problem.GetDoFSolution('all')) """ ExtForce = self.GetMatrix() * U if NumberOfVariable == None: return [ ExtForce.GetVariable(var, self.__Mesh) for var in range(Variable.GetNumberOfVariable()) ] else: return [ ExtForce.GetVariable(var, self.__Mesh) for var in range(NumberOfVariable) ]
def __init__(self, Density, ID=""): if ID == "": ID = "Inertia" WeakForm.__init__(self, ID) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == "3D": Variable("DispZ") Variable.SetVector('Disp', ('DispX', 'DispY', 'DispZ')) else: Variable.SetVector('Disp', ('DispX', 'DispY')) self.__Density = Density
def _GetSpecificNumberOfVariables(self, idmesh): assert isinstance( idmesh, int), 'idmesh must an integer, not a ' + str(type(idmesh)) if idmesh in self.__SpecificVariableRank: return max(self.__SpecificVariableRank[idmesh].values()) + 1 else: return Variable.GetNumberOfVariable()
def __init__(self, u, x=0, ordre=0, decentrement=0, vir=0): self.mesh = None if isinstance(u, str): u = Variable.GetRank(u) if isinstance(x, str): x = Coordinate.GetRank(x) if isinstance(u, int): self.coef = [1] if vir == 0: self.op = [OpDerive(u, x, ordre, decentrement)] self.op_vir = [1] else: self.op_vir = [OpDerive(u, x, ordre, decentrement)] self.op = [1] elif isinstance(u, list) and isinstance(x, list) and isinstance( ordre, list): self.op = u self.op_vir = x self.coef = ordre else: raise NameError('Argument error')
def __init__(self, CurrentConstitutiveLaw, Section, Jx, Iyy, Izz, k=0, ID = ""): #k: shear shape factor if isinstance(CurrentConstitutiveLaw, str): CurrentConstitutiveLaw = ConstitutiveLaw.GetAll()[CurrentConstitutiveLaw] if ID == "": ID = CurrentConstitutiveLaw.GetID() WeakForm.__init__(self,ID) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == '3D': Variable("DispZ") Variable("RotX") #torsion rotation Variable("RotY") Variable("RotZ") Variable.SetVector('Disp' , ('DispX', 'DispY', 'DispZ') , 'global') Variable.SetVector('Rot' , ('RotX', 'RotY', 'RotZ') , 'global') elif ProblemDimension.Get() == '2Dplane': Variable("RotZ") Variable.SetVector('Disp' , ['DispX', 'DispY'], 'global' ) Variable.SetVector('Rot' , ['RotZ'] ) elif ProblemDimension.Get() == '2Dstress': assert 0, "No 2Dstress model for a beam kinematic. Choose '2Dplane' instead." self.__ConstitutiveLaw = CurrentConstitutiveLaw self.__parameters = {'Section': Section, 'Jx': Jx, 'Iyy':Iyy, 'Izz':Izz, 'k':k}
def __init__(self, CurrentConstitutiveLaw, ID="", nlgeom=False): if isinstance(CurrentConstitutiveLaw, str): CurrentConstitutiveLaw = ConstitutiveLaw.GetAll( )[CurrentConstitutiveLaw] if ID == "": ID = CurrentConstitutiveLaw.GetID() WeakForm.__init__(self, ID) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == "3D": Variable("DispZ") Variable.SetVector('Disp', ('DispX', 'DispY', 'DispZ')) else: #2D assumed Variable.SetVector('Disp', ('DispX', 'DispY')) self.__ConstitutiveLaw = CurrentConstitutiveLaw self.__InitialStressTensor = 0 self.__InitialGradDispTensor = None self.__nlgeom = nlgeom #geometric non linearities if nlgeom: if ProblemDimension.Get() == "3D": GradOperator = [[ OpDiff(IDvar, IDcoord, 1) for IDcoord in ['X', 'Y', 'Z'] ] for IDvar in ['DispX', 'DispY', 'DispZ']] #NonLinearStrainOperatorVirtual = 0.5*(vir(duk/dxi) * duk/dxj + duk/dxi * vir(duk/dxj)) using voigt notation and with a 2 factor on non diagonal terms NonLinearStrainOperatorVirtual = [ sum([ GradOperator[k][i].virtual() * GradOperator[k][i] for k in range(3) ]) for i in range(3) ] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][0].virtual() * GradOperator[k][1] + GradOperator[k][1].virtual() * GradOperator[k][0] for k in range(3) ]) ] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][0].virtual() * GradOperator[k][2] + GradOperator[k][2].virtual() * GradOperator[k][0] for k in range(3) ]) ] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][1].virtual() * GradOperator[k][2] + GradOperator[k][2].virtual() * GradOperator[k][1] for k in range(3) ]) ] else: GradOperator = [[ OpDiff(IDvar, IDcoord, 1) for IDcoord in ['X', 'Y'] ] for IDvar in ['DispX', 'DispY']] NonLinearStrainOperatorVirtual = [ sum([ GradOperator[k][i].virtual() * GradOperator[k][i] for k in range(2) ]) for i in range(2) ] + [0] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][0].virtual() * GradOperator[k][1] + GradOperator[k][1].virtual() * GradOperator[k][0] for k in range(2) ]) ] + [0, 0] self.__NonLinearStrainOperatorVirtual = NonLinearStrainOperatorVirtual else: self.__NonLinearStrainOperatorVirtual = 0
def __init__(self, E=None, nu = None, S=None, Jx=None, Iyy=None, Izz = None, R = None, k=0, ID = ""): """ Weak formulation dedicated to treat parametric problems using Bernoulli beams for isotropic materials Arugments ---------- ID: str ID of the weak formulation List of other optional parameters E: Young Modulus nu: Poisson Ratio S: Section area Jx: Torsion constant Iyy, Izz: Second moment of area, if Izz is not specified, Iyy = Izz is assumed k is a scalar. k=0 for no shear effect. For other values, k is the shear area coefficient When the differntial operator is generated (using PGD.Assembly) the parameters are searched among the CoordinateID defining the associated mesh. If a parameter is not found , a Numeric value should be specified in argument. In the particular case of cylindrical beam, the radius R can be specified instead of S, Jx, Iyy and Izz. S = pi * R**2 Jx = pi * R**4/2 Iyy = Izz = pi * R**4/4 """ WeakForm.__init__(self,ID) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == '3D': Variable("DispZ") Variable("RotX") #torsion rotation Variable('RotY') Variable('RotZ') # Variable.SetDerivative('DispZ', 'RotY', sign = -1) #only valid with Bernoulli model # Variable.SetDerivative('DispY', 'RotZ') #only valid with Bernoulli model Variable.SetVector('Disp' , ('DispX', 'DispY', 'DispZ') , 'global') Variable.SetVector('Rot' , ('RotX', 'RotY', 'RotZ') , 'global') elif ProblemDimension.Get() == '2Dplane': Variable('RotZ') Variable.SetVector('Disp' , ('DispX', 'DispY'), 'global' ) Variable.SetVector('Rot' , ('RotZ')) elif ProblemDimension.Get() == '2Dstress': assert 0, "No 2Dstress model for a beam kinematic. Choose '2Dplane' instead." if R is not None: S = np.pi * R**2 Jx = np.pi * R**4/2 Iyy = Izz = np.pi * R**4/4 self.__parameters = {'E':E, 'nu':nu, 'S':S, 'Jx':Jx, 'Iyy':Iyy, 'Izz':Izz, 'k':k}
def ComputeGlobalMatrix(self): mesh = self.__Mesh dim = mesh.GetDimension() wf = self.__weakForm.GetDifferentialOperator(mesh) nvar = [ mesh._GetSpecificNumberOfVariables(idmesh) for idmesh in range(dim) ] AA = [] BB = 0 for ii in range(len(wf.op)): if wf.op[ ii] == 1: #only virtual operator -> compute a separated array BBadd = [] else: #virtual and real operators -> compute a separated operator if isinstance(wf.coef[ii], SeparatedArray): nb_term_coef = wf.coef[ii].nbTerm() AA += [[] for term in range(nb_term_coef)] else: AA.append([]) for dd, subMesh in enumerate(mesh.GetListMesh()): elmType = self.__listElementType[dd] nb_pg = self.__listNumberOfGaussPoints[dd] MatGaussianQuadrature = AssemblyPGD._Assembly__GetGaussianQuadratureMatrix( subMesh, elmType, nb_pg) MatrixChangeOfBasis = AssemblyPGD._Assembly__GetChangeOfBasisMatrix( subMesh) coef_vir = [1] var_vir = [mesh._GetSpecificVariableRank(dd, wf.op_vir[ii].u) ] #list in case there is an angular variable if 'X' in subMesh.GetCoordinateID( ): #test if the subMesh is related to the spatial coordinates (Variable derivative are only for spatial derivative in beam or shell models) if not (Variable.GetDerivative(wf.op_vir[ii].u) is None): var_vir.append( mesh._GetSpecificVariableRank( dd, Variable.GetDerivative(wf.op_vir[ii].u)[0])) coef_vir.append( Variable.GetDerivative(wf.op_vir[ii].u)[1]) Matvir = (RowBlocMatrix( AssemblyPGD._Assembly__GetElementaryOp( subMesh, wf.op_vir[ii], elmType, nb_pg), nvar[dd], var_vir, coef_vir) * MatrixChangeOfBasis).T if wf.op[ ii] == 1: #only virtual operator -> compute a separated array if isinstance( wf.coef[ii], (Number, np.floating)): #and self.op_vir[ii] != 1: if dd == 0: BBadd.append( wf.coef[ii] * Matvir * MatGaussianQuadrature.data.reshape(-1, 1)) else: BBadd.append( Matvir * MatGaussianQuadrature.data.reshape(-1, 1)) elif isinstance(wf.coef[ii], SeparatedArray): coef_PG = AssemblyPGD._Assembly__ConvertToGaussPoints( subMesh, wf.coef[ii].data[dd], elmType, nb_pg) BBadd.append( Matvir * (MatGaussianQuadrature.data.reshape(-1, 1) * coef_PG)) else: #virtual and real operators -> compute a separated operator coef = [1] var = [mesh._GetSpecificVariableRank(dd, wf.op[ii].u) ] #list in case there is an angular variable if 'X' in subMesh.GetCoordinateID( ): #test if the subMesh is related to the spatial coordinates (Variable derivative are only for spatial derivative in beam or shell models) if not (Variable.GetDerivative(wf.op[ii].u) is None): var.append( mesh._GetSpecificVariableRank( dd, Variable.GetDerivative(wf.op[ii].u)[0])) coef.append(Variable.GetDerivative(wf.op[ii].u)[1]) Mat = RowBlocMatrix( AssemblyPGD._Assembly__GetElementaryOp( subMesh, wf.op[ii], elmType, nb_pg), nvar[dd], var, coef) * MatrixChangeOfBasis if isinstance( wf.coef[ii], (Number, np.floating)): #and self.op_vir[ii] != 1: if dd == 0: AA[-1].append(wf.coef[ii] * Matvir * MatGaussianQuadrature * Mat) else: AA[-1].append(Matvir * MatGaussianQuadrature * Mat) elif isinstance(wf.coef[ii], SeparatedArray): coef_PG = AssemblyPGD._Assembly__ConvertToGaussPoints( subMesh, wf.coef[ii].data[dd], elmType, nb_pg) for kk in range(nb_term_coef): #CoefMatrix is a diag matrix that includes the gaussian quadrature coefficients and the value of wf.coef at gauss points CoefMatrix = sparse.csr_matrix( (MatGaussianQuadrature.data * coef_PG[:, kk], MatGaussianQuadrature.indices, MatGaussianQuadrature.indptr), shape=MatGaussianQuadrature.shape) AA[-nb_term_coef + kk].append(Matvir * CoefMatrix * Mat) if wf.op[ii] == 1: BB = BB - SeparatedArray(BBadd) if AA == []: self.SetMatrix(0) else: self.SetMatrix(SeparatedOperator(AA)) self.SetVector(BB)
def __init__(self, InitialStressTensor=0, ID=""): if ID == "": ID = "InitialStress" WeakForm.__init__(self, ID) if InitialStressTensor == 0: InitialStressTensor = [ 0, 0, 0, 0, 0, 0 ] #list of the six stress component (sig_xx, sig_yy, sig_zz, sig_yz, sig_xz, sigxy) Variable("DispX") Variable("DispY") if ProblemDimension.Get() == "3D": Variable("DispZ") if ProblemDimension.Get() == "3D": GradOperator = [[ OpDiff(IDvar, IDcoord, 1) for IDcoord in ['X', 'Y', 'Z'] ] for IDvar in ['DispX', 'DispY', 'DispZ']] #NonLinearStrainOperatorVirtual = 0.5*(vir(duk/dxi) * duk/dxj + duk/dxi * vir(duk/dxj)) using voigt notation and with a 2 factor on non diagonal terms NonLinearStrainOperatorVirtual = [ sum([ GradOperator[k][i].virtual() * GradOperator[k][i] for k in range(3) ]) for i in range(3) ] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][1].virtual() * GradOperator[k][2] + GradOperator[k][2].virtual() * GradOperator[k][1] for k in range(3) ]) ] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][0].virtual() * GradOperator[k][2] + GradOperator[k][2].virtual() * GradOperator[k][0] for k in range(3) ]) ] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][0].virtual() * GradOperator[k][1] + GradOperator[k][1].virtual() * GradOperator[k][0] for k in range(3) ]) ] else: GradOperator = [[ Util.OpDiff(IDvar, IDcoord, 1) for IDcoord in ['X', 'Y'] ] for IDvar in ['DispX', 'DispY']] NonLinearStrainOperatorVirtual = [ sum([ GradOperator[k][i].virtual() * GradOperator[k][i] for k in range(2) ]) for i in range(2) ] + [0, 0, 0] NonLinearStrainOperatorVirtual += [ sum([ GradOperator[k][0].virtual() * GradOperator[k][1] + GradOperator[k][1].virtual() * GradOperator[k][0] for k in range(2) ]) ] self.__NonLinearStrainOperatorVirtual = NonLinearStrainOperatorVirtual self.__InitialStressTensor = InitialStressTensor self.__typeOperator = 'all'