Example #1
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: `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()))
Example #2
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])
Example #3
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
Example #4
0
 def getBoundaryNodesPositions(self, tag_name="bound"):
     """
   get a dictionary contains FE boundary node IDs and corresponding positions
   use data on "Solution" FunctionSpace to export FE node IDs (DataPoint IDs)
   note that though "ContinousFunction" and "Solution" FunctionSpace have save number of DataPoints,
   their numbering order are not the same!!!
   Therefore, always use coordiates and IDs of DataPoints on "Solution" for data communication
   """
     tag = self.getDomain().getTag(tag_name)
     # get "Solution" FunctinonSpace
     fs = escript.Solution(self.getDomain())
     # get coordinates with "Solution" FunctionSpace numbering order
     # fs and fs.getX().getFunctionSpace() are the same
     x = fs.getX()
     # get domain FunctionSpace, note below is different from fs.getX().getFunctionSpace()
     domFS = fs.getDomain().getX().getFunctionSpace()
     num = x.getNumberOfDataPoints()
     pos = {}
     for i in xrange(num):
         refId = fs.getReferenceIDFromDataPointNo(i)
         # domain FunctionSpace DataPoint IDs = RefId-1
         if domFS.getTagFromDataPointNo(refId - 1) == tag:
             pos[i] = x.getTupleForDataPoint(i)
     return pos
Example #5
0
    def __init__(self,
                 domain,
                 mode,
                 freq_def,
                 tags,
                 rho,
                 rho_1d,
                 ifc_1d,
                 xstep=100,
                 zstep=100,
                 maps=None,
                 plot=False,
                 limits=None):
        """
    DESCRIPTION:
    ------------
    Constructor which initialises the 2D magnetotelluric class:
    (*) check for argument type
    (*) check for valid argument values
    (*) initialises required values

    ARGUMENTS:
    ----------
    param  domain       :: the 2d mesh domain
    type   domain       :: ``escript data object``

    param  mode         :: TE or TM mode
    type   mode         :: ``string``

    param  freq_def     :: highest/lowest frequency & points per decade
    type   freq_def     :: ``dictionary``

    param  tags         :: the tag names of the regions defined in the mesh
    type   tags         :: ``list``

    param  rho          :: the resistivity values of the regions in the mesh
    type   rho          :: ``list``

    param  rho_1d       :: the resistivity values at the left & right boundary
    type   rho_1d       :: ``dictionary``

    param  ifc_1d       :: the layer interface depths of the left & right boundary
    type   ifc_1d       :: ``dictionary``

    param  xstep        :: user-defined step size for horizontal sample list
    type   xstep        :: ``number``  (optional)

    param  zstep        :: user-defined step size for vertical sample list
    type   zstep        :: ``number``  (optional)

    param  maps         :: list with user-defined  functions which map the resistivity for each region
    type   maps         :: ``list``    (optional)

    param  plot         :: user-defined flag to show a plot of apparent resistivity and phase at each frequency
    type   plot         :: ``boolean`` (optional)



    DATA ATTRIBUTES:
    ----------------
    self.domain         :: escript data object of mesh
    self.X              :: escript data object with all mesh coordinates
    self.mode           :: string with TE or TM mode
    self.xmin           :: float with x-coordinate minimum
    self.xmax           :: float with x-coordinate maximum
    self.zmin           :: float with z-coordinate minimum
    self.zmax           :: float with z-coordinate maximum
    self.zstep          :: number with sample step in vertical direction
    self.xstep          :: number with sample step in horizontal direction
    self.rho            :: list with resistivity values of all regions
    self.rho_1d         :: dictionary with resistivity values at boundaries left/right
    self.ifc_1d         :: dictionary with interface depths at boundaries left/right
    self.plot           :: boolean flag to show plots of apparent resistivity and phase
    self.sigma          :: escript data object with the conductivity model (based on 'rho' and 'maps')
    self.frequencies    :: list of sounding frequencies
    self.boundary_mask  :: Dirichlet mask at boundaries
    """

        if not HAVE_FINLEY:
            raise ImportError("Finley module not available")
        #make python3 compatible, since long disappeared in python 3
        if sys.version_info[0] == 3:
            long_type = int
        else:
            long_type = long
        # ---
        # Checks
        # ---

        # Types:
        if not isinstance(domain, escript.Domain):
            raise ValueError("Input parameter DOMAIN must be an Escript mesh")
        if not isinstance(mode, str):
            raise ValueError("Input parameter MODE must be a string")
        if not isinstance(freq_def, dict) or len(freq_def) != 3:
            raise ValueError(
                "Input parameter FREQ_DEF must be a dictionary with length 3")
        if not isinstance(tags, list) or not all(
                isinstance(t, str) for t in tags):
            raise ValueError("Input parameter TAGS must be a list of strings")
        if not isinstance(rho, list) or not all(
                isinstance(d, (int, long_type, float)) for d in rho):
            raise ValueError("Input parameter RHO must be a list of numbers")
        if not isinstance(rho_1d, dict) or len(rho_1d) != 2:
            raise ValueError(
                "Input parameter RHO_1D must be a dictionary with length 2")
        if not isinstance(ifc_1d, dict) or len(ifc_1d) != 2:
            raise ValueError(
                "Input parameter IFC_1D must be a dictionary with length 2")
        if not isinstance(xstep, (int, long_type, float)):
            raise ValueError("Optional input parameter XSTEP must be a number")
        if not isinstance(zstep, (int, long_type, float)):
            raise ValueError("Optional input parameter ZSTEP must be a number")
        if maps is not None:
            if not isinstance(maps, list) or not all(
                    isinstance(m, (types.FunctionType, types.NoneType))
                    for m in maps):
                raise ValueError(
                    "Optional input parameter MAPS must be a list of Functions or Nones"
                )
        if plot is not None:
            if not isinstance(plot, bool):
                raise ValueError(
                    "Optional input parameter PLOT must be True or False")

        # Values:
        if mode.upper() != "TE" and mode.upper() != "TM":  # Check mode:
            raise ValueError(
                "Input parameter mode must be either 'TE' or 'TM'")
        if not 'high' in freq_def and not 'low' in freq_def and not 'step' in freq_def:
            raise ValueError(
                "Input dictionary FREQ_DEF must have keys 'high', 'low' and 'step' defined"
            )
        if freq_def['high'] < freq_def['low']:
            raise ValueError(
                "High frequency value is smaller than low frequency value in input parameter FREQ_DEF"
            )
        if freq_def['step'] < 1:
            raise ValueError(
                "Step frequency value is smaller than 1 in input parameter FREQ_DEF"
            )
        if not all(r > 0 for r in rho):  # Check resistivity values:
            raise ValueError("Input parameter RHO must be all positive")
        if len(rho) != len(tags):  # Check resistivity list-length:
            raise ValueError(
                "Input parameter RHO must have the same length as input parameter TAGS"
            )
        if not 'left' in rho_1d and not 'right' in rho_1d:
            raise ValueError(
                "Input dictionary RHO_1D must have keys 'left' and 'right' defined"
            )
        if not 'left' in ifc_1d and not 'right' in ifc_1d:
            raise ValueError(
                "Input dictionary IFC_1D must have keys 'left' and 'right' defined"
            )
        if len(ifc_1d['left']) - 1 != len(rho_1d['left']) and len(
                ifc_1d['right']) - 1 != len(rho_1d['right']):
            raise ValueError(
                "Lists with values in input dictionary RHO_1D must have length equal to IFC_1D"
            )
        if xstep < 0.5:  # Step size should be non-zero but should not be smaller than 0.5m:
            raise ValueError("Input parameter XSTEP must be at least 0.5")
        if zstep < 0.5:  # Step size should be non-zero but should not be smaller than 0.5m:
            raise ValueError("Input parameter ZSTEP must be at least 0.5")

        # ---
        # Domain coordinates & tags:
        # ---

        # Extract the model coordinates..
        X = escript.Solution(domain).getX()

        # Get the Min/Max coordinates:
        xmin = escript.inf(X[0])
        xmax = escript.sup(X[0])
        zmin = escript.inf(X[1])
        zmax = escript.sup(X[1])

        # Get the tag names from the mesh file
        mesh_tags = escript.getTagNames(domain)

        if xmin >= xmax or zmin >= zmax:
            raise ValueError("The mesh limits are not valid (min >= max)")
        if zmin >= 0:
            raise ValueError(
                "The mesh must be defined with a negative vertical axis")
        if not set(mesh_tags) == set(tags):
            print("user-tags:", tags)
            print("mesh-tags:", mesh_tags)
            raise ValueError(
                "Input parameter TAGS does not match the tags defined in the mesh"
            )

        # ---
        # Define the boundary mask:
        # ---

        boundary_mask = self.__setBoundaryMask(X)

        # ---
        # Calculate list of sounding frequencies:
        # ---

        frequencies = self.__getSoundingFrequencies(freq_def)

        # ---
        # Tag the domain with conductivity maps:
        # ---

        sigma_model = self.__tagDomain(domain, X, tags, rho, maps)

        # Check for valid values
        if escript.inf(sigma_model) < 0 or escript.sup(sigma_model) < 0:
            raise ValueError("Negative conductivity encountered")
        if cmath.isnan( escript.inf(sigma_model) ) or \
           cmath.isnan( escript.sup(sigma_model) ) or \
           cmath.isinf( escript.sup(sigma_model) ):
            raise ValueError("The conductivity model contains NaNs or INFs")

        # ---
        # Projector and Locator objects.
        # ---

        print("Setting up Escript Locator and Projector objects...")

        # Setup a list with sample points along the vertical mesh extent, bottom to top:
        xsample = self.__getSamplePoints(escript.inf(X[0]),
                                         escript.sup(X[0]),
                                         xstep,
                                         constant=0.0)

        # Get the locations of mesh points at the surface via the Locator object
        # operating on the continuous function-space (i.e. nodes) of the domain.
        loc = pdetools.Locator(escript.ContinuousFunction(domain), xsample)

        # Instantiate the Projector class with smoothing on (fast=False);
        # the Projector is used to calculate the gradient correctly.
        proj = pdetools.Projector(domain, reduce=False, fast=False)

        # ---
        # Print information:
        # ---

        print("")
        print("=" * 72)
        print("Escript MT2D, version", self.__version)
        print("=" * 72)
        print("Mesh XMin/XMax       : ", xmin, xmax)
        print("Mesh ZMin/ZMax       : ", zmin, zmax)
        print("Number of Tags       : ", len(tags))
        print("Mapping              : ", {
            True: 'Yes',
            False: 'No'
        }[maps is not None])
        print("Conductivity Model   : ", sigma_model)
        print("Nr of Frequencies    : ", len(frequencies))
        print("Start/End/Step (Hz)  : ", freq_def["high"], freq_def["low"],
              freq_def["step"])
        print("Mode                 : ", mode.upper())
        print("Solver               : ", MT_2D._solver)
        print("Show plots           : ", plot)
        print("=" * 72)
        print("")

        if self._debug:
            print("Mesh-Info     : ")
            print(domain.print_mesh_info(full=False))

        # ---
        # Set all required variables as data attributes
        # ---

        self.domain = domain
        self.X = X
        self.mode = mode
        self.xmin = xmin
        self.xmax = xmax
        self.zmin = zmin
        self.zmax = zmax
        self.zstep = zstep
        self.xstep = xstep
        self.rho = rho
        self.rho_1d = rho_1d
        self.ifc_1d = ifc_1d
        self.plot = plot
        self.limits = limits
        self.sigma = sigma_model
        self.frequencies = frequencies
        self.boundary_mask = boundary_mask
        self.proj = proj
        self.loc = loc
Example #6
0
    def __init__(self,
                 domain,
                 v_p,
                 wavelet,
                 source_tag,
                 source_vector=[1., 0.],
                 eps=0.,
                 delta=0.,
                 azimuth=0.,
                 dt=None,
                 p0=None,
                 v0=None,
                 absorption_zone=300 * U.m,
                 absorption_cut=1e-2,
                 lumping=True):
        """
           initialize the HTI wave solver

           :param domain: domain of the problem
           :type domain: `Doamin`
           :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 azimuth: azimuth (rotation around verticle axis)
           :param gamma: third Thompsen parameter
           :param rho: density
           :param dt: time step size. If not present a suitable time step size is calculated.
           :param p0: initial solution (Q(t=0), P(t=0)). 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.
           """
        DIM = domain.getDim()
        f = createAbsorptionLayerFunction(v_p.getFunctionSpace().getX(),
                                          absorption_zone, absorption_cut)

        self.v2_p = v_p**2
        self.v2_t = self.v2_p * escript.sqrt(1 + 2 * delta)
        self.v2_n = self.v2_p * (1 + 2 * eps)

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

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

        if dt == None:
            dt = min(
                min(escript.inf(domain.getSize() / escript.sqrt(self.v2_p)),
                    escript.inf(domain.getSize() / escript.sqrt(self.v2_t)),
                    escript.inf(domain.getSize() / escript.sqrt(self.v2_n))),
                wavelet.getTimeScale()) * 0.2

        super(SonicHTIWave, self).__init__(dt, u0=p0, 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=escript.kronecker(2),
                              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)
Example #7
0
    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
Example #8
0
    def __init__(self,
                 domain,
                 v_p,
                 v_s,
                 wavelet,
                 source_tag,
                 source_vector=[1., 0., 0.],
                 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
       """
        DIM = domain.getDim()
        self.fastAssembler = hasattr(
            domain, "createAssembler") and not disable_fast_assemblers
        f = createAbsorptionLayerFunction(v_p.getFunctionSpace().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(HTIWave, 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.c23 = self.c33 - 2 * self.c66

        if self.fastAssembler:
            C = [("c11", self.c11), ("c23", self.c23), ("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)
Example #9
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))))