Example #1
0
    def __init__(self, domain, w, data,  coordinates=None,
                                 fixPotentialAtBottom=False,
                                 tol=1e-8):
        """
        initializes a new forward model with potential.

        :param domain: domain of the model
        :type domain: `Domain`
        :param w: data weighting factors
        :type w: ``Vector`` or list of ``Vector``
        :param data: data
        :type data: ``Vector`` or list of ``Vector``
        :param coordinates: defines coordinate system to be used
        :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation`
        :param fixPotentialAtBottom: if true potential is fixed to zero at the bottom of the domain
                                     in addition to the top.
        :type fixPotentialAtBottom: ``bool``
        :param tol: tolerance of underlying PDE
        :type tol: positive ``float``
        """
        super(ForwardModelWithPotential, self).__init__()
        self.__domain = domain
        self.__trafo = makeTransformation(domain, coordinates)

        try:
            n=len(w)
            m=len(data)
            if not m == n:
                raise ValueError("Length of weight and data must be the same.")
            self.__weight = w
            self.__data = data
        except TypeError:
            self.__weight = [w]
            self.__data = [data]

        BX = boundingBox(domain)
        DIM = domain.getDim()
        x = domain.getX()
        self.__pde=LinearSinglePDE(domain)
        self.__pde.getSolverOptions().setTolerance(tol)
        self.__pde.setSymmetryOn()
        z=x[DIM-1]
        q0=whereZero(z-BX[DIM-1][1])
        if fixPotentialAtBottom: q0+=whereZero(z-BX[DIM-1][0])
        self.__pde.setValue(q=q0)

        self.edge_lengths=np.asarray(boundingBoxEdgeLengths(domain))
        self.diameter=1./sqrt(sum(1./self.edge_lengths**2))

        self.__origweight=[]
        for s in range(len(self.__weight)):
            # save a copy of the original weights in case of rescaling
            self.__origweight.append(1.*self.__weight[s])

        if not self.__trafo.isCartesian():
            fd=1./self.__trafo.getScalingFactors()
            fw=self.__trafo.getScalingFactors()*sqrt(self.__trafo.getVolumeFactor())
            for s in range(len(self.__weight)):
                self.__weight[s] = fw * self.__weight[s]
                self.__data[s]   = fd * self.__data[s]
Example #2
0
    def __init__(self, domain, locator, delphiIn, sampleTags, phiPrimary,
                 sigmaPrimary, w=1., coordinates=None, tol=1e-8,
                 saveMemory=True, b=None):
        """
        setup new forward model
        
        :param domain: the domain of the model
        :type: escript domain
        :param locator: contains locator to the measurement pairs
        :type: `list` of ``Locator``
        :param: delphiIn: this is v_pq, the potential difference for the
                          current source and a set of measurement pairs.
                          A list of measured potential differences is expected.
                          Note this should be the secondary potential only.
        :type delphiIn: tuple
        :param sampleTags: tags of measurement points from which potential
                           differences will be calculated.
        :type sampleTags: list of tuples
        :param phiPrimary: primary potential.
        :type phiPrimary: `Scalar`
        """
        super(DcRes, self).__init__()

        if not isinstance(sampleTags, list):
            raise ValueError("sampleTags must be a list.")
        if not len(sampleTags) == len(delphiIn):
            raise ValueError("sampleTags and delphiIn must have the same length.")
        if not len(sampleTags)>0:
            raise ValueError("sampleTags list is empty.")
        if not isinstance(sampleTags[0], tuple) and not isinstance(sampleTags[0], list):
            raise ValueError("sampleTags must be a list of tuples or a list of lists.")

        if isinstance(w, float) or isinstance(w, int):
            w = [float(w) for z in delphiIn]
            self.__w = w
        else:
            self.__w = w
        if not len(w) == len(delphiIn):
            raise ValueError("Number of confidence factors and number of potential input values don't match.")

        self.__trafo = makeTransformation(domain, coordinates)
        if not self.getCoordinateTransformation().isCartesian():
            raise ValueError("Non-Cartesian Coordinates are not supported yet.")
        if not isinstance(locator, Locator):
            raise ValueError("locator must be an escript locator object")

        self.__domain = domain
        self.__tol = tol
        self.__locator = locator
        self.delphiIn = delphiIn
        self.__sampleTags = sampleTags
        self.__sigmaPrimary = sigmaPrimary
        self.__phiPrimary = phiPrimary
        self.__pde = None
        if not saveMemory:
            self.__pde=self.setUpPDE()
