def interpolateEscriptData(domain, data): """ esys.weipa does not support the function spaces Solution and ReducedSolution. This function interpolates Data defined on those function spaces to compatible alternatives. """ from esys.escript import Solution, ReducedSolution from esys.escript import ContinuousFunction, ReducedContinuousFunction from esys.escript.util import interpolate new_data={} for n,d in sorted(list(data.items()), key=lambda x: x[0]): if not d.isEmpty(): fs=d.getFunctionSpace() if domain is None: domain=fs.getDomain() elif domain != fs.getDomain(): raise ValueError("weipa: All Data must be on the same domain!") new_data[n]=d try: if fs == Solution(domain): new_data[n]=interpolate(d, ContinuousFunction(domain)) elif domain.getDescription().startswith("speckley"): new_data[n]=interpolate(d, ContinuousFunction(domain)) elif fs == ReducedSolution(domain): new_data[n]=interpolate(d, ReducedContinuousFunction(domain)) except RuntimeError as e: if str(e).startswith("FunctionSpaceException"): pass else: raise e return domain,new_data
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 __init__(self, domain, pore0=0., perm=1.e-5, kf=2.2e9, dt=0.001, ng=1, useMPI=False, np=1, rtol=1.e-2): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param pore0: type float, initial pore pressure :param perm: type float, d^2/(150 mu_f) in KC equation :param kf: type float, bulk modulus of the fluid :param dt: type float, time step for calculation :param ng: type integer, number of Gauss points :param useMPI: type boolean, use MPI or not :param np: type integer, number of processors :param rtol: type float, relevative tolerance for global convergence """ self.__domain = domain self.__upde = LinearPDE(domain, numEquations=domain.getDim(), numSolutions=domain.getDim()) self.__ppde = LinearPDE(domain, numEquations=1, numSolutions=1) # use reduced interpolation for pore pressure self.__ppde.setReducedOrderOn() self.__upde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.__ppde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.__upde.setSymmetryOn() self.__ppde.setSymmetryOn() self.__dt = dt self.__bulkFluid = kf self.__numGaussPoints = ng self.__rtol = rtol self.__stress = escript.Tensor(0, escript.Function(domain)) self.__S = escript.Tensor4(0, escript.Function(domain)) self.__pool = get_pool(mpi=useMPI, threads=np) self.__scenes = self.__pool.map(initLoad, range(ng)) st = self.__pool.map(getStressAndTangent2D, self.__scenes) for i in xrange(ng): self.__stress.setValueOfDataPoint(i, st[i][0]) self.__S.setValueOfDataPoint(i, st[i][1]) self.__strain = escript.Tensor(0, escript.Function(domain)) self.__pore = escript.Scalar(pore0, escript.ReducedSolution(domain)) self.__pgauss = util.interpolate(pore0, escript.Function(domain)) self.__permeability = perm self.__meanStressRate = escript.Scalar(0, escript.Function(domain)) self.__r = escript.Vector( 0, escript.Solution(domain)) #Dirichlet BC for 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 __init__(self,domain,pore0=0.,perm=1.e-5,kf=2.2e9,dt=0.001,ng=1,useMPI=False,np=1,rtol=1.e-2): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param pore0: type float, initial pore pressure :param perm: type float, d^2/(150 mu_f) in KC equation :param kf: type float, bulk modulus of the fluid :param dt: type float, time step for calculation :param ng: type integer, number of Gauss points :param useMPI: type boolean, use MPI or not :param np: type integer, number of processors :param rtol: type float, relevative tolerance for global convergence """ self.__domain=domain self.__upde=LinearPDE(domain,numEquations=domain.getDim(),numSolutions=domain.getDim()) self.__ppde=LinearPDE(domain,numEquations=1,numSolutions=1) # use reduced interpolation for pore pressure self.__ppde.setReducedOrderOn() try: self.__upde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.__ppde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) except: #import time print("=======================================================================") print("For better performance compile python-escript with direct solver method") print("=======================================================================") input("Press Enter to continue...") #time.sleep(5) self.__upde.setSymmetryOn() self.__ppde.setSymmetryOn() self.__dt=dt self.__bulkFluid=kf self.__numGaussPoints=ng self.__rtol=rtol self.__stress=escript.Tensor(0,escript.Function(domain)) self.__S=escript.Tensor4(0,escript.Function(domain)) self.__pool=get_pool(mpi=useMPI,threads=np) self.__scenes=self.__pool.map(initLoad,list(range(ng))) st = self.__pool.map(getStressAndTangent2D,self.__scenes) for i in range(ng): self.__stress.setValueOfDataPoint(i,st[i][0]) self.__S.setValueOfDataPoint(i,st[i][1]) self.__strain=escript.Tensor(0,escript.Function(domain)) self.__pore=escript.Scalar(pore0,escript.ReducedSolution(domain)) self.__pgauss=util.interpolate(pore0,escript.Function(domain)) self.__permeability=perm self.__meanStressRate=escript.Scalar(0,escript.Function(domain)) self.__r=escript.Vector(0,escript.Solution(domain)) #Dirichlet BC for u
def saveVoxet(filename, **data): """ Writes `Data` objects to a file using the GOCAD Voxet file format as separate properties on the same grid. At the moment only Data on a `ripley` domain can be saved in this format. Note that this function will produce one header file (ending in .vo) and a separate property file for each `Data` object. :param filename: name of the output file ('.vo' is added if required) :type filename: ``str`` :note: All data objects have to be defined on the same ripley domain and either defined on reduced Function or on a `FunctionSpace` that allows interpolation to reduced Function. """ from esys.escript import ReducedFunction from esys.escript.util import interpolate from esys.ripley.ripleycpp import DATATYPE_FLOAT32, BYTEORDER_BIG_ENDIAN new_data={} domain=None for n,d in sorted(data.items(), key=lambda x: x[0]): if d.isEmpty(): continue fs=d.getFunctionSpace() if domain is None: domain=fs.getDomain() elif domain != fs.getDomain(): raise ValueError("saveVoxet: All Data must be on the same domain!") try: nd=interpolate(d, ReducedFunction(domain)) except: raise ValueError("saveVoxet: Unable to interpolate all Data to reduced Function!") new_data[n]=nd if filename[-3:]=='.vo': fileprefix=filename[:-3]+"_" else: fileprefix=filename+"_" filename=filename+'.vo' origin, spacing, NE = domain.getGridParameters() # Voxet "origin" actually refers to centre of first cell so shift: origin = tuple([ origin[i] + spacing[i]/2. for i in range(len(origin)) ]) # flip vertical origin origin=origin[:-1]+(-origin[-1],) axis_max=NE[:-1]+(-NE[-1],) midpoint=tuple([n/2 for n in NE]) if domain.getDim() == 2: origin=origin+(0.,) spacing=spacing+(1.,) NE=NE+(1,) midpoint=midpoint+(0,) axis_max=axis_max+(0,) mainvar=list(new_data.keys())[0] f=open(filename,'w') f.write("GOCAD Voxet 1\nHEADER {\nname: escriptdata\n") f.write("sections: 3 1 1 %d 2 1 %d 3 1 %d\n"%midpoint) f.write("painted: on\nascii: off\n*painted*variable: %s\n}"%mainvar) f.write(""" GOCAD_ORIGINAL_COORDINATE_SYSTEM NAME "gocad Local" AXIS_NAME X Y Z AXIS_UNIT m m m ZPOSITIVE Depth END_ORIGINAL_COORDINATE_SYSTEM\n""") f.write("AXIS_O %0.2f %0.2f %0.2f\n"%origin) f.write("AXIS_U %0.2f 0 0\n"%spacing[0]) f.write("AXIS_V 0 %0.2f 0\n"%spacing[1]) f.write("AXIS_W 0 0 %0.2f\n"%spacing[2]) f.write("AXIS_MIN 0 0 0\n") f.write("AXIS_MAX %d %d %d\n"%axis_max) f.write("AXIS_N %d %d %d\n"%NE) f.write("\n") num=0 for n,d in sorted(new_data.items(), key=lambda x: x[0]): num=num+1 propfile=fileprefix+n domain.writeBinaryGrid(d, propfile, BYTEORDER_BIG_ENDIAN, DATATYPE_FLOAT32) f.write("\nPROPERTY %d %s\n"%(num, n)) f.write("PROPERTY_SUBCLASS %d QUANTITY Float\n"%num) f.write("PROP_ESIZE %d 4\n"%num) f.write("PROP_ETYPE %d IEEE\n"%num) f.write("PROP_FORMAT %d RAW\n"%num) f.write("PROP_OFFSET %d 0\n"%num) f.write("PROP_FILE %d %s\n"%(num,propfile)) f.close()