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
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 SonicWave(WaveBase): """ Solving the sonic wave equation `p_tt = (v_p**2 * p_i)_i + f(t) * delta_s` where (p-) velocity v_p. f(t) is wavelet acting at a point source term at positon s """ 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 _getAcceleration(self, t, u): """ returns the acceleraton for time t and solution u at time t """ self.__r.setTaggedValue(self.__source_tag, self.__wavelet.getValue(t)) self.__mypde.setValue(X=-grad(u,Function(self.__mypde.getDomain())), y_dirac= self.__r) return self.__mypde.getSolution()