Esempio n. 1
0
    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
Esempio n. 2
0
 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
Esempio n. 3
0
 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
Esempio n. 4
0
   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