コード例 #1
0
ファイル: AssemblyPGD.py プロジェクト: pruliere/simple_FE
    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
コード例 #2
0
 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
コード例 #3
0
ファイル: LocalFrame.py プロジェクト: 3MAH/fedoo
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
コード例 #4
0
ファイル: AssemblyPGD.py プロジェクト: pruliere/simple_FE
    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))
        ])
コード例 #5
0
ファイル: AssemblyPGD.py プロジェクト: pruliere/simple_FE
    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)