コード例 #1
0
 def initialize(self,
                b=escript.Data(),
                f=escript.Data(),
                specified_u_mask=escript.Data(),
                specified_u_val=escript.Data(),
                dt=0):
     """
   initialize the model for each time step, e.g. assign parameters
   :param b: type vector, body force on FunctionSpace, e.g. gravity
   :param f: type vector, boundary traction on FunctionSpace (FunctionOnBoundary)
   :param specified_u_mask: type vector, mask of location for Dirichlet boundary
   :param specified_u_val: type vector, specified displacement for Dirichlet boundary
   """
     self.__pde.setValue(Y=b, y=f, q=specified_u_mask, r=specified_u_val)
     # if FEDENodeMap is given
     if self.__FEDENodeMap:
         # assign dt_FE/dt_DE_ext to self.__nsOfDE_ext
         dt_ext = self.__pool.apply(getScenetDt, (self.__sceneExt, ))
         self.__nsOfDE_ext = int(round(dt / dt_ext))
         print "Ratio between time step in FE and exterior DE domain: %1.1e" % self.__nsOfDE_ext
     dt_int = self.__pool.map(getScenetDt, self.__scenes)
     # assign a list of dt_FE/dt_DE_int to self.__nsOfDE_int
     self.__nsOfDE_int = numpy.round(numpy.array(dt) / dt_int).astype(int)
     print "Maximum ratio between time step in FE and interior DE domains: %1.1e" % max(
         self.__nsOfDE_int)
     if dt == 0:
         raise RuntimeError, "Time step in FE domain is not given"
     self.__dt = dt
     print "Time step in FE domain:%1.1e" % self.__dt
コード例 #2
0
    def getPotential(self):
        """
        returns a list containing 3 lists one for each the primary, secondary
        and total potential.
        """


        primCon=self.primaryConductivity
        coords=self.domain.getX()
        pde=LinearPDE(self.domain, numEquations=1)
        tol=1e-8
        pde.getSolverOptions().setTolerance(tol)
        pde.setSymmetryOn()

        DIM=self.domain.getDim()
        x=self.domain.getX()
        q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1]))
        for i in xrange(DIM-1):
            xi=x[i]
            q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi))
        A = self.secondaryConductivity * es.kronecker(self.domain)
        pde.setValue(A=A,q=q)

        delPhiSecondary = []
        delPhiPrimary = []
        delPhiTotal = []
        if(len(self.electrodes[0])==3):

            for i in range(self.numElectrodes-1):
                analyticRs=es.Data(0,(3,),es.ContinuousFunction(self.domain))
                analyticRs[0]=(coords[0]-self.electrodes[i][0])
                analyticRs[1]=(coords[1]-self.electrodes[i][1])
                analyticRs[2]=(coords[2])
                rsMag=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**0.5
                analyticPrimaryPot=(self.current*(1./primCon))/(2*pi*(rsMag+(es.whereZero(rsMag)*0.0000001))) #the magic number 0.0000001 is to avoid devide by 0
                analyticRsPolePower=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**1.5
                analyticRsPolePower = analyticRsPolePower+(es.whereZero(analyticRsPolePower)*0.0000001)
                gradUPrimary = es.Data(0,(3,),es.ContinuousFunction(self.domain))
                gradUPrimary[0] =(self.current/(2*pi*primCon)) * (analyticRs[0]/analyticRsPolePower)
                gradUPrimary[1] =(self.current/(2*pi*primCon)) * (analyticRs[1]/analyticRsPolePower)
                gradUPrimary[2] =(self.current/(2*pi*primCon)) * (analyticRs[2]/analyticRsPolePower)
                gradUPrimary=-gradUPrimary
                X=(primCon-self.secondaryConductivity) * gradUPrimary
                pde.setValue(X=X)
                u=pde.getSolution()
                loc=Locator(self.domain,self.electrodes[i+1])
                delPhiSecondary.append(loc.getValue(u))
                delPhiPrimary.append(loc.getValue(analyticPrimaryPot))
        else:
            raise NotImplementedError("2d forward model is not yet implemented")

        self.delPhiSecondary = delPhiSecondary
        self.delPhiPrimary = delPhiPrimary
        for i in range(len(delPhiPrimary)):
            delPhiTotal.append(delPhiPrimary[i] + delPhiSecondary[i])
        self.delPhiTotal=delPhiTotal
        return [delPhiPrimary, delPhiSecondary, delPhiTotal]
コード例 #3
0
 def initialize(self, b=escript.Data(), f=escript.Data(), specified_u_mask=escript.Data(), specified_u_val=escript.Data()):
    """
    initialize the model for each time step, e.g. assign parameters
    :param b: type vector, body force on FunctionSpace, e.g. gravity
    :param f: type vector, boundary traction on FunctionSpace (FunctionOnBoundary)
    :param specified_u_mask: type vector, mask of location for Dirichlet boundary
    :param specified_u_val: type vector, specified displacement for Dirichlet boundary
    """
    self.__pde.setValue(Y=b,y=f,q=specified_u_mask,r=specified_u_val)