Example #3
0
    def __init__(self,
                 domain,
                 p0=0.,
                 level0=0,
                 gravity0=-9.81 * U.m * U.sec**(-2),
                 background_density=2670 * U.kg * U.m**(-3),
                 gravity_constant=U.Gravitational_Constant,
                 coordinates=None,
                 tol=1e-8):
        """
        :param domain: domain of the model
        :type domain: `Domain`
        :param p0: pressure at level0
        :type p0: scalar `Data` or ``float``
        :param background_density: defines background_density in kg/m^3
        :type background_density: ``float``
        :param coordinates: defines coordinate system to be used
        :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation`
        :param tol: tolerance of underlying PDE
        :type tol: positive ``float``
        :param level0: pressure for z>=`level0` is set to zero.
        :type level0: ``float``
        :param gravity0: vertical background gravity at `level0`
        :type gravity0: ``float``
        """
        DIM = domain.getDim()
        self.__domain = domain
        self.__trafo = makeTransformation(domain, coordinates)
        self.__pde = LinearSinglePDE(domain)
        self.__pde.getSolverOptions().setTolerance(tol)
        self.__pde.setSymmetryOn()

        z = domain.getX()[DIM - 1]
        self.__pde.setValue(q=whereNonNegative(z - level0), r=p0)

        fw = self.__trafo.getScalingFactors(
        )**2 * self.__trafo.getVolumeFactor()
        A = self.__pde.createCoefficient("A")
        for i in range(DIM):
            A[i, i] = fw[i]
        self.__pde.setValue(A=A)
        z = Function(domain).getX()[DIM - 1]
        self.__g_b = 4 * PI * gravity_constant / self.__trafo.getScalingFactors(
        )[DIM - 1] * background_density * (level0 - z) + gravity0
        self.__rho_b = background_density
Example #4
0
    def __init__(self, domain, p0=0., level0=0, gravity0=-9.81*U.m*U.sec**(-2),
                 background_density=2670* U.kg*U.m**(-3),
                 gravity_constant=U.Gravitational_Constant,
                 coordinates=None, tol=1e-8):
        """
        :param domain: domain of the model
        :type domain: `Domain`
        :param p0: pressure at level0
        :type p0: scalar `Data` or ``float``
        :param background_density: defines background_density in kg/m^3
        :type background_density: ``float``
        :param coordinates: defines coordinate system to be used
        :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation`
        :param tol: tolerance of underlying PDE
        :type tol: positive ``float``
        :param level0: pressure for z>=`level0` is set to zero.
        :type level0: ``float``
        :param gravity0: vertical background gravity at `level0`
        :type gravity0: ``float``
        """
        DIM=domain.getDim()
        self.__domain = domain
        self.__trafo=makeTransformation(domain, coordinates)
        self.__pde=LinearSinglePDE(domain)
        self.__pde.getSolverOptions().setTolerance(tol)
        self.__pde.setSymmetryOn()

        z = domain.getX()[DIM-1]
        self.__pde.setValue(q=whereNonNegative(z-level0), r=p0)

        fw = self.__trafo.getScalingFactors()**2 * self.__trafo.getVolumeFactor()
        A=self.__pde.createCoefficient("A")
        for i in range(DIM): A[i,i]=fw[i]
        self.__pde.setValue(A=A)
        z = Function(domain).getX()[DIM-1]
        self.__g_b= 4*PI*gravity_constant/self.__trafo.getScalingFactors()[DIM-1]*background_density*(level0-z) + gravity0
        self.__rho_b=background_density
