def solve(self, iter_max=100): """ solve the equation using Newton-Ralphson scheme """ iterate = 0 rtol = self.getRelTolerance() stress = self.getCurrentStress() s = self.getCurrentTangent() x_safe = self.__domain.getX() self.__pde.setValue(A=s, X=-stress) #residual0=util.L2(self.__pde.getRightHandSide()) # using force error u = self.__pde.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 = 1.0 # initial error before iteration converged = (err < rtol) while (not converged) and (iterate < iter_max): if self.__verbose: print( "Not converged after %d iteration(s)! Relative error: %e" % (iterate, err)) iterate += 1 self.__domain.setX(x_safe + u) self.__pde.setValue(A=update_s, X=-update_stress, r=escript.Data()) #residual=util.L2(self.__pde.getRightHandSide()) du = self.__pde.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 * 0.001: # 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) #if err>err_safe: # to ensure consistent convergence, however this may not be achieved due to fluctuation! # raise RuntimeError,"No improvement of convergence with iterations! Relative error: %e"%err """ update 'domain geometry', 'stress', 'tangent operator', 'accumulated strain' and 'simulation scenes'. """ self.__domain.setX(x_safe + u) self.__stress = update_stress self.__S = update_s self.__strain += D self.__scenes = update_scenes if self.__verbose: print( "Convergence reached after %d iteration(s)! Relative error: %e" % (iterate, err)) return u
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, iter_max=100): """ solve the equation using Newton-Ralphson scheme ??where is the equation """ iterate=0 rtol=self.getRelTolerance() stress=self.getCurrentStress() s=self.getCurrentTangent() x_safe=self.__domain.getX() self.__pde.setValue(A=s, X=-stress)#stress is negative,here uses - to change to positive #residual0=util.L2(self.__pde.getRightHandSide()) # using force error u=self.__pde.getSolution() # trial solution, displacement D=util.grad(u) # trial strain tensor (obtained from FEM part) #fout1=open('./result/gradU.dat','w') #fout1.write(str(D)+'\n') # !!!!!! following steps: obtain stress and tangent operator from DEM part update_stress,update_s,update_scenes=self.applyStrain_getStressTangentDEM(st=D)#input grad(u) from FEM to DEM to get D&sigma #fout2=open('./result/stress&tangOper.dat','w') #fout2.write('tangent'+'\n'+str(update_s)+'\n'+'stress'+'\n'+str(update_stress)) #saveGauss2D(name='./result/gradU+stress+tangent.dat',gradU=D, stress=update_stress, tangent=update_s) #print(type(D)) gradU is a <class 'esys.escriptcore.escriptcpp.Data'> how to transfer to a list to output err=1.0 # initial error before iteration converged=(err<rtol) while not converged: if self.__verbose: print "Not converged after %d iteration(s)! Relative error: %e"%(iterate,err) if iterate>50: rtol = 0.05 #enlarge rtol from 0.01(default) to 0.05 when iterate > 50 if iterate>iter_max: raise RuntimeError,"Convergence not reached after %s steps."%(iter_max) iterate+=1 self.__domain.setX(x_safe+u)#update nodal displacement to do the following calculation self.__pde.setValue(A=update_s,X=-update_stress,r=escript.Data()) #residual=util.L2(self.__pde.getRightHandSide()) du=self.__pde.getSolution() #we do NR iteration to get du u+=du l,d=util.L2(u),util.L2(du) #to get the l2 norm of u and du err=d/l # displacement error, alternatively using force error 'residual' converged=(err<rtol) if err>rtol*0.001: # only update DEM parts when error is large enough???why times 0.001? #it seems whether or not it is converged, the lines below 'if' will always be excuted. So why do we need if? can we just remove it self.__domain.setX(x_safe) #x_safe is constant in this part 'solve' and is not updated. D=util.grad(u) update_stress,update_s,update_scenes=self.applyStrain_getStressTangentDEM(st=D)#DEM calculation!! ''' fout.write('iterate='+str(iterate)+'\n'+'scenes='+'\n'+str(update_scenes)+'\n') ''' #if err>err_safe: # to ensure consistent convergence, however this may not be achieved due to fluctuation! # raise RuntimeError,"No improvement of convergence with iterations! Relative error: %e"%err """ update 'domain geometry', 'stress', 'tangent operator', 'accumulated strain' and 'simulation scenes'. """ self.__domain.setX(x_safe+u) self.__stress=update_stress self.__S=update_s self.__strain+=D self.__scenes=update_scenes if self.__verbose: print "Convergence reached after %d iteration(s)! Relative error: %e"%(iterate,err) return u