コード例 #1
0
 def __init__(self,domain,dim,ng=1,useMPI=False,np=1,rho=2.35e3,mIds=False,\
              FEDENodeMap=False,DE_ext=False,FEDEBoundMap=False,conf=False):
     """
   initialization of the problem, i.e. model constructor
   :param domain: type Domain, domain of the problem
   :param ng: type integer, number of Gauss points
   :param useMPI: type boolean, use MPI or not
   :param np: type integer, number of processors
   :param rho: type float, density of material
   :param mIds: a list contains membrane node IDs
   :param FEDENodeMap: a dictionary with FE and DE boundary node IDs in keys and values
   :param DE_ext: name of file which saves initial state of exterior DE domain
   :param FEDEBoundMap: a dictionary with FE and DE boundary element IDs in keys and values (deprecated)
   :param conf: type float, conf pressure on membrane
   """
     self.__domain = domain
     self.__pde = LinearPDE(self.__domain,
                            numEquations=dim,
                            numSolutions=dim)
     self.__pde.getSolverOptions().setSolverMethod(
         SolverOptions.HRZ_LUMPING)
     self.__pde.setSymmetryOn()
     self.__numGaussPoints = ng
     self.__rho = rho
     self.__mIds = mIds
     self.__FEDENodeMap = FEDENodeMap
     self.__FEDEBoundMap = FEDEBoundMap
     self.__conf = conf
     self.__pool = get_pool(mpi=useMPI, threads=np)
     self.__scenes = self.__pool.map(initLoad, range(ng))
     self.__strain = escript.Tensor(0, escript.Function(self.__domain))
     self.__stress = escript.Tensor(0, escript.Function(self.__domain))
     self.__u = escript.Vector(0, escript.Solution(self.__domain))
     self.__u_last = escript.Vector(0, escript.Solution(self.__domain))
     self.__u_t = escript.Vector(0, escript.Solution(self.__domain))
     self.__dt = 0
     # ratio between timesteps in internal DE and FE domain
     self.__nsOfDE_int = 1
     # if FEDENodeMap is given, employ exterior DE domain
     if self.__FEDENodeMap:
         self.__sceneExt = self.__pool.apply(initLoadExt, (DE_ext, ))
         # ratio between timesteps in external DE and FE domain
         self.__nsOfDE_ext = 1
         # get interface nodal forces as boundary condition
         self.__FEf = self.__pool.apply(
             initNbc, (self.__sceneExt, self.__conf, mIds, FEDENodeMap))
         """
      # get interface nodal tractions as boundary condition (deprecated)
      self.__Nbc=escript.Vector(0,escript.Solution(self.__domain))
      FENbc = self.__pool.apply(initNbc,(self.__sceneExt,self.__conf,mIds,FEDENodeMap))
      for FEid in FENbc.keys():
         self.__Nbc.setValueOfDataPoint(FEid,FENbc[FEid])
      """
     # get stress tensor at material points
     s = self.__pool.map(getStress2D, self.__scenes)
     for i in xrange(ng):
         self.__stress.setValueOfDataPoint(i, s[i])
コード例 #2
0
    def __init__(self,
                 domain,
                 pore0=0.,
                 perm=1.e-5,
                 kf=2.2e9,
                 dt=0.001,
                 ng=1,
                 useMPI=False,
                 np=1,
                 rtol=1.e-2):
        """
      initialization of the problem, i.e. model constructor
      :param domain: type Domain, domain of the problem
      :param pore0: type float, initial pore pressure
      :param perm: type float, d^2/(150 mu_f) in KC equation
      :param kf: type float, bulk modulus of the fluid
      :param dt: type float, time step for calculation
      :param ng: type integer, number of Gauss points
      :param useMPI: type boolean, use MPI or not
      :param np: type integer, number of processors
      :param rtol: type float, relevative tolerance for global convergence
      """
        self.__domain = domain
        self.__upde = LinearPDE(domain,
                                numEquations=domain.getDim(),
                                numSolutions=domain.getDim())
        self.__ppde = LinearPDE(domain, numEquations=1, numSolutions=1)
        # use reduced interpolation for pore pressure
        self.__ppde.setReducedOrderOn()

        self.__upde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT)
        self.__ppde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT)
        self.__upde.setSymmetryOn()
        self.__ppde.setSymmetryOn()

        self.__dt = dt
        self.__bulkFluid = kf
        self.__numGaussPoints = ng
        self.__rtol = rtol
        self.__stress = escript.Tensor(0, escript.Function(domain))
        self.__S = escript.Tensor4(0, escript.Function(domain))
        self.__pool = get_pool(mpi=useMPI, threads=np)
        self.__scenes = self.__pool.map(initLoad, range(ng))
        st = self.__pool.map(getStressAndTangent2D, self.__scenes)
        for i in xrange(ng):
            self.__stress.setValueOfDataPoint(i, st[i][0])
            self.__S.setValueOfDataPoint(i, st[i][1])
        self.__strain = escript.Tensor(0, escript.Function(domain))
        self.__pore = escript.Scalar(pore0, escript.ReducedSolution(domain))
        self.__pgauss = util.interpolate(pore0, escript.Function(domain))
        self.__permeability = perm
        self.__meanStressRate = escript.Scalar(0, escript.Function(domain))
        self.__r = escript.Vector(
            0, escript.Solution(domain))  #Dirichlet BC for u