Example #5
0
    def __init__(self, domain, omega, w, data, F, coordinates=None,
                 fixAtBottom=False, tol=1e-8, saveMemory=True, scaleF=True):
        """
        initializes a new forward model with acoustic wave form inversion.

        :param domain: domain of the model
        :type domain: `Domain`
        :param w: weighting factors
        :type w: ``Scalar``
        :param data: real and imaginary part of data
        :type data: ``Data`` of shape (2,)
        :param F: real and imaginary part of source given at Dirac points,
                  on surface or at volume.
        :type F: ``Data`` of shape (2,)
        :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 PDE to minimize memory requests. This will
                           require more compute time as the matrix needs to be
                           reallocated.
        :type saveMemory: ``bool``
        :param scaleF: if true source F is scaled to minimize defect.
        :type scaleF: ``bool``
        :param fixAtBottom: if true pressure is fixed to zero at the bottom of
                            the domain
        :type fixAtBottom: ``bool``
        """
        super(AcousticWaveForm, self).__init__()
        self.__trafo = makeTransformation(domain, coordinates)
        if not self.getCoordinateTransformation().isCartesian():
            raise ValueError("Non-Cartesian Coordinates are not supported yet.")
        if not isinstance(data, Data):
            raise ValueError("data must be an escript.Data object.")
        if not data.getFunctionSpace() == FunctionOnBoundary(domain):
            raise ValueError("data must be defined on boundary")
        if not data.getShape() == (2,):
            raise ValueError("data must have shape (2,) (real and imaginary part).")
        if w is None:
            w = 1.
        if not isinstance(w, Data):
            w = Data(w, FunctionOnBoundary(domain))
        else:
            if not w.getFunctionSpace() == FunctionOnBoundary(domain):
                raise ValueError("Weights must be defined on boundary.")
            if not w.getShape() == ():
                raise ValueError("Weights must be scalar.")

        self.__domain = domain
        self.__omega = omega
        self.__weight = w
        self.__data = data
        self.scaleF = scaleF
        if scaleF:
            A = integrate(self.__weight*length(self.__data)**2)
            if A > 0:
                self.__data*=1./sqrt(A)

        self.__BX = boundingBox(domain)
        self.edge_lengths = np.asarray(boundingBoxEdgeLengths(domain))

        if not isinstance(F, Data):
            F=interpolate(F,  DiracDeltaFunctions(domain))
        if not F.getShape() == (2,):
            raise ValueError("Source must have shape (2,) (real and imaginary part).")

        self.__F=Data()
        self.__f=Data()
        self.__f_dirac=Data()

        if F.getFunctionSpace() == DiracDeltaFunctions(domain):
            self.__f_dirac=F
        elif F.getFunctionSpace() == FunctionOnBoundary(domain):
            self.__f=F
        else:
            self.__F=F
        self.__tol=tol
        self.__fixAtBottom=fixAtBottom
        self.__pde=None
        if not saveMemory:
            self.__pde=self.setUpPDE()
    def __init__(self,
                 domain,
                 locator,
                 delphiIn,
                 sampleTags,
                 phiPrimary,
                 sigmaPrimary,
                 w=1.,
                 coordinates=None,
                 tol=1e-8,
                 saveMemory=True,
                 b=None):
        """
        setup new forward model
        
        :param domain: the domain of the model
        :type: escript domain
        :param locator: contains locator to the measurement pairs
        :type: `list` of ``Locator``
        :param: delphiIn: this is v_pq, the potential difference for the
                          current source and a set of measurement pairs.
                          A list of measured potential differences is expected.
                          Note this should be the secondary potential only.
        :type delphiIn: tuple
        :param sampleTags: tags of measurement points from which potential
                           differences will be calculated.
        :type sampleTags: list of tuples
        :param phiPrimary: primary potential.
        :type phiPrimary: `Scalar`
        """
        super(DcRes, self).__init__()

        if not isinstance(sampleTags, list):
            raise ValueError("sampleTags must be a list.")
        if not len(sampleTags) == len(delphiIn):
            raise ValueError(
                "sampleTags and delphiIn must have the same length.")
        if not len(sampleTags) > 0:
            raise ValueError("sampleTags list is empty.")
        if not isinstance(sampleTags[0], tuple) and not isinstance(
                sampleTags[0], list):
            raise ValueError(
                "sampleTags must be a list of tuples or a list of lists.")

        if isinstance(w, float) or isinstance(w, int):
            w = [float(w) for z in delphiIn]
            self.__w = w
        else:
            self.__w = w
        if not len(w) == len(delphiIn):
            raise ValueError(
                "Number of confidence factors and number of potential input values don't match."
            )

        self.__trafo = makeTransformation(domain, coordinates)
        if not self.getCoordinateTransformation().isCartesian():
            raise ValueError(
                "Non-Cartesian Coordinates are not supported yet.")
        if not isinstance(locator, Locator):
            raise ValueError("locator must be an escript locator object")

        self.__domain = domain
        self.__tol = tol
        self.__locator = locator
        self.delphiIn = delphiIn
        self.__sampleTags = sampleTags
        self.__sigmaPrimary = sigmaPrimary
        self.__phiPrimary = phiPrimary
        self.__pde = None
        if not saveMemory:
            self.__pde = self.setUpPDE()