コード例 #4
0
ファイル: msFEMup.py プロジェクト: HuanranWU/Yade
 def initialize(self, b=escript.Data(), f=escript.Data(), umsk=escript.Data(), uvalue=escript.Data(), flux=escript.Data(), pmsk=escript.Data(), pvalue=escript.Data()):
    """
    initialize the model for each time step, e.g. assign parameters
    :param b: type vector, body force on FunctionSpace, e.g. gravity
    :param f: type vector, boundary traction on FunctionSpace (FunctionOnBoundary)
    :param umsk: type vector, mask of location for Dirichlet boundary
    :param uvalue: type vector, specified displacement for Dirichlet boundary
    """
    self.__upde.setValue(Y=b,y=f,q=umsk,r=uvalue)
    self.__ppde.setValue(y=flux,q=pmsk,r=pvalue)
    self.__r=uvalue                  
コード例 #5
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)
コード例 #6
0
 def test_replaceNaNConstant(self):
     dom=self.domain
     dat = es.Data(10,es.ContinuousFunction(dom))
     dat=(dat*0)/0
     self.assertTrue(dat.hasNaN(),"dat should contain NaN but its doesn't")
     dat.replaceNaN(10)
     self.assertEqual(es.Lsup(dat), 10)
     dat = es.Data(10,es.ContinuousFunction(dom))
     dat.promote()
     dat=(dat*0)/0
     self.assertTrue(dat.hasNaN(),"dat should contain NaN but its doesn't")
     dat.replaceNaN(4+3j)
     self.assertEqual(es.Lsup(dat), 5)
コード例 #7
0
ファイル: flow.py プロジェクト: aishugang/esys-escript
 def doInitialization(self):
     """
        initialize model
        """
     self.__p_old = None
     self.__p_very_old = None
     self.__dt_old = None
     self.__pde = lpde.LameEquation(self.domain)
     self.__pde.getSolverOptions().setSolverMethod(
         lpde.SolverOptions.DIRECT)
     if self.location_prescribed_velocity is None:
         self.location_prescribed_velocit = es.Data()
     if self.prescribed_velocity is None:
         self.prescribed_velocity = es.Data()
コード例 #8
0
 def applyStrain(self, st=escript.Data()):
     st = st.toListOfTuples()
     st = numpy.array(st).reshape(-1, 4)
     # load DEM packing with strain
     arScenes = self.__pool.map_async(
         shear2D, zip(self.__scenes, st, self.__nsOfDE_int))
     return arScenes
コード例 #9
0
 def solveSolid(self, p_iter_gauss=escript.Data(), iter_max=50):
     """
   solve the pde for displacement using Newton-Ralphson scheme
   """
     k = util.kronecker(self.__domain)
     p = p_iter_gauss * k
     iterate = 0
     rtol = self.__rtol
     stress_safe = self.__stress
     s_safe = self.__S
     x_safe = self.__domain.getX()
     self.__upde.setValue(A=s_safe, X=-stress_safe + p, r=self.__r)
     #residual0=util.L2(self.__pde.getRightHandSide()) # using force error
     u = self.__upde.getSolution()  # trial solution, displacement
     D = util.grad(u)  # trial strain tensor
     # !!!!!! obtain stress and tangent operator from DEM part
     update_stress, update_s, update_scenes = self.applyStrain_getStressTangentDEM(
         st=D)
     err = util.Lsup(u)  # initial error before iteration
     converged = (err < 1.e-12)
     while (not converged) and (iterate < iter_max):
         #if iterate>iter_max:
         #   raise RuntimeError,"Convergence for Newton-Raphson failed after %s steps."%(iter_max)
         iterate += 1
         self.__domain.setX(x_safe + u)
         self.__upde.setValue(A=update_s,
                              X=-update_stress + p,
                              r=escript.Data())
         #residual=util.L2(self.__pde.getRightHandSide())
         du = self.__upde.getSolution()
         u += du
         l, d = util.L2(u), util.L2(du)
         err = d / l  # displacement error, alternatively using force error 'residual'
         converged = (err < rtol)
         if err > rtol**3:  # only update DEM parts when error is large enough
             self.__domain.setX(x_safe)
             D = util.grad(u)
             update_stress, update_s, update_scenes = self.applyStrain_getStressTangentDEM(
                 st=D)
     """reset domain geometry to original until global convergence"""
     self.__domain.setX(x_safe)
     return u, D, update_stress, update_s, update_scenes
