def fget(self): if(self._area is None or self._normals is None): # Compute areas of cell faces if(self.dim == 2): xy = self.gridN A, B = Utils.indexCube('AB', self.vnC+1, np.array([self.nNx, self.nCy])) edge1 = xy[B, :] - xy[A, :] normal1 = np.c_[edge1[:, 1], -edge1[:, 0]] area1 = length2D(edge1) A, D = Utils.indexCube('AD', self.vnC+1, np.array([self.nCx, self.nNy])) # Note that we are doing A-D to make sure the normal points the right way. # Think about it. Look at the picture. Normal points towards C iff you do this. edge2 = xy[A, :] - xy[D, :] normal2 = np.c_[edge2[:, 1], -edge2[:, 0]] area2 = length2D(edge2) self._area = np.r_[Utils.mkvc(area1), Utils.mkvc(area2)] self._normals = [normalize2D(normal1), normalize2D(normal2)] elif(self.dim == 3): A, E, F, B = Utils.indexCube('AEFB', self.vnC+1, np.array([self.nNx, self.nCy, self.nCz])) normal1, area1 = Utils.faceInfo(self.gridN, A, E, F, B, average=False, normalizeNormals=False) A, D, H, E = Utils.indexCube('ADHE', self.vnC+1, np.array([self.nCx, self.nNy, self.nCz])) normal2, area2 = Utils.faceInfo(self.gridN, A, D, H, E, average=False, normalizeNormals=False) A, B, C, D = Utils.indexCube('ABCD', self.vnC+1, np.array([self.nCx, self.nCy, self.nNz])) normal3, area3 = Utils.faceInfo(self.gridN, A, B, C, D, average=False, normalizeNormals=False) self._area = np.r_[Utils.mkvc(area1), Utils.mkvc(area2), Utils.mkvc(area3)] self._normals = [normal1, normal2, normal3] return self._area
def test_regularizationMesh(self): for i, mesh in enumerate(self.meshlist): print('Testing {0:d}D'.format(mesh.dim)) # mapping = r.mapPair(mesh) # reg = r(mesh, mapping=mapping) # m = np.random.rand(mapping.nP) if mesh.dim == 1: indAct = Utils.mkvc(mesh.gridCC <= 0.8) elif mesh.dim == 2: indAct = ( Utils.mkvc( mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:, 0]) + 0.5 ) ) elif mesh.dim == 3: indAct = ( Utils.mkvc( mesh.gridCC[:, -1] <= 2*np.sin(2*np.pi*mesh.gridCC[:, 0]) + 0.5 * 2*np.sin(2*np.pi*mesh.gridCC[:, 1]) + 0.5 ) ) regmesh = Regularization.RegularizationMesh( mesh, indActive=indAct ) assert (regmesh.vol == mesh.vol[indAct]).all()
def test_regularization_ActiveCells(self): for R in dir(Regularization): r = getattr(Regularization, R) if not inspect.isclass(r): continue if not issubclass(r, Regularization.BaseRegularization): continue for i, mesh in enumerate(self.meshlist): print('Testing Active Cells {0:d}D'.format((mesh.dim))) if mesh.dim == 1: indActive = Utils.mkvc(mesh.gridCC <= 0.8) elif mesh.dim == 2: indActive = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5) elif mesh.dim == 3: indActive = Utils.mkvc(mesh.gridCC[:,-1] <= 2*np.sin(2*np.pi*mesh.gridCC[:,0])+0.5 * 2*np.sin(2*np.pi*mesh.gridCC[:,1])+0.5) for indAct in [indActive, indActive.nonzero()[0]]: # test both bool and integers reg = r(mesh, indActive=indAct) m = np.random.rand(mesh.nC)[indAct] reg.mref = np.ones_like(m)*np.mean(m) print('Check: phi_m (mref) = {0:f}'.format(reg.eval(reg.mref))) passed = reg.eval(reg.mref) < TOL self.assertTrue(passed) print('Check:', R) passed = Tests.checkDerivative(lambda m : [reg.eval(m), reg.evalDeriv(m)], m, plotIt=False) self.assertTrue(passed) print('Check 2 Deriv:', R) passed = Tests.checkDerivative(lambda m : [reg.evalDeriv(m), reg.eval2Deriv(m)], m, plotIt=False) self.assertTrue(passed)
def set_ij_height(self): """ Compute (I, J) indicies to form sparse sensitivity matrix This will be used in GlobalEM1DProblem when after sensitivity matrix for each sounding is computed """ I = [] J = [] shift_for_J = 0 shift_for_I = 0 m = self.n_layer for i in range(n_sounding): n = self.nD_vec[i] J_temp = np.tile(np.arange(m), (n, 1)) + shift_for_J I_temp = ( np.tile(np.arange(n), (1, m)).reshape((n, m), order='F') + shift_for_I ) J.append(Utils.mkvc(J_temp)) I.append(Utils.mkvc(I_temp)) shift_for_J += m shift_for_I = I_temp[-1, -1] + 1 J = np.hstack(J).astype(int) I = np.hstack(I).astype(int) return (I, J)
def Jvec(self, m, v, f=None): if f is None: f = self.fields(m) self.curModel = m Jv = self.dataPair(self.survey) #same size as the data A = self.getA() for src in self.survey.srcList: u_src = f[src, self._solutionType] # solution vector dA_dm_v = self.getADeriv(u_src, v) dRHS_dm_v = self.getRHSDeriv(src, v) du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: df_dmFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv[src, rx] = rx.evalDeriv(src, self.mesh, f, df_dm_v) # Conductivity (d u / d log sigma) if self._formulation is 'EB': return -Utils.mkvc(Jv) # Conductivity (d u / d log rho) if self._formulation is 'HJ': return Utils.mkvc(Jv)
def test_ana_forward(self): survey = PF.BaseMag.BaseMagSurvey() Inc = 45.0 Dec = 45.0 Btot = 51000 b0 = PF.MagAnalytics.IDTtoxyz(Inc, Dec, Btot) survey.setBackgroundField(Inc, Dec, Btot) xr = np.linspace(-300, 300, 41) yr = np.linspace(-300, 300, 41) X, Y = np.meshgrid(xr, yr) Z = np.ones((xr.size, yr.size)) * 150 rxLoc = np.c_[Utils.mkvc(X), Utils.mkvc(Y), Utils.mkvc(Z)] survey.rxLoc = rxLoc self.prob.pair(survey) u = self.prob.fields(self.chi) B = u["B"] bxa, bya, bza = PF.MagAnalytics.MagSphereAnaFunA( rxLoc[:, 0], rxLoc[:, 1], rxLoc[:, 2], 100.0, 0.0, 0.0, 0.0, 0.01, b0, "secondary" ) dpred = survey.projectFieldsAsVector(B) err = np.linalg.norm(dpred - np.r_[bxa, bya, bza]) / np.linalg.norm(np.r_[bxa, bya, bza]) self.assertTrue(err < 0.08)
def Jtvec(self, m, v, f=None): if f is None: f = self.fields(m) self.model = m # Ensure v is a data object. if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) Jtv = np.zeros(m.size) AT = self.getA() for src in self.survey.srcList: u_src = f[src, self._solutionType] for rx in src.rxList: PTv = rx.evalDeriv(src, self.mesh, f, v[src, rx], adjoint=True) # wrt f, need possibility wrt m df_duTFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_duT, df_dmT = df_duTFun(src, None, PTv, adjoint=True) ATinvdf_duT = self.Ainv * df_duT dA_dmT = self.getADeriv(u_src, ATinvdf_duT, adjoint=True) dRHS_dmT = self.getRHSDeriv(src, ATinvdf_duT, adjoint=True) du_dmT = -dA_dmT + dRHS_dmT Jtv += (df_dmT + du_dmT).astype(float) # Conductivity ((d u / d log sigma).T) if self._formulation == 'EB': return -Utils.mkvc(Jtv) # Conductivity ((d u / d log rho).T) if self._formulation == 'HJ': return Utils.mkvc(Jtv)
def forward(self, m, f=None): if f is None: f = self.fields(m) self.curModel = m Jv = self.dataPair(self.survey) #same size as the data # A = self.getA() JvAll = [] for tind in range(len(self.survey.times)): #Pseudo-chareability t = self.survey.times[tind] v = self.DebyeTime(t) for src in self.survey.srcList: u_src = f[src, self._solutionType] # solution vector dA_dm_v = self.getADeriv(u_src, v) dRHS_dm_v = self.getRHSDeriv(src, v) du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: timeindex = rx.getTimeP(self.survey.times) if timeindex[tind]: df_dmFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv[src, rx, t] = rx.evalDeriv(src, self.mesh, f, df_dm_v) # Conductivity (d u / d log sigma) if self._formulation is 'EB': return -Utils.mkvc(Jv) # Resistivity (d u / d log rho) if self._formulation is 'HJ': return Utils.mkvc(Jv)
def _fastInnerProduct(self, projType, prop=None, invProp=False, invMat=False): """ Fast version of getFaceInnerProduct. This does not handle the case of a full tensor prop. :param numpy.array prop: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6)) :param str projType: 'E' or 'F' :param bool returnP: returns the projection matrices :param bool invProp: inverts the material property :param bool invMat: inverts the matrix :rtype: scipy.sparse.csr_matrix :return: M, the inner product matrix (nF, nF) """ assert projType in ["F", "E"], "projType must be 'F' for faces or 'E'" " for edges" if prop is None: prop = np.ones(self.nC) if invProp: prop = 1.0 / prop if Utils.isScalar(prop): prop = prop * np.ones(self.nC) # number of elements we are averaging (equals dim for regular # meshes, but for cyl, where we use symmetry, it is 1 for edge # variables and 2 for face variables) if self._meshType == "CYL": n_elements = np.sum(getattr(self, "vn" + projType).nonzero()) else: n_elements = self.dim # Isotropic? or anisotropic? if prop.size == self.nC: Av = getattr(self, "ave" + projType + "2CC") Vprop = self.vol * Utils.mkvc(prop) M = n_elements * Utils.sdiag(Av.T * Vprop) elif prop.size == self.nC * self.dim: Av = getattr(self, "ave" + projType + "2CCV") # if cyl, then only certain components are relevant due to symmetry # for faces, x, z matters, for edges, y (which is theta) matters if self._meshType == "CYL": if projType == "E": prop = prop[:, 1] # this is the action of a projection mat elif projType == "F": prop = prop[:, [0, 2]] V = sp.kron(sp.identity(n_elements), Utils.sdiag(self.vol)) M = Utils.sdiag(Av.T * V * Utils.mkvc(prop)) else: return None if invMat: return Utils.sdInv(M) else: return M
def getJ(self, sigma, emax, senseoption=True): """ Computing sensitivity for airbonre time domain EM IP inversion. """ Meinv = self.mesh.getEdgeInnerProduct(invMat=True) MeSig = self.mesh.getEdgeInnerProduct(sigma) Asiginf = self.mesh.nodalGrad.T*MeSig*self.mesh.nodalGrad MeDeriv = self.mesh.getEdgeInnerProductDeriv(np.ones(self.mesh.nC)) print ">>Factorizing ADC matrix" if senseoption == True: # ctx = DMumpsContext() # if ctx.myid == 0: # ctx.set_icntl(14, 60) # ctx.set_centralized_sparse(Asiginf) # ctx.run(job=4) # Factorization Ainv = MumpsSolver(Asiginf) ntx = self.survey.xyz_tx.shape[0] J = np.zeros((ntx, self.mesh.nC)) J1_temp = np.zeros(self.mesh.nC) J2_temp = np.zeros(self.mesh.nC) print ">>Computing sensitivity" for i in range (ntx): stdout.write( (" \r%d/%d transmitter") % (i, ntx) ) stdout.flush() S_temp = MeDeriv((emax[i,:]))*Utils.sdiag(sigma) G_temp = BiotSavart.BiotSavartFun(self.mesh, self.survey.xyz_tx[i,:], component = 'z') # Considering eIP term in jIP if senseoption == True: rhs = self.mesh.nodalGrad.T*MeSig*Meinv*self.mesh.aveE2CCV.T*G_temp.T # if ctx.myid == 0: # x = rhs.copy() # ctx.set_rhs(x) # ctx.run(job=3) # Solve x = Ainv*rhs J1_temp = Utils.mkvc((S_temp.T*self.mesh.nodalGrad*x).T) J2_temp = Utils.mkvc(G_temp*self.mesh.aveE2CCV*Meinv*S_temp) J[i,:] = J1_temp - J2_temp # Only consider polarization current else: J2_temp = Utils.mkvc(G_temp*self.mesh.aveE2CCV*Meinv*S_temp) J[i,:] = - J2_temp stdout.write("\n") if senseoption == True: ctx.destroy() self.J = J self.sigma = sigma self.emax = emax
def fget(self): if self._gridFy is None: N = self.r(self.gridN, 'N', 'N', 'M') if self.dim == 2: XY = [Utils.mkvc(0.5 * (n[:-1, :] + n[1:, :])) for n in N] self._gridFy = np.c_[XY[0], XY[1]] elif self.dim == 3: XYZ = [Utils.mkvc(0.25 * (n[:-1, :, :-1] + n[:-1, :, 1:] + n[1:, :, :-1] + n[1:, :, 1:])) for n in N] self._gridFy = np.c_[XYZ[0], XYZ[1], XYZ[2]] return self._gridFy
def CondSphereAnalFunB(x, y, z, R, x0, y0, z0, sig1, sig2, E0, flag): """ test Analytic function for Electro-Static problem. The set up here is conductive sphere in whole-space. * (x0,y0,z0) * (x0, y0, z0 ): is the center location of sphere * r: is the radius of the sphere .. math:: \mathbf{E}_0 = E_0\hat{x} """ if (~np.size(x)==np.size(y)==np.size(z)): print "Specify same size of x, y, z" return dim = x.shape x = Utils.mkvc(x-x0) y = Utils.mkvc(y-y0) z = Utils.mkvc(z-z0) ind = np.sqrt((x)**2+(y)**2+(z)**2 ) < R r = Utils.mkvc(np.sqrt((x)**2+(y)**2+(z)**2 )) Hx = np.zeros(x.size) Hy = np.zeros(x.size) Hz = np.zeros(x.size) # Inside of the sphere rf2 = 3*sig1/(sig2+2*sig1) Hpy = -sig1*E0/2*z Hpz = sig1*E0/2*y if (flag == 'total'): Hy[ind] = -3/2*sig2*E0*(rf2)*z[ind] Hz[ind] = 3/2*sig2*E0*(rf2)*y[ind] elif (flag == 'secondary'): Hy[ind] = -3/2*sig2*E0*(rf2)*z[ind] - Hpy[ind] Hz[ind] = 3/2*sig2*E0*(rf2)*y[ind] - Hpz[ind] # Outside of the sphere rf1 = (sig2-sig1)/(sig2+2*sig1) if (flag == 'total'): Hy[~ind] = sig1*(E0/r[~ind]**3*(R**3)*rf1*(-z[~ind]))+Hpy Hz[~ind] = sig1*(E0/r[~ind]**3*(R**3)*rf1*( y[~ind]))+Hpz elif (flag == 'secondary'): Hy[~ind] = sig1*(E0/r[~ind]**3*(R**3)*rf1*(-z[~ind])) Hz[~ind] = sig1*(E0/r[~ind]**3*(R**3)*rf1*( y[~ind])) return np.reshape(mu_0*Hx, x.shape, order='F'), np.reshape(mu_0*Hy, x.shape, order='F'), np.reshape(mu_0*Hz, x.shape, order='F')
def getError(self): #Test function phi = lambda x: np.cos(0.5*np.pi*x) j_fun = lambda x: -0.5*np.pi*np.sin(0.5*np.pi*x) q_fun = lambda x: -0.25*(np.pi**2)*np.cos(0.5*np.pi*x) xc_ana = phi(self.M.gridCC) q_ana = q_fun(self.M.gridCC) j_ana = j_fun(self.M.gridFx) #TODO: Check where our boundary conditions are CCx or Nx vecN = self.M.vectorNx vecC = self.M.vectorCCx phi_bc = phi(vecC[[0,-1]]) j_bc = j_fun(vecN[[0,-1]]) P, Pin, Pout = self.M.getBCProjWF([['dirichlet', 'neumann']]) Mc = self.M.getFaceInnerProduct() McI = Utils.sdInv(self.M.getFaceInnerProduct()) V = Utils.sdiag(self.M.vol) G = -Pin.T*Pin*self.M.faceDiv.T * V D = self.M.faceDiv j = McI*(G*xc_ana + P*phi_bc) q = V*D*Pin.T*Pin*j + V*D*Pout.T*j_bc # Rearrange if we know q to solve for x A = V*D*Pin.T*Pin*McI*G rhs = V*q_ana - V*D*Pin.T*Pin*McI*P*phi_bc - V*D*Pout.T*j_bc # A = D*McI*G # rhs = q_ana - D*McI*P*phi_bc if self.myTest == 'j': err = np.linalg.norm((Pin*j-Pin*j_ana), np.inf) elif self.myTest == 'q': err = np.linalg.norm((q-V*q_ana), np.inf) elif self.myTest == 'xc': #TODO: fix the null space xc, info = sp.linalg.minres(A, rhs, tol = 1e-6) err = np.linalg.norm((xc-xc_ana), np.inf) if info > 0: print('Solve does not work well') print('ACCURACY', np.linalg.norm(Utils.mkvc(A*xc) - rhs)) elif self.myTest == 'xcJ': #TODO: fix the null space xc, info = sp.linalg.minres(A, rhs, tol = 1e-6) j = McI*(G*xc + P*phi_bc) err = np.linalg.norm((Pin*j-Pin*j_ana), np.inf) if info > 0: print('Solve does not work well') print('ACCURACY', np.linalg.norm(Utils.mkvc(A*xc) - rhs)) return err
def test_SetGet(self): F = self.F nSrc = F.survey.nSrc nT = F.survey.prob.nT + 1 e = np.random.rand(F.mesh.nE, nSrc, nT) F[:, 'e'] = e b = np.random.rand(F.mesh.nF, nSrc, nT) F[:, 'b'] = b self.assertTrue(np.all(F[:, 'e'] == e)) self.assertTrue(np.all(F[:, 'b'] == b)) F[:] = {'b': b, 'e': e} self.assertTrue(np.all(F[:, 'e'] == e)) self.assertTrue(np.all(F[:, 'b'] == b)) for s in zero_types: F[:, 'b'] = s self.assertTrue(np.all(F[:, 'b'] == b*0)) b = np.random.rand(F.mesh.nF, 1, nT) F[self.Src0, 'b'] = b self.assertTrue(np.all(F[self.Src0, 'b'] == b[:, 0, :])) b = np.random.rand(F.mesh.nF, 1, nT) F[self.Src0, 'b', 0] = b[:, :, 0] self.assertTrue(np.all(F[self.Src0, 'b', 0] == Utils.mkvc(b[:, 0, 0], 2))) phi = np.random.rand(F.mesh.nC, 2, nT) F[[self.Src0, self.Src1], 'phi'] = phi self.assertTrue(np.all(F[[self.Src0, self.Src1], 'phi'] == phi)) fdict = F[:] self.assertTrue(type(fdict) is dict) self.assertTrue(sorted([k for k in fdict]) == ['b', 'e', 'phi']) b = np.random.rand(F.mesh.nF, 2, nT) F[[self.Src0, self.Src1], 'b'] = b self.assertTrue(F[self.Src0]['b'].shape == (F.mesh.nF, nT)) self.assertTrue(F[self.Src0, 'b'].shape == (F.mesh.nF, nT)) self.assertTrue(np.all(F[self.Src0, 'b'] == b[:, 0, :])) self.assertTrue(np.all(F[self.Src1, 'b'] == b[:, 1, :])) self.assertTrue(np.all(F[self.Src0, 'b', 1] == Utils.mkvc(b[:, 0, 1], 2))) self.assertTrue(np.all(F[self.Src1, 'b', 1] == Utils.mkvc(b[:, 1, 1], 2))) self.assertTrue(np.all(F[self.Src0, 'b', 4] == Utils.mkvc(b[:, 0, 4], 2))) self.assertTrue(np.all(F[self.Src1, 'b', 4] == Utils.mkvc(b[:, 1, 4], 2))) b = np.random.rand(F.mesh.nF, 2, nT) F[[self.Src0, self.Src1], 'b', 0] = b[:, :, 0]
def test_rotatePointsFromNormals(self): np.random.seed(10) v0 = np.random.rand(3) v0*= 1./np.linalg.norm(v0) np.random.seed(15) v1 = np.random.rand(3) v1*= 1./np.linalg.norm(v1) v2 = Utils.mkvc(Utils.coordutils.rotatePointsFromNormals(Utils.mkvc(v0,2).T,v0,v1)) self.assertTrue(np.linalg.norm(v2-v1) < tol)
def MagSphereAnaFunA(x, y, z, R, xc, yc, zc, chi, Bo, flag): """Computing boundary condition using Congrous sphere method. This is designed for secondary field formulation. >> Input mesh: Mesh class Bo: np.array([Box, Boy, Boz]): Primary magnetic flux Chi: susceptibility at cell volume .. math:: \\vec{B}(r) = \\frac{\mu_0}{4\pi}\\frac{m}{\| \\vec{r}-\\vec{r}_0\|^3}[3\hat{m}\cdot\hat{r}-\hat{m}] """ if (~np.size(x)==np.size(y)==np.size(z)): print("Specify same size of x, y, z") return dim = x.shape x = Utils.mkvc(x) y = Utils.mkvc(y) z = Utils.mkvc(z) Bot = np.sqrt(sum(Bo**2)) mx = Bo[0]/Bot my = Bo[1]/Bot mz = Bo[2]/Bot ind = np.sqrt((x-xc)**2+(y-yc)**2+(z-zc)**2 ) < R Bx = np.zeros(x.size) By = np.zeros(x.size) Bz = np.zeros(x.size) # Inside of the sphere rf2 = 3/(chi+3)*(1+chi) if (flag == 'total'): Bx[ind] = Bo[0]*(rf2) By[ind] = Bo[1]*(rf2) Bz[ind] = Bo[2]*(rf2) elif (flag == 'secondary'): Bx[ind] = Bo[0]*(rf2)-Bo[0] By[ind] = Bo[1]*(rf2)-Bo[1] Bz[ind] = Bo[2]*(rf2)-Bo[2] r = Utils.mkvc(np.sqrt((x-xc)**2+(y-yc)**2+(z-zc)**2 )) V = 4*np.pi*R**3/3 mom = Bot/mu_0*chi/(1+chi/3)*V const = mu_0/(4*np.pi)*mom mdotr = (mx*(x[~ind]-xc)/r[~ind] + my*(y[~ind]-yc)/r[~ind] + mz*(z[~ind]-zc)/r[~ind]) Bx[~ind] = const/(r[~ind]**3)*(3*mdotr*(x[~ind]-xc)/r[~ind]-mx) By[~ind] = const/(r[~ind]**3)*(3*mdotr*(y[~ind]-yc)/r[~ind]-my) Bz[~ind] = const/(r[~ind]**3)*(3*mdotr*(z[~ind]-zc)/r[~ind]-mz) return Bx, By, Bz
def getError(self): #Test function phi = lambda x: np.cos(np.pi*x) j_fun = lambda x: -np.pi*np.sin(np.pi*x) q_fun = lambda x: -(np.pi**2)*np.cos(np.pi*x) xc_ana = phi(self.M.gridCC) q_ana = q_fun(self.M.gridCC) j_ana = j_fun(self.M.gridFx) #TODO: Check where our boundary conditions are CCx or Nx # vec = self.M.vectorNx vec = self.M.vectorCCx phi_bc = phi(vec[[0,-1]]) j_bc = j_fun(vec[[0,-1]]) P, Pin, Pout = self.M.getBCProjWF([['dirichlet', 'dirichlet']]) Mc = self.M.getFaceInnerProduct() McI = Utils.sdInv(self.M.getFaceInnerProduct()) V = Utils.sdiag(self.M.vol) G = -Pin.T*Pin*self.M.faceDiv.T * V D = self.M.faceDiv j = McI*(G*xc_ana + P*phi_bc) q = V*D*Pin.T*Pin*j + V*D*Pout.T*j_bc # Rearrange if we know q to solve for x A = V*D*Pin.T*Pin*McI*G rhs = V*q_ana - V*D*Pin.T*Pin*McI*P*phi_bc - V*D*Pout.T*j_bc # A = D*McI*G # rhs = q_ana - D*McI*P*phi_bc if self.myTest == 'j': err = np.linalg.norm((j-j_ana), np.inf) elif self.myTest == 'q': err = np.linalg.norm((q-V*q_ana), np.inf) elif self.myTest == 'xc': #TODO: fix the null space solver = SolverCG(A, maxiter=1000) xc = solver * (rhs) print('ACCURACY', np.linalg.norm(Utils.mkvc(A*xc) - rhs)) err = np.linalg.norm((xc-xc_ana), np.inf) elif self.myTest == 'xcJ': #TODO: fix the null space xc = Solver(A) * (rhs) print(np.linalg.norm(Utils.mkvc(A*xc) - rhs)) j = McI*(G*xc + P*phi_bc) err = np.linalg.norm((j-j_ana), np.inf) return err
def run(plotIt=True, nx=5, ny=5): # 2D mesh mesh = Mesh.TensorMesh([nx, ny], x0='CC') xtopo = mesh.vectorNx # define a topographic surface topo = 0.4*np.sin(xtopo*5) # make it an array Topo = np.hstack([Utils.mkvc(xtopo, 2), Utils.mkvc(topo, 2)]) # Compare the different options indtopoCC_near = surface2ind_topo(mesh, Topo, gridLoc='CC', method='nearest') indtopoN_near = surface2ind_topo(mesh, Topo, gridLoc='N', method='nearest') indtopoCC_linear = surface2ind_topo(mesh, Topo, gridLoc='CC', method='linear') indtopoN_linear = surface2ind_topo(mesh, Topo, gridLoc='N', method='linear') indtopoCC_cubic = surface2ind_topo(mesh, Topo, gridLoc='CC', method='cubic') indtopoN_cubic = surface2ind_topo(mesh, Topo, gridLoc='N', method='cubic') if plotIt: fig, ax = plt.subplots(2, 3, figsize=(9, 6)) ax = mkvc(ax) xinterpolate = np.linspace(mesh.gridN[:, 0].min(), mesh.gridN[:, 0].max(),100) listindex = [indtopoCC_near,indtopoN_near,indtopoCC_linear,indtopoN_linear,indtopoCC_cubic,indtopoN_cubic] listmethod = ['nearest','nearest', 'linear', 'linear', 'cubic', 'cubic'] for i in range(6): mesh.plotGrid(ax=ax[i], nodes=True, centers=True) mesh.plotImage(listindex[i], ax=ax[i], pcolorOpts = {"alpha":0.5, "cmap":plt.cm.gray}) ax[i].scatter(Topo[:,0], Topo[:,1], color = 'black', marker = 'o',s = 50) ax[i].plot( xinterpolate, interp1d(Topo[:, 0], Topo[:, 1], kind=listmethod[i])(xinterpolate), '--k', linewidth=3 ) ax[i].xaxis.set_ticklabels([]) ax[i].yaxis.set_ticklabels([]) ax[i].set_aspect('equal') ax[i].set_xlabel('') ax[i].set_ylabel('') ax[0].set_xlabel('Nearest Interpolation', fontsize=16) ax[2].set_xlabel('Linear Interpolation', fontsize=16) ax[4].set_xlabel('Cubic Interpolation', fontsize=16) ax[0].set_ylabel('Cells Center \n based selection', fontsize=16) ax[1].set_ylabel('Nodes \n based selection', fontsize=16) plt.tight_layout()
def test_regularization_ActiveCells(self): for R in dir(Regularization): r = getattr(Regularization, R) if not inspect.isclass(r): continue if not issubclass(r, ObjectiveFunction.BaseObjectiveFunction): continue if r.__name__ in IGNORE_ME: continue for i, mesh in enumerate(self.meshlist): print('Testing Active Cells {0:d}D'.format((mesh.dim))) if mesh.dim == 1: indActive = Utils.mkvc(mesh.gridCC <= 0.8) elif mesh.dim == 2: indActive = Utils.mkvc(mesh.gridCC[:, -1] <= ( 2*np.sin(2*np.pi*mesh.gridCC[:, 0])+0.5) ) elif mesh.dim == 3: indActive = Utils.mkvc(mesh.gridCC[:, -1] <= ( 2 * np.sin(2*np.pi*mesh.gridCC[:, 0])+0.5 * 2 * np.sin(2*np.pi*mesh.gridCC[:, 1])+0.5) ) if mesh.dim < 3 and r.__name__[-1] == 'z': continue if mesh.dim < 2 and r.__name__[-1] == 'y': continue for indAct in [indActive, indActive.nonzero()[0]]: # test both bool and integers if indAct.dtype != bool: nP = indAct.size else: nP = int(indAct.sum()) reg = r( mesh, indActive=indAct, mapping=Maps.IdentityMap(nP=nP) ) m = np.random.rand(mesh.nC)[indAct] mref = np.ones_like(m)*np.mean(m) reg.mref = mref print( '--- Checking {} ---\n'.format( reg.__class__.__name__ ) ) passed = reg.test(m, eps=TOL) self.assertTrue(passed)
def gridEy(self): """ Edge staggered grid in the y direction. """ if getattr(self, '_gridEy', None) is None: N = self.r(self.gridN, 'N', 'N', 'M') if self.dim == 2: XY = [Utils.mkvc(0.5 * (n[:, :-1] + n[:, 1:])) for n in N] self._gridEy = np.c_[XY[0], XY[1]] elif self.dim == 3: XYZ = [Utils.mkvc(0.5 * (n[:, :-1, :] + n[:, 1:, :])) for n in N] self._gridEy = np.c_[XYZ[0], XYZ[1], XYZ[2]] return self._gridEy
def test_data(self): V = [] for src in self.D.survey.srcList: for rx in src.rxList: v = np.random.rand(rx.nD) V += [v] self.D[src, rx] = v self.assertTrue(np.all(v == self.D[src, rx])) V = np.concatenate(V) self.assertTrue(np.all(V == Utils.mkvc(self.D))) D2 = Survey.Data(self.D.survey, V) self.assertTrue(np.all(Utils.mkvc(D2) == Utils.mkvc(self.D)))
def MagSphereAnaFun(x, y, z, R, x0, y0, z0, mu1, mu2, H0, flag='total'): """ test Analytic function for Magnetics problem. The set up here is magnetic sphere in whole-space assuming that the inducing field is oriented in the x-direction. * (x0, y0, z0) * (x0, y0, z0 ): is the center location of sphere * r: is the radius of the sphere .. math:: \mathbf{H}_0 = H_0\hat{x} """ if (~np.size(x)==np.size(y)==np.size(z)): print("Specify same size of x, y, z") return dim = x.shape x = Utils.mkvc(x) y = Utils.mkvc(y) z = Utils.mkvc(z) ind = np.sqrt((x-x0)**2+(y-y0)**2+(z-z0)**2) < R r = Utils.mkvc(np.sqrt((x-x0)**2+(y-y0)**2+(z-z0)**2)) Bx = np.zeros(x.size) By = np.zeros(x.size) Bz = np.zeros(x.size) # Inside of the sphere rf2 = 3*mu1/(mu2+2*mu1) if flag is 'total' and any(ind): Bx[ind] = mu2*H0*(rf2) elif (flag == 'secondary'): Bx[ind] = mu2*H0*(rf2)-mu1*H0 By[ind] = 0. Bz[ind] = 0. # Outside of the sphere rf1 = (mu2-mu1)/(mu2+2*mu1) if (flag == 'total'): Bx[~ind] = mu1*(H0+H0/r[~ind]**5*(R**3)*rf1*(2*(x[~ind]-x0)**2-(y[~ind]-y0)**2-(z[~ind]-z0)**2)) elif (flag == 'secondary'): Bx[~ind] = mu1*(H0/r[~ind]**5*(R**3)*rf1*(2*(x[~ind]-x0)**2-(y[~ind]-y0)**2-(z[~ind]-z0)**2)) By[~ind] = mu1*(H0/r[~ind]**5*(R**3)*rf1*(3*(x[~ind]-x0)*(y[~ind]-y0))) Bz[~ind] = mu1*(H0/r[~ind]**5*(R**3)*rf1*(3*(x[~ind]-x0)*(z[~ind]-z0))) return np.reshape(Bx, x.shape, order='F'), np.reshape(By, x.shape, order='F'), np.reshape(Bz, x.shape, order='F')
def setUp(self): # Define sphere parameters self.rad = 2. self.rho = 0.1 # Define a mesh cs = 0.2 hxind = [(cs, 21)] hyind = [(cs, 21)] hzind = [(cs, 21)] mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCC') # Get cells inside the sphere sph_ind = PF.MagAnalytics.spheremodel(mesh, 0., 0., 0., self.rad) # Adjust density for volume difference Vratio = (4./3.*np.pi*self.rad**3.) / (np.sum(sph_ind)*cs**3.) model = np.ones(mesh.nC)*self.rho*Vratio self.model = model[sph_ind] # Create reduced identity map for Linear Pproblem idenMap = Maps.IdentityMap(nP=int(sum(sph_ind))) # Create plane of observations xr = np.linspace(-20, 20, 21) yr = np.linspace(-20, 20, 21) X, Y = np.meshgrid(xr, yr) # Move obs plane 2 radius away from sphere Z = np.ones((xr.size, yr.size))*2.*self.rad self.locXyz = np.c_[Utils.mkvc(X), Utils.mkvc(Y), Utils.mkvc(Z)] rxLoc = PF.BaseGrav.RxObs(self.locXyz) srcField = PF.BaseGrav.SrcField([rxLoc]) self.survey = PF.BaseGrav.LinearSurvey(srcField) self.prob_x = PF.Gravity.GravityIntegral(mesh, rhoMap=idenMap, actInd=sph_ind, forwardOnly=True, rx_type='x') self.prob_y = PF.Gravity.GravityIntegral(mesh, rhoMap=idenMap, actInd=sph_ind, forwardOnly=True, rx_type='y') self.prob_z = PF.Gravity.GravityIntegral(mesh, rhoMap=idenMap, actInd=sph_ind, forwardOnly=True, rx_type='z')
def vol(self): """Construct cell volumes of the 3D model as 1d array.""" if getattr(self, '_vol', None) is None: vh = self.h # Compute cell volumes if self.dim == 1: self._vol = Utils.mkvc(vh[0]) elif self.dim == 2: # Cell sizes in each direction self._vol = Utils.mkvc(np.outer(vh[0], vh[1])) elif self.dim == 3: # Cell sizes in each direction self._vol = Utils.mkvc(np.outer(Utils.mkvc(np.outer(vh[0], vh[1])), vh[2])) return self._vol
def test_rotationMatrixFromNormals(self): np.random.seed(0) v0 = np.random.rand(3) v0 *= 1./np.linalg.norm(v0) np.random.seed(5) v1 = np.random.rand(3) v1 *= 1./np.linalg.norm(v1) Rf = Utils.coordutils.rotationMatrixFromNormals(v0,v1) Ri = Utils.coordutils.rotationMatrixFromNormals(v1,v0) self.assertTrue(np.linalg.norm(Utils.mkvc(Rf.dot(v0) - v1)) < tol) self.assertTrue(np.linalg.norm(Utils.mkvc(Ri.dot(v1) - v0)) < tol)
def CondSphereAnalFunJ(x, y, z, R, x0, y0, z0, sig1, sig2, E0, flag): """ test Analytic function for Electro-Static problem. The set up here is conductive sphere in whole-space. * (x0,y0,z0) * (x0, y0, z0 ): is the center location of sphere * r: is the radius of the sphere .. math:: \mathbf{E}_0 = E_0\hat{x} """ if (~np.size(x)==np.size(y)==np.size(z)): print "Specify same size of x, y, z" return dim = x.shape x = Utils.mkvc(x-x0) y = Utils.mkvc(y-y0) z = Utils.mkvc(z-z0) ind = np.sqrt((x)**2+(y)**2+(z)**2 ) < R r = Utils.mkvc(np.sqrt((x)**2+(y)**2+(z)**2 )) Jx = np.zeros(x.size) Jy = np.zeros(x.size) Jz = np.zeros(x.size) # Inside of the sphere rf2 = 3*sig1/(sig2+2*sig1) if (flag == 'total'): Jx[ind] = sig2*E0*(rf2) elif (flag == 'secondary'): Jx[ind] = sig2*E0*(rf2)-sig1*E0 Jy[ind] = 0. Jz[ind] = 0. # Outside of the sphere rf1 = (sig2-sig1)/(sig2+2*sig1) if (flag == 'total'): Jx[~ind] = sig1*(E0+E0/r[~ind]**5*(R**3)*rf1*(2*x[~ind]**2-y[~ind]**2-z[~ind]**2)) elif (flag == 'secondary'): Jx[~ind] = sig1*(E0/r[~ind]**5*(R**3)*rf1*(2*x[~ind]**2-y[~ind]**2-z[~ind]**2)) Jy[~ind] = sig1*(E0/r[~ind]**5*(R**3)*rf1*(3*x[~ind]*y[~ind])) Jz[~ind] = sig1*(E0/r[~ind]**5*(R**3)*rf1*(3*x[~ind]*z[~ind])) return np.reshape(Jx, x.shape, order='F'), np.reshape(Jy, x.shape, order='F'), np.reshape(Jz, x.shape, order='F')
def hzAnalyticDipoleF(r, freq, sigma, secondary=True, mu=mu_0): """ 4.56 in Ward and Hohmann .. plot:: import matplotlib.pyplot as plt from SimPEG import EM freq = np.logspace(-1, 6, 61) test = EM.Analytics.FDEM.hzAnalyticDipoleF(100, freq, 0.001, secondary=False) plt.loglog(freq, abs(test.real)) plt.loglog(freq, abs(test.imag)) plt.title('Response at $r$=100m') plt.xlabel('Frequency') plt.ylabel('Response') plt.legend(('real','imag')) plt.show() """ r = np.abs(r) k = np.sqrt(-1j*2.*np.pi*freq*mu*sigma) m = 1 front = m / (2. * np.pi * (k**2) * (r**5) ) back = 9 - ( 9 + 9j * k * r - 4 * (k**2) * (r**2) - 1j * (k**3) * (r**3)) * np.exp(-1j*k*r) hz = front*back if secondary: hp =-1/(4*np.pi*r**3) hz = hz-hp if hz.ndim == 1: hz = Utils.mkvc(hz,2) return hz
def Jvec(self, m, v, u=None): """ Sensitivity times a vector. :param numpy.array m: inversion model (nP,) :param numpy.array v: vector which we take sensitivity product with (nP,) :param SimPEG.EM.FDEM.Fields u: fields object :rtype numpy.array: :return: Jv (ndata,) """ if u is None: u = self.fields(m) self.curModel = m Jv = self.dataPair(self.survey) for freq in self.survey.freqs: A = self.getA(freq) Ainv = self.Solver(A, **self.solverOpts) for src in self.survey.getSrcByFreq(freq): u_src = u[src, self._solutionType] dA_dm_v = self.getADeriv(freq, u_src, v) dRHS_dm_v = self.getRHSDeriv(freq, src, v) du_dm_v = Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: df_dmFun = getattr(u, '_%sDeriv'%rx.projField, None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv[src, rx] = rx.evalDeriv(src, self.mesh, u, df_dm_v) Ainv.clean() return Utils.mkvc(Jv)
def Wd(self): """getWd(survey) The data weighting matrix. The default is based on the norm of the data plus a noise floor. :rtype: scipy.sparse.csr_matrix :return: Wd """ if getattr(self, '_Wd', None) is None: survey = self.survey if getattr(survey,'std', None) is None: print('SimPEG.DataMisfit.l2_DataMisfit assigning default std of 5%') survey.std = 0.05 if getattr(survey, 'eps', None) is None: print('SimPEG.DataMisfit.l2_DataMisfit assigning default eps of 1e-5 * ||dobs||') survey.eps = np.linalg.norm(Utils.mkvc(survey.dobs),2)*1e-5 self._Wd = Utils.sdiag(1/(abs(survey.dobs)*survey.std+survey.eps)) return self._Wd
def Jvec(self, m, v, f=None): self.model = m # When sensitivity matrix J is stored if self.storeJ: J = self.getJ(m, f=f) Jv = Utils.mkvc(np.dot(J, v)) return self.sign * Jv else: if f is None: f = self.fields(m) Jv = [] for src in self.survey.srcList: u_src = f[src, self._solutionType] # solution vector dA_dm_v = self.getADeriv(u_src.flatten(), v, adjoint=False) dRHS_dm_v = self.getRHSDeriv(src, v) du_dm_v = self.Ainv * ( - dA_dm_v + dRHS_dm_v ) for rx in src.rxList: df_dmFun = getattr(f, '_{0!s}Deriv'.format(rx.projField), None) df_dm_v = df_dmFun(src, du_dm_v, v, adjoint=False) Jv.append(rx.evalDeriv(src, self.mesh, f, df_dm_v)) # Conductivity (d u / d log sigma) - EB form # Resistivity (d u / d log rho) - HJ form return self.sign*np.hstack(Jv)
def test_rotateMatrixFromNormals(self): np.random.seed(20) n0 = np.random.rand(3) n0 *= 1. / np.linalg.norm(n0) np.random.seed(25) n1 = np.random.rand(3) n1 *= 1. / np.linalg.norm(n1) np.random.seed(30) scale = np.random.rand(100, 1) XYZ0 = scale * n0 XYZ1 = scale * n1 XYZ2 = Utils.coordutils.rotatePointsFromNormals(XYZ0, n0, n1) self.assertTrue( np.linalg.norm(Utils.mkvc(XYZ1) - Utils.mkvc(XYZ2)) / np.linalg.norm(Utils.mkvc(XYZ1)) < tol)
def gridEz(self): """ Edge staggered grid in the z direction. """ if getattr(self, '_gridEz', None) is None and self.dim == 3: N = self.r(self.gridN, 'N', 'N', 'M') XYZ = [Utils.mkvc(0.5 * (n[:, :, :-1] + n[:, :, 1:])) for n in N] self._gridEz = np.c_[XYZ[0], XYZ[1], XYZ[2]] return self._gridEz