def setupERTPDE(domain, tolerance=1e-8, poisson=True, debug=0): """ used to setup all PDEs fro ERT related inversion. If available TRILINOS is usered. :param domain: domain of the PDE :type domain: `esys.escript.AbstractDomain` :param tolerance: solver tolerance :type tolerance: `float` :param poisson: if True TRILINOS settings fro Poisson problems is set. :type poisson: `bool` :return: linear, scalar PDE with real coefficients. :rtype: `esys.escript.linearPDEs.LinearPDE` """ pde = LinearSinglePDE(domain, isComplex=False) pde.setSymmetryOn() optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.PCG) optionsG.setTolerance(tolerance) if hasFeature('trilinos'): if debug and getMPIRankWorld() == 0: print("TRILINOS solver used.") optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) if poisson: optionsG.setTrilinosParameter("problem:type", "Poisson-3D") optionsG.setTrilinosParameter("verbosity", "none") optionsG.setTrilinosParameter("number of equations", 1) optionsG.setTrilinosParameter("problem: symmetric", True) return pde
def setupERTPDE(domain, poisson=True): """ used t setup all ERT PDEs """ pde = LinearSinglePDE(domain, isComplex=False) pde.setSymmetryOn() optionsG = pde.getSolverOptions() #optionsG.setSolverMethod(SolverOptions.DIRECT) optionsG.setSolverMethod(SolverOptions.PCG) optionsG.setTolerance(1e-8) if True and hasFeature('trilinos'): #print("trilinos solver used.") optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) if poisson: optionsG.setTrilinosParameter("problem:type", "Poisson-3D") optionsG.setTrilinosParameter("verbosity", "none") optionsG.setTrilinosParameter("number of equations", 1) #optionsG.setTrilinosParameter("max levels", 3) # 10 is default 3 seems to be a good number #optionsG.setTrilinosParameter("cycle type", "V") optionsG.setTrilinosParameter("problem: symmetric", True) #optionsG.setTrilinosParameter("smoother: pre or post", "both") #optionsG.setTrilinosParameter("Convergence Tolerance", 1e-12) return pde
def __createPDE(self, airLayer=None): pde = LinearSinglePDE( self.domain, isComplex=True, ) optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.DIRECT) pde.setSymmetryOn() if self.useFastSolver and hasFeature('trilinos'): # ignored for now! optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) optionsG.setTrilinosParameter("problem: symmetric", True) z = self.domain.getX()[self.domain.getDim() - 1] b = inf(z) if airLayer is None: self.airLayer = whereNonNegative(z - sup(z)) elif isinstance(airLayer, float) or isinstance(airLayer, int): self.airLayer = whereNonNegative(z - airLayer) else: self.airLayer = wherePositive( interpolate(airLayer, Solution(self.domain))) if self.fixBottom: pde.setValue(q=self.airLayer + whereZero(z - b), r=self.airLayer) else: pde.setValue(q=self.airLayer, r=self.airLayer) return pde
def __init__(self, domain, w, data, coordinates=None, fixPotentialAtBottom=False, tol=1e-8): """ initializes a new forward model with potential. :param domain: domain of the model :type domain: `Domain` :param w: data weighting factors :type w: ``Vector`` or list of ``Vector`` :param data: data :type data: ``Vector`` or list of ``Vector`` :param coordinates: defines coordinate system to be used :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation` :param fixPotentialAtBottom: if true potential is fixed to zero at the bottom of the domain in addition to the top. :type fixPotentialAtBottom: ``bool`` :param tol: tolerance of underlying PDE :type tol: positive ``float`` """ super(ForwardModelWithPotential, self).__init__() self.__domain = domain self.__trafo = makeTransformation(domain, coordinates) try: n=len(w) m=len(data) if not m == n: raise ValueError("Length of weight and data must be the same.") self.__weight = w self.__data = data except TypeError: self.__weight = [w] self.__data = [data] BX = boundingBox(domain) DIM = domain.getDim() x = domain.getX() self.__pde=LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z=x[DIM-1] q0=whereZero(z-BX[DIM-1][1]) if fixPotentialAtBottom: q0+=whereZero(z-BX[DIM-1][0]) self.__pde.setValue(q=q0) self.edge_lengths=np.asarray(boundingBoxEdgeLengths(domain)) self.diameter=1./sqrt(sum(1./self.edge_lengths**2)) self.__origweight=[] for s in range(len(self.__weight)): # save a copy of the original weights in case of rescaling self.__origweight.append(1.*self.__weight[s]) if not self.__trafo.isCartesian(): fd=1./self.__trafo.getScalingFactors() fw=self.__trafo.getScalingFactors()*sqrt(self.__trafo.getVolumeFactor()) for s in range(len(self.__weight)): self.__weight[s] = fw * self.__weight[s] self.__data[s] = fd * self.__data[s]
def test_complex_params_Brick(self): domain=Brick(order=2,n0=10,n1=10,n2=10) pde = LinearSinglePDE(domain, isComplex=True) pde.setValue(D=1j) pde.setValue(Y=1.0) self.assertTrue(Lsup(pde.getSolution())==1.0, "Failed test_complex_params_Brick") del domain
def __init__(self, domain, p0=0., level0=0, gravity0=-9.81 * U.m * U.sec**(-2), background_density=2670 * U.kg * U.m**(-3), gravity_constant=U.Gravitational_Constant, coordinates=None, tol=1e-8): """ :param domain: domain of the model :type domain: `Domain` :param p0: pressure at level0 :type p0: scalar `Data` or ``float`` :param background_density: defines background_density in kg/m^3 :type background_density: ``float`` :param coordinates: defines coordinate system to be used :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation` :param tol: tolerance of underlying PDE :type tol: positive ``float`` :param level0: pressure for z>=`level0` is set to zero. :type level0: ``float`` :param gravity0: vertical background gravity at `level0` :type gravity0: ``float`` """ DIM = domain.getDim() self.__domain = domain self.__trafo = makeTransformation(domain, coordinates) self.__pde = LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z = domain.getX()[DIM - 1] self.__pde.setValue(q=whereNonNegative(z - level0), r=p0) fw = self.__trafo.getScalingFactors( )**2 * self.__trafo.getVolumeFactor() A = self.__pde.createCoefficient("A") for i in range(DIM): A[i, i] = fw[i] self.__pde.setValue(A=A) z = Function(domain).getX()[DIM - 1] self.__g_b = 4 * PI * gravity_constant / self.__trafo.getScalingFactors( )[DIM - 1] * background_density * (level0 - z) + gravity0 self.__rho_b = background_density
def __createPDE(self): """ Create the PDE and set boundary conditions. """ pde = LinearSinglePDE(self.domain, isComplex=False) domdim = self.domain.getDim() zdim = domdim - 1 optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.PCG) pde.setSymmetryOn() pde.setValue(A=kronecker(domdim)) x = self.domain.getX() q = whereZero(x[zdim] - sup(x[zdim])) if self.fixBase: q += whereZero(x[zdim] - inf(x[zdim])) pde.setValue(q=q) if hasFeature('trilinos'): optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) return pde
def __init__(self, domain, v_p, wavelet, source_tag, dt=None, p0=None, p0_t=None, absorption_zone=300*U.m, absorption_cut=1e-2, lumping=True): """ initialize the sonic wave solver :param domain: domain of the problem :type domain: `Domain` :param v_p: p-velocity field :type v_p: `Scalar` :param wavelet: wavelet to describe the time evolution of source term :type wavelet: `Wavelet` :param source_tag: tag of the source location :type source_tag: 'str' or 'int' :param dt: time step size. If not present a suitable time step size is calculated. :param p0: initial solution. If not present zero is used. :param p0_t: initial solution change rate. If not present zero is used. :param absorption_zone: thickness of absorption zone :param absorption_cut: boundary value of absorption decay factor :param lumping: if True mass matrix lumping is being used. This is accelerates the computing but introduces some diffusion. """ f=createAbsorptionLayerFunction(Function(domain).getX(), absorption_zone, absorption_cut) v_p=v_p*f if p0 == None: p0=Scalar(0.,Solution(domain)) else: p0=interpolate(p0, Solution(domain )) if p0_t == None: p0_t=Scalar(0.,Solution(domain)) else: p0_t=interpolate(p0_t, Solution(domain )) if dt == None: dt=min(inf((1./5.)*domain.getSize()/v_p), wavelet.getTimeScale()) super(SonicWave, self).__init__( dt, u0=p0, v0=p0_t, t0=0.) self.__wavelet=wavelet self.__mypde=LinearSinglePDE(domain) if lumping: self.__mypde.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) self.__mypde.setSymmetryOn() self.__mypde.setValue(D=1./v_p**2) self.__source_tag=source_tag self.__r=Scalar(0., DiracDeltaFunctions(self.__mypde.getDomain()))
def __init__(self, domain, p0=0., level0=0, gravity0=-9.81*U.m*U.sec**(-2), background_density=2670* U.kg*U.m**(-3), gravity_constant=U.Gravitational_Constant, coordinates=None, tol=1e-8): """ :param domain: domain of the model :type domain: `Domain` :param p0: pressure at level0 :type p0: scalar `Data` or ``float`` :param background_density: defines background_density in kg/m^3 :type background_density: ``float`` :param coordinates: defines coordinate system to be used :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation` :param tol: tolerance of underlying PDE :type tol: positive ``float`` :param level0: pressure for z>=`level0` is set to zero. :type level0: ``float`` :param gravity0: vertical background gravity at `level0` :type gravity0: ``float`` """ DIM=domain.getDim() self.__domain = domain self.__trafo=makeTransformation(domain, coordinates) self.__pde=LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z = domain.getX()[DIM-1] self.__pde.setValue(q=whereNonNegative(z-level0), r=p0) fw = self.__trafo.getScalingFactors()**2 * self.__trafo.getVolumeFactor() A=self.__pde.createCoefficient("A") for i in range(DIM): A[i,i]=fw[i] self.__pde.setValue(A=A) z = Function(domain).getX()[DIM-1] self.__g_b= 4*PI*gravity_constant/self.__trafo.getScalingFactors()[DIM-1]*background_density*(level0-z) + gravity0 self.__rho_b=background_density
def __createPDE(self): """ Create the PDE and set boundary conditions. """ pde = LinearSinglePDE(self.domain, isComplex=False) optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.PCG) pde.setSymmetryOn() pde.setValue(A=kronecker(self.domain.getDim())) x = self.domain.getX() pde.setValue(A=kronecker(self.domain)) if self.fixVert: pde.setValue( q=whereZero(x[0] - inf(x[0])) + whereZero(x[0] - sup(x[0])) + whereZero(x[1] - inf(x[1])) + whereZero(x[1] - sup(x[1]))) elif self.fixBase: pde.setValue(q=whereZero(x[2] - inf(x[2]))) else: pde.setValue(q=whereZero(x[0] - inf(x[0])) * whereZero(x[1] - inf(x[1])) * whereZero(x[2] - inf(x[2]))) if hasFeature('trilinos'): optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) return pde
def runValetAcceleration(order): domain=finley.Rectangle(100,10,order) x=domain.getX() # test Velet scheme dt=inf(domain.getSize()/c)*(1./6.) q=whereZero(x[0])+whereZero(x[0]-1.) mypde_f=LinearSinglePDE(domain) mypde_f.setSymmetryOn() mypde_f.setValue(D=1,q=q) u_f_old=ref_u(x,-dt) u_f=ref_u(x,0) mypde_HRZ=LinearSinglePDE(domain) mypde_HRZ.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) mypde_HRZ.setValue(D=1,q=q) u_HRZ_old=ref_u(x,-dt) u_HRZ=ref_u(x,0) mypde_RS=LinearSinglePDE(domain) mypde_RS.getSolverOptions().setSolverMethod(SolverOptions.ROWSUM_LUMPING) mypde_RS.setValue(D=1,q=q) u_RS_old=ref_u(x,-dt) u_RS=ref_u(x,0) l=Locator(domain,[0.5,0.5]) t=0 u=ref_u(x,t) t_list=[t] u_list=[l(u)] f_list=[l(u_f)] HRZ_list=[l(u_HRZ)] RS_list=[l(u_RS)] print(t_list[-1], u_list[-1], f_list[-1], HRZ_list[-1] , RS_list[-1]) while t< 4/n/c: t+=dt u=ref_u(x,t) mypde_f.setValue(X=-c**2*grad(u_f), r=-c**2*u) mypde_HRZ.setValue(X=-c**2*grad(u_HRZ), r=-c**2*u) mypde_RS.setValue(X=-c**2*grad(u_RS), r=-c**2*u) a_f=mypde_f.getSolution() a_HRZ=mypde_HRZ.getSolution() a_RS=mypde_RS.getSolution() u_f, u_f_old = 2*u_f-u_f_old + dt**2*a_f , u_f u_HRZ, u_HRZ_old = 2*u_HRZ-u_HRZ_old + dt**2*a_HRZ , u_HRZ u_RS, u_RS_old = 2*u_RS-u_RS_old + dt**2*a_RS , u_RS t_list.append(t) u_list.append(l(u)) f_list.append(l(u_f)) HRZ_list.append(l(u_HRZ)) RS_list.append(l(u_RS)) print(t_list[-1], u_list[-1], f_list[-1], HRZ_list[-1] , RS_list[-1]) import matplotlib.pyplot as plt if getMPIRankWorld() == 0: plt.clf() plt.plot(t_list, u_list, '-', label="exact", linewidth=1) plt.plot(t_list, f_list, '-', label="full", linewidth=1) plt.plot(t_list, HRZ_list, '-', label="HRZ lumping", linewidth=1) plt.plot(t_list, RS_list, '-', label="row sum lumping", linewidth=1) plt.axis([0.,max(t_list),-1.3,1.3]) plt.xlabel('time') plt.ylabel('displacement') plt.legend() plt.savefig('lumping_valet_a_%d.png'%order, format='png')
def runTaylorGalerkinIncremental(order): domain = finley.Rectangle(100, 10, order) x = domain.getX() # test Velet scheme dt = inf(domain.getSize() / length(v)) * (1.0 / 6.0) q = whereZero(x[0]) + whereZero(x[0] - 1.0) mypde_f = LinearSinglePDE(domain) mypde_f.setSymmetryOn() mypde_f.setValue(D=1, q=q) u_f = ref_u(x, 0) mypde_HRZ = LinearSinglePDE(domain) mypde_HRZ.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) mypde_HRZ.setValue(D=1, q=q) u_HRZ = ref_u(x, 0) mypde_RS = LinearSinglePDE(domain) mypde_RS.getSolverOptions().setSolverMethod(SolverOptions.ROWSUM_LUMPING) mypde_RS.setValue(D=1, q=q) u_RS = ref_u(x, 0) l = Locator(domain, [0.5, 0.5]) t = 0 u = ref_u(x, t) t_list = [t] u_list = [l(u)] f_list = [l(u_f)] HRZ_list = [l(u_HRZ)] RS_list = [l(u_RS)] print(t_list[-1], u_list[-1], f_list[-1], HRZ_list[-1], RS_list[-1]) while t < 1.0 / Lsup(v): t += dt u = ref_u(x, t) mypde_f.setValue(X=-dt / 2.0 * u_f * v, r=ref_u(x, t - dt / 2) - u_f) mypde_HRZ.setValue(X=-dt / 2.0 * u_HRZ * v, r=ref_u(x, t - dt / 2) - u_f) mypde_RS.setValue(X=-dt / 2.0 * u_RS * v, r=ref_u(x, t - dt / 2) - u_f) u_f_h = u_f + mypde_f.getSolution() u_HRZ_h = u_HRZ + mypde_HRZ.getSolution() u_RS_h = u_RS + mypde_RS.getSolution() mypde_f.setValue(X=-dt * u_f_h * v, r=u - u_f) mypde_HRZ.setValue(X=-dt * u_HRZ_h * v, r=u - u_HRZ) mypde_RS.setValue(X=-dt * u_RS_h * v, r=u - u_RS) u_f = u_f + mypde_f.getSolution() u_HRZ = u_HRZ + mypde_HRZ.getSolution() u_RS = u_RS + mypde_RS.getSolution() t_list.append(t) u_list.append(l(u)) f_list.append(l(u_f)) HRZ_list.append(l(u_HRZ)) RS_list.append(l(u_RS)) print(t_list[-1], u_list[-1], f_list[-1], HRZ_list[-1], RS_list[-1], " : ", sup(u)) import matplotlib.pyplot as plt if getMPIRankWorld() == 0: plt.clf() plt.plot(t_list, u_list, "-", label="exact", linewidth=1) plt.plot(t_list, f_list, "-", label="full", linewidth=1) plt.plot(t_list, HRZ_list, "-", label="HRZ lumping", linewidth=1) plt.plot(t_list, RS_list, "-", label="row sum lumping", linewidth=1) plt.axis([0.0, max(t_list), -0.3, 2.0]) plt.xlabel("time") plt.ylabel("displacement") plt.legend() plt.savefig("lumping_SUPG_du_%d.png" % order, format="png")
def __createPDE(self): """ Create the PDE and set boundary conditions. """ pde = LinearSinglePDE(self.domain, isComplex=False) optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.PCG) pde.setSymmetryOn() if self.useFastSolver and hasFeature('trilinos'): optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) if self.fixAllFaces: x=pde.getDomain().getX()[0] y=pde.getDomain().getX()[1] z=pde.getDomain().getX()[2] pde.setValue(q=whereZero(x-inf(x))+whereZero(x-sup(x))+ whereZero(y-inf(y))+whereZero(y-sup(y))+whereZero(z-inf(z))) else: z=pde.getDomain().getX()[2] pde.setValue(q=whereZero(z-inf(z))) return pde
w_step=max(int(nstep/50),1)*0+1 toler = 0.001 teta1 = 0.5 teta2 = 0.5 teta3 = 1 # =0 split A; =1 split B # create domain: dom=Rectangle(int(nel*L/min(L,H)),int(nel*H/min(L,H)),order=1, l0=L, l1=H) x=dom.getX() momentumStep1=LinearPDESystem(dom) momentumStep1.setValue(q=whereZero(x[0])*[1.,0.]+whereZero(x[1])*[0.,1.]) # fix x0=0 and x1=0 face_mask=whereZero(FunctionOnBoundary(dom).getX()[1]) pressureStep2=LinearSinglePDE(dom) pressureStep2.setReducedOrderOn() pressureStep2.setValue(q=whereZero(x[0]-L)+whereZero(x[1]-H)) momentumStep3=LinearPDESystem(dom) momentumStep3.setValue(q=whereZero(x[0])*[1.,0.]+whereZero(x[1])*[0.,1.]) # # initial values: # U=Vector(0.,Solution(dom)) p=ro*g*(L-ReducedSolution(dom).getX()[0])*(H-ReducedSolution(dom).getX()[1])/3 p=ro*g*(H-ReducedSolution(dom).getX()[1]) dev_stress=Tensor(0.,Function(dom)) t=dt istep=0
class IsostaticPressure(object): """ class to calculate isostatic pressure field correction due to gravity forces """ def __init__(self, domain, p0=0., level0=0, gravity0=-9.81 * U.m * U.sec**(-2), background_density=2670 * U.kg * U.m**(-3), gravity_constant=U.Gravitational_Constant, coordinates=None, tol=1e-8): """ :param domain: domain of the model :type domain: `Domain` :param p0: pressure at level0 :type p0: scalar `Data` or ``float`` :param background_density: defines background_density in kg/m^3 :type background_density: ``float`` :param coordinates: defines coordinate system to be used :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation` :param tol: tolerance of underlying PDE :type tol: positive ``float`` :param level0: pressure for z>=`level0` is set to zero. :type level0: ``float`` :param gravity0: vertical background gravity at `level0` :type gravity0: ``float`` """ DIM = domain.getDim() self.__domain = domain self.__trafo = makeTransformation(domain, coordinates) self.__pde = LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z = domain.getX()[DIM - 1] self.__pde.setValue(q=whereNonNegative(z - level0), r=p0) fw = self.__trafo.getScalingFactors( )**2 * self.__trafo.getVolumeFactor() A = self.__pde.createCoefficient("A") for i in range(DIM): A[i, i] = fw[i] self.__pde.setValue(A=A) z = Function(domain).getX()[DIM - 1] self.__g_b = 4 * PI * gravity_constant / self.__trafo.getScalingFactors( )[DIM - 1] * background_density * (level0 - z) + gravity0 self.__rho_b = background_density def getPressure(self, g=None, rho=None): """ return the pressure for gravity force anomaly `g` and density anomaly `rho` :param g: gravity anomaly data :type g: ``Vector`` :param rho: gravity anomaly data :type rho: ``Scalar`` :return: pressure distribution :rtype: ``Scalar`` """ if not g: g = Vector(0., Function(self.__domain)) if not rho: rho = Scalar(0., Function(self.__domain)) g2 = (rho * self.__g_b) * [0, 0, 1] + self.__rho_b * g + rho * g # Tests need to be updated before the following is uncommented: #g2=((rho+self.__rho_b) * self.__g_b)*[0,0,1] + self.__rho_b*g + rho*g d = self.__trafo.getScalingFactors() V = self.__trafo.getVolumeFactor() self.__pde.setValue(X=-g2 * d * V) #self.__pde.setValue(X = g2*d*V) return self.__pde.getSolution()
def __createPDE(self): """ Create the PDE and set boundary conditions. """ pde = LinearSinglePDE( self.domain, isComplex=True, ) optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.DIRECT) pde.setSymmetryOn() if self.useFastSolver and hasFeature('trilinos'): # ignored for now! optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) pde.setValue(A=kronecker(self.domain.getDim())) z = self.domain.getX()[self.domain.getDim() - 1] t = sup(z) if self.fixBottom: b = inf(z) pde.setValue(q=whereZero(z - t) + whereZero(z - b), r=(z - b) / (t - b)) else: pde.setValue(q=whereZero(z - t), r=1.) return pde
from esys.escript import * from esys.escript.linearPDEs import LinearSinglePDE from esys.weipa import saveVTK try: from esys.finley import Rectangle HAVE_FINLEY = True except ImportError: HAVE_FINLEY = False # generate domain: if not HAVE_FINLEY: print("Finley module not available") else: mydomain=Rectangle(30,30, l0=3, l1=2, diracPoints=[(1.,1.), (2.,1.)], diracTags=['in', 'out']) # fix the solution on the boundary x = mydomain.getX() gammaD = whereZero(x[0])+whereZero(x[1])+whereZero(x[0]-3.)+whereZero(x[1]-2.) # fix the solution on the boundary s=Scalar(0., DiracDeltaFunctions(mydomain)) s.setTaggedValue('in', +1.) s.setTaggedValue('out', -1.) # define PDE and get its solution u mypde = LinearSinglePDE(domain=mydomain) mypde.setValue(q=gammaD, A=kronecker(2), y_dirac=s) u = mypde.getSolution() print("Solution = ",str(u)) # write u to an external file saveVTK("u.vtu",sol=u)
u0=1/(4.*pi*E*T0)**(DIM/2.)*exp(-length(dom.getX()-getCenter(T0))**2/(4.*E*T0)) print("QUALITY ",QUALITY(T0,u0)) x=Function(dom).getX() if DIM == 2: V=OMEGA0*(x[0]*[0,-1]+x[1]*[1,0]) else: V=OMEGA0*(x[0]*[0,cos(ALPHA),0]+x[1]*[-cos(ALPHA),0,sin(ALPHA)]+x[2]*[0.,-sin(ALPHA),0.]) #=================== fc=TransportPDE(dom,num_equations=1,theta=THETA) x=Function(dom).getX() fc.setValue(M=Scalar(1.,Function(dom)),C=V,A=-Scalar(E,Function(dom))*kronecker(dom)) #============== if TEST_SUPG: supg=LinearSinglePDE(dom) supg.setValue(D=1.) supg.setSolverMethod(supg.LUMPING) dt_supg=1./(1./inf(dom.getSize()/length(V))+1./inf(dom.getSize()**2/E))*0.3 u_supg=u0*1. c=0 saveVTK("u.%s.vtu"%c,u=u0) fc.setInitialSolution(u0) t=T0 while t<T_END: print("time step t=",t+dt) u=fc.solve(dt) if TEST_SUPG: #========== supg tests ================ nn=max(ceil(dt/dt_supg),1.)
def runTaylorGalerkinIncremental(order): domain = finley.Rectangle(100, 10, order) x = domain.getX() # test Velet scheme dt = inf(domain.getSize() / length(v)) * (1. / 6.) q = whereZero(x[0]) + whereZero(x[0] - 1.) mypde_f = LinearSinglePDE(domain) mypde_f.setSymmetryOn() mypde_f.setValue(D=1, q=q) u_f = ref_u(x, 0) mypde_HRZ = LinearSinglePDE(domain) mypde_HRZ.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) mypde_HRZ.setValue(D=1, q=q) u_HRZ = ref_u(x, 0) mypde_RS = LinearSinglePDE(domain) mypde_RS.getSolverOptions().setSolverMethod(SolverOptions.ROWSUM_LUMPING) mypde_RS.setValue(D=1, q=q) u_RS = ref_u(x, 0) l = Locator(domain, [0.5, 0.5]) t = 0 u = ref_u(x, t) t_list = [t] u_list = [l(u)] f_list = [l(u_f)] HRZ_list = [l(u_HRZ)] RS_list = [l(u_RS)] print(t_list[-1], u_list[-1], f_list[-1], HRZ_list[-1], RS_list[-1]) while t < 1. / Lsup(v): t += dt u = ref_u(x, t) mypde_f.setValue(X=-dt / 2. * u_f * v, r=ref_u(x, t - dt / 2) - u_f) mypde_HRZ.setValue(X=-dt / 2. * u_HRZ * v, r=ref_u(x, t - dt / 2) - u_f) mypde_RS.setValue(X=-dt / 2. * u_RS * v, r=ref_u(x, t - dt / 2) - u_f) u_f_h = u_f + mypde_f.getSolution() u_HRZ_h = u_HRZ + mypde_HRZ.getSolution() u_RS_h = u_RS + mypde_RS.getSolution() mypde_f.setValue(X=-dt * u_f_h * v, r=u - u_f) mypde_HRZ.setValue(X=-dt * u_HRZ_h * v, r=u - u_HRZ) mypde_RS.setValue(X=-dt * u_RS_h * v, r=u - u_RS) u_f = u_f + mypde_f.getSolution() u_HRZ = u_HRZ + mypde_HRZ.getSolution() u_RS = u_RS + mypde_RS.getSolution() t_list.append(t) u_list.append(l(u)) f_list.append(l(u_f)) HRZ_list.append(l(u_HRZ)) RS_list.append(l(u_RS)) print(t_list[-1], u_list[-1], f_list[-1], HRZ_list[-1], RS_list[-1], " : ", sup(u)) import matplotlib.pyplot as plt if getMPIRankWorld() == 0: plt.clf() plt.plot(t_list, u_list, '-', label="exact", linewidth=1) plt.plot(t_list, f_list, '-', label="full", linewidth=1) plt.plot(t_list, HRZ_list, '-', label="HRZ lumping", linewidth=1) plt.plot(t_list, RS_list, '-', label="row sum lumping", linewidth=1) plt.axis([0., max(t_list), -.3, 2.]) plt.xlabel('time') plt.ylabel('displacement') plt.legend() plt.savefig('lumping_SUPG_du_%d.png' % order, format='png')
x = Function(dom).getX() if DIM == 2: V = OMEGA0 * (x[0] * [0, -1] + x[1] * [1, 0]) else: V = OMEGA0 * (x[0] * [0, cos(ALPHA), 0] + x[1] * [-cos(ALPHA), 0, sin(ALPHA)] + x[2] * [0., -sin(ALPHA), 0.]) #=================== fc = TransportPDE(dom, num_equations=1, theta=THETA) x = Function(dom).getX() fc.setValue(M=Scalar(1., Function(dom)), C=V, A=-Scalar(E, Function(dom)) * kronecker(dom)) #============== if TEST_SUPG: supg = LinearSinglePDE(dom) supg.setValue(D=1.) supg.setSolverMethod(supg.LUMPING) dt_supg = 1. / (1. / inf(dom.getSize() / length(V)) + 1. / inf(dom.getSize()**2 / E)) * 0.3 u_supg = u0 * 1. c = 0 saveVTK("u.%s.vtu" % c, u=u0) fc.setInitialSolution(u0) t = T0 while t < T_END: print("time step t=", t + dt) u = fc.solve(dt) if TEST_SUPG: #========== supg tests ================
from esys.escript import * from esys.weipa import saveVTK, saveSilo from esys.escript.linearPDEs import LinearSinglePDE, SolverOptions from esys.finley import ReadGmsh from esys.escript.pdetools import Locator print("read in mesh") domain = ReadGmsh("simplemesh.msh", 3, optimize=True) pde = LinearSinglePDE(domain, isComplex=False) pde.setSymmetryOn() x = domain.getX() pde.setValue(A=kronecker(3), Y=1, q=whereZero(x[0] - inf(x[0]))) options = pde.getSolverOptions() options.setPackage(SolverOptions.TRILINOS) options.setSolverMethod(SolverOptions.PCG) options.setPreconditioner(SolverOptions.AMG) options.setTrilinosParameter("multigrid algorithm", "sa") options.setTrilinosParameter("sa: damping factor", 1.3) options.setTrilinosParameter("max levels", 10) options.setTrilinosParameter("coarse: max size", 2000) options.setTrilinosParameter("coarse: type", "SuperLU") options.setTrilinosParameter("verbosity", "low") print("solve pde") u = pde.getSolution() saveSilo("asimple", u=u) print("finished")
def __createPDE(self): """ Create the PDE and set boundary conditions. """ pde = LinearSinglePDE(self.domain, isComplex=False) optionsG = pde.getSolverOptions() optionsG.setSolverMethod(SolverOptions.PCG) pde.setSymmetryOn() assert self.source.getFunctionSpace() == DiracDeltaFunctions(self.domain) sigma=interpolate(self.sigma, Function(self.domain)) pde.setValue(A=sigma*kronecker(self.domain), y_dirac=self.source) if self.useFastSolver and hasFeature('trilinos'): optionsG.setPackage(SolverOptions.TRILINOS) optionsG.setPreconditioner(SolverOptions.AMG) if self.fixAllFaces: x=pde.getDomain().getX()[0] y=pde.getDomain().getX()[1] z=pde.getDomain().getX()[2] pde.setValue(q=whereZero(x-inf(x))+whereZero(x-sup(x))+ whereZero(y-inf(y))+whereZero(y-sup(y))+whereZero(z-inf(z))) else: z=pde.getDomain().getX()[2] pde.setValue(q=whereZero(z-inf(z))) return pde
class ForwardModelWithPotential(ForwardModel): """ Base class for a forward model using a potential such as magnetic or gravity. It defines a cost function: defect = 1/2 sum_s integrate( ( weight_i[s] * ( r_i - data_i[s] ) )**2 ) where s runs over the survey, weight_i are weighting factors, data_i are the data, and r_i are the results produced by the forward model. It is assumed that the forward model is produced through postprocessing of the solution of a potential PDE. """ def __init__(self, domain, w, data, coordinates=None, fixPotentialAtBottom=False, tol=1e-8): """ initializes a new forward model with potential. :param domain: domain of the model :type domain: `Domain` :param w: data weighting factors :type w: ``Vector`` or list of ``Vector`` :param data: data :type data: ``Vector`` or list of ``Vector`` :param coordinates: defines coordinate system to be used :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation` :param fixPotentialAtBottom: if true potential is fixed to zero at the bottom of the domain in addition to the top. :type fixPotentialAtBottom: ``bool`` :param tol: tolerance of underlying PDE :type tol: positive ``float`` """ super(ForwardModelWithPotential, self).__init__() self.__domain = domain self.__trafo = makeTransformation(domain, coordinates) try: n = len(w) m = len(data) if not m == n: raise ValueError("Length of weight and data must be the same.") self.__weight = w self.__data = data except TypeError: self.__weight = [w] self.__data = [data] BX = boundingBox(domain) DIM = domain.getDim() x = domain.getX() self.__pde = LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z = x[DIM - 1] q0 = whereZero(z - BX[DIM - 1][1]) if fixPotentialAtBottom: q0 += whereZero(z - BX[DIM - 1][0]) self.__pde.setValue(q=q0) self.edge_lengths = np.asarray(boundingBoxEdgeLengths(domain)) self.diameter = 1. / sqrt(sum(1. / self.edge_lengths**2)) self.__origweight = [] for s in range(len(self.__weight)): # save a copy of the original weights in case of rescaling self.__origweight.append(1. * self.__weight[s]) if not self.__trafo.isCartesian(): fd = 1. / self.__trafo.getScalingFactors() fw = self.__trafo.getScalingFactors() * sqrt( self.__trafo.getVolumeFactor()) for s in range(len(self.__weight)): self.__weight[s] = fw * self.__weight[s] self.__data[s] = fd * self.__data[s] def _rescaleWeights(self, scale=1., fetch_factor=1.): """ rescales the weights such that *sum_s integrate( ( weight_i[s] *data_i[s]) (weight_j[s]*1/L_j) * L**2 * fetch_factor )=scale* """ if not scale > 0: raise ValueError("Value for scale must be positive.") A = 0 # copy back original weights before rescaling self.__weight = [1. * ow for ow in self.__origweight] for s in range(len(self.__weight)): if self.__data[s].getShape() == (): ff = self.__weight[s]**2 * self.__data[s] / length( self.edge_lengths) else: ff = inner(self.__weight[s], self.__data[s]) * inner( self.__weight[s], 1 / self.edge_lengths) A += integrate(abs(ff * fetch_factor)) if A > 0: A = sqrt(scale / A) / self.diameter if not self.__trafo.isCartesian(): A *= self.__trafo.getScalingFactors() * sqrt( self.__trafo.getVolumeFactor()) for s in range(len(self.__weight)): self.__weight[s] *= A else: raise ValueError("Rescaling of weights failed.") def getDomain(self): """ Returns the domain of the forward model. :rtype: `Domain` """ return self.__domain def getMisfitWeights(self): """ Returns the weights of the misfit function :rtype: ``list`` of ``Data`` """ return self.__weight def getData(self): """ Returns the data :rtype: ``list`` of ``Data`` """ return self.__data def getDataFunctionSpace(self): """ Returns the ``FunctionSpace`` of the data :rtype: ``FunctionSpace`` """ return self.getData()[0].getFunctionSpace() def getCoordinateTransformation(self): """ returns the coordinate transformation being used :rtype: ``CoordinateTransformation`` """ return self.__trafo def getPDE(self): """ Return the underlying PDE. :rtype: `LinearPDE` """ return self.__pde def _getDefect(self, result): """ Returns the defect value. :param result: a result vector :type result: `Vector` :rtype: ``float`` """ A = 0. for s in range(len(self.__weight)): A += integrate(inner(self.__weight[s], self.__data[s] - result)**2) return A / 2 def getDefectGradient(self, result): Y = 0. for s in range(len(self.__weight)): Y = inner(self.__weight[s], self.__data[s] - result) * self.__weight[s] + Y return Y def getSurvey(self, index=None): """ Returns the pair (data_index, weight_index), where data_i is the data of survey i, weight_i is the weighting factor for survey i. If index is None, all surveys will be returned in a pair of lists. """ if index is None: return self.__data, self.__weight if index >= len(self.__data): raise IndexError("Forward model only has %d surveys" % len(self.__data)) return self.__data[index], self.__weight[index]
class IsostaticPressure(object): """ class to calculate isostatic pressure field correction due to gravity forces """ def __init__(self, domain, p0=0., level0=0, gravity0=-9.81*U.m*U.sec**(-2), background_density=2670* U.kg*U.m**(-3), gravity_constant=U.Gravitational_Constant, coordinates=None, tol=1e-8): """ :param domain: domain of the model :type domain: `Domain` :param p0: pressure at level0 :type p0: scalar `Data` or ``float`` :param background_density: defines background_density in kg/m^3 :type background_density: ``float`` :param coordinates: defines coordinate system to be used :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation` :param tol: tolerance of underlying PDE :type tol: positive ``float`` :param level0: pressure for z>=`level0` is set to zero. :type level0: ``float`` :param gravity0: vertical background gravity at `level0` :type gravity0: ``float`` """ DIM=domain.getDim() self.__domain = domain self.__trafo=makeTransformation(domain, coordinates) self.__pde=LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z = domain.getX()[DIM-1] self.__pde.setValue(q=whereNonNegative(z-level0), r=p0) fw = self.__trafo.getScalingFactors()**2 * self.__trafo.getVolumeFactor() A=self.__pde.createCoefficient("A") for i in range(DIM): A[i,i]=fw[i] self.__pde.setValue(A=A) z = Function(domain).getX()[DIM-1] self.__g_b= 4*PI*gravity_constant/self.__trafo.getScalingFactors()[DIM-1]*background_density*(level0-z) + gravity0 self.__rho_b=background_density def getPressure(self, g = None, rho=None): """ return the pressure for gravity force anomaly `g` and density anomaly `rho` :param g: gravity anomaly data :type g: ``Vector`` :param rho: gravity anomaly data :type rho: ``Scalar`` :return: pressure distribution :rtype: ``Scalar` """ if not g: g=Vector(0., Function(self.__domain)) if not rho: rho=Scalar(0., Function(self.__domain)) g2=(rho * self.__g_b)*[0,0,1] + self.__rho_b*g + rho*g # Tests need to be updated before the following is uncommented: #g2=((rho+self.__rho_b) * self.__g_b)*[0,0,1] + self.__rho_b*g + rho*g d=self.__trafo.getScalingFactors() V= self.__trafo.getVolumeFactor() self.__pde.setValue(X = -g2*d*V) #self.__pde.setValue(X = g2*d*V) return self.__pde.getSolution()
def __init__(self, domain, w, data, coordinates=None, fixPotentialAtBottom=False, tol=1e-8): """ initializes a new forward model with potential. :param domain: domain of the model :type domain: `Domain` :param w: data weighting factors :type w: ``Vector`` or list of ``Vector`` :param data: data :type data: ``Vector`` or list of ``Vector`` :param coordinates: defines coordinate system to be used :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation` :param fixPotentialAtBottom: if true potential is fixed to zero at the bottom of the domain in addition to the top. :type fixPotentialAtBottom: ``bool`` :param tol: tolerance of underlying PDE :type tol: positive ``float`` """ super(ForwardModelWithPotential, self).__init__() self.__domain = domain self.__trafo = makeTransformation(domain, coordinates) try: n = len(w) m = len(data) if not m == n: raise ValueError("Length of weight and data must be the same.") self.__weight = w self.__data = data except TypeError: self.__weight = [w] self.__data = [data] BX = boundingBox(domain) DIM = domain.getDim() x = domain.getX() self.__pde = LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z = x[DIM - 1] q0 = whereZero(z - BX[DIM - 1][1]) if fixPotentialAtBottom: q0 += whereZero(z - BX[DIM - 1][0]) self.__pde.setValue(q=q0) self.edge_lengths = np.asarray(boundingBoxEdgeLengths(domain)) self.diameter = 1. / sqrt(sum(1. / self.edge_lengths**2)) self.__origweight = [] for s in range(len(self.__weight)): # save a copy of the original weights in case of rescaling self.__origweight.append(1. * self.__weight[s]) if not self.__trafo.isCartesian(): fd = 1. / self.__trafo.getScalingFactors() fw = self.__trafo.getScalingFactors() * sqrt( self.__trafo.getVolumeFactor()) for s in range(len(self.__weight)): self.__weight[s] = fw * self.__weight[s] self.__data[s] = fd * self.__data[s]
try: from esys.finley import Rectangle HAVE_FINLEY = True except ImportError: HAVE_FINLEY = False # generate domain: if not HAVE_FINLEY: print("Finley module not available") else: mydomain = Rectangle(30, 30, l0=3, l1=2, diracPoints=[(1., 1.), (2., 1.)], diracTags=['in', 'out']) # fix the solution on the boundary x = mydomain.getX() gammaD = whereZero(x[0]) + whereZero( x[1]) + whereZero(x[0] - 3.) + whereZero(x[1] - 2.) # fix the solution on the boundary s = Scalar(0., DiracDeltaFunctions(mydomain)) s.setTaggedValue('in', +1.) s.setTaggedValue('out', -1.) # define PDE and get its solution u mypde = LinearSinglePDE(domain=mydomain) mypde.setValue(q=gammaD, A=kronecker(2), y_dirac=s) u = mypde.getSolution() print("Solution = ", str(u)) # write u to an external file saveVTK("u.vtu", sol=u)
class ForwardModelWithPotential(ForwardModel): """ Base class for a forward model using a potential such as magnetic or gravity. It defines a cost function: defect = 1/2 sum_s integrate( ( weight_i[s] * ( r_i - data_i[s] ) )**2 ) where s runs over the survey, weight_i are weighting factors, data_i are the data, and r_i are the results produced by the forward model. It is assumed that the forward model is produced through postprocessing of the solution of a potential PDE. """ def __init__(self, domain, w, data, coordinates=None, fixPotentialAtBottom=False, tol=1e-8): """ initializes a new forward model with potential. :param domain: domain of the model :type domain: `Domain` :param w: data weighting factors :type w: ``Vector`` or list of ``Vector`` :param data: data :type data: ``Vector`` or list of ``Vector`` :param coordinates: defines coordinate system to be used :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation` :param fixPotentialAtBottom: if true potential is fixed to zero at the bottom of the domain in addition to the top. :type fixPotentialAtBottom: ``bool`` :param tol: tolerance of underlying PDE :type tol: positive ``float`` """ super(ForwardModelWithPotential, self).__init__() self.__domain = domain self.__trafo = makeTransformation(domain, coordinates) try: n=len(w) m=len(data) if not m == n: raise ValueError("Length of weight and data must be the same.") self.__weight = w self.__data = data except TypeError: self.__weight = [w] self.__data = [data] BX = boundingBox(domain) DIM = domain.getDim() x = domain.getX() self.__pde=LinearSinglePDE(domain) self.__pde.getSolverOptions().setTolerance(tol) self.__pde.setSymmetryOn() z=x[DIM-1] q0=whereZero(z-BX[DIM-1][1]) if fixPotentialAtBottom: q0+=whereZero(z-BX[DIM-1][0]) self.__pde.setValue(q=q0) self.edge_lengths=np.asarray(boundingBoxEdgeLengths(domain)) self.diameter=1./sqrt(sum(1./self.edge_lengths**2)) self.__origweight=[] for s in range(len(self.__weight)): # save a copy of the original weights in case of rescaling self.__origweight.append(1.*self.__weight[s]) if not self.__trafo.isCartesian(): fd=1./self.__trafo.getScalingFactors() fw=self.__trafo.getScalingFactors()*sqrt(self.__trafo.getVolumeFactor()) for s in range(len(self.__weight)): self.__weight[s] = fw * self.__weight[s] self.__data[s] = fd * self.__data[s] def _rescaleWeights(self, scale=1., fetch_factor=1.): """ rescales the weights such that *sum_s integrate( ( weight_i[s] *data_i[s]) (weight_j[s]*1/L_j) * L**2 * fetch_factor )=scale* """ if not scale > 0: raise ValueError("Value for scale must be positive.") A=0 # copy back original weights before rescaling self.__weight=[1.*ow for ow in self.__origweight] for s in range(len(self.__weight)): A += integrate(abs(inner(self.__weight[s], self.__data[s]) * inner(self.__weight[s], 1/self.edge_lengths) * fetch_factor)) if A > 0: A=sqrt(scale/A)/self.diameter if not self.__trafo.isCartesian(): A*=self.__trafo.getScalingFactors()*sqrt(self.__trafo.getVolumeFactor()) for s in range(len(self.__weight)): self.__weight[s]*=A else: raise ValueError("Rescaling of weights failed.") def getDomain(self): """ Returns the domain of the forward model. :rtype: `Domain` """ return self.__domain def getCoordinateTransformation(self): """ returns the coordinate transformation being used :rtype: ``CoordinateTransformation`` """ return self.__trafo def getPDE(self): """ Return the underlying PDE. :rtype: `LinearPDE` """ return self.__pde def _getDefect(self, result): """ Returns the defect value. :param result: a result vector :type result: `Vector` :rtype: ``float`` """ A=0. for s in range(len(self.__weight)): A += integrate( inner(self.__weight[s], self.__data[s]-result)**2 ) return A/2 def getDefectGradient(self, result): Y=0. for s in range(len(self.__weight)): Y = inner(self.__weight[s], self.__data[s]-result) * self.__weight[s] + Y return Y def getSurvey(self, index=None): """ Returns the pair (data_index, weight_index), where data_i is the data of survey i, weight_i is the weighting factor for survey i. If index is None, all surveys will be returned in a pair of lists. """ if index is None: return self.__data, self.__weight if index>=len(self.__data): raise IndexError("Forward model only has %d surveys"%len(self.__data)) return self.__data[index], self.__weight[index]