Exemple #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
Exemple #2
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
Exemple #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
Exemple #4
0
    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]
Exemple #5
0
 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
Exemple #6
0
    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
Exemple #7
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
Exemple #8
0
        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()))
Exemple #9
0
    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
Exemple #10
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
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 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")
Exemple #14
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
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
Exemple #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()
Exemple #17
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
Exemple #18
0
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)
Exemple #19
0
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.)
Exemple #20
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')
Exemple #21
0
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 ================
Exemple #22
0
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
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")
Exemple #24
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
Exemple #25
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]
Exemple #26
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()
Exemple #27
0
    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]
Exemple #28
0
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)
Exemple #29
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]