コード例 #3
0
ファイル: magtel2d.py プロジェクト: aishugang/esys-escript
    def __tagDomain(self, domain, X, tags, rho, maps):
        """
    DESCRIPTION:
    -----------
    Defines the conductivity model. Conductivities of tagged regions can be mapped
    via user-defined functions passed in 'maps'. If no user-defined functions are
    passed, a constant value is applied as provided in list 'rho' for each region.
    User-defined functions have 3 arguments: x-coordinate, z-coordinate, resistivity.

    ARGUMENTS:
    ----------
    domain  :: escript object of mesh
    X       :: escript object with all coordinates
    tags    :: list with domain tags
    rho     :: list with domain resistivities
    maps    :: list with user-defined resistivity mappings

    RETURNS:
    --------
    sigma   :: escript object of conductivity model

    """
        # Setup the conductivity structure (acts on elements and can be discontinuous).
        sigma = escript.Scalar(0, escript.Function(domain))

        # Setup conductivity domains.
        for i in range(len(tags)):

            # Default: assign conductivity which is the inverse of resistivity:
            m = 1.0 / rho[i]

            # Map a user-defined conductivity distribution if given:
            if maps is not None:
                # Guard against undefined elements:
                if maps[i] is not None:
                    # Map the conductivity according to the defined functions:
                    m = maps[i](X[0], X[1], rho[i])

            # Tag the mesh with the conductivity distributions at each iteration:
            sigma += m * escript.insertTaggedValues(
                escript.Scalar(0, escript.Function(domain)), **{tags[i]: 1})

        if self._debug == True:
            sigma.expand()
            mydir = os.getcwd()
            dbgfl = mydir + os.sep + "mt2d_sigma_dbg.silo"
            print("")
            print("DEBUG: writing SILO debug output of conductivity model:")
            print(dbgfl)
            print("")
            weipa.saveSilo(dbgfl, sigma=sigma)

        # All done:
        return sigma
コード例 #4
0
 def applyStrain_getStressTangentDEM(self, st=escript.Data()):
     st = st.toListOfTuples()
     st = numpy.array(st).reshape(-1, 9)
     stress = escript.Tensor(0, escript.Function(self.__domain))
     S = escript.Tensor4(0, escript.Function(self.__domain))
     scenes = self.__pool.map(shear, zip(self.__scenes, st))
     st = self.__pool.map(getStressAndTangent, scenes)
     for i in xrange(self.__numGaussPoints):
         stress.setValueOfDataPoint(i, st[i][0])
         S.setValueOfDataPoint(i, st[i][1])
     return stress, S, scenes
コード例 #5
0
ファイル: msFEM2D.py プロジェクト: marceloteixeira30/yade
    def __init__(self,
                 domain,
                 ng=1,
                 useMPI=False,
                 np=1,
                 random=False,
                 rtol=1.e-2,
                 usePert=False,
                 pert=-2.e-6,
                 verbose=False):
        """
      initialization of the problem, i.e. model constructor
      :param domain: type Domain, domain of the problem
      :param ng: type integer, number of Gauss points
      :param useMPI: type boolean, use MPI or not
      :param np: type integer, number of processors
      :param random: type boolean, if or not use random density field
      :param rtol: type float, relevative tolerance for global convergence
      :param usePert: type boolean, if or not use perturbation method
      :param pert: type float, perturbated strain applied to DEM to obtain tangent operator
      :param verbose: type boolean, if or not print messages during calculation
      """
        self.__domain = domain
        self.__pde = LinearPDE(domain,
                               numEquations=self.__domain.getDim(),
                               numSolutions=self.__domain.getDim())
        self.__pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT)
        self.__pde.setSymmetryOn()
        #self.__pde.getSolverOptions().setTolerance(rtol**2)
        #self.__pde.getSolverOptions().setPackage(SolverOptions.UMFPACK)
        self.__numGaussPoints = ng
        self.__rtol = rtol
        self.__usepert = usePert
        self.__pert = pert
        self.__verbose = verbose
        self.__pool = get_pool(mpi=useMPI, threads=np)
        self.__scenes = self.__pool.map(initLoad, range(ng))
        self.__strain = escript.Tensor(0, escript.Function(self.__domain))
        self.__stress = escript.Tensor(0, escript.Function(self.__domain))
        self.__S = escript.Tensor4(0, escript.Function(self.__domain))

        if self.__usepert:
            s = self.__pool.map(getStressTensor, self.__scenes)
            t = self.__pool.map(getTangentOperator,
                                zip(self.__scenes, repeat(pert)))
            for i in xrange(ng):
                self.__stress.setValueOfDataPoint(i, s[i])
                self.__S.setValueOfDataPoint(i, t[i])
        else:
            st = self.__pool.map(getStressAndTangent2D, self.__scenes)
            for i in xrange(ng):
                self.__stress.setValueOfDataPoint(i, st[i][0])
                self.__S.setValueOfDataPoint(i, st[i][1])
コード例 #6
0
ファイル: msFEM3D.py プロジェクト: HuanranWU/Yade
    def __init__(self,
                 domain,
                 ng=1,
                 useMPI=False,
                 np=1,
                 random=False,
                 rtol=1.e-2,
                 verbose=False):
        """
      initialization of the problem, i.e. model constructor
      :param domain: type Domain, domain of the problem
      :param ng: type integer, number of Gauss points
      :param useMPI: type boolean, use MPI or not
      :param np: type integer, number of processors
      :param random: type boolean, if or not use random density field
      :param rtol: type float, relevant tolerance for global convergence
      :param verbose: type boolean, if or not print messages during calculation
      """
        self.__domain = domain
        self.__pde = LinearPDE(domain,
                               numEquations=self.__domain.getDim(),
                               numSolutions=self.__domain.getDim())
        try:
            self.__pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT)
        except:
            #import time
            print(
                "======================================================================="
            )
            print(
                "For better performance compile python-escript with direct solver method"
            )
            print(
                "======================================================================="
            )
            input("Press Enter to continue...")
            #time.sleep(5)
        self.__pde.setSymmetryOn()
        #self.__pde.getSolverOptions().setTolerance(rtol**2)
        #self.__pde.getSolverOptions().setPackage(SolverOptions.UMFPACK)
        self.__numGaussPoints = ng
        self.__rtol = rtol
        self.__verbose = verbose
        self.__pool = get_pool(mpi=useMPI, threads=np)
        self.__scenes = self.__pool.map(initLoad, list(range(ng)))
        self.__strain = escript.Tensor(0, escript.Function(self.__domain))
        self.__stress = escript.Tensor(0, escript.Function(self.__domain))
        self.__S = escript.Tensor4(0, escript.Function(self.__domain))

        st = self.__pool.map(getStressAndTangent, self.__scenes)
        for i in range(ng):
            self.__stress.setValueOfDataPoint(i, st[i][0])
            self.__S.setValueOfDataPoint(i, st[i][1])
