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 dot(self, FF): if self.data == []: return 0 if isinstance(FF, SeparatedArray): if FF.dim == self.GetDimension(): ntA = self.NumberOfOperators() nf = FF.nbTerm() CC = [ sp.c_[sp.zeros((self.GetShapeRow(dd), ntA * nf))] for dd in range(self.GetDimension()) ] colone = 0 for kk in range(ntA): for dd in range(self.GetDimension()): CC[dd][:, colone:colone + nf] = self.data[kk][dd] * FF.data[dd] colone += nf else: raise NameError('Dimensions doesnt match') return SeparatedArray(CC) elif isinstance(FF, Number): if FF == 0: return 0 new_op = SeparatedOperator(self) ntA = new_op.NumberOfOperators() for kk in range(ntA): new_op.data[kk][0] *= FF return new_op else: return NotImplemented
def SeparatedLocalFrame(localFrame, mesh, dimensions=('X', 'Y', 'Z')): """ Permit to automatically assign the localFrame to the appropriate submesh of the mesh object Generate a local frame under the form of the (3,3) shaped array dedicated of SeparatedArray objects This functions work only if the local frame is restricted to one subspace. """ dim = localFrame.shape[-1] idmesh = mesh.FindCoordinateID(dimensions[0]) if idmesh != mesh.FindCoordinateID(dimensions[1]): raise NameError( "'{}' and '{}' coordinates should be associated to the same subMesh" .format(dimensions[0], dimensions[1])) if dim == 3: if idmesh != mesh.FindCoordinateID(dimensions[3]): raise NameError( "'{}' and '{}' coordinates should be associated to the same subMesh. Consider using a 2D local frame." .format(dimensions[0], dimensions[2])) id_crd = [] for label in dimensions: if label == 'X': id_crd.append(0) elif label == 'Y': id_crd.append(1) elif label == 'Z': id_crd.append(2) else: raise NameError( "Coordinates for local frame should be 'X', 'Y' or 'Z'. '{}' unknown." .format(label)) newLocalFrame = np.zeros( (3, 3), dtype=object) #the resulting local frame is always in dim = 3 for j in range(dim): for i in range(dim): newLocalFrame[i, id_crd[j]] = SeparatedArray([ np.c_[localFrame[:, i, j]] if k == idmesh else np.array([[1.]]) for k in range(mesh.GetDimension()) ]) return newLocalFrame
def GetElementResult(self, operator, U): """ Not a Static Method. Return some element results based on the finite element discretization of a differential operator on a mesh being given the dof results and the type of elements. Parameters ---------- mesh: string or Mesh If mesh is a string, it should be a meshID. Define the mesh to get the results from operator: OpDiff Differential operator defining the required results U: numpy.ndarray Vector containing all the DoF solution Return: numpy.ndarray A Vector containing the values on each element. It is computed using an arithmetic mean of the values from gauss points The vector lenght is the number of element in the mesh """ list_nb_elm = self.__Mesh.GetNumberOfElements() res = AssemblyPGD.__GetResultGaussPoints( self.__Mesh, operator, U, self.__listElementType, self.__listNumberOfGaussPoints) NumberOfGaussPoint = [ res.data[dd].shape[0] // list_nb_elm[dd] for dd in range(len(res)) ] return SeparatedArray([ np.reshape(res.data[dd], (NumberOfGaussPoint[dd], list_nb_elm[dd], -1)).sum(0) / NumberOfGaussPoint[dd] for dd in range(len(res)) ])
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)