Example #7
0
    def __init__(self,
                 domain,
                 w,
                 data,
                 coordinates=None,
                 fixPotentialAtBottom=False,
                 tol=1e-8):
        """
        initializes a new forward model with potential.

        :param domain: domain of the model
        :type domain: `Domain`
        :param w: data weighting factors
        :type w: ``Vector`` or list of ``Vector``
        :param data: data
        :type data: ``Vector`` or list of ``Vector``
        :param coordinates: defines coordinate system to be used
        :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation`
        :param fixPotentialAtBottom: if true potential is fixed to zero at the bottom of the domain
                                     in addition to the top.
        :type fixPotentialAtBottom: ``bool``
        :param tol: tolerance of underlying PDE
        :type tol: positive ``float``
        """
        super(ForwardModelWithPotential, self).__init__()
        self.__domain = domain
        self.__trafo = makeTransformation(domain, coordinates)

        try:
            n = len(w)
            m = len(data)
            if not m == n:
                raise ValueError("Length of weight and data must be the same.")
            self.__weight = w
            self.__data = data
        except TypeError:
            self.__weight = [w]
            self.__data = [data]

        BX = boundingBox(domain)
        DIM = domain.getDim()
        x = domain.getX()
        self.__pde = LinearSinglePDE(domain)
        self.__pde.getSolverOptions().setTolerance(tol)
        self.__pde.setSymmetryOn()
        z = x[DIM - 1]
        q0 = whereZero(z - BX[DIM - 1][1])
        if fixPotentialAtBottom: q0 += whereZero(z - BX[DIM - 1][0])
        self.__pde.setValue(q=q0)

        self.edge_lengths = np.asarray(boundingBoxEdgeLengths(domain))
        self.diameter = 1. / sqrt(sum(1. / self.edge_lengths**2))

        self.__origweight = []
        for s in range(len(self.__weight)):
            # save a copy of the original weights in case of rescaling
            self.__origweight.append(1. * self.__weight[s])

        if not self.__trafo.isCartesian():
            fd = 1. / self.__trafo.getScalingFactors()
            fw = self.__trafo.getScalingFactors() * sqrt(
                self.__trafo.getVolumeFactor())
            for s in range(len(self.__weight)):
                self.__weight[s] = fw * self.__weight[s]
                self.__data[s] = fd * self.__data[s]
    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()