Пример #1
0
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
Пример #2
0
 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
Пример #3
0
 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
Пример #4
0
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
Пример #5
0
 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
Пример #6
0
 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
Пример #7
0
 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
Пример #8
0
 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
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')
Пример #10
0
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')
Пример #11
0
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]
Пример #12
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()
Пример #13
0
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')
Пример #14
0
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]
Пример #15
0
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")
Пример #16
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()
Пример #17
0
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()
Пример #18
0
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")