コード例 #7
0
ファイル: coordinates.py プロジェクト: aishugang/esys-escript
    def __init__(self, domain, reference=CartesianReferenceSystem()):
        """
        set up the orthogonal coordinate transformation.

        :param domain: domain in the domain of the coordinate transformation
        :type domain: `esys.escript.AbstractDomain`
        :param reference: the reference system
        :type reference: `ReferenceSystem`
        """
        self.__domain = domain
        self.__reference_system = reference
        self._volumefactor = esc.Scalar(1., esc.Function(domain))
        self._scaling_factors = esc.Vector(1., esc.Function(domain))
コード例 #8
0
 def solve(self, globalIter=10, solidIter=50):
     """
   solve the coupled PDE using fixed-stress split method,
   call solveSolid to get displacement
   """
     rtol = self.__rtol
     x_safe = self.__domain.getX()
     k = util.kronecker(self.__domain)
     kdr = util.inner(k, util.tensor_mult(self.__S, k)) / 4.
     n = self.getEquivalentPorosity()
     perm = self.__permeability * n**3 / (1. - n)**2 * k
     kf = self.__bulkFluid
     dt = self.__dt
     self.__ppde.setValue(A=perm,
                          D=(n / kf + 1. / kdr) / dt,
                          Y=(n / kf + 1. / kdr) / dt * self.__pgauss -
                          self.__meanStressRate / kdr)
     p_iter_old = self.__ppde.getSolution()
     p_iter_gauss = util.interpolate(p_iter_old,
                                     escript.Function(self.__domain))
     u_old, D, sig, s, scene = self.solveSolid(p_iter_gauss=p_iter_gauss,
                                               iter_max=solidIter)
     converge = False
     iterate = 0
     while (not converge) and (iterate < globalIter):
         iterate += 1
         self.__ppde.setValue(Y=n / kf / dt * self.__pgauss +
                              1. / kdr / dt * p_iter_gauss -
                              util.trace(D) / dt)
         p_iter = self.__ppde.getSolution()
         p_err = util.L2(p_iter - p_iter_old) / util.L2(p_iter)
         p_iter_old = p_iter
         p_iter_gauss = util.interpolate(p_iter,
                                         escript.Function(self.__domain))
         u, D, sig, s, scene = self.solveSolid(p_iter_gauss=p_iter_gauss,
                                               iter_max=solidIter)
         u_err = util.L2(u - u_old) / util.L2(u)
         u_old = u
         converge = (u_err <= rtol and p_err <= rtol * .1)
     self.__meanStressRate = (util.trace(sig - self.__stress) / 2. -
                              p_iter_gauss + self.__pgauss) / dt
     self.__pore = p_iter_old
     self.__pgauss = p_iter_gauss
     self.__domain.setX(x_safe + u_old)
     self.__strain += D
     self.__stress = sig
     self.__S = s
     self.__scenes = scene
     return u_old
