# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
from typing import Optional
import numpy as np
from sympy import Symbol, DiracDelta, Matrix
from sympy.utilities.lambdify import lambdify
from BasicTools.FE.Spaces.SpaceBase import SpaceBase, SpaceAtIntegrationPoints
[docs]class SymSpaceBase(SpaceBase):
def __init__(self):
super(SymSpaceBase,self).__init__()
#----symbolic part use Create() to pass to the next step ------------
self.xi = Symbol("xi")
self.eta = Symbol("eta")
self.phi = Symbol("phi")
self.symN = None
self.symdNdxi = None
self.__created__ = False
def __getstate__(self):
return None
def __setstat__(self,state):
self.__init__()
[docs] def GetNumberOfShapeFunctions(self):
return len(self.symN)
[docs] def Created(self):
return self.__created__
[docs] def Create(self, force=False):
if self.__created__ and not force:
return
self.__created__ = True
def DiractDeltaNumeric(data,der=None):
if abs(data)>1e-15 :
return 0
else:
return 1
allcoords = (self.xi,self.eta,self.phi)
self.lcoords = tuple( (self.xi,self.eta,self.phi)[x] for x in range(self.GetDimensionality()) )
nbSF = self.GetNumberOfShapeFunctions()
nbDim = self.GetDimensionality()
subsList = [ (DiracDelta(0),1.), (DiracDelta(0,1),1.), (DiracDelta(0,2),1.) ]
lambdifyList = [ {"DiracDelta":DiractDeltaNumeric}, "numpy"]
############# shape function treatement ########################
clean_N = self.symN.subs(subsList)
self.fct_N_Matrix = lambdify(allcoords,[ clean_N[i] for i in range(nbSF) ], lambdifyList )
############# shape functions first derivative #################
self.symdNdxi = [[None]*nbSF for i in range(nbDim)]
for i in range(nbDim ) :
for j in range(nbSF) :
self.symdNdxi[i][j] = self.symN[j].diff(self.lcoords[i])
self.symdNdxi = Matrix(self.symdNdxi)
if self.symdNdxi.shape == (0,0):
self.fct_dNdxi_Matrix = lambda xi,chi,phi: np.empty((0,0))
else:
self.fct_dNdxi_Matrix = lambdify(allcoords,self.symdNdxi.subs(subsList) , lambdifyList )
############ shape functions second derivative ################
self.symdNdxidxi = [ None ]*nbSF
self.fct_dNdxidxi_Matrix = [ None ]*nbSF
for i in range(nbSF) :
self.symdNdxidxi[i] = [[0]*nbDim for j in range(nbDim ) ]
for j in range(nbDim):
for k in range(nbDim):
func = self.symN[i].diff(self.lcoords[j]).diff(self.lcoords[k])
self.symdNdxidxi[i][j][k] = func
self.symdNdxidxi[i] = Matrix(self.symdNdxidxi[i])
self.fct_dNdxidxi_Matrix[i] = lambdify(allcoords,self.symdNdxidxi[i].subs(subsList) , lambdifyList )
#This is not perfect because for P2 spaces we check only the number of shape functions
if np.all([ dof[0]=="P" and nb==dof[1] for nb,dof in enumerate(self.dofAttachments)]) :
self.fromConnectivityCompatible = True
[docs] def SetIntegrationRule(self, points, weights):
self.Create()
res = SpaceAtIntegrationPoints()
res.SetIntegrationRule(self,points,weights)
return res
[docs] def GetPosOfShapeFunction(self,i,Xi):
valN = self.GetShapeFunc(self.posN[i,:])
return np.dot(valN,Xi).T
[docs] def GetShapeFunc_default(self,xi=0,chi=0,phi=0):
return self.fct_N_Matrix(xi,chi,phi)
[docs] def GetShapeFunc(self,qcoor):
return np.asarray(self.GetShapeFunc_default(*qcoor), dtype=float)
[docs] def GetShapeFuncDer_default(self,xi=0,chi=0,phi=0):
return self.fct_dNdxi_Matrix(xi,chi,phi)
[docs] def GetShapeFuncDer(self,qcoor):
return np.asarray(self.GetShapeFuncDer_default(*qcoor), dtype=float)
[docs] def GetShapeFuncDerDer_default(self,xi=0,chi=0,phi=0):
return [ np.asarray(x(xi,chi,phi),dtype=float) for x in self.fct_dNdxidxi_Matrix ]
[docs] def GetShapeFuncDerDer(self,qcoor):
return self.GetShapeFuncDerDer_default(*qcoor)
[docs]def CheckIntegrity():
return "ok"