#la fonction auxiliary_problem calcule les A locaux : l'argument principal est C_list, la liste des tenseurs d'élasticité, et la fonction renvoie Aloc, un tableau à trois dimensions. Aloc[i] correspond à la moyenne du tenseur de localisation sur la case i, calculé par homogénéisation périodique
defauxiliary_problem(C_list,n,gamma,K):
M=np.array([[0.foriinrange(12)]forjinrange(12)])
foriinrange(4):
S=np.linalg.inv(C_list[i]-K)
forkinrange(3):
forlinrange(3):
M[i*3+l,3*i+k]=S[l,k]
gamma_=gamma[n-1]
T=np.linalg.inv(M-gamma_)
Chom=np.array([[1.,0.,0.],
[0.,1.,0.],
[0.,0.,1.]])
MT_=np.array([[0.,0.,0.],
[0.,0.,0.],
[0.,0.,0.]])
T_=np.array([[0.,0.,0.],
[0.,0.,0.],
[0.,0.,0.]])
E=np.array([np.array([[0.,0.,0.],
[0.,0.,0.],
[0.,0.,0.]])foriinrange(4)])
MT=np.dot(M,T)
forkinrange(3):
forlinrange(3):
forjinrange(4):
foriinrange(4):
E[i,l,k]+=MT[3*i+l,3*j+k]
T_[l,k]+=0.25*T[3*i+l,3*j+k]
MT_[l,k]+=0.25*MT[3*i+l,3*j+k]
foriinrange(4):
E[i]=np.dot(E[i],np.linalg.inv(MT_))
Chom=K+np.dot(T_,np.linalg.inv(MT_))
returnChom,E
#la fonction tC prend en argument un tableau de type tCA et renvoie le tableau de tenseurs d'élasticité qui sera celui de l'étape d'après
#la fonction Chom prend en argument le tableau initial tC0 des tenseurs d'élasticité associés à la grille image de taille n, et appelle les fonctions décrites plus haut pour calculer les nouveaux tableaux de tenseurs d'élasticité associés à chaque étape. La fonction enregistre ces tableaux à chaque étape dans un fichier. Le nombre d'étapes 'e' doit être précisé pour des méthodes 10 ou 11.
#cf 'Contenu des fichiers' à propos de 'reference'
defreference(tabC,res1,c,ec,fr):
#res=256
k,ll,mm,nn=tabC.shape
mesh=UnitSquareMesh(res1,res1,"crossed")
classLocalC(UserExpression):
def__init__(self,Cij,mesh):
self.Cij=Cij
self.Nx,self.Ny,a,b=Cij.shape
asserta==3andb==3,"Wrong shape"
self.mesh=mesh
UserExpression.__init__(self)
defeval_cell(self,value,x,ufc_cell):
p=Cell(mesh,ufc_cell.index).midpoint()
i,j=int(p[0]*(self.Nx)),int(p[1]*(self.Ny))
value[:]=self.Cij[j,i,:,:].flatten()
defvalue_shape(self):
return(3,3)
#Ici on crée, à partir du tableau des tenseurs d'élasticité correspondant au domaine dont on veut calculer le Chom, un tableau Cv représentant le même Cn mais adapté à une résolution plus fine 'res'
# Cv = np.array([[np.zeros((3,3)) for i in range(res)] for j in range(res)])
# for i0 in range(k):
# for j0 in range(k):
# for i in range(int(i0*res/k),int((i0+1)*res/k)):
# for j in range (int(j0*res/k),int((j0+1)*res/k)):
# Cv[i,j]=tabC[i0,j0]
# plt.imshow(tabC[:,:,0,0])
# plt.show()
# plt.close()
# plt.imshow(Cv[:,:,0,0])
# plt.show()
# plt.close()
#Cvar est la transformation du tableau Cv en une fonction définie sur 'mesh'
Cvar=LocalC(tabC,mesh)
# class used to define the periodic boundary map
classPeriodicBoundary(SubDomain):
def__init__(self,vertices,tolerance=DOLFIN_EPS):
""" vertices stores the coordinates of the 4 unit cell corners"""
SubDomain.__init__(self,tolerance)
self.tol=tolerance
self.vv=vertices
self.a1=self.vv[1,:]-self.vv[0,:]# first vector generating periodicity
self.a2=self.vv[3,:]-self.vv[0,:]# second vector generating periodicity
# check if UC vertices form indeed a parallelogram
ifnear(x[0],self.vv[2,0],self.tol)andnear(x[1],self.vv[2,1],self.tol):# if on top-right corner
y[0]=x[0]-(self.a1[0]+self.a2[0])
y[1]=x[1]-(self.a1[1]+self.a2[1])
elifnear(x[0],self.vv[1,0]+x[1]*self.a2[0]/self.vv[2,1],self.tol):# if on right boundary
y[0]=x[0]-self.a1[0]
y[1]=x[1]-self.a1[1]
else:# should be on top boundary
y[0]=x[0]-self.a2[0]
y[1]=x[1]-self.a2[1]
#la fonction reference_problem prend en argument C, donnant le tenseur d'élasticité en un point de 'mesh', et renvoie le Chom du domaine. k étant le nombre de phases différentes sur le domaine, qui correspond à la taille du tableau Cn pris en argument par la fonction 'reference'