コード例 #9
0
ファイル: seismic.py プロジェクト: aishugang/esys-escript
    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: `escript.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(
            escript.Function(domain).getX(), absorption_zone, absorption_cut)
        v_p = v_p * f

        if p0 == None:
            p0 = escript.Scalar(0., escript.Solution(domain))
        else:
            p0 = escript.interpolate(p0, escript.Solution(domain))

        if p0_t == None:
            p0_t = escript.Scalar(0., escript.Solution(domain))
        else:
            p0_t = escript.interpolate(p0_t, escript.Solution(domain))

        if dt == None:
            dt = min(escript.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 = lpde.LinearSinglePDE(domain)
        if lumping:
            self.__mypde.getSolverOptions().setSolverMethod(
                lpde.SolverOptions.HRZ_LUMPING)
        self.__mypde.setSymmetryOn()
        self.__mypde.setValue(D=1. / v_p**2)
        self.__source_tag = source_tag
        self.__r = escript.Scalar(
            0., escript.DiracDeltaFunctions(self.__mypde.getDomain()))
コード例 #10
0
ファイル: coordinates.py プロジェクト: aishugang/esys-escript
    def __init__(self, domain, reference=WGS84ReferenceSystem()):
        """
        set up the orthogonal coordinate transformation.

        :param domain: domain in the domain of the coordinate transformation
        :type domain: `esys.escript.AbstractDomain`
        :param reference: the reference system
        :type reference: `ReferenceSystem`

        """
        DIM = domain.getDim()
        super(GeodeticCoordinateTransformation,
              self).__init__(domain, reference)

        a = reference.getSemiMajorAxis()
        f = reference.getFlattening()
        f_a = reference.getAngularUnit()
        f_h = reference.getHeightUnit()

        x = esc.Function(domain).getX()
        if DIM == 2:
            phi = 0.
        else:
            phi = x[1] * f_a
        h = x[DIM - 1] * f_h

        e = esc.sqrt(2 * f - f**2)
        N = a / esc.sqrt(1 - e**2 * esc.sin(phi)**2)
        M = (a * (1 - e**2)) / esc.sqrt(1 - e**2 * esc.sin(phi)**2)**3
        v_phi = f_a * (M + h)
        v_lam = f_a * (N + h) * esc.cos(phi)
        v_h = f_h
        s = esc.Vector(1., esc.Function(domain))
        if DIM == 2:
            v = v_phi * v_h
            s[0] = 1 / v_lam
            s[1] = 1 / v_h
        else:
            v = v_phi * v_lam * v_h
            s[0] = 1 / v_lam
            s[1] = 1 / v_phi
            s[2] = 1 / v_h

        self._volumefactor = v
        self._scaling_factors = s
コード例 #11
0
ファイル: seismic.py プロジェクト: aishugang/esys-escript
 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=-escript.grad(u, escript.Function(self.__mypde.getDomain())),
         y_dirac=self.__r)
     return self.__mypde.getSolution()
コード例 #12
0
 def applyStrain_getStressTangentDEM(self,st=escript.Data()):
    st = st.toListOfTuples()
    st = numpy.array(st).reshape(-1,4) #-1 means the num of rows if determined by column num 4(strain tensor of each GP has 4 values)
    stress = escript.Tensor(0,escript.Function(self.__domain))
    S = escript.Tensor4(0,escript.Function(self.__domain))
    scenes = self.__pool.map(shear2D,zip(self.__scenes,st)) #zip is from python; shear2D is the key part of DEM
    if self.__usepert:
       s = self.__pool.map(getStressTensor,scenes)
       t = self.__pool.map(getTangentOperator,zip(scenes,repeat(self.__pert)))
       for i in xrange(self.__numGaussPoints):
          stress.setValueOfDataPoint(i,s[i])
          S.setValueOfDataPoint(i,t[i])
    else:
       ST = self.__pool.map(getStressAndTangent2D,scenes)
       for i in xrange(self.__numGaussPoints):
          stress.setValueOfDataPoint(i,ST[i][0])
          S.setValueOfDataPoint(i,ST[i][1])
    return stress,S,scenes #stress is sigma. S means tangent operator. scenes??
コード例 #13
0
 def getCurrentTangent(self):
     """
   return current tangent operator
   type Tensor4 on FunctionSpace
   """
     t = escript.Tensor4(0, escript.Function(self.__domain))
     st = self.__pool.map(getStressAndTangent2D, self.__scenes)
     for i in xrange(self.__numGaussPoints):
         t.setValueOfDataPoint(i, st[i][1])
     return t
コード例 #14
0
 def applyStrain_getStressTangentDEM(self, st=escript.Data()):
     st = st.toListOfTuples()
     st = numpy.array(st).reshape(-1, 4)
     stress = escript.Tensor(0, escript.Function(self.__domain))
     S = escript.Tensor4(0, escript.Function(self.__domain))
     scenes = self.__pool.map(shear2D, list(zip(self.__scenes, st)))
     if self.__usepert:
         s = self.__pool.map(getStressTensor, scenes)
         t = self.__pool.map(getTangentOperator,
                             list(zip(scenes, repeat(self.__pert))))
         for i in range(self.__numGaussPoints):
             stress.setValueOfDataPoint(i, s[i])
             S.setValueOfDataPoint(i, t[i])
     else:
         ST = self.__pool.map(getStressAndTangent2D, scenes)
         for i in range(self.__numGaussPoints):
             stress.setValueOfDataPoint(i, ST[i][0])
             S.setValueOfDataPoint(i, ST[i][1])
     return stress, S, scenes
コード例 #15
0
 def __init__(self,domain,ng=1,np=1,random=False,rtol=1.e-2,usePert=False,pert=-2.e-6,verbose=False):
    """
    initialization of the problem, i.e. model constructor
    :param domain: type Domain, domain of the problem
    :param ng: type integer, number of Gauss points
    :param np: type integer, number of processors
    :param random: type boolean, if or not use random density field
    :param rtol: type float, relevative tolerance for global convergence
    :param usePert: type boolean, if or not use perturbation method
    :param pert: type float, perturbated strain applied to DEM to obtain tangent operator
    :param verbose: type boolean, if or not print messages during calculation
    """
    self.__domain=domain
    self.__pde=LinearPDE(domain,numEquations=self.__domain.getDim(),numSolutions=self.__domain.getDim())
    self.__pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT)
    #self.__pde.getSolverOptions().setTolerance(rtol**2)
    #self.__pde.getSolverOptions().setPackage(SolverOptions.UMFPACK)
    self.__numGaussPoints=ng
    self.__rtol=rtol
    self.__usepert=usePert
    self.__pert=pert
    self.__verbose=verbose
    self.__pool=Pool(processes=np)
    self.__scenes=self.__pool.map(initLoad,range(ng))#where is initLoad???from simDEM.py,to load RVEs; map(function, iterable)
    self.__strain=escript.Tensor(0,escript.Function(self.__domain))
    '''Tensor(value=0., what=FunctionSpace(), expanded=False) returns a Data object of shape (d,d) in the FunctionSpace what, where d is the spatial dimension of the Domain of what. Values are initialized with value, a double precision quantity(here is 0). If expanded is True the Data object is represented in expanded form.
    '''
    self.__stress=escript.Tensor(0,escript.Function(self.__domain))
    #Function(domain): returns the general FunctionSpace on the Domain domain. Data objects in this type of general FunctionSpace are defined over the whole geometric region defined by domain.
    self.__S=escript.Tensor4(0,escript.Function(self.__domain))
    #Tensor4 is similar to Tensor, which returns a Data object of shape (d,d,d,d)
    #simDEM part
    if self.__usepert:    #here usepert=false, so this is not invoked.
       s = self.__pool.map(getStressTensor,self.__scenes)  #getstresstensor is defined in simDEM, but here it is not invoked.
       t = self.__pool.map(getTangentOperator,zip(self.__scenes,repeat(pert)))#to get initial D and sigma
       for i in xrange(ng):
          self.__stress.setValueOfDataPoint(i,s[i])
          self.__S.setValueOfDataPoint(i,t[i])
    else:
       st = self.__pool.map(getStressAndTangent2D,self.__scenes)
       for i in xrange(ng):
          self.__stress.setValueOfDataPoint(i,st[i][0])
          self.__S.setValueOfDataPoint(i,st[i][1])
コード例 #16
0
    def getGradientAtPoint(self):
        """
        returns the gradient of the cost function J with respect to m.

        :note: This implementation returns Y_k=dPsi/dm_k and X_kj=dPsi/dm_kj
        """

        # Using cached values
        m = self.__pre_input
        grad_m = self.__pre_args

        mu = self.__mu
        mu_c = self.__mu_c
        DIM = self.getDomain().getDim()
        numLS = self.getNumLevelSets()

        grad_m = escript.grad(m, escript.Function(m.getDomain()))
        if self.__w0 is not None:
            Y = m * self.__w0 * mu
        else:
            if numLS == 1:
                Y = escript.Scalar(0, grad_m.getFunctionSpace())
            else:
                Y = escript.Data(0, (numLS, ), grad_m.getFunctionSpace())

        if self.__w1 is not None:

            if numLS == 1:
                X = grad_m * self.__w1 * mu
            else:
                X = grad_m * self.__w1
                for k in range(numLS):
                    X[k, :] *= mu[k]
        else:
            X = escript.Data(0, grad_m.getShape(), grad_m.getFunctionSpace())

        # cross gradient terms:
        if numLS > 1:
            for k in range(numLS):
                grad_m_k = grad_m[k, :]
                l2_grad_m_k = escript.length(grad_m_k)**2
                for l in range(k):
                    grad_m_l = grad_m[l, :]
                    l2_grad_m_l = escript.length(grad_m_l)**2
                    grad_m_lk = inner(grad_m_l, grad_m_k)
                    f = mu_c[l, k] * self.__wc[l, k]
                    X[l, :] += f * (l2_grad_m_k * grad_m_l -
                                    grad_m_lk * grad_m_k)
                    X[k, :] += f * (l2_grad_m_l * grad_m_k -
                                    grad_m_lk * grad_m_l)

        return pdetools.ArithmeticTuple(Y, X)
コード例 #17
0
 def applyStrain_getStressDEM(self, st=escript.Data(), dynRelax=False):
     st = st.toListOfTuples()
     st = numpy.array(st).reshape(-1, 4)
     stress = escript.Tensor(0, escript.Function(self.__domain))
     # load DEM packing with strain
     scenes = self.__pool.map(
         shear2D, zip(self.__scenes, st, self.__nsOfDE_int,
                      repeat(dynRelax)))
     # return homogenized stress
     s = self.__pool.map(getStress2D, scenes)
     for i in xrange(self.__numGaussPoints):
         stress.setValueOfDataPoint(i, s[i])
     return stress, scenes
コード例 #18
0
 def getLocalAvgRotation(self):
     rot = escript.Vector(0, escript.Function(self.__domain))
     r = self.__pool.map(avgRotation, self.__scenes)
     for i in xrange(self.__numGaussPoints):
         rot.setValueOfDataPoint(i, r[i])
     return rot
コード例 #19
0
 def getLocalVoidRatio(self):
     void = escript.Scalar(0, escript.Function(self.__domain))
     e = self.__pool.map(getVoidRatio, self.__scenes)
     for i in xrange(self.__numGaussPoints):
         void.setValueOfDataPoint(i, e[i])
     return void
コード例 #20
0
 def getLocalDebondNum(self):
    num=escript.Scalar(0,escript.Function(self.__domain))
    n = self.__pool.map(DebondNum,self.__scenes)
    for i in xrange(self.__numGaussPoints):
       num.setValueOfDataPoint(i,n[i])
    return num
コード例 #21
0
ファイル: msFEMup.py プロジェクト: HuanranWU/Yade
 def getEquivalentPorosity(self):
    porosity=escript.Scalar(0,escript.Function(self.__domain))
    p = self.__pool.map(getEquivalentPorosity,self.__scenes)
    for i in range(self.__numGaussPoints):
       porosity.setValueOfDataPoint(i,p[i])
    return porosity
コード例 #22
0
 def getLocalFabric(self):
     fabric = escript.Tensor(0, escript.Function(self.__domain))
     f = self.__pool.map(getFabric, self.__scenes)
     for i in xrange(self.__numGaussPoints):
         fabric.setValueOfDataPoint(i, f[i])
     return fabric
コード例 #23
0
    def setup(self,
              domainbuilder,
              rho0=None,
              drho=None,
              rho_z0=None,
              rho_beta=None,
              k0=None,
              dk=None,
              k_z0=None,
              k_beta=None,
              w0=None,
              w1=None,
              w_gc=None,
              rho_at_depth=None,
              k_at_depth=None):
        """
        Sets up the inversion from an instance ``domainbuilder`` of a
        `DomainBuilder`. Gravity and magnetic data attached to the
        ``domainbuilder`` are considered in the inversion.
        If magnetic data are given as scalar it is assumed that values are
        collected in direction of the background magnetic field.

        :param domainbuilder: Domain builder object with gravity source(s)
        :type domainbuilder: `DomainBuilder`
        :param rho0: reference density, see `DensityMapping`. If not specified, zero is used.
        :type rho0: ``float`` or `Scalar`
        :param drho: density scale, see `DensityMapping`. If not specified, 2750kg/m^3 is used.
        :type drho: ``float`` or `Scalar`
        :param rho_z0: reference depth for depth weighting for density, see `DensityMapping`. If not specified, zero is used.
        :type rho_z0: ``float`` or `Scalar`
        :param rho_beta: exponent for  depth weighting  for density, see `DensityMapping`. If not specified, zero is used.
        :type rho_beta: ``float`` or `Scalar`
        :param k0: reference susceptibility, see `SusceptibilityMapping`. If not specified, zero is used.
        :type k0: ``float`` or `Scalar`
        :param dk: susceptibility scale, see `SusceptibilityMapping`. If not specified, 2750kg/m^3 is used.
        :type dk: ``float`` or `Scalar`
        :param k_z0: reference depth for depth weighting for susceptibility, see `SusceptibilityMapping`. If not specified, zero is used.
        :type k_z0: ``float`` or `Scalar`
        :param k_beta: exponent for  depth weighting for susceptibility, see `SusceptibilityMapping`. If not specified, zero is used.
        :type k_beta: ``float`` or `Scalar`
        :param w0: weighting factors for level set term regularization, see `Regularization`. If not set zero is assumed.
        :type w0: `es.Data` or ``ndarray`` of shape (2,)
        :param w1: weighting factor for the gradient term in the regularization see `Regularization`. If not set zero is assumed
        :type w1: `es.Data` or ``ndarray`` of shape (2,DIM)
        :param w_gc: weighting factor for the cross gradient term in the regularization, see `Regularization`. If not set one is assumed
        :type w_gc: `Scalar` or `float`
        :param k_at_depth: value for susceptibility at depth, see `DomainBuilder`.
        :type k_at_depth: ``float`` or ``None``
        :param rho_at_depth: value for density at depth, see `DomainBuilder`.
        :type rho_at_depth: ``float`` or ``None``
        """
        self.logger.info('Retrieving domain...')
        dom = domainbuilder.getDomain()
        DIM = dom.getDim()
        trafo = makeTransformation(dom, domainbuilder.getReferenceSystem())
        #========================
        self.logger.info('Creating mappings ...')
        rho_mask = domainbuilder.getSetDensityMask()
        if rho_at_depth:
            rho2 = rho_mask * rho_at_depth + (1 - rho_mask) * rho0
        elif rho0:
            rho2 = (1 - rho_mask) * rho0
        else:
            rho2 = 0

        k_mask = domainbuilder.getSetSusceptibilityMask()
        if k_at_depth:
            k2 = k_mask * k_at_depth + (1 - k_mask) * k0
        elif k0:
            k2 = (1 - k_mask) * k0
        else:
            k2 = 0

        rho_mapping = DensityMapping(dom,
                                     rho0=rho2,
                                     drho=drho,
                                     z0=rho_z0,
                                     beta=rho_beta)
        rho_scale_mapping = rho_mapping.getTypicalDerivative()
        self.logger.debug("rho_scale_mapping = %s" % rho_scale_mapping)
        k_mapping = SusceptibilityMapping(dom,
                                          k0=k2,
                                          dk=dk,
                                          z0=k_z0,
                                          beta=k_beta)
        k_scale_mapping = k_mapping.getTypicalDerivative()
        self.logger.debug("k_scale_mapping = %s" % k_scale_mapping)
        #========================
        self.logger.info("Setting up regularization...")

        if w1 is None:
            w1 = np.ones((2, DIM))

        wc = es.Data(0., (2, 2), es.Function(dom))
        if w_gc is None:
            wc[0, 1] = 1
        else:
            wc[0, 1] = w_gc

        reg_mask = es.Data(0., (2, ), es.Solution(dom))
        reg_mask[self.DENSITY] = rho_mask
        reg_mask[self.SUSCEPTIBILITY] = k_mask
        regularization=Regularization(dom, numLevelSets=2,\
                               w0=w0, w1=w1,wc=wc, location_of_set_m=reg_mask, coordinates=trafo)
        #====================================================================
        self.logger.info("Retrieving gravity surveys...")
        surveys = domainbuilder.getGravitySurveys()
        g = []
        w = []
        for g_i, sigma_i in surveys:
            w_i = es.safeDiv(1., sigma_i)
            if g_i.getRank() == 0:
                g_i = g_i * es.kronecker(DIM)[DIM - 1]
            if w_i.getRank() == 0:
                w_i = w_i * es.kronecker(DIM)[DIM - 1]
            g.append(g_i)
            w.append(w_i)
            self.logger.debug("Added gravity survey:")
            self.logger.debug("g = %s" % g_i)
            self.logger.debug("sigma = %s" % sigma_i)
            self.logger.debug("w = %s" % w_i)

        self.logger.info("Setting up gravity model...")
        gravity_model = GravityModel(
            dom,
            w,
            g,
            fixPotentialAtBottom=self._fixGravityPotentialAtBottom,
            coordinates=trafo)
        gravity_model.rescaleWeights(rho_scale=rho_scale_mapping)
        #====================================================================
        self.logger.info("Retrieving magnetic field surveys...")
        d_b = es.normalize(domainbuilder.getBackgroundMagneticFluxDensity())
        surveys = domainbuilder.getMagneticSurveys()
        B = []
        w = []
        for B_i, sigma_i in surveys:
            w_i = es.safeDiv(1., sigma_i)
            if self.magnetic_intensity_data:
                if not B_i.getRank() == 0:
                    B_i = es.length(B_i)
                if not w_i.getRank() == 0:
                    w_i = length(w_i)
            else:
                if B_i.getRank() == 0:
                    B_i = B_i * d_b
                if w_i.getRank() == 0:
                    w_i = w_i * d_b
            B.append(B_i)
            w.append(w_i)
            self.logger.debug("Added magnetic survey:")
            self.logger.debug("B = %s" % B_i)
            self.logger.debug("sigma = %s" % sigma_i)
            self.logger.debug("w = %s" % w_i)

        self.logger.info("Setting up magnetic model...")
        if self.self_demagnetization:
            magnetic_model = SelfDemagnetizationModel(
                dom,
                w,
                B,
                domainbuilder.getBackgroundMagneticFluxDensity(),
                fixPotentialAtBottom=self._fixMagneticPotentialAtBottom,
                coordinates=trafo)
        else:
            if self.magnetic_intensity_data:
                magnetic_model = MagneticIntensityModel(
                    dom,
                    w,
                    B,
                    domainbuilder.getBackgroundMagneticFluxDensity(),
                    fixPotentialAtBottom=self._fixMagneticPotentialAtBottom,
                    coordinates=trafo)
            else:
                magnetic_model = MagneticModel(
                    dom,
                    w,
                    B,
                    domainbuilder.getBackgroundMagneticFluxDensity(),
                    fixPotentialAtBottom=self._fixMagneticPotentialAtBottom,
                    coordinates=trafo)
        magnetic_model.rescaleWeights(k_scale=k_scale_mapping)
        #====================================================================
        self.logger.info("Setting cost function...")
        self.setCostFunction(
            InversionCostFunction(regularization,
                                  ((rho_mapping, self.DENSITY),
                                   (k_mapping, self.SUSCEPTIBILITY)),
                                  ((gravity_model, 0), (magnetic_model, 1))))
コード例 #24
0
ファイル: seismic.py プロジェクト: aishugang/esys-escript
    def __init__(self,
                 domain,
                 v_p,
                 v_s,
                 wavelet,
                 source_tag,
                 source_vector=[0., 0., 1.],
                 eps=0.,
                 gamma=0.,
                 delta=0.,
                 rho=1.,
                 dt=None,
                 u0=None,
                 v0=None,
                 absorption_zone=None,
                 absorption_cut=1e-2,
                 lumping=True,
                 disable_fast_assemblers=False):
        """
        initialize the VTI wave solver

        :param domain: domain of the problem
        :type domain: `Domain`
        :param v_p: vertical p-velocity field
        :type v_p: `escript.Scalar`
        :param v_s: vertical s-velocity field
        :type v_s: `escript.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 source_vector: source orientation vector
        :param eps: first Thompsen parameter
        :param delta: second Thompsen parameter
        :param gamma: third Thompsen parameter
        :param rho: density
        :param dt: time step size. If not present a suitable time step size is calculated.
        :param u0: initial solution. If not present zero is used.
        :param v0: 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.
        :param disable_fast_assemblers: if True, forces use of slower and more general PDE assemblers
        :type disable_fast_assemblers: `boolean`
        """
        DIM = domain.getDim()
        self.fastAssembler = hasattr(
            domain, "createAssembler") and not disable_fast_assemblers
        f = createAbsorptionLayerFunction(
            escript.Function(domain).getX(), absorption_zone, absorption_cut)

        f = escript.interpolate(f, escript.Function(domain))

        v_p = v_p * f
        v_s = v_s * f

        if u0 == None:
            u0 = escript.Vector(0., escript.Solution(domain))
        else:
            u0 = escript.interpolate(p0, escript.Solution(domain))

        if v0 == None:
            v0 = escript.Vector(0., escript.Solution(domain))
        else:
            v0 = escript.interpolate(v0, escript.Solution(domain))

        if dt == None:
            dt = min((1. / 5.) * min(escript.inf(domain.getSize() / v_p),
                                     escript.inf(domain.getSize() / v_s)),
                     wavelet.getTimeScale())

        super(VTIWave, self).__init__(dt, u0=u0, v0=v0, t0=0.)

        self.__wavelet = wavelet

        self.c33 = v_p**2 * rho
        self.c44 = v_s**2 * rho
        self.c11 = (1 + 2 * eps) * self.c33
        self.c66 = (1 + 2 * gamma) * self.c44
        self.c13 = escript.sqrt(2 * self.c33 * (self.c33 - self.c44) * delta +
                                (self.c33 - self.c44)**2) - self.c44
        self.c12 = self.c11 - 2 * self.c66

        if self.fastAssembler:
            C = [("c11", self.c11), ("c12", self.c12), ("c13", self.c13),
                 ("c33", self.c33), ("c44", self.c44), ("c66", self.c66)]
            if "speckley" in domain.getDescription().lower():
                C = [(n, escript.interpolate(d,
                                             escript.ReducedFunction(domain)))
                     for n, d in C]
            self.__mypde = lpde.WavePDE(domain, C)
        else:
            self.__mypde = lpde.LinearPDESystem(domain)
            self.__mypde.setValue(X=self.__mypde.createCoefficient('X'))

        if lumping:
            self.__mypde.getSolverOptions().setSolverMethod(
                lpde.SolverOptions.HRZ_LUMPING)
        self.__mypde.setSymmetryOn()
        self.__mypde.setValue(D=rho * escript.kronecker(DIM))
        self.__source_tag = source_tag

        if DIM == 2:
            source_vector = [source_vector[0], source_vector[2]]

        self.__r = escript.Vector(
            0, escript.DiracDeltaFunctions(self.__mypde.getDomain()))
        self.__r.setTaggedValue(self.__source_tag, source_vector)
コード例 #25
0
ファイル: seismic.py プロジェクト: aishugang/esys-escript
    def __init__(self,
                 domain,
                 v_p,
                 v_s,
                 wavelet,
                 source_tag,
                 source_vector=[0., 1.],
                 eps=0.,
                 delta=0.,
                 theta=0.,
                 rho=1.,
                 dt=None,
                 u0=None,
                 v0=None,
                 absorption_zone=300 * U.m,
                 absorption_cut=1e-2,
                 lumping=True):
        """
           initialize the TTI wave solver

           :param domain: domain of the problem
           :type domain: `Domain`
           :param v_p: vertical p-velocity field
           :type v_p: `escript.Scalar`
           :param v_s: vertical s-velocity field
           :type v_s: `escript.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 source_vector: source orientation vector
           :param eps: first Thompsen parameter
           :param delta: second Thompsen parameter
           :param theta: tilting (in Rad)
           :param rho: density
           :param dt: time step size. If not present a suitable time step size is calculated.
           :param u0: initial solution. If not present zero is used.
           :param v0: 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.
           """
        cos = escript.cos
        sin = escript.sin
        DIM = domain.getDim()
        if not DIM == 2:
            raise ValueError("Only 2D is supported.")
        f = createAbsorptionLayerFunction(
            escript.Function(domain).getX(), absorption_zone, absorption_cut)

        v_p = v_p * f
        v_s = v_s * f

        if u0 == None:
            u0 = escript.Vector(0., escript.Solution(domain))
        else:
            u0 = escript.interpolate(p0, escript.Solution(domain))

        if v0 == None:
            v0 = escript.Vector(0., escript.Solution(domain))
        else:
            v0 = escript.interpolate(v0, escript.Solution(domain))

        if dt == None:
            dt = min((1. / 5.) * min(escript.inf(domain.getSize() / v_p),
                                     escript.inf(domain.getSize() / v_s)),
                     wavelet.getTimeScale())

        super(TTIWave, self).__init__(dt, u0=u0, v0=v0, t0=0.)

        self.__wavelet = wavelet

        self.__mypde = lpde.LinearPDESystem(domain)
        if lumping:
            self.__mypde.getSolverOptions().setSolverMethod(
                lpde.SolverOptions.HRZ_LUMPING)
        self.__mypde.setSymmetryOn()
        self.__mypde.setValue(D=rho * escript.kronecker(DIM),
                              X=self.__mypde.createCoefficient('X'))
        self.__source_tag = source_tag

        self.__r = escript.Vector(
            0, escript.DiracDeltaFunctions(self.__mypde.getDomain()))
        self.__r.setTaggedValue(self.__source_tag, source_vector)

        c0_33 = v_p**2 * rho
        c0_66 = v_s**2 * rho
        c0_11 = (1 + 2 * eps) * c0_33
        c0_13 = escript.sqrt(2 * c0_33 * (c0_33 - c0_66) * delta +
                             (c0_33 - c0_66)**2) - c0_66

        self.c11 = c0_11 * cos(theta)**4 - 2 * c0_13 * cos(
            theta)**4 + 2 * c0_13 * cos(theta)**2 + c0_33 * sin(
                theta)**4 - 4 * c0_66 * cos(theta)**4 + 4 * c0_66 * cos(
                    theta)**2
        self.c13 = -c0_11 * cos(theta)**4 + c0_11 * cos(
            theta)**2 + c0_13 * sin(theta)**4 + c0_13 * cos(
                theta)**4 - c0_33 * cos(theta)**4 + c0_33 * cos(
                    theta)**2 + 4 * c0_66 * cos(theta)**4 - 4 * c0_66 * cos(
                        theta)**2
        self.c16 = (-2 * c0_11 * cos(theta)**2 - 4 * c0_13 * sin(theta)**2 +
                    2 * c0_13 + 2 * c0_33 * sin(theta)**2 - 8 * c0_66 *
                    sin(theta)**2 + 4 * c0_66) * sin(theta) * cos(theta) / 2
        self.c33 = c0_11 * sin(theta)**4 - 2 * c0_13 * cos(
            theta)**4 + 2 * c0_13 * cos(theta)**2 + c0_33 * cos(
                theta)**4 - 4 * c0_66 * cos(theta)**4 + 4 * c0_66 * cos(
                    theta)**2
        self.c36 = (2 * c0_11 * cos(theta)**2 - 2 * c0_11 +
                    4 * c0_13 * sin(theta)**2 - 2 * c0_13 +
                    2 * c0_33 * cos(theta)**2 + 8 * c0_66 * sin(theta)**2 -
                    4 * c0_66) * sin(theta) * cos(theta) / 2
        self.c66 = -c0_11 * cos(theta)**4 + c0_11 * cos(
            theta)**2 + 2 * c0_13 * cos(theta)**4 - 2 * c0_13 * cos(
                theta)**2 - c0_33 * cos(theta)**4 + c0_33 * cos(
                    theta)**2 + c0_66 * sin(theta)**4 + 3 * c0_66 * cos(
                        theta)**4 - 2 * c0_66 * cos(theta)**2
コード例 #26
0
    def __init__(self,
                 domain,
                 omega,
                 x,
                 Z,
                 eta=None,
                 w0=1.,
                 mu=4 * math.pi * 1e-7,
                 sigma0=0.01,
                 airLayerLevel=None,
                 fixAirLayer=False,
                 coordinates=None,
                 tol=1e-8,
                 saveMemory=False,
                 directSolver=True):
        """
        initializes a new forward model.

        :param domain: domain of the model
        :type domain: `Domain`
        :param omega: frequency
        :type omega: positive ``float``
        :param x: coordinates of measurements
        :type x: ``list`` of ``tuple`` with ``float``
        :param Z: measured impedance (possibly scaled)
        :type Z: ``list`` of ``complex``
        :param eta: spatial confidence radius
        :type eta:  positive ``float`` or ``list`` of  positive ``float``
        :param w0: confidence factors for meassurements.
        :type w0: ``None`` or a list of positive ``float``
        :param mu: permeability
        :type mu: ``float``
        :param sigma0: background conductivity
        :type sigma0: ``float``
        :param airLayerLevel: position of the air layer from to bottom of the domain. If
                              not set the air layer starts at the top of the domain
        :type airLayerLevel: ``float`` or ``None``        
        :param fixAirLayer: fix air layer (TM mode)
        :type fixAirLayer: ``bool``
        :param coordinates: defines coordinate system to be used (not supported yet)
        :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation`
        :param tol: tolerance of underlying PDE
        :type tol: positive ``float``
        :param saveMemory: if true stiffness matrix is deleted after solution
                           of the PDE to minimize memory use. This will
                           require more compute time as the matrix needs to be
                           reallocated at each iteration.
        :type saveMemory: ``bool``
        :param directSolver: if true a direct solver (rather than an iterative
                             solver) will be used to solve the PDE
        :type directSolver: ``bool``
        """
        super(MT2DBase, self).__init__()
        self.__trafo = coords.makeTransformation(domain, coordinates)
        if not self.getCoordinateTransformation().isCartesian():
            raise ValueError(
                "Non-Cartesian coordinates are not supported yet.")
        if len(x) != len(Z):
            raise ValueError(
                "Number of data points and number of impedance values don't match."
            )

        if eta is None:
            eta = escript.sup(domain.getSize()) * 0.45

        if isinstance(eta, float) or isinstance(eta, int):
            eta = [float(eta)] * len(Z)
        elif not len(eta) == len(Z):
            raise ValueError(
                "Number of confidence radii and number of impedance values don't match."
            )

        if isinstance(w0, float) or isinstance(w0, int):
            w0 = [float(w0)] * len(Z)
        elif not len(w0) == len(Z):
            raise ValueError(
                "Number of confidence factors and number of impedance values don't match."
            )

        self.__domain = domain
        self._omega_mu = omega * mu
        self._ks = escript.sqrt(self._omega_mu * sigma0 / 2.)

        xx = escript.Function(domain).getX()
        totalS = 0
        self._Z = [
            escript.Scalar(0., escript.Function(domain)),
            escript.Scalar(0., escript.Function(domain))
        ]
        self._weight = escript.Scalar(0., escript.Function(domain))

        for s in range(len(Z)):
            chi = self.getWeightingFactor(xx, 1., x[s], eta[s])
            f = escript.integrate(chi)
            if f < eta[s]**2 * 0.01:
                raise ValueError(
                    "Zero weight (almost) for data point %s. Change eta or refine mesh."
                    % (s, ))
            w02 = w0[s] / f
            totalS += w02
            self._Z[0] += chi * Z[s].real
            self._Z[1] += chi * Z[s].imag
            self._weight += chi * w02 / (abs(Z[s])**2)

        if not totalS > 0:
            raise ValueError(
                "Scaling of weight factors failed as sum is zero.")

        DIM = domain.getDim()
        z = domain.getX()[DIM - 1]
        self._ztop = escript.sup(z)
        self._zbottom = escript.inf(z)
        if airLayerLevel is None:
            airLayerLevel = self._ztop
        self._airLayerLevel = airLayerLevel

        # botton:
        mask0 = escript.whereZero(z - self._zbottom)
        r = mask0 * [
            escript.exp(self._ks * (self._zbottom - airLayerLevel)) *
            escript.cos(self._ks * (self._zbottom - airLayerLevel)),
            escript.exp(self._ks * (self._zbottom - airLayerLevel)) *
            escript.sin(self._ks * (self._zbottom - airLayerLevel))
        ]

        #top:
        if fixAirLayer:
            mask1 = escript.whereNonNegative(z - airLayerLevel)
            r += mask1 * [1, 0]
        else:
            mask1 = escript.whereZero(z - self._ztop)
            r += mask1 * [
                self._ks * (self._ztop - airLayerLevel) + 1, self._ks *
                (self._ztop - airLayerLevel)
            ]

        self._q = (mask0 + mask1) * [1, 1]
        self._r = r
        #====================================
        self.__tol = tol
        self._directSolver = directSolver
        self._saveMemory = saveMemory
        self.__pde = None
        if not saveMemory:
            self.__pde = self.setUpPDE()