def solve(self, damp=.2, dynRelax=False): """ solve the equation of motion in centeral difference scheme """ # get initial coordinate x = self.getDomain().getX() # density matrix kron = util.kronecker(self.getDomain().getDim()) rho = self.__rho * kron # stress at (n) time step stress_last = self.getCurrentStress() # set coefficients for ODE self.__pde.setValue(D=rho) self.setRHS(X=-stress_last) # solve acceleration at (n) time step from ODE u_tt = self.__pde.getSolution() # update velocity at (n+1/2) time step self.__u_t = 1. / (2. + damp * self.__dt) * ( (2. - damp * self.__dt) * self.__u_t + 2. * self.__dt * u_tt) # get displacement increment du = self.__dt * self.__u_t # update strain D = util.grad(du) self.__strain += D # update displacement and domain geometry at (n+1) time step self.__u += du self.__domain.setX(x + du) # !!!!!! apply displacement increment and get boundary force from DE exterior domain, if any if self.__FEDENodeMap: DEdu = self.getBoundaryDisplacement(du) """ # apply boundary velocity and get boundary traction (deprecated) self.__Nbc,self.__sceneExt=self.applyDisplIncrement_getTractionDEM(DEdu=DEdu) """ # apply boundary velocity and return an asynResult object arFEfAndSceneExt = self.applyDisplIncrement_getForceDEM( DEdu=DEdu, dynRelax=dynRelax) # !!!!!! update stress and scenes from DEM part using strain at (n+1) time step self.__stress, self.__scenes = self.applyStrain_getStressDEM( st=D, dynRelax=dynRelax) """ # !!!!!! update scenes and return asynResult objects (deprecated) arScenes = self.applyStrain(st=D) # !!!!!! retrieve data from asyncResults # update interior DE scenes self.__scenes = arScenes.get() # assign new stresses to gauss points from interior DE scenes s = self.__pool.map(getStress2D,self.__scenes) for i in xrange(self.__numGaussPoints): self.__stress.setValueOfDataPoint(i,s[i]) """ # if exterior DE domain is given, update scene and boundary force if self.__FEDENodeMap: self.__FEf, self.__sceneExt = arFEfAndSceneExt.get() return self.__u, self.__u_t
def solve(self,damp=.2,dynRelax=False): """ solve the equation of motion in centeral difference scheme """ # get initial coordinate x = self.getDomain().getX() # density matrix kron = util.kronecker(self.getDomain().getDim()) rho = self.__rho*kron # stress at (n) time step stress_last = self.getCurrentStress() # set coefficients for ODE self.__pde.setValue(D=rho) self.setRHS(X=-stress_last) # solve acceleration at (n) time step from ODE u_tt = self.__pde.getSolution() # update velocity at (n+1/2) time step self.__u_t = 1./(2.+damp*self.__dt)*((2.-damp*self.__dt)*self.__u_t + 2.*self.__dt*u_tt) # get displacement increment du = self.__dt*self.__u_t # update strain D = util.grad(du) self.__strain += D # update displacement and domain geometry at (n+1) time step self.__u += du self.__domain.setX(x+du) # !!!!!! apply displacement increment and get boundary force from DE exterior domain, if any if self.__FEDENodeMap: DEdu = self.getBoundaryDisplacement(du) """ # apply boundary velocity and get boundary traction (deprecated) self.__Nbc,self.__sceneExt=self.applyDisplIncrement_getTractionDEM(DEdu=DEdu) """ # apply boundary velocity and return an asynResult object arFEfAndSceneExt=self.applyDisplIncrement_getForceDEM(DEdu=DEdu,dynRelax=dynRelax) # !!!!!! update stress and scenes from DEM part using strain at (n+1) time step self.__stress,self.__scenes = self.applyStrain_getStressDEM(st=D,dynRelax=dynRelax) """ # !!!!!! update scenes and return asynResult objects (deprecated) arScenes = self.applyStrain(st=D) # !!!!!! retrieve data from asyncResults # update interior DE scenes self.__scenes = arScenes.get() # assign new stresses to gauss points from interior DE scenes s = self.__pool.map(getStress2D,self.__scenes) for i in xrange(self.__numGaussPoints): self.__stress.setValueOfDataPoint(i,s[i]) """ # if exterior DE domain is given, update scene and boundary force if self.__FEDENodeMap: self.__FEf,self.__sceneExt = arFEfAndSceneExt.get() return self.__u, self.__u_t
def solve(self, globalIter=10, solidIter=50): """ solve the coupled PDE using fixed-stress split method, call solveSolid to get displacement """ rtol = self.__rtol x_safe = self.__domain.getX() k = util.kronecker(self.__domain) kdr = util.inner(k, util.tensor_mult(self.__S, k)) / 4. n = self.getEquivalentPorosity() perm = self.__permeability * n**3 / (1. - n)**2 * k kf = self.__bulkFluid dt = self.__dt self.__ppde.setValue(A=perm, D=(n / kf + 1. / kdr) / dt, Y=(n / kf + 1. / kdr) / dt * self.__pgauss - self.__meanStressRate / kdr) p_iter_old = self.__ppde.getSolution() p_iter_gauss = util.interpolate(p_iter_old, escript.Function(self.__domain)) u_old, D, sig, s, scene = self.solveSolid(p_iter_gauss=p_iter_gauss, iter_max=solidIter) converge = False iterate = 0 while (not converge) and (iterate < globalIter): iterate += 1 self.__ppde.setValue(Y=n / kf / dt * self.__pgauss + 1. / kdr / dt * p_iter_gauss - util.trace(D) / dt) p_iter = self.__ppde.getSolution() p_err = util.L2(p_iter - p_iter_old) / util.L2(p_iter) p_iter_old = p_iter p_iter_gauss = util.interpolate(p_iter, escript.Function(self.__domain)) u, D, sig, s, scene = self.solveSolid(p_iter_gauss=p_iter_gauss, iter_max=solidIter) u_err = util.L2(u - u_old) / util.L2(u) u_old = u converge = (u_err <= rtol and p_err <= rtol * .1) self.__meanStressRate = (util.trace(sig - self.__stress) / 2. - p_iter_gauss + self.__pgauss) / dt self.__pore = p_iter_old self.__pgauss = p_iter_gauss self.__domain.setX(x_safe + u_old) self.__strain += D self.__stress = sig self.__S = s self.__scenes = scene return u_old
def solveSolid(self, p_iter_gauss=escript.Data(), iter_max=50): """ solve the pde for displacement using Newton-Ralphson scheme """ k = util.kronecker(self.__domain) p = p_iter_gauss * k iterate = 0 rtol = self.__rtol stress_safe = self.__stress s_safe = self.__S x_safe = self.__domain.getX() self.__upde.setValue(A=s_safe, X=-stress_safe + p, r=self.__r) #residual0=util.L2(self.__pde.getRightHandSide()) # using force error u = self.__upde.getSolution() # trial solution, displacement D = util.grad(u) # trial strain tensor # !!!!!! obtain stress and tangent operator from DEM part update_stress, update_s, update_scenes = self.applyStrain_getStressTangentDEM( st=D) err = util.Lsup(u) # initial error before iteration converged = (err < 1.e-12) while (not converged) and (iterate < iter_max): #if iterate>iter_max: # raise RuntimeError,"Convergence for Newton-Raphson failed after %s steps."%(iter_max) iterate += 1 self.__domain.setX(x_safe + u) self.__upde.setValue(A=update_s, X=-update_stress + p, r=escript.Data()) #residual=util.L2(self.__pde.getRightHandSide()) du = self.__upde.getSolution() u += du l, d = util.L2(u), util.L2(du) err = d / l # displacement error, alternatively using force error 'residual' converged = (err < rtol) if err > rtol**3: # only update DEM parts when error is large enough self.__domain.setX(x_safe) D = util.grad(u) update_stress, update_s, update_scenes = self.applyStrain_getStressTangentDEM( st=D) """reset domain geometry to original until global convergence""" self.__domain.setX(x_safe) return u, D, update_stress, update_s, update_scenes
def solve(self, globalIter=10, solidIter=50): """ solve the coupled PDE using fixed-stress split method, call solveSolid to get displacement """ rtol=self.__rtol x_safe=self.__domain.getX() k=util.kronecker(self.__domain) kdr=util.inner(k,util.tensor_mult(self.__S,k))/4. n=self.getEquivalentPorosity() perm=self.__permeability*n**3/(1.-n)**2*k kf=self.__bulkFluid dt=self.__dt self.__ppde.setValue(A=perm,D=(n/kf+1./kdr)/dt,Y=(n/kf+1./kdr)/dt*self.__pgauss-self.__meanStressRate/kdr) p_iter_old=self.__ppde.getSolution() p_iter_gauss=util.interpolate(p_iter_old,escript.Function(self.__domain)) u_old,D,sig,s,scene=self.solveSolid(p_iter_gauss=p_iter_gauss,iter_max=solidIter) converge=False iterate=0 while (not converge) and (iterate<globalIter): iterate += 1 self.__ppde.setValue(Y=n/kf/dt*self.__pgauss+1./kdr/dt*p_iter_gauss-util.trace(D)/dt) p_iter=self.__ppde.getSolution() p_err=util.L2(p_iter-p_iter_old)/util.L2(p_iter) p_iter_old=p_iter p_iter_gauss=util.interpolate(p_iter,escript.Function(self.__domain)) u,D,sig,s,scene=self.solveSolid(p_iter_gauss=p_iter_gauss,iter_max=solidIter) u_err=util.L2(u-u_old)/util.L2(u) u_old=u converge=(u_err<=rtol and p_err <= rtol*.1) self.__meanStressRate=(util.trace(sig-self.__stress)/2.-p_iter_gauss+self.__pgauss)/dt self.__pore=p_iter_old self.__pgauss=p_iter_gauss self.__domain.setX(x_safe+u_old) self.__strain+=D self.__stress=sig self.__S=s self.__scenes=scene return u_old
def solveSolid(self, p_iter_gauss=escript.Data(), iter_max=50): """ solve the pde for displacement using Newton-Ralphson scheme """ k=util.kronecker(self.__domain) p=p_iter_gauss*k iterate=0 rtol=self.__rtol stress_safe=self.__stress s_safe=self.__S x_safe=self.__domain.getX() self.__upde.setValue(A=s_safe, X=-stress_safe+p, r=self.__r) #residual0=util.L2(self.__pde.getRightHandSide()) # using force error u=self.__upde.getSolution() # trial solution, displacement D=util.grad(u) # trial strain tensor # !!!!!! obtain stress and tangent operator from DEM part update_stress,update_s,update_scenes=self.applyStrain_getStressTangentDEM(st=D) err=util.Lsup(u) # initial error before iteration converged=(err<1.e-12) while (not converged) and (iterate<iter_max): #if iterate>iter_max: # raise RuntimeError,"Convergence for Newton-Raphson failed after %s steps."%(iter_max) iterate+=1 self.__domain.setX(x_safe+u) self.__upde.setValue(A=update_s,X=-update_stress+p,r=escript.Data()) #residual=util.L2(self.__pde.getRightHandSide()) du=self.__upde.getSolution() u+=du l,d=util.L2(u),util.L2(du) err=d/l # displacement error, alternatively using force error 'residual' converged=(err<rtol) if err>rtol**3: # only update DEM parts when error is large enough self.__domain.setX(x_safe) D=util.grad(u) update_stress,update_s,update_scenes=self.applyStrain_getStressTangentDEM(st=D) """reset domain geometry to original until global convergence""" self.__domain.setX(x_safe) return u,D,update_stress,update_s,update_scenes