コード例 #10
0
 def applyDisplIncrement_getForceDEM(self,
                                     DEdu=escript.Data(),
                                     dynRelax=False):
     """
   apply displacement increment to the external DE domain,
   and get boundary force from DE interface nodes
   """
     arFEfAndSceneExt = self.__pool.apply_async( \
                           moveInterface_getForce2D,(self.__sceneExt,self.__conf,DEdu,dynRelax, \
                           self.__mIds,self.__FEDENodeMap,self.__nsOfDE_ext))
     return arFEfAndSceneExt
コード例 #11
0
ファイル: msFEM3D.py プロジェクト: HuanranWU/Yade
    def solve(self, iter_max=100):
        """
      solve the equation using Newton-Ralphson scheme
      """
        iterate = 0
        rtol = self.getRelTolerance()
        stress = self.getCurrentStress()
        s = self.getCurrentTangent()
        x_safe = self.__domain.getX()
        self.__pde.setValue(A=s, X=-stress)
        #residual0=util.L2(self.__pde.getRightHandSide()) # using force error
        u = self.__pde.getSolution()  # trial solution, displacement
        D = util.grad(u)  # trial strain tensor
        # !!!!!! obtain stress and tangent operator from DEM part
        update_stress, update_s, update_scenes = self.applyStrain_getStressTangentDEM(
            st=D)
        err = 1.0  # initial error before iteration
        converged = (err < rtol)
        while (not converged) and (iterate < iter_max):
            if self.__verbose:
                print(
                    "Not converged after %d iteration(s)! Relative error: %e" %
                    (iterate, err))
            iterate += 1
            self.__domain.setX(x_safe + u)
            self.__pde.setValue(A=update_s, X=-update_stress, r=escript.Data())
            #residual=util.L2(self.__pde.getRightHandSide())
            du = self.__pde.getSolution()
            u += du
            l, d = util.L2(u), util.L2(du)
            err = d / l  # displacement error, alternatively using force error 'residual'
            converged = (err < rtol)
            if err > rtol * 0.001:  # only update DEM parts when error is large enough
                self.__domain.setX(x_safe)
                D = util.grad(u)
                update_stress, update_s, update_scenes = self.applyStrain_getStressTangentDEM(
                    st=D)

            #if err>err_safe: # to ensure consistent convergence, however this may not be achieved due to fluctuation!
            #   raise RuntimeError,"No improvement of convergence with iterations! Relative error: %e"%err
        """
      update 'domain geometry', 'stress', 'tangent operator',
      'accumulated strain' and 'simulation scenes'.
      """
        self.__domain.setX(x_safe + u)
        self.__stress = update_stress
        self.__S = update_s
        self.__strain += D
        self.__scenes = update_scenes
        if self.__verbose:
            print(
                "Convergence reached after %d iteration(s)! Relative error: %e"
                % (iterate, err))
        return u
コード例 #12
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
コード例 #13
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
コード例 #14
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??
コード例 #15
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
コード例 #16
0
 def setRHS(self, X, Y=escript.Data()):
     """
   set right hande side of PDE, including X_{ij} and Y_i
   X: stress tensor at (n) time step
   Y: vector, (equivalent) body force at (n) time step
   Note that boundary force, if any, is set inhere
   """
     # apply internal stress and equivalent body force
     self.__pde.setValue(X=X, Y=Y)
     # if exterior DE domain is given
     if self.__FEDENodeMap:
         FEf = self.getFEf()
         rhs = self.__pde.getRightHandSide()
         # !!!!!! apply boundary force to the right hande side of PDE
         for FEid in FEf.keys():
             rhs_i = rhs.getTupleForDataPoint(FEid)
             rhs_i_new = [sum(f) for f in zip(rhs_i, FEf[FEid])]
             rhs.setValueOfDataPoint(FEid, rhs_i_new)
     # consider Neumann boundary conditions
     rhs -= rhs * self.__pde.getCoefficient('q')
     """
コード例 #17
0
   def solve(self, iter_max=100):
      """
      solve the equation using Newton-Ralphson scheme ??where is the equation
      """
      iterate=0
      rtol=self.getRelTolerance()
      stress=self.getCurrentStress()
      s=self.getCurrentTangent()
      x_safe=self.__domain.getX()
      self.__pde.setValue(A=s, X=-stress)#stress is negative,here uses - to change to positive
      #residual0=util.L2(self.__pde.getRightHandSide()) # using force error
      u=self.__pde.getSolution()  # trial solution, displacement
      D=util.grad(u)              # trial strain tensor (obtained from FEM part)

      #fout1=open('./result/gradU.dat','w')
      #fout1.write(str(D)+'\n')

      # !!!!!! following steps: obtain stress and tangent operator from DEM part
      update_stress,update_s,update_scenes=self.applyStrain_getStressTangentDEM(st=D)#input grad(u) from FEM to DEM to get D&sigma
      #fout2=open('./result/stress&tangOper.dat','w')
      #fout2.write('tangent'+'\n'+str(update_s)+'\n'+'stress'+'\n'+str(update_stress))
      #saveGauss2D(name='./result/gradU+stress+tangent.dat',gradU=D, stress=update_stress, tangent=update_s) 
      #print(type(D))  gradU is a <class 'esys.escriptcore.escriptcpp.Data'> how to transfer to a list to output
      err=1.0 # initial error before iteration
      converged=(err<rtol)
      while not converged:
         if self.__verbose:
            print "Not converged after %d iteration(s)! Relative error: %e"%(iterate,err)
         if iterate>50:
            rtol = 0.05 #enlarge rtol from 0.01(default) to 0.05 when iterate > 50
         if iterate>iter_max:
            raise RuntimeError,"Convergence not reached after %s steps."%(iter_max)
         iterate+=1
         self.__domain.setX(x_safe+u)#update nodal displacement to do the following calculation
         self.__pde.setValue(A=update_s,X=-update_stress,r=escript.Data())
         #residual=util.L2(self.__pde.getRightHandSide())
         du=self.__pde.getSolution() #we do NR iteration to get du
         u+=du
         l,d=util.L2(u),util.L2(du) #to get the l2 norm of u and du
         err=d/l # displacement error, alternatively using force error 'residual'
         converged=(err<rtol)
         if err>rtol*0.001: # only update DEM parts when error is large enough???why times 0.001?
         #it seems whether or not it is converged, the lines below 'if' will always be excuted. So why do we need if? can we just remove it 
            self.__domain.setX(x_safe) #x_safe is constant in this part 'solve' and is not updated.
            D=util.grad(u)
            update_stress,update_s,update_scenes=self.applyStrain_getStressTangentDEM(st=D)#DEM calculation!!
            
            '''
	    fout.write('iterate='+str(iterate)+'\n'+'scenes='+'\n'+str(update_scenes)+'\n')
	    '''

         
         #if err>err_safe: # to ensure consistent convergence, however this may not be achieved due to fluctuation!
         #   raise RuntimeError,"No improvement of convergence with iterations! Relative error: %e"%err
      """
      update 'domain geometry', 'stress', 'tangent operator',
      'accumulated strain' and 'simulation scenes'.
      """
      self.__domain.setX(x_safe+u)
      
      
      self.__stress=update_stress
      self.__S=update_s
      self.__strain+=D
      self.__scenes=update_scenes
      

      if self.__verbose:
         print "Convergence reached after %d iteration(s)! Relative error: %e"%(iterate,err)
      return u
コード例 #18
0
    def getPotential(self):
        """
        Returns 3 list each made up of a number of list containing primary, secondary and total
        potentials diferences. Each of the lists contain a list for each value of n.
        """

        primCon=self.primaryConductivity
        coords=self.domain.getX()
        pde=LinearPDE(self.domain, numEquations=1)
        tol=1e-8
        pde.getSolverOptions().setTolerance(tol)
        pde.setSymmetryOn()

        DIM=self.domain.getDim()
        x=self.domain.getX()
        q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1]))
        for i in xrange(DIM-1):
            xi=x[i]
            q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi))
        A = self.secondaryConductivity * es.kronecker(self.domain)
        pde.setValue(A=A,q=q)

        delPhiSecondaryList = []
        delPhiPrimaryList = []
        delPhiTotalList = []
        for i in range(1,self.n+1): # 1 to n
            maxR = self.numElectrodes - 1 - i #max amount of readings that will fit in the survey
            delPhiSecondary = []
            delPhiPrimary = []
            delPhiTotal = []
            for j in range(maxR):
                analyticRs=es.Data(0,(3,),es.ContinuousFunction(self.domain))
                analyticRs[0]=(coords[0]-self.electrodes[j][0])
                analyticRs[1]=(coords[1]-self.electrodes[j][1])
                analyticRs[2]=(coords[2])
                rsMag=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**0.5
                analyticPrimaryPot=(self.current*(1./primCon))/(2*pi*(rsMag+(es.whereZero(rsMag)*0.0000001))) #the magic number 0.0000001 is to avoid devide by 0

                analyticRsPolePower=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**1.5
                analyticRsPolePower = analyticRsPolePower+(es.whereZero(analyticRsPolePower)*0.0000001)
                gradUPrimary = es.Data(0,(3,),es.ContinuousFunction(self.domain))
                gradUPrimary[0] =(self.current/(2*pi*primCon)) * (analyticRs[0]/analyticRsPolePower)
                gradUPrimary[1] =(self.current/(2*pi*primCon)) * (analyticRs[1]/analyticRsPolePower)
                gradUPrimary[2] =(self.current/(2*pi*primCon)) * (analyticRs[2]/analyticRsPolePower)
                gradUPrimary=-gradUPrimary
                X=(primCon-self.secondaryConductivity) * gradUPrimary
                pde.setValue(X=X)
                u=pde.getSolution()
                loc=Locator(self.domain,[self.electrodes[i+j],self.electrodes[i+j+1]])
                valPrimary=loc.getValue(analyticPrimaryPot)
                valSecondary=loc.getValue(u)
                delPhiPrimary.append(valPrimary[1]-valPrimary[0])
                delPhiSecondary.append(valSecondary[1]-valSecondary[0])
                delPhiTotal.append(delPhiPrimary[j]+delPhiSecondary[j])

            delPhiPrimaryList.append(delPhiPrimary)
            delPhiSecondaryList.append(delPhiSecondary)
            delPhiTotalList.append(delPhiTotal)



        self.delPhiPrimaryList=delPhiPrimaryList
        self.delPhiSecondaryList=delPhiSecondaryList
        self.delPhiTotalList = delPhiTotalList

        return [delPhiPrimaryList, delPhiSecondaryList, delPhiTotalList]
コード例 #19
0
    def getPotential(self):
        """
        returns a list containing 3 lists one for each the primary, secondary
        and total potential.
        """

        primCon=self.primaryConductivity
        coords=self.domain.getX()
        pde=LinearPDE(self.domain, numEquations=1)
        tol=1e-8
        pde.getSolverOptions().setTolerance(tol)
        pde.setSymmetryOn()

        DIM=self.domain.getDim()
        x=self.domain.getX()
        q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1]))
        for i in xrange(DIM-1):
            xi=x[i]
            q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi))
        A = self.secondaryConductivity * es.kronecker(self.domain)
        pde.setValue(A=A,q=q)

        delPhiSecondary = []
        delPhiPrimary = []
        delPhiTotal = []
        if(len(self.electrodes[0])==3):

            for i in range(self.numElectrodes-3):
                analyticRsOne=es.Data(0,(3,),es.ContinuousFunction(self.domain))
                analyticRsOne[0]=(coords[0]-self.electrodes[i][0])
                analyticRsOne[1]=(coords[1]-self.electrodes[i][1])
                analyticRsOne[2]=(coords[2])
                rsMagOne=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**0.5
                analyticRsTwo=es.Data(0,(3,),es.ContinuousFunction(self.domain))
                analyticRsTwo[0]=(coords[0]-self.electrodes[i+3][0])
                analyticRsTwo[1]=(coords[1]-self.electrodes[i+3][1])
                analyticRsTwo[2]=(coords[2])
                rsMagTwo=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**0.5
                rsMagOne+=(es.whereZero(rsMagOne)*0.0000001)
                rsMagTwo+=(es.whereZero(rsMagTwo)*0.0000001)
                analyticPrimaryPot=(self.current/(2*pi*primCon*rsMagOne))-(self.current/(2*pi*primCon*rsMagTwo))

                analyticRsOnePower=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**1.5
                analyticRsOnePower = analyticRsOnePower+(es.whereZero(analyticRsOnePower)*0.0001)
                analyticRsTwoPower=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**1.5
                analyticRsTwoPower = analyticRsTwoPower+(es.whereZero(analyticRsTwoPower)*0.0001)

                gradAnalyticPrimaryPot = es.Data(0,(3,),es.ContinuousFunction(self.domain))
                gradAnalyticPrimaryPot[0] =(self.current/(2*pi*primCon)) \
                        * ((-analyticRsOne[0]/analyticRsOnePower) \
                            + (analyticRsTwo[0]/analyticRsTwoPower))
                gradAnalyticPrimaryPot[1] =(self.current/(2*pi*primCon)) \
                        * ((-analyticRsOne[1]/analyticRsOnePower) \
                            + (analyticRsTwo[1]/analyticRsTwoPower))
                gradAnalyticPrimaryPot[2] =(self.current/(2*pi*primCon)) \
                        * ((-analyticRsOne[2]/analyticRsOnePower)
                            + (analyticRsTwo[2]/analyticRsTwoPower))
                X=(primCon-self.secondaryConductivity) * (gradAnalyticPrimaryPot)
                pde.setValue(X=X)
                u=pde.getSolution()
                loc=Locator(self.domain,[self.electrodes[i+1],self.electrodes[i+2]])
                valPrimary=loc.getValue(analyticPrimaryPot)
                valSecondary=loc.getValue(u)
                delPhiPrimary.append(valPrimary[1]-valPrimary[0])
                delPhiSecondary.append(valSecondary[1]-valSecondary[0])
                delPhiTotal.append(delPhiPrimary[i]+delPhiSecondary[i])
        else:
            raise NotImplementedError("2d forward model is not yet implemented")

        self.delPhiSecondary = delPhiSecondary
        self.delPhiPrimary = delPhiPrimary
        self.delPhiTotal=delPhiTotal
        return [delPhiPrimary, delPhiSecondary, delPhiTotal]
コード例 #20
0
    def getPotentialAnalytic(self):
        """
        Returns 3 list each made up of a number of list containing primary, secondary and total
        potentials diferences. Each of the lists contain a list for each value of n.
        """
        coords=self.domain.getX()
        pde=LinearPDE(self.domain, numEquations=1)
        tol=1e-8
        pde.getSolverOptions().setTolerance(tol)
        pde.setSymmetryOn()
        primCon=self.primaryConductivity
        DIM=self.domain.getDim()
        x=self.domain.getX()
        q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1]))
        for i in xrange(DIM-1):
            xi=x[i]
            q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi))
        A = self.secondaryConductivity * es.kronecker(self.domain)
        pde.setValue(A=A,q=q)


        delPhiSecondaryList = []
        delPhiPrimaryList = []
        delPhiTotalList = []
        for i in range(1,self.n+1): # 1 to n
            maxR = self.numElectrodes - 1 - (2*i) #max amount of readings that will fit in the survey
            delPhiSecondary = []
            delPhiPrimary = []
            delPhiTotal = []
            for j in range(maxR):
                analyticRsOne=es.Data(0,(3,),es.ContinuousFunction(self.domain))
                analyticRsOne[0]=(coords[0]-self.electrodes[j][0])
                analyticRsOne[1]=(coords[1]-self.electrodes[j][1])
                analyticRsOne[2]=(coords[2])
                rsMagOne=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**0.5
                analyticRsTwo=es.Data(0,(3,),es.ContinuousFunction(self.domain))
                analyticRsTwo[0]=(coords[0]-self.electrodes[j + ((2*i) + 1)][0])
                analyticRsTwo[1]=(coords[1]-self.electrodes[j + ((2*i) + 1)][1])
                analyticRsTwo[2]=(coords[2])
                rsMagTwo=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**0.5
                self.sources.append([self.electrodeTags[j], self.electrodeTags[j + ((2*i) + 1)]])
                rsMagOne+=(es.whereZero(rsMagOne)*0.0000001)
                rsMagTwo+=(es.whereZero(rsMagTwo)*0.0000001)
                
                analyticPrimaryPot=(self.current/(2*pi*primCon*rsMagOne))-(self.current/(2*pi*primCon*rsMagTwo))
                analyticRsOnePower=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**1.5
                analyticRsOnePower = analyticRsOnePower+(es.whereZero(analyticRsOnePower)*0.0001)
                analyticRsTwoPower=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**1.5
                analyticRsTwoPower = analyticRsTwoPower+(es.whereZero(analyticRsTwoPower)*0.0001)

                gradAnalyticPrimaryPot = es.Data(0,(3,),es.ContinuousFunction(self.domain))
                gradAnalyticPrimaryPot[0] =(self.current/(2*pi*primCon)) * ((-analyticRsOne[0]/analyticRsOnePower) + (analyticRsTwo[0]/analyticRsTwoPower))
                gradAnalyticPrimaryPot[1] =(self.current/(2*pi*primCon)) * ((-analyticRsOne[1]/analyticRsOnePower) + (analyticRsTwo[1]/analyticRsTwoPower))
                gradAnalyticPrimaryPot[2] =(self.current/(2*pi*primCon)) * ((-analyticRsOne[2]/analyticRsOnePower) + (analyticRsTwo[2]/analyticRsTwoPower))
                X=(primCon-self.secondaryConductivity) * (gradAnalyticPrimaryPot)
                pde.setValue(X=X)
                u=pde.getSolution()
                loc=Locator(self.domain,[self.electrodes[j+i],self.electrodes[j+i+1]])
                self.samples.append([self.electrodeTags[j+i],self.electrodeTags[j+i+1]])
                valPrimary=loc.getValue(analyticPrimaryPot)
                valSecondary=loc.getValue(u)
                delPhiPrimary.append(valPrimary[1]-valPrimary[0])
                delPhiSecondary.append(valSecondary[1]-valSecondary[0])
                delPhiTotal.append(delPhiPrimary[j]+delPhiSecondary[j])
            delPhiPrimaryList.append(delPhiPrimary)
            delPhiSecondaryList.append(delPhiSecondary)
            delPhiTotalList.append(delPhiTotal)

        self.delPhiPrimaryList=delPhiPrimaryList
        self.delPhiSecondaryList=delPhiSecondaryList
        self.delPhiTotalList = delPhiTotalList
        return [delPhiPrimaryList, delPhiSecondaryList, delPhiTotalList]
コード例 #21
0
    def __init__(self,
                 domain,
                 numLevelSets=1,
                 w0=None,
                 w1=None,
                 wc=None,
                 location_of_set_m=escript.Data(),
                 useDiagonalHessianApproximation=False,
                 tol=1e-8,
                 coordinates=None,
                 scale=None,
                 scale_c=None):
        """
        initialization.

        :param domain: domain
        :type domain: `Domain`
        :param numLevelSets: number of level sets
        :type numLevelSets: ``int``
        :param w0: weighting factor for the m**2 term. If not set zero is assumed.
        :type w0: ``Scalar`` if ``numLevelSets`` == 1 or `Data` object of shape
                  (``numLevelSets`` ,) if ``numLevelSets`` > 1
        :param w1: weighting factor for the grad(m_i) terms. If not set zero is assumed
        :type w1: ``Vector`` if ``numLevelSets`` == 1 or `Data` object of shape
                  (``numLevelSets`` , DIM) if ``numLevelSets`` > 1
        :param wc: weighting factor for the cross gradient terms. If not set
                   zero is assumed. Used for the case if ``numLevelSets`` > 1
                   only. Only values ``wc[l,k]`` in the lower triangle (l<k)
                   are used.
        :type wc: `Data` object of shape (``numLevelSets`` , ``numLevelSets``)
        :param location_of_set_m: marks location of zero values of the level
                                  set function ``m`` by a positive entry.
        :type location_of_set_m: ``Scalar`` if ``numLevelSets`` == 1 or `Data`
                object of shape (``numLevelSets`` ,) if ``numLevelSets`` > 1
        :param useDiagonalHessianApproximation: if True cross gradient terms
                    between level set components are ignored when calculating
                    approximations of the inverse of the Hessian Operator.
                    This can speed-up the calculation of the inverse but may
                    lead to an increase of the number of iteration steps in the
                    inversion.
        :type useDiagonalHessianApproximation: ``bool``
        :param tol: tolerance when solving the PDE for the inverse of the
                    Hessian Operator
        :type tol: positive ``float``

        :param coordinates: defines coordinate system to be used
        :type coordinates: ReferenceSystem` or `SpatialCoordinateTransformation`
        :param scale: weighting factor for level set function variation terms.
                      If not set one is used.
        :type scale: ``Scalar`` if ``numLevelSets`` == 1 or `Data` object of
                     shape (``numLevelSets`` ,) if ``numLevelSets`` > 1
        :param scale_c: scale for the cross gradient terms. If not set
                   one is assumed. Used for the case if ``numLevelSets`` > 1
                   only. Only values ``scale_c[l,k]`` in the lower triangle
                   (l<k) are used.
        :type scale_c: `Data` object of shape (``numLevelSets``,``numLevelSets``)

        """
        if w0 is None and w1 is None:
            raise ValueError("Values for w0 or for w1 must be given.")
        if wc is None and numLevelSets > 1:
            raise ValueError("Values for wc must be given.")

        self.__pre_input = None
        self.__pre_args = None
        self.logger = logging.getLogger('inv.%s' % self.__class__.__name__)
        self.__domain = domain
        DIM = self.__domain.getDim()
        self.__numLevelSets = numLevelSets
        self.__trafo = makeTransformation(domain, coordinates)
        self.__pde = linearPDEs.LinearPDE(self.__domain,
                                          numEquations=self.__numLevelSets,
                                          numSolutions=self.__numLevelSets)
        self.__pde.getSolverOptions().setTolerance(tol)
        self.__pde.setSymmetryOn()
        self.__pde.setValue(
            A=self.__pde.createCoefficient('A'),
            D=self.__pde.createCoefficient('D'),
        )
        try:
            self.__pde.setValue(q=location_of_set_m)
        except linearPDEs.IllegalCoefficientValue:
            raise ValueError(
                "Unable to set location of fixed level set function.")

        # =========== check the shape of the scales: ========================
        if scale is None:
            if numLevelSets == 1:
                scale = 1.
            else:
                scale = np.ones((numLevelSets, ))
        else:
            scale = np.asarray(scale)
            if numLevelSets == 1:
                if scale.shape == ():
                    if not scale > 0:
                        raise ValueError("Value for scale must be positive.")
                else:
                    raise ValueError("Unexpected shape %s for scale." %
                                     scale.shape)
            else:
                if scale.shape is (numLevelSets, ):
                    if not min(scale) > 0:
                        raise ValueError(
                            "All values for scale must be positive.")
                else:
                    raise ValueError("Unexpected shape %s for scale." %
                                     scale.shape)

        if scale_c is None or numLevelSets < 2:
            scale_c = np.ones((numLevelSets, numLevelSets))
        else:
            scale_c = np.asarray(scale_c)
            if scale_c.shape == (numLevelSets, numLevelSets):
                if not all([[scale_c[l, k] > 0. for l in range(k)]
                            for k in range(1, numLevelSets)]):
                    raise ValueError(
                        "All values in the lower triangle of scale_c must be positive."
                    )
            else:
                raise ValueError("Unexpected shape %s for scale." %
                                 scale_c.shape)
        # ===== check the shape of the weights: =============================
        if w0 is not None:
            w0 = escript.interpolate(
                w0, self.__pde.getFunctionSpaceForCoefficient('D'))
            s0 = w0.getShape()
            if numLevelSets == 1:
                if not s0 == ():
                    raise ValueError("Unexpected shape %s for weight w0." %
                                     (s0, ))
            else:
                if not s0 == (numLevelSets, ):
                    raise ValueError("Unexpected shape %s for weight w0." %
                                     (s0, ))
            if not self.__trafo.isCartesian():
                w0 *= self.__trafo.getVolumeFactor()
        if not w1 is None:
            w1 = escript.interpolate(
                w1, self.__pde.getFunctionSpaceForCoefficient('A'))
            s1 = w1.getShape()
            if numLevelSets == 1:
                if not s1 == (DIM, ):
                    raise ValueError("Unexpected shape %s for weight w1." %
                                     (s1, ))
            else:
                if not s1 == (numLevelSets, DIM):
                    raise ValueError("Unexpected shape %s for weight w1." %
                                     (s1, ))
            if not self.__trafo.isCartesian():
                f = self.__trafo.getScalingFactors(
                )**2 * self.__trafo.getVolumeFactor()
                if numLevelSets == 1:
                    w1 *= f
                else:
                    for i in range(numLevelSets):
                        w1[i, :] *= f

        if numLevelSets == 1:
            wc = None
        else:
            wc = escript.interpolate(
                wc, self.__pde.getFunctionSpaceForCoefficient('A'))
            sc = wc.getShape()
            if not sc == (numLevelSets, numLevelSets):
                raise ValueError("Unexpected shape %s for weight wc." % (sc, ))
            if not self.__trafo.isCartesian():
                raise ValueError(
                    "Non-cartesian coordinates for cross-gradient term is not supported yet."
                )
        # ============= now we rescale weights: =============================
        L2s = np.asarray(escript.boundingBoxEdgeLengths(domain))**2
        L4 = 1 / np.sum(1 / L2s)**2
        if numLevelSets == 1:
            A = 0
            if w0 is not None:
                A = escript.integrate(w0)
            if w1 is not None:
                A += escript.integrate(inner(w1, 1 / L2s))
            if A > 0:
                f = scale / A
                if w0 is not None:
                    w0 *= f
                if w1 is not None:
                    w1 *= f
            else:
                raise ValueError("Non-positive weighting factor detected.")
        else:  # numLevelSets > 1
            for k in range(numLevelSets):
                A = 0
                if w0 is not None:
                    A = escript.integrate(w0[k])
                if w1 is not None:
                    A += escript.integrate(inner(w1[k, :], 1 / L2s))
                if A > 0:
                    f = scale[k] / A
                    if w0 is not None:
                        w0[k] *= f
                    if w1 is not None:
                        w1[k, :] *= f
                else:
                    raise ValueError(
                        "Non-positive weighting factor for level set component %d detected."
                        % k)

                # and now the cross-gradient:
                if wc is not None:
                    for l in range(k):
                        A = escript.integrate(wc[l, k]) / L4
                        if A > 0:
                            f = scale_c[l, k] / A
                            wc[l, k] *= f
#                       else:
#                           raise ValueError("Non-positive weighting factor for cross-gradient level set components %d and %d detected."%(l,k))

        self.__w0 = w0
        self.__w1 = w1
        self.__wc = wc

        self.__pde_is_set = False
        if self.__numLevelSets > 1:
            self.__useDiagonalHessianApproximation = useDiagonalHessianApproximation
        else:
            self.__useDiagonalHessianApproximation = True
        self._update_Hessian = True

        self.__num_tradeoff_factors = numLevelSets + (
            (numLevelSets - 1) * numLevelSets) // 2
        self.setTradeOffFactors()
        self.__vol_d = escript.vol(self.__domain)
コード例 #22
0
    def __init__(self,
                 domain,
                 omega,
                 w,
                 data,
                 F,
                 coordinates=None,
                 fixAtBottom=False,
                 tol=1e-10,
                 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: ``escript.Data`` of shape (2,)
        :param F: real and imaginary part of source given at Dirac points,
                  on surface or at volume.
        :type F: ``escript.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 = edc.makeTransformation(domain, coordinates)
        if not self.getCoordinateTransformation().isCartesian():
            raise ValueError(
                "Non-Cartesian Coordinates are not supported yet.")
        if not isinstance(data, escript.Data):
            raise ValueError("data must be an escript.Data object.")
        if not data.getFunctionSpace() == escript.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, escript.Data):
            w = escript.Data(w, escript.FunctionOnBoundary(domain))
        else:
            if not w.getFunctionSpace() == escript.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 = escript.integrate(self.__weight *
                                  escript.length(self.__data)**2)
            if A > 0:
                self.__data *= 1. / escript.sqrt(A)

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

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

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

        if F.getFunctionSpace() == escript.DiracDeltaFunctions(domain):
            self.__f_dirac = F
        elif F.getFunctionSpace() == escript.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()
コード例 #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,
                 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)