def doSlice(v): if vType == "CC": return getIndSlice(self.r(v, "CC", "CC", "M")) elif vType == "CCv": assert view == "vec", "Other types for CCv not supported" else: # Now just deal with 'F' and 'E' (x,y,z, maybe...) aveOp = "ave" + vType + ("2CCV" if view == "vec" else "2CC") Av = getattr(self, aveOp) if v.size == Av.shape[1]: v = Av * v else: v = self.r(v, vType[0], vType) # get specific component v = Av * v # we should now be averaged to cell centers (might be a vector) v = self.r(v.reshape((self.nC, -1), order="F"), "CC", "CC", "M") if view == "vec": outSlice = [] if "X" not in normal: outSlice.append(getIndSlice(v[0])) if "Y" not in normal: outSlice.append(getIndSlice(v[1])) if "Z" not in normal: outSlice.append(getIndSlice(v[2])) return np.r_[mkvc(outSlice[0]), mkvc(outSlice[1])] else: return getIndSlice(self.r(v, "CC", "CC", "M"))
def getJtJdiag(self, m, W=None): """ Return the diagonal of JtJ """ dmudm = self.chiMap.deriv(m) self._dSdm = None self._dfdm = None self.model = m if (self.gtgdiag is None) and (self.modelType != 'amplitude'): if W is None: w = np.ones(self.G.shape[1]) else: w = W.diagonal() self.gtgdiag = np.zeros(dmudm.shape[1]) for ii in range(self.G.shape[0]): self.gtgdiag += (w[ii]*self.G[ii, :]*dmudm)**2. if self.coordinate_system == 'cartesian': if self.modelType == 'amplitude': return np.sum((W * self.dfdm * self.G * dmudm)**2., axis=0) else: return self.gtgdiag else: # spherical if self.modelType == 'amplitude': return np.sum(((W * self.dfdm) * self.G * (self.dSdm * dmudm))**2., axis=0) else: Japprox = sdiag(mkvc(self.gtgdiag)**0.5*dmudm.T) * (self.dSdm * dmudm) return mkvc(np.sum(Japprox.power(2), axis=0))
def gridDrappedXYZ(width, height, spacing, x0=(0, 0, 0), topo=None): """ grid_survey(width) Generate concentric grid surveys centered at the origin :grid: List of grid spacing :width: Grid width return: rxLoc an n-by-3 receiver locations """ nCx = int(width/spacing) nCy = int(height/spacing) dx = width/nCx dy = height/nCy rxVec = -width/2. + dx/2. + np.asarray(range(nCx))*dx ryVec = -height/2. + dy/2. + np.asarray(range(nCy))*dy rxGridx, rxGridy = np.meshgrid(rxVec, ryVec) rxGridx += x0[0] rxGridy += x0[1] if topo is not None: rxGridz = sp.interpolate.griddata(topo[:, :2], topo[:, 2], (rxGridx, rxGridy), method='linear') + x0[2] else: rxGridz = np.zeros_like(rxGridx) + x0[2] return np.c_[mkvc(rxGridx), mkvc(rxGridy), mkvc(rxGridz)]
def gridCC(self): if getattr(self, '_gridCC', None) is None: X, Y = np.meshgrid(self.hx, self.hy) self._gridCC = np.c_[mkvc(X), mkvc(Y)] return self._gridCC
def refine_box(mesh): # Refine for sphere xp, yp, zp = np.meshgrid([-55., 50.], [-50., 50.], [-40., 20.]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] mesh = refine_tree_xyz(mesh, xyz, octree_levels=[2], method='box', finalize=False) return mesh
def refine_topography(mesh): # Define topography and refine [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy) zz = -3 * np.exp((xx**2 + yy**2) / 60**2) + 45. topo = np.c_[mkvc(xx), mkvc(yy), mkvc(zz)] mesh = refine_tree_xyz(mesh, topo, octree_levels=[3, 2], method='surface', finalize=False) return mesh
def Jtvec(self, m, v, u=None): """ :param numpy.array m: Conductivity model :param numpy.ndarray,SimPEG.Survey.Data v: vector (data object) :param simpegEM.TDEM.FieldsTDEM u: Fields resulting from m :rtype: numpy.ndarray :return: w (model object) Multiplying \\\(\\\mathbf{J}^\\\\top\\\) onto a vector can be broken into three steps * Compute \\\(\\\\vec{p} = \\\mathbf{Q}^\\\\top \\\\vec{v}\\\) * Solve \\\(\\\hat{\\\mathbf{A}}^\\\\top \\\\vec{y} = \\\\vec{p}\\\) * Compute \\\(\\\\vec{w} = -\\\mathbf{G}^\\\\top y\\\) """ if self.verbose: print '%s\nCalculating J^T(v)\n%s'%('*'*50,'*'*50) self.curModel = m if u is None: u = self.fields(m) if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) p = self.survey.projectFieldsDeriv(u, v=v, adjoint=True) y = self.solveAht(m, p) w = self.Gtvec(m, y, u) if self.verbose: print '%s\nDone calculating J^T(v)\n%s'%('*'*50,'*'*50) return - mkvc(w)
def Jvec(self, m, v, f=None): """ :param numpy.array m: Conductivity model :param numpy.ndarray v: vector (model object) :param FieldsTDEM f: Fields resulting from m :rtype: numpy.ndarray :return: w (data object) Multiplying \\\(\\\mathbf{J}\\\) onto a vector can be broken into three steps * Compute \\\(\\\\vec{p} = \\\mathbf{G}v\\\) * Solve \\\(\\\hat{\\\mathbf{A}} \\\\vec{y} = \\\\vec{p}\\\) * Compute \\\(\\\\vec{w} = -\\\mathbf{Q} \\\\vec{y}\\\) """ if self.verbose: print '{0!s}\nCalculating J(v)\n{1!s}'.format('*' * 50, '*' * 50) self.curModel = m if f is None: f = self.fields(m) p = self.Gvec(m, v, f) y = self.solveAh(m, p) Jv = self.survey.evalDeriv(f, v=y) if self.verbose: print '{0!s}\nDone calculating J(v)\n{1!s}'.format( '*' * 50, '*' * 50) return -mkvc(Jv)
def calculate(self): self.nD = self.rxLoc.shape[0] if self.parallelized: if self.n_cpu is None: # By default take half the cores, turns out be faster # than running full threads self.n_cpu = int(multiprocessing.cpu_count()/2) pool = multiprocessing.Pool(self.n_cpu) result = pool.map(self.calcTrow, [self.rxLoc[ii, :] for ii in range(self.nD)]) pool.close() pool.join() else: result = [] for ii in range(self.nD): result += [self.calcTrow(self.rxLoc[ii, :])] self.progress(ii, self.nD) if self.forwardOnly: return mkvc(np.vstack(result)) else: return np.vstack(result)
def upwardContinuation(self, z=0): """ Function to calculate upward continued data """ self.heightUC = z upFact = -( np.sqrt(self.Kx**2. + self.Ky**2.) * z / np.sqrt(self.dx**2. + self.dy**2.) ) FzUpw = self.gridFFT*np.exp(upFact) zUpw_pad = np.fft.ifft2(FzUpw) zUpw = np.real( zUpw_pad[self.npady:-self.npady, self.npadx:-self.npadx]) self._valuesFilledUC = zUpw.copy() if self.indNan is not None: zUpw = mkvc(zUpw) zUpw[self.indNan] = np.nan zUpw = zUpw.reshape(self.values.shape, order='F') return zUpw
def setRTP(self, isRTP): if isRTP: if np.isnan(self.inc): print("Attibute 'inc' needs to be set") if np.isnan(self.dec): print("Attibute 'dec' needs to be set") h0_xyz = MathUtils.dipazm_2_xyz(self.inc, self.dec) Frtp = self.gridFFT / ( (h0_xyz[2] + 1j*(self.Kx*h0_xyz[0] + self.Ky*h0_xyz[1]))**2. ) rtp_pad = np.fft.ifft2(Frtp) rtp = np.real( rtp_pad[self.npady:-self.npady, self.npadx:-self.npadx]) if self.indNan is not None: rtp = mkvc(rtp) rtp[self.indNan] = np.nan rtp = rtp.reshape(self.values.shape, order='F') self._RTP = rtp for prop in gridProps: setattr(self, '_{}'.format(prop), None) else: self._RTP = None for prop in gridProps: setattr(self, '_{}'.format(prop), None)
def test_zero(self): z = Zero() assert z == 0 assert not (z < 0) assert z <= 0 assert not (z > 0) assert z >= 0 assert +z == z assert -z == z assert z + 1 == 1 assert z + 3 +z == 3 assert z - 3 == -3 assert z - 3 -z == -3 assert 3*z == 0 assert z*3 == 0 assert z/3 == 0 a = 1 a += z assert a == 1 a = 1 a += z assert a == 1 self.assertRaises(ZeroDivisionError, lambda:3/z) assert mkvc(z) == 0 assert sdiag(z)*a == 0 assert z.T == 0 assert z.transpose == 0
def Jtvec(self, m, v, f=None): """ :param numpy.array m: Conductivity model :param numpy.ndarray v: vector (or a :class:`SimPEG.Survey.Data` object) :param FieldsTDEM u: Fields resulting from m :rtype: numpy.ndarray :return: w (model object) Multiplying \\\(\\\mathbf{J}^\\\\top\\\) onto a vector can be broken into three steps * Compute \\\(\\\\vec{p} = \\\mathbf{Q}^\\\\top \\\\vec{v}\\\) * Solve \\\(\\\hat{\\\mathbf{A}}^\\\\top \\\\vec{y} = \\\\vec{p}\\\) * Compute \\\(\\\\vec{w} = -\\\mathbf{G}^\\\\top y\\\) """ if self.verbose: print '{0!s}\nCalculating J^T(v)\n{1!s}'.format('*' * 50, '*' * 50) self.curModel = m if f is None: f = self.fields(m) if not isinstance(v, self.dataPair): v = self.dataPair(self.survey, v) p = self.survey.evalDeriv(f, v=v, adjoint=True) y = self.solveAht(m, p) w = self.Gtvec(m, y, f) if self.verbose: print '{0!s}\nDone calculating J^T(v)\n{1!s}'.format( '*' * 50, '*' * 50) return -mkvc(w)
def eval(self, prob): if prob._formulation == 'HJ': inds = closestPoints(prob.mesh, self.loc) q = np.zeros(prob.mesh.nC) q[inds] = self.current * np.r_[1.] elif prob._formulation == 'EB': q = prob.mesh.getInterpolationMat(self.loc, locType='N').todense() q = self.current * mkvc(q) return q
def eval(self, prob): if prob._formulation == 'HJ': inds = closestPoints(prob.mesh, self.loc, gridLoc='CC') q = np.zeros(prob.mesh.nC) q[inds] = self.current * np.r_[1., -1.] elif prob._formulation == 'EB': qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense() qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense() q = self.current * mkvc(qa+qb) return q
def eval(self, prob): if prob._formulation == 'HJ': inds = closestPoints(prob.mesh, self.loc, gridLoc='CC') q = np.zeros(prob.mesh.nC) q[inds] = self.current * np.r_[1., -1.] elif prob._formulation == 'EB': qa = prob.mesh.getInterpolationMat(self.loc[0], locType='N').todense() qb = -prob.mesh.getInterpolationMat(self.loc[1], locType='N').todense() q = self.current * mkvc(qa + qb) return q
def GravSphereFreeSpace(x, y, z, R, xc, yc, zc, rho): """ Computing the induced response of magnetic sphere in free-space. >> Input x, y, z: Observation locations R: radius of the sphere xc, yc, zc: Location of the sphere rho: Density of sphere By convention, z-component is positive downward for a positive density anomaly """ if (~np.size(x) == np.size(y) == np.size(z)): print("Specify same size of x, y, z") return unit_conv = 1e+8 # Unit conversion from SI to (mgal*g/cc) x = mkvc(x) y = mkvc(y) z = mkvc(z) nobs = len(x) M = R**3. * 4. / 3. * np.pi * rho rx = (x - xc) ry = (y - yc) rz = (zc - z) rvec = np.c_[rx, ry, rz] r = np.sqrt((rx)**2 + (ry)**2 + (rz)**2) g = -G * (1. / r**2) * M * unit_conv gx = g * (rx / r) gy = g * (ry / r) gz = g * (rz / r) return gx, gy, gz
def GravSphereFreeSpace(x, y, z, R, xc, yc, zc, rho): """ Computing the induced response of gravity sphere in free-space. >> Input x, y, z: Observation locations R: radius of the sphere xc, yc, zc: Location of the sphere rho: Density of sphere By convention, z-component is positive downward for a positive density anomaly """ if (~np.size(x) == np.size(y) == np.size(z)): print("Specify same size of x, y, z") return unit_conv = 1e+8 # Unit conversion from SI to (mgal*g/cc) x = mkvc(x) y = mkvc(y) z = mkvc(z) nobs = len(x) M = R**3. * 4. / 3. * np.pi * rho rx = (x - xc) ry = (y - yc) rz = (zc - z) rvec = np.c_[rx, ry, rz] r = np.sqrt((rx)**2 + (ry)**2 + (rz)**2) g = -G * (1. / r**2) * M * unit_conv gx = g * (rx / r) gy = g * (ry / r) gz = g * (rz / r) return gx, gy, gz
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 NMOstack(data, xorig, time, v): if np.isscalar(v): v = np.ones_like(time) * v Time = (time.reshape([1, -1])).repeat(data.shape[0], axis=0) singletrace = np.zeros(data.shape[1]) for i in range(time.size): toffset = np.sqrt(xorig**2 / v[i]**2 + time[i]**2) Time = (time.reshape([1, -1])).repeat(data.shape[0], axis=0) Toffset = (toffset.reshape([-1, 1])).repeat(data.shape[1], axis=1) indmin = np.argmin(abs(Time - Toffset), axis=1) singletrace[i] = (mkvc(data)[sub2ind( data.shape, np.c_[np.arange(data.shape[0]), indmin])]).sum() return singletrace
def fields(self, m): self.model = self.rhoMap*m if self.forwardOnly: # Compute the linear operation without forming the full dense G fields = self.Intrgl_Fwr_Op() return mkvc(fields) else: vec = np.dot(self.G, (self.model).astype(np.float32)) return vec.astype(np.float64)
def fields(self, m): model = self.rhoMap*m if self.forwardOnly: # Compute the linear operation without forming the full dense G fields = self.Intrgl_Fwr_Op(m=m) return mkvc(fields) else: vec = np.dot(self.G, model.astype(np.float32)) return vec.astype(np.float64)
def doSlice(v): if vType == 'CC': return getIndSlice(self.r(v, 'CC', 'CC', 'M')) elif vType == 'CCv': assert view == 'vec', 'Other types for CCv not supported' else: # Now just deal with 'F' and 'E' (x,y,z, maybe...) aveOp = 'ave' + vType + ('2CCV' if view == 'vec' else '2CC') Av = getattr(self, aveOp) if v.size == Av.shape[1]: v = Av * v else: v = self.r(v, vType[0], vType) # get specific component v = Av * v # we should now be averaged to cell centers (might be a vector) v = self.r(v.reshape((self.nC, -1), order='F'), 'CC', 'CC', 'M') if view == 'vec': outSlice = [] if 'X' not in normal: outSlice.append(getIndSlice(v[0])) if 'Y' not in normal: outSlice.append(getIndSlice(v[1])) if 'Z' not in normal: outSlice.append(getIndSlice(v[2])) return np.r_[mkvc(outSlice[0]), mkvc(outSlice[1])] else: return getIndSlice(self.r(v, 'CC', 'CC', 'M'))
def doSlice(v): if vType == 'CC': return getIndSlice(self.r(v,'CC','CC','M')) elif vType == 'CCv': assert view == 'vec', 'Other types for CCv not supported' else: # Now just deal with 'F' and 'E' (x,y,z, maybe...) aveOp = 'ave' + vType + ('2CCV' if view == 'vec' else '2CC') Av = getattr(self,aveOp) if v.size == Av.shape[1]: v = Av * v else: v = self.r(v,vType[0],vType) # get specific component v = Av * v # we should now be averaged to cell centers (might be a vector) v = self.r(v.reshape((self.nC,-1),order='F'),'CC','CC','M') if view == 'vec': outSlice = [] if 'X' not in normal: outSlice.append(getIndSlice(v[0])) if 'Y' not in normal: outSlice.append(getIndSlice(v[1])) if 'Z' not in normal: outSlice.append(getIndSlice(v[2])) return np.r_[mkvc(outSlice[0]), mkvc(outSlice[1])] else: return getIndSlice(self.r(v,'CC','CC','M'))
def firstVertical(self): if getattr(self, '_firstVertical', None) is None: FHzD = self.gridFFT*np.sqrt(self.Kx**2. + self.Ky**2.) fhzd_pad = np.fft.ifft2(FHzD) firstVD = np.real( fhzd_pad[self.npady:-self.npady, self.npadx:-self.npadx]) if self.indNan is not None: firstVD = mkvc(firstVD) firstVD[self.indNan] = np.nan firstVD = firstVD.reshape(self.values.shape, order='F') self._firstVertical = firstVD return self._firstVertical
def derivativeX(self): if getattr(self, '_derivativeX', None) is None: FHxD = (self.Kx*1j)*self.gridFFT fhxd_pad = np.fft.ifft2(FHxD) derivX = np.real( fhxd_pad[self.npady:-self.npady, self.npadx:-self.npadx]) if self.indNan is not None: derivX = mkvc(derivX) derivX[self.indNan] = np.nan derivX = derivX.reshape(self.values.shape, order='F') self._derivativeX = derivX return self._derivativeX
def dfdm(self): if self.model is None: self.model = np.zeros(self.G.shape[1]) if getattr(self, '_dfdm', None) is None: Bxyz = self.Bxyz_a(self.chiMap * self.model) # Bx = sp.spdiags(Bxyz[:, 0], 0, self.nD, self.nD) # By = sp.spdiags(Bxyz[:, 1], 0, self.nD, self.nD) # Bz = sp.spdiags(Bxyz[:, 2], 0, self.nD, self.nD) ii = np.kron(np.asarray(range(self.survey.nD), dtype='int'), np.ones(3)) jj = np.asarray(range(3*self.survey.nD), dtype='int') # (data, (row, col)), shape=(3, 3)) # P = s self._dfdm = sp.csr_matrix(( mkvc(Bxyz), (ii,jj)), shape=(self.survey.nD, 3*self.survey.nD)) return self._dfdm
def valuesFilled(self): if getattr(self, '_valuesFilled', None) is None: values = mkvc(self.values) indVal = np.where(~self.indNan)[0] tree = cKDTree(self.gridCC[indVal, :]) dists, indexes = tree.query(self.gridCC[self.indNan, :]) uInd = np.unique(indVal[indexes]) xyz = self.gridCC[uInd, :] _, values[self.indNan] = MathUtils.minCurvatureInterp( xyz, values[uInd], xyzOut=self.gridCC[self.indNan, :]) self._valuesFilled = values.reshape(self.values.shape, order='F') return self._valuesFilled
def rotatePointsFromNormals(XYZ,n0,n1,x0=np.r_[0.,0.,0.]): """ rotates a grid so that the vector n0 is aligned with the vector n1 :param numpy.array n0: vector of length 3, should have norm 1 :param numpy.array n1: vector of length 3, should have norm 1 :param numpy.array x0: vector of length 3, point about which we perform the rotation :rtype: numpy.array, 3x3 :return: rotation matrix which rotates the frame so that n0 is aligned with n1 """ R = rotationMatrixFromNormals(n0, n1) assert XYZ.shape[1] == 3, "Grid XYZ should be 3 wide" assert len(x0) == 3, "x0 should have length 3" X0 = np.ones([XYZ.shape[0],1])*mkvc(x0) return (XYZ - X0).dot(R.T) + X0 # equivalent to (R*(XYZ - X0)).T + X0
def derivativeY(self): if getattr(self, '_derivativeY', None) is None: FHyD = (self.Ky*1j)*self.gridFFT fhyd_pad = np.fft.ifft2(FHyD) derivY = np.real( fhyd_pad[self.npady:-self.npady, self.npadx:-self.npadx]) if self.indNan is not None: derivY = mkvc(derivY) derivY[self.indNan] = np.nan derivY = derivY.reshape(self.values.shape, order='F') self._derivativeY = derivY return self._derivativeY
def gridPadded(self): if getattr(self, '_gridPadded', None) is None: if getattr(self, '_valuesFilledUC', None) is not None: # if ~np.array_equal( # self.valuesFilled[~np.isnan(self.valuesFilled)], # self.values[~np.isnan(self.indNan)] # ): # self._valuesFilled = None grid = self.valuesFilledUC else: if np.any(np.isnan(self.values)): self.indNan = np.isnan(mkvc(self.values)) grid = self.valuesFilled else: grid = self.values # Add paddings dpad = np.c_[ np.fliplr(grid[:, 0:self.npadx]), grid, np.fliplr(grid[:, -self.npadx:]) ] dpad = np.r_[ np.flipud(dpad[0:self.npady, :]), dpad, np.flipud(dpad[-self.npady:, :]) ] # Tapper the paddings rampx = -np.cos(np.pi*np.asarray(range(self.npadx))/self.npadx) rampx = np.r_[rampx, np.ones(grid.shape[1]), -rampx]/2. + 0.5 rampy = -np.cos(np.pi*np.asarray(range(self.npady))/self.npady) rampy = np.r_[rampy, np.ones(grid.shape[0]), -rampy]/2. + 0.5 tapperx, tappery = np.meshgrid(rampx, rampy) self._gridPadded = tapperx*tappery*dpad return self._gridPadded
def rotatePointsFromNormals(XYZ, n0, n1, x0=np.r_[0., 0., 0.]): """ rotates a grid so that the vector n0 is aligned with the vector n1 :param numpy.array n0: vector of length 3, should have norm 1 :param numpy.array n1: vector of length 3, should have norm 1 :param numpy.array x0: vector of length 3, point about which we perform the rotation :rtype: numpy.array, 3x3 :return: rotation matrix which rotates the frame so that n0 is aligned with n1 """ R = rotationMatrixFromNormals(n0, n1) assert XYZ.shape[1] == 3, "Grid XYZ should be 3 wide" assert len(x0) == 3, "x0 should have length 3" X0 = np.ones([XYZ.shape[0], 1]) * mkvc(x0) return (XYZ - X0).dot(R.T) + X0 # equivalent to (R*(XYZ - X0)).T + X0
def Jvec(self, m, v, u=None): """ :param numpy.array m: Conductivity model :param numpy.ndarray v: vector (model object) :param simpegEM.TDEM.FieldsTDEM u: Fields resulting from m :rtype: numpy.ndarray :return: w (data object) Multiplying \\\(\\\mathbf{J}\\\) onto a vector can be broken into three steps * Compute \\\(\\\\vec{p} = \\\mathbf{G}v\\\) * Solve \\\(\\\hat{\\\mathbf{A}} \\\\vec{y} = \\\\vec{p}\\\) * Compute \\\(\\\\vec{w} = -\\\mathbf{Q} \\\\vec{y}\\\) """ if self.verbose: print '%s\nCalculating J(v)\n%s'%('*'*50,'*'*50) self.curModel = m if u is None: u = self.fields(m) p = self.Gvec(m, v, u) y = self.solveAh(m, p) Jv = self.survey.projectFieldsDeriv(u, v=y) if self.verbose: print '%s\nDone calculating J(v)\n%s'%('*'*50,'*'*50) return - mkvc(Jv)
def plotGrid(self, ax=None, nodes=False, faces=False, centers=False, edges=False, lines=True, showIt=False): """Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions. .. plot:: :include-source: from SimPEG import Mesh, Utils X, Y = Utils.exampleLrmGrid([3,3],'rotate') M = Mesh.CurvilinearMesh([X, Y]) M.plotGrid(showIt=True) """ import matplotlib.pyplot as plt import matplotlib from mpl_toolkits.mplot3d import Axes3D axOpts = {'projection':'3d'} if self.dim == 3 else {} if ax is None: ax = plt.subplot(111, **axOpts) NN = self.r(self.gridN, 'N', 'N', 'M') if self.dim == 2: if lines: X1 = np.c_[mkvc(NN[0][:-1, :]), mkvc(NN[0][1:, :]), mkvc(NN[0][:-1, :])*np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :]), mkvc(NN[1][1:, :]), mkvc(NN[1][:-1, :])*np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1]), mkvc(NN[0][:, 1:]), mkvc(NN[0][:, :-1])*np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1]), mkvc(NN[1][:, 1:]), mkvc(NN[1][:, :-1])*np.nan].flatten() X = np.r_[X1, X2] Y = np.r_[Y1, Y2] ax.plot(X, Y, 'b-') if centers: ax.plot(self.gridCC[:,0],self.gridCC[:,1],'ro') # Nx = self.r(self.normals, 'F', 'Fx', 'V') # Ny = self.r(self.normals, 'F', 'Fy', 'V') # Tx = self.r(self.tangents, 'E', 'Ex', 'V') # Ty = self.r(self.tangents, 'E', 'Ey', 'V') # ax.plot(self.gridN[:, 0], self.gridN[:, 1], 'bo') # nX = np.c_[self.gridFx[:, 0], self.gridFx[:, 0] + Nx[0]*length, self.gridFx[:, 0]*np.nan].flatten() # nY = np.c_[self.gridFx[:, 1], self.gridFx[:, 1] + Nx[1]*length, self.gridFx[:, 1]*np.nan].flatten() # ax.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'rs') # ax.plot(nX, nY, 'r-') # nX = np.c_[self.gridFy[:, 0], self.gridFy[:, 0] + Ny[0]*length, self.gridFy[:, 0]*np.nan].flatten() # nY = np.c_[self.gridFy[:, 1], self.gridFy[:, 1] + Ny[1]*length, self.gridFy[:, 1]*np.nan].flatten() # #ax.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'gs') # ax.plot(nX, nY, 'g-') # tX = np.c_[self.gridEx[:, 0], self.gridEx[:, 0] + Tx[0]*length, self.gridEx[:, 0]*np.nan].flatten() # tY = np.c_[self.gridEx[:, 1], self.gridEx[:, 1] + Tx[1]*length, self.gridEx[:, 1]*np.nan].flatten() # ax.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'r^') # ax.plot(tX, tY, 'r-') # nX = np.c_[self.gridEy[:, 0], self.gridEy[:, 0] + Ty[0]*length, self.gridEy[:, 0]*np.nan].flatten() # nY = np.c_[self.gridEy[:, 1], self.gridEy[:, 1] + Ty[1]*length, self.gridEy[:, 1]*np.nan].flatten() # #ax.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'g^') # ax.plot(nX, nY, 'g-') elif self.dim == 3: X1 = np.c_[mkvc(NN[0][:-1, :, :]), mkvc(NN[0][1:, :, :]), mkvc(NN[0][:-1, :, :])*np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :, :]), mkvc(NN[1][1:, :, :]), mkvc(NN[1][:-1, :, :])*np.nan].flatten() Z1 = np.c_[mkvc(NN[2][:-1, :, :]), mkvc(NN[2][1:, :, :]), mkvc(NN[2][:-1, :, :])*np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1, :]), mkvc(NN[0][:, 1:, :]), mkvc(NN[0][:, :-1, :])*np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1, :]), mkvc(NN[1][:, 1:, :]), mkvc(NN[1][:, :-1, :])*np.nan].flatten() Z2 = np.c_[mkvc(NN[2][:, :-1, :]), mkvc(NN[2][:, 1:, :]), mkvc(NN[2][:, :-1, :])*np.nan].flatten() X3 = np.c_[mkvc(NN[0][:, :, :-1]), mkvc(NN[0][:, :, 1:]), mkvc(NN[0][:, :, :-1])*np.nan].flatten() Y3 = np.c_[mkvc(NN[1][:, :, :-1]), mkvc(NN[1][:, :, 1:]), mkvc(NN[1][:, :, :-1])*np.nan].flatten() Z3 = np.c_[mkvc(NN[2][:, :, :-1]), mkvc(NN[2][:, :, 1:]), mkvc(NN[2][:, :, :-1])*np.nan].flatten() X = np.r_[X1, X2, X3] Y = np.r_[Y1, Y2, Y3] Z = np.r_[Z1, Z2, Z3] ax.plot(X, Y, 'b', zs=Z) ax.set_zlabel('x3') ax.grid(True) ax.set_xlabel('x1') ax.set_ylabel('x2') if showIt: plt.show()
def _plotCylTensorMesh(self, plotType, *args, **kwargs): if not self.isSymmetric: raise Exception('We have not yet implemented this type of view.') assert plotType in ['plotImage', 'plotGrid'] # Hackity Hack: # Just create a TM and use its view. from SimPEG.Mesh import TensorMesh vType = kwargs.pop('vType', None) if vType is not None: if vType.upper() != 'CCV': if vType.upper() == 'F': val = mkvc(self.aveF2CCV * args[0]) kwargs['vType'] = 'CCv' # now the vector is cell centered if vType.upper() == 'E': val = mkvc(self.aveE2CCV * args[0]) args = (val,) + args[1:] mirror = kwargs.pop('mirror', None) if mirror is True: # create a mirrored mesh hx = np.hstack([np.flipud(self.hx), self.hx]) x00 = self.x0[0] - self.hx.sum() M = TensorMesh([hx, self.hz], x0=[x00, self.x0[2]]) # mirror the data if len(args) > 0: val = args[0] if len(val) == self.nC: # only a single value at cell centers val = val.reshape(self.vnC[0], self.vnC[2], order='F') val = mkvc(np.vstack([np.flipud(val), val])) elif len(val) == 2*self.nC: val_x = val[:self.nC] val_z = val[self.nC:] val_x = val_x.reshape(self.vnC[0], self.vnC[2], order='F') val_x = mkvc(np.vstack([-1.*np.flipud(val_x), val_x])) # by symmetry val_z = val_z.reshape(self.vnC[0], self.vnC[2], order='F') val_z = mkvc(np.vstack([np.flipud(val_z), val_z])) val = np.hstack([val_x, val_z]) args = (val,) + args[1:] else: M = TensorMesh([self.hx, self.hz], x0=[self.x0[0], self.x0[2]]) ax = kwargs.get('ax', None) if ax is None: fig = plt.figure() ax = plt.subplot(111) kwargs['ax'] = ax else: assert isinstance(ax, matplotlib.axes.Axes), "ax must be an matplotlib.axes.Axes" fig = ax.figure # Don't show things in the TM.plotImage showIt = kwargs.get('showIt', False) kwargs['showIt'] = False out = getattr(M, plotType)(*args, **kwargs) ax.set_xlabel('x') ax.set_ylabel('z') if showIt: plt.show() return out
def Intrgl_Fwr_Op(self, m=None, magType='H0', rx_type='tmi'): """ Magnetic forward operator in integral form magType = 'H0' | 'x' | 'y' | 'z' rx_type = 'tmi' | 'x' | 'y' | 'z' Return _G = Linear forward operator | (forwardOnly)=data """ if m is not None: self.model = self.chiMap*m # Find non-zero cells if getattr(self, 'actInd', None) is not None: if self.actInd.dtype == 'bool': inds = np.where(self.actInd)[0] else: inds = self.actInd else: inds = np.asarray(range(self.mesh.nC)) nC = len(inds) # Create active cell projector P = sp.csr_matrix((np.ones(nC), (inds, range(nC))), shape=(self.mesh.nC, nC)) # Create vectors of nodal location # (lower and upper coners for each cell) if isinstance(self.mesh, Mesh.TreeMesh): # Get upper and lower corners of each cell bsw = (self.mesh.gridCC - self.mesh.h_gridded/2.) tne = (self.mesh.gridCC + self.mesh.h_gridded/2.) xn1, xn2 = bsw[:, 0], tne[:, 0] yn1, yn2 = bsw[:, 1], tne[:, 1] zn1, zn2 = bsw[:, 2], tne[:, 2] else: xn = self.mesh.vectorNx yn = self.mesh.vectorNy zn = self.mesh.vectorNz yn2, xn2, zn2 = np.meshgrid(yn[1:], xn[1:], zn[1:]) yn1, xn1, zn1 = np.meshgrid(yn[:-1], xn[:-1], zn[:-1]) # If equivalent source, use semi-infite prism if self.equiSourceLayer: zn1 -= 1000. self.Yn = P.T*np.c_[mkvc(yn1), mkvc(yn2)] self.Xn = P.T*np.c_[mkvc(xn1), mkvc(xn2)] self.Zn = P.T*np.c_[mkvc(zn1), mkvc(zn2)] # survey = self.survey self.rxLoc = self.survey.srcField.rxList[0].locs if magType == 'H0': if getattr(self, 'M', None) is None: self.M = matutils.dip_azimuth2cartesian(np.ones(nC) * self.survey.srcField.param[1], np.ones(nC) * self.survey.srcField.param[2]) Mx = sdiag(self.M[:, 0] * self.survey.srcField.param[0]) My = sdiag(self.M[:, 1] * self.survey.srcField.param[0]) Mz = sdiag(self.M[:, 2] * self.survey.srcField.param[0]) self.Mxyz = sp.vstack((Mx, My, Mz)) elif magType == 'full': self.Mxyz = sp.identity(3*nC) * self.survey.srcField.param[0] else: raise Exception('magType must be: "H0" or "full"') # Loop through all observations and create forward operator (nD-by-nC) print("Begin forward: M=" + magType + ", Rx type= " + self.rx_type) # Switch to determine if the process has to be run in parallel job = Forward( rxLoc=self.rxLoc, Xn=self.Xn, Yn=self.Yn, Zn=self.Zn, n_cpu=self.n_cpu, forwardOnly=self.forwardOnly, model=self.model, rx_type=self.rx_type, Mxyz=self.Mxyz, P=self.ProjTMI, parallelized=self.parallelized ) G = job.calculate() return G
def Jvec(self, m, v, u=None): """ Computing Jacobian multiplied by vector By setting our problem as .. math :: \mathbf{C}(\mathbf{m}, \mathbf{u}) = \mathbf{A}\mathbf{u} - \mathbf{rhs} = 0 And taking derivative w.r.t m .. math :: \\nabla \mathbf{C}(\mathbf{m}, \mathbf{u}) = \\nabla_m \mathbf{C}(\mathbf{m}) \delta \mathbf{m} + \\nabla_u \mathbf{C}(\mathbf{u}) \delta \mathbf{u} = 0 \\frac{\delta \mathbf{u}}{\delta \mathbf{m}} = - [\\nabla_u \mathbf{C}(\mathbf{u})]^{-1}\\nabla_m \mathbf{C}(\mathbf{m}) With some linear algebra we can have .. math :: \\nabla_u \mathbf{C}(\mathbf{u}) = \mathbf{A} \\nabla_m \mathbf{C}(\mathbf{m}) = \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u} - \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} .. math :: \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u} = \\frac{\partial \mathbf{\mu}}{\partial \mathbf{m}} \left[\Div \diag (\Div^T \mathbf{u}) \dMfMuI \\right] \dMfMuI = \diag(\MfMui)^{-1}_{vec} \mathbf{Av}_{F2CC}^T\diag(\mathbf{v})\diag(\\frac{1}{\mu^2}) \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} = \\frac{\partial \mathbf{\mu}}{\partial \mathbf{m}} \left[ \Div \diag(\M^f_{\mu_{0}^{-1}}\mathbf{B}_0) \dMfMuI \\right] - \diag(\mathbf{v})\mathbf{D} \mathbf{P}_{out}^T\\frac{\partial B_{sBC}}{\partial \mathbf{m}} In the end, .. math :: \\frac{\delta \mathbf{u}}{\delta \mathbf{m}} = - [ \mathbf{A} ]^{-1}\left[ \\frac{\partial \mathbf{A}}{\partial \mathbf{m}}(\mathbf{m})\mathbf{u} - \\frac{\partial \mathbf{rhs}(\mathbf{m})}{\partial \mathbf{m}} \\right] A little tricky point here is we are not interested in potential (u), but interested in magnetic flux (B). Thus, we need sensitivity for B. Now we take derivative of B w.r.t m and have .. math :: \\frac{\delta \mathbf{B}} {\delta \mathbf{m}} = \\frac{\partial \mathbf{\mu} } {\partial \mathbf{m} } \left[ \diag(\M^f_{\mu_{0}^{-1} } \mathbf{B}_0) \dMfMuI \\ - \diag (\Div^T\mathbf{u})\dMfMuI \\right ] - (\MfMui)^{-1}\Div^T\\frac{\delta\mathbf{u}}{\delta \mathbf{m}} Finally we evaluate the above, but we should remember that .. note :: We only want to evalute .. math :: \mathbf{J}\mathbf{v} = \\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}}\mathbf{v} Since forming sensitivity matrix is very expensive in that this monster is "big" and "dense" matrix!! """ if u is None: u = self.fields(m) B, u = u['B'], u['u'] mu = self.muMap * (m) dmudm = self.muDeriv # dchidmu = sdiag(1 / mu_0 * np.ones(self.mesh.nC)) vol = self.mesh.vol Div = self._Div Dface = self.mesh.faceDiv P = self.survey.projectFieldsDeriv(B) # Projection matrix B0 = self.getB0() MfMuIvec = 1 / self.MfMui.diagonal() dMfMuI = sdiag(MfMuIvec**2) * \ self.mesh.aveF2CC.T * sdiag(vol * 1. / mu**2) # A = self._Div*self.MfMuI*self._Div.T # RHS = Div*MfMuI*MfMu0*B0 - Div*B0 + Mc*Dface*Pout.T*Bbc # C(m,u) = A*m-rhs # dudm = -(dCdu)^(-1)dCdm dCdu = self.getA(m) dCdm_A = Div * (sdiag(Div.T * u) * dMfMuI * dmudm) dCdm_RHS1 = Div * (sdiag(self.MfMu0 * B0) * dMfMuI) # temp1 = (Dface * (self._Pout.T * self.Bbc_const * self.Bbc)) # dCdm_RHS2v = (sdiag(vol) * temp1) * \ # np.inner(vol, dchidmu * dmudm * v) # dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v dCdm_RHSv = dCdm_RHS1 * (dmudm * v) dCdm_v = dCdm_A * v - dCdm_RHSv m1 = sp.linalg.interface.aslinearoperator( sdiag(1 / dCdu.diagonal()) ) sol, info = sp.linalg.bicgstab(dCdu, dCdm_v, tol=1e-6, maxiter=1000, M=m1) if info > 0: print("Iterative solver did not work well (Jvec)") # raise Exception ("Iterative solver did not work well") # B = self.MfMuI*self.MfMu0*B0-B0-self.MfMuI*self._Div.T*u # dBdm = d\mudm*dBd\mu dudm = -sol dBdmv = ( sdiag(self.MfMu0 * B0) * (dMfMuI * (dmudm * v)) - sdiag(Div.T * u) * (dMfMuI * (dmudm * v)) - self.MfMuI * (Div.T * (dudm)) ) return mkvc(P * dBdmv)
def plotGrid(self, ax=None, nodes=False, faces=False, centers=False, edges=False, lines=True, showIt=False): """Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions. .. plot:: :include-source: from SimPEG import Mesh, Utils X, Y = Utils.exampleLrmGrid([3,3],'rotate') M = Mesh.CurvilinearMesh([X, Y]) M.plotGrid(showIt=True) """ import matplotlib.pyplot as plt import matplotlib from mpl_toolkits.mplot3d import Axes3D axOpts = {"projection": "3d"} if self.dim == 3 else {} if ax is None: ax = plt.subplot(111, **axOpts) NN = self.r(self.gridN, "N", "N", "M") if self.dim == 2: if lines: X1 = np.c_[mkvc(NN[0][:-1, :]), mkvc(NN[0][1:, :]), mkvc(NN[0][:-1, :]) * np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :]), mkvc(NN[1][1:, :]), mkvc(NN[1][:-1, :]) * np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1]), mkvc(NN[0][:, 1:]), mkvc(NN[0][:, :-1]) * np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1]), mkvc(NN[1][:, 1:]), mkvc(NN[1][:, :-1]) * np.nan].flatten() X = np.r_[X1, X2] Y = np.r_[Y1, Y2] ax.plot(X, Y, "b-") if centers: ax.plot(self.gridCC[:, 0], self.gridCC[:, 1], "ro") # Nx = self.r(self.normals, 'F', 'Fx', 'V') # Ny = self.r(self.normals, 'F', 'Fy', 'V') # Tx = self.r(self.tangents, 'E', 'Ex', 'V') # Ty = self.r(self.tangents, 'E', 'Ey', 'V') # ax.plot(self.gridN[:, 0], self.gridN[:, 1], 'bo') # nX = np.c_[self.gridFx[:, 0], self.gridFx[:, 0] + Nx[0]*length, self.gridFx[:, 0]*np.nan].flatten() # nY = np.c_[self.gridFx[:, 1], self.gridFx[:, 1] + Nx[1]*length, self.gridFx[:, 1]*np.nan].flatten() # ax.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'rs') # ax.plot(nX, nY, 'r-') # nX = np.c_[self.gridFy[:, 0], self.gridFy[:, 0] + Ny[0]*length, self.gridFy[:, 0]*np.nan].flatten() # nY = np.c_[self.gridFy[:, 1], self.gridFy[:, 1] + Ny[1]*length, self.gridFy[:, 1]*np.nan].flatten() # #ax.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'gs') # ax.plot(nX, nY, 'g-') # tX = np.c_[self.gridEx[:, 0], self.gridEx[:, 0] + Tx[0]*length, self.gridEx[:, 0]*np.nan].flatten() # tY = np.c_[self.gridEx[:, 1], self.gridEx[:, 1] + Tx[1]*length, self.gridEx[:, 1]*np.nan].flatten() # ax.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'r^') # ax.plot(tX, tY, 'r-') # nX = np.c_[self.gridEy[:, 0], self.gridEy[:, 0] + Ty[0]*length, self.gridEy[:, 0]*np.nan].flatten() # nY = np.c_[self.gridEy[:, 1], self.gridEy[:, 1] + Ty[1]*length, self.gridEy[:, 1]*np.nan].flatten() # #ax.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'g^') # ax.plot(nX, nY, 'g-') elif self.dim == 3: X1 = np.c_[mkvc(NN[0][:-1, :, :]), mkvc(NN[0][1:, :, :]), mkvc(NN[0][:-1, :, :]) * np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :, :]), mkvc(NN[1][1:, :, :]), mkvc(NN[1][:-1, :, :]) * np.nan].flatten() Z1 = np.c_[mkvc(NN[2][:-1, :, :]), mkvc(NN[2][1:, :, :]), mkvc(NN[2][:-1, :, :]) * np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1, :]), mkvc(NN[0][:, 1:, :]), mkvc(NN[0][:, :-1, :]) * np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1, :]), mkvc(NN[1][:, 1:, :]), mkvc(NN[1][:, :-1, :]) * np.nan].flatten() Z2 = np.c_[mkvc(NN[2][:, :-1, :]), mkvc(NN[2][:, 1:, :]), mkvc(NN[2][:, :-1, :]) * np.nan].flatten() X3 = np.c_[mkvc(NN[0][:, :, :-1]), mkvc(NN[0][:, :, 1:]), mkvc(NN[0][:, :, :-1]) * np.nan].flatten() Y3 = np.c_[mkvc(NN[1][:, :, :-1]), mkvc(NN[1][:, :, 1:]), mkvc(NN[1][:, :, :-1]) * np.nan].flatten() Z3 = np.c_[mkvc(NN[2][:, :, :-1]), mkvc(NN[2][:, :, 1:]), mkvc(NN[2][:, :, :-1]) * np.nan].flatten() X = np.r_[X1, X2, X3] Y = np.r_[Y1, Y2, Y3] Z = np.r_[Z1, Z2, Z3] ax.plot(X, Y, "b", zs=Z) ax.set_zlabel("x3") ax.grid(True) ax.set_xlabel("x1") ax.set_ylabel("x2") if showIt: plt.show()
# Get extent of points F = NearestNDInterpolator(topo[:, :2], topo[:, 2]) zOffset = 0 # Cycle through the first 3 octree levels for ii in range(3): dx = mesh.hx.min() * 2**ii nCx = int((limx[0] - limx[1]) / dx) nCy = int((limy[0] - limy[1]) / dx) # Create a grid at the octree level in xy CCx, CCy = np.meshgrid(np.linspace(limx[1], limx[0], nCx), np.linspace(limy[1], limy[0], nCy)) z = F(mkvc(CCx), mkvc(CCy)) # level means number of layers in current OcTree level for level in range(int(nCpad[ii])): mesh.insert_cells(np.c_[mkvc(CCx), mkvc(CCy), z - zOffset], np.ones_like(z) * maxLevel - ii, finalize=False) zOffset += dx mesh.finalize() # Define an active cells from topo actv = Utils.surface2ind_topo(mesh, topo) nC = int(actv.sum())
def test_mkvc3(self): x = mkvc(self.a, 3) self.assertTrue(x.shape, (3, 1, 1))
def plotGrid(self, length=0.05, showIt=False): """Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions. .. plot:: :include-source: from SimPEG import Mesh, Utils X, Y = Utils.exampleCurvGird([3,3],'rotate') M = Mesh.CurvilinearMesh([X, Y]) M.plotGrid(showIt=True) """ NN = self.r(self.gridN, 'N', 'N', 'M') if self.dim == 2: fig = plt.figure(2) fig.clf() ax = plt.subplot(111) X1 = np.c_[mkvc(NN[0][:-1, :]), mkvc(NN[0][1:, :]), mkvc(NN[0][:-1, :]) * np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :]), mkvc(NN[1][1:, :]), mkvc(NN[1][:-1, :]) * np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1]), mkvc(NN[0][:, 1:]), mkvc(NN[0][:, :-1]) * np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1]), mkvc(NN[1][:, 1:]), mkvc(NN[1][:, :-1]) * np.nan].flatten() X = np.r_[X1, X2] Y = np.r_[Y1, Y2] plt.plot(X, Y) plt.hold(True) Nx = self.r(self.normals, 'F', 'Fx', 'V') Ny = self.r(self.normals, 'F', 'Fy', 'V') Tx = self.r(self.tangents, 'E', 'Ex', 'V') Ty = self.r(self.tangents, 'E', 'Ey', 'V') plt.plot(self.gridN[:, 0], self.gridN[:, 1], 'bo') nX = np.c_[self.gridFx[:, 0], self.gridFx[:, 0] + Nx[0] * length, self.gridFx[:, 0] * np.nan].flatten() nY = np.c_[self.gridFx[:, 1], self.gridFx[:, 1] + Nx[1] * length, self.gridFx[:, 1] * np.nan].flatten() plt.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'rs') plt.plot(nX, nY, 'r-') nX = np.c_[self.gridFy[:, 0], self.gridFy[:, 0] + Ny[0] * length, self.gridFy[:, 0] * np.nan].flatten() nY = np.c_[self.gridFy[:, 1], self.gridFy[:, 1] + Ny[1] * length, self.gridFy[:, 1] * np.nan].flatten() #plt.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'gs') plt.plot(nX, nY, 'g-') tX = np.c_[self.gridEx[:, 0], self.gridEx[:, 0] + Tx[0] * length, self.gridEx[:, 0] * np.nan].flatten() tY = np.c_[self.gridEx[:, 1], self.gridEx[:, 1] + Tx[1] * length, self.gridEx[:, 1] * np.nan].flatten() plt.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'r^') plt.plot(tX, tY, 'r-') nX = np.c_[self.gridEy[:, 0], self.gridEy[:, 0] + Ty[0] * length, self.gridEy[:, 0] * np.nan].flatten() nY = np.c_[self.gridEy[:, 1], self.gridEy[:, 1] + Ty[1] * length, self.gridEy[:, 1] * np.nan].flatten() #plt.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'g^') plt.plot(nX, nY, 'g-') plt.axis('equal') elif self.dim == 3: fig = plt.figure(3) fig.clf() ax = fig.add_subplot(111, projection='3d') X1 = np.c_[mkvc(NN[0][:-1, :, :]), mkvc(NN[0][1:, :, :]), mkvc(NN[0][:-1, :, :]) * np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :, :]), mkvc(NN[1][1:, :, :]), mkvc(NN[1][:-1, :, :]) * np.nan].flatten() Z1 = np.c_[mkvc(NN[2][:-1, :, :]), mkvc(NN[2][1:, :, :]), mkvc(NN[2][:-1, :, :]) * np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1, :]), mkvc(NN[0][:, 1:, :]), mkvc(NN[0][:, :-1, :]) * np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1, :]), mkvc(NN[1][:, 1:, :]), mkvc(NN[1][:, :-1, :]) * np.nan].flatten() Z2 = np.c_[mkvc(NN[2][:, :-1, :]), mkvc(NN[2][:, 1:, :]), mkvc(NN[2][:, :-1, :]) * np.nan].flatten() X3 = np.c_[mkvc(NN[0][:, :, :-1]), mkvc(NN[0][:, :, 1:]), mkvc(NN[0][:, :, :-1]) * np.nan].flatten() Y3 = np.c_[mkvc(NN[1][:, :, :-1]), mkvc(NN[1][:, :, 1:]), mkvc(NN[1][:, :, :-1]) * np.nan].flatten() Z3 = np.c_[mkvc(NN[2][:, :, :-1]), mkvc(NN[2][:, :, 1:]), mkvc(NN[2][:, :, :-1]) * np.nan].flatten() X = np.r_[X1, X2, X3] Y = np.r_[Y1, Y2, Y3] Z = np.r_[Z1, Z2, Z3] plt.plot(X, Y, 'b', zs=Z) ax.set_zlabel('x3') ax.grid(True) ax.hold(False) ax.set_xlabel('x1') ax.set_ylabel('x2') if showIt: plt.show()
def _plotImage2D(self, v, vType='CC', grid=False, view='real', ax=None, clim=None, showIt=False, pcolorOpts={}, streamOpts={'color': 'k'}, gridOpts={'color': 'k'}): vTypeOptsCC = ['N', 'CC', 'Fx', 'Fy', 'Ex', 'Ey'] vTypeOptsV = ['CCv', 'F', 'E'] vTypeOpts = vTypeOptsCC + vTypeOptsV if view == 'vec': assert vType in vTypeOptsV, "vType must be in ['%s'] when view='vec'" % "','".join( vTypeOptsV) assert vType in vTypeOpts, "vType must be in ['%s']" % "','".join( vTypeOpts) viewOpts = ['real', 'imag', 'abs', 'vec'] assert view in viewOpts, "view must be in ['%s']" % "','".join( viewOpts) if ax is None: fig = plt.figure() ax = plt.subplot(111) else: assert isinstance( ax, matplotlib.axes.Axes), "ax must be an matplotlib.axes.Axes" fig = ax.figure # Reshape to a cell centered variable if vType == 'CC': pass elif vType == 'CCv': assert view == 'vec', 'Other types for CCv not supported' elif vType in ['F', 'E', 'N']: aveOp = 'ave' + vType + ('2CCV' if view == 'vec' else '2CC') v = getattr( self, aveOp) * v # average to cell centers (might be a vector) elif vType in ['Fx', 'Fy', 'Ex', 'Ey']: aveOp = 'ave' + vType[0] + '2CCV' v = getattr( self, aveOp) * v # average to cell centers (might be a vector) xORy = {'x': 0, 'y': 1}[vType[1]] v = v.reshape((self.nC, -1), order='F')[:, xORy] out = () if view in ['real', 'imag', 'abs']: v = self.r(v, 'CC', 'CC', 'M') v = getattr(np, view)(v) # e.g. np.real(v) if clim is None: clim = [v.min(), v.max()] v = np.ma.masked_where(np.isnan(v), v) out += (ax.pcolormesh(self.vectorNx, self.vectorNy, v.T, vmin=clim[0], vmax=clim[1], **pcolorOpts), ) elif view in ['vec']: U, V = self.r(v.reshape((self.nC, -1), order='F'), 'CC', 'CC', 'M') if clim is None: uv = np.sqrt(U**2 + V**2) clim = [uv.min(), uv.max()] # Matplotlib seems to not support irregular # spaced vectors at the moment. So we will # Interpolate down to a regular mesh at the # smallest mesh size in this 2D slice. nxi = int(self.hx.sum() / self.hx.min()) nyi = int(self.hy.sum() / self.hy.min()) tMi = self.__class__([ np.ones(nxi) * self.hx.sum() / nxi, np.ones(nyi) * self.hy.sum() / nyi ], self.x0) P = self.getInterpolationMat(tMi.gridCC, 'CC', zerosOutside=True) Ui = tMi.r(P * mkvc(U), 'CC', 'CC', 'M') Vi = tMi.r(P * mkvc(V), 'CC', 'CC', 'M') # End Interpolation out += (ax.pcolormesh(self.vectorNx, self.vectorNy, np.sqrt(U**2 + V**2).T, vmin=clim[0], vmax=clim[1], **pcolorOpts), ) out += (ax.streamplot(tMi.vectorCCx, tMi.vectorCCy, Ui.T, Vi.T, **streamOpts), ) if grid: xXGrid = np.c_[self.vectorNx, self.vectorNx, np.nan * np.ones(self.nNx)].flatten() xYGrid = np.c_[self.vectorNy[0] * np.ones(self.nNx), self.vectorNy[-1] * np.ones(self.nNx), np.nan * np.ones(self.nNx)].flatten() yXGrid = np.c_[self.vectorNx[0] * np.ones(self.nNy), self.vectorNx[-1] * np.ones(self.nNy), np.nan * np.ones(self.nNy)].flatten() yYGrid = np.c_[self.vectorNy, self.vectorNy, np.nan * np.ones(self.nNy)].flatten() out += (ax.plot(np.r_[xXGrid, yXGrid], np.r_[xYGrid, yYGrid], **gridOpts)[0], ) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_xlim(*self.vectorNx[[0, -1]]) ax.set_ylim(*self.vectorNy[[0, -1]]) if showIt: plt.show() return out
def calcTrow(self, xyzLoc): """ Load in the active nodes of a tensor mesh and computes the gravity tensor for a given observation location xyzLoc[obsx, obsy, obsz] INPUT: Xn, Yn, Zn: Node location matrix for the lower and upper most corners of all cells in the mesh shape[nC,2] M OUTPUT: Tx = [Txx Txy Txz] Ty = [Tyx Tyy Tyz] Tz = [Tzx Tzy Tzz] where each elements have dimension 1-by-nC. Only the upper half 5 elements have to be computed since symetric. Currently done as for-loops but will eventually be changed to vector indexing, once the topography has been figured out. """ NewtG = constants.G*1e+8 # Convertion from mGal (1e-5) and g/cc (1e-3) eps = 1e-8 # add a small value to the locations to avoid # Pre-allocate space for 1D array row = np.zeros((1, self.Xn.shape[0])) dz = xyzLoc[2] - self.Zn dy = self.Yn - xyzLoc[1] dx = self.Xn - xyzLoc[0] # Compute contribution from each corners for aa in range(2): for bb in range(2): for cc in range(2): r = ( mkvc(dx[:, aa]) ** 2 + mkvc(dy[:, bb]) ** 2 + mkvc(dz[:, cc]) ** 2 ) ** (0.50) if self.rx_type == 'x': row -= NewtG * (-1) ** aa * (-1) ** bb * (-1) ** cc * ( dy[:, bb] * np.log(dz[:, cc] + r + eps) + dz[:, cc] * np.log(dy[:, bb] + r + eps) - dx[:, aa] * np.arctan(dy[:, bb] * dz[:, cc] / (dx[:, aa] * r + eps))) elif self.rx_type == 'y': row -= NewtG * (-1) ** aa * (-1) ** bb * (-1) ** cc * ( dx[:, aa] * np.log(dz[:, cc] + r + eps) + dz[:, cc] * np.log(dx[:, aa] + r + eps) - dy[:, bb] * np.arctan(dx[:, aa] * dz[:, cc] / (dy[:, bb] * r + eps))) else: row -= NewtG * (-1) ** aa * (-1) ** bb * (-1) ** cc * ( dx[:, aa] * np.log(dy[:, bb] + r + eps) + dy[:, bb] * np.log(dx[:, aa] + r + eps) - dz[:, cc] * np.arctan(dx[:, aa] * dy[:, bb] / (dz[:, cc] * r + eps))) if self.forwardOnly: return np.dot(row, self.model) else: return row
def test_mkvc1(self): x = mkvc(self.a) self.assertTrue(x.shape, (3,))
def plotGrid(self, length=0.05, showIt=False): """Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions. .. plot:: :include-source: from SimPEG import Mesh, Utils X, Y = Utils.exampleCurvGird([3,3],'rotate') M = Mesh.CurvilinearMesh([X, Y]) M.plotGrid(showIt=True) """ NN = self.r(self.gridN, 'N', 'N', 'M') if self.dim == 2: fig = plt.figure(2) fig.clf() ax = plt.subplot(111) X1 = np.c_[mkvc(NN[0][:-1, :]), mkvc(NN[0][1:, :]), mkvc(NN[0][:-1, :])*np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :]), mkvc(NN[1][1:, :]), mkvc(NN[1][:-1, :])*np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1]), mkvc(NN[0][:, 1:]), mkvc(NN[0][:, :-1])*np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1]), mkvc(NN[1][:, 1:]), mkvc(NN[1][:, :-1])*np.nan].flatten() X = np.r_[X1, X2] Y = np.r_[Y1, Y2] plt.plot(X, Y) plt.hold(True) Nx = self.r(self.normals, 'F', 'Fx', 'V') Ny = self.r(self.normals, 'F', 'Fy', 'V') Tx = self.r(self.tangents, 'E', 'Ex', 'V') Ty = self.r(self.tangents, 'E', 'Ey', 'V') plt.plot(self.gridN[:, 0], self.gridN[:, 1], 'bo') nX = np.c_[self.gridFx[:, 0], self.gridFx[:, 0] + Nx[0]*length, self.gridFx[:, 0]*np.nan].flatten() nY = np.c_[self.gridFx[:, 1], self.gridFx[:, 1] + Nx[1]*length, self.gridFx[:, 1]*np.nan].flatten() plt.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'rs') plt.plot(nX, nY, 'r-') nX = np.c_[self.gridFy[:, 0], self.gridFy[:, 0] + Ny[0]*length, self.gridFy[:, 0]*np.nan].flatten() nY = np.c_[self.gridFy[:, 1], self.gridFy[:, 1] + Ny[1]*length, self.gridFy[:, 1]*np.nan].flatten() #plt.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'gs') plt.plot(nX, nY, 'g-') tX = np.c_[self.gridEx[:, 0], self.gridEx[:, 0] + Tx[0]*length, self.gridEx[:, 0]*np.nan].flatten() tY = np.c_[self.gridEx[:, 1], self.gridEx[:, 1] + Tx[1]*length, self.gridEx[:, 1]*np.nan].flatten() plt.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'r^') plt.plot(tX, tY, 'r-') nX = np.c_[self.gridEy[:, 0], self.gridEy[:, 0] + Ty[0]*length, self.gridEy[:, 0]*np.nan].flatten() nY = np.c_[self.gridEy[:, 1], self.gridEy[:, 1] + Ty[1]*length, self.gridEy[:, 1]*np.nan].flatten() #plt.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'g^') plt.plot(nX, nY, 'g-') plt.axis('equal') elif self.dim == 3: fig = plt.figure(3) fig.clf() ax = fig.add_subplot(111, projection='3d') X1 = np.c_[mkvc(NN[0][:-1, :, :]), mkvc(NN[0][1:, :, :]), mkvc(NN[0][:-1, :, :])*np.nan].flatten() Y1 = np.c_[mkvc(NN[1][:-1, :, :]), mkvc(NN[1][1:, :, :]), mkvc(NN[1][:-1, :, :])*np.nan].flatten() Z1 = np.c_[mkvc(NN[2][:-1, :, :]), mkvc(NN[2][1:, :, :]), mkvc(NN[2][:-1, :, :])*np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, :-1, :]), mkvc(NN[0][:, 1:, :]), mkvc(NN[0][:, :-1, :])*np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, :-1, :]), mkvc(NN[1][:, 1:, :]), mkvc(NN[1][:, :-1, :])*np.nan].flatten() Z2 = np.c_[mkvc(NN[2][:, :-1, :]), mkvc(NN[2][:, 1:, :]), mkvc(NN[2][:, :-1, :])*np.nan].flatten() X3 = np.c_[mkvc(NN[0][:, :, :-1]), mkvc(NN[0][:, :, 1:]), mkvc(NN[0][:, :, :-1])*np.nan].flatten() Y3 = np.c_[mkvc(NN[1][:, :, :-1]), mkvc(NN[1][:, :, 1:]), mkvc(NN[1][:, :, :-1])*np.nan].flatten() Z3 = np.c_[mkvc(NN[2][:, :, :-1]), mkvc(NN[2][:, :, 1:]), mkvc(NN[2][:, :, :-1])*np.nan].flatten() X = np.r_[X1, X2, X3] Y = np.r_[Y1, Y2, Y3] Z = np.r_[Z1, Z2, Z3] plt.plot(X, Y, 'b', zs=Z) ax.set_zlabel('x3') ax.grid(True) ax.hold(False) ax.set_xlabel('x1') ax.set_ylabel('x2') if showIt: plt.show()
def test_mkvc2(self): x = mkvc(self.a, 2) self.assertTrue(x.shape, (3, 1))
def _plotImage2D( self, v, vType="CC", grid=False, view="real", ax=None, clim=None, showIt=False, pcolorOpts=None, streamOpts=None, gridOpts=None, ): if pcolorOpts is None: pcolorOpts = {} if streamOpts is None: streamOpts = {"color": "k"} if gridOpts is None: gridOpts = {"color": "k"} vTypeOptsCC = ["N", "CC", "Fx", "Fy", "Ex", "Ey"] vTypeOptsV = ["CCv", "F", "E"] vTypeOpts = vTypeOptsCC + vTypeOptsV if view == "vec": assert vType in vTypeOptsV, "vType must be in ['{0!s}'] when view='vec'".format("','".join(vTypeOptsV)) assert vType in vTypeOpts, "vType must be in ['{0!s}']".format("','".join(vTypeOpts)) viewOpts = ["real", "imag", "abs", "vec"] assert view in viewOpts, "view must be in ['{0!s}']".format("','".join(viewOpts)) if ax is None: fig = plt.figure() ax = plt.subplot(111) else: assert isinstance(ax, matplotlib.axes.Axes), "ax must be an matplotlib.axes.Axes" fig = ax.figure # Reshape to a cell centered variable if vType == "CC": pass elif vType == "CCv": assert view == "vec", "Other types for CCv not supported" elif vType in ["F", "E", "N"]: aveOp = "ave" + vType + ("2CCV" if view == "vec" else "2CC") v = getattr(self, aveOp) * v # average to cell centers (might be a vector) elif vType in ["Fx", "Fy", "Ex", "Ey"]: aveOp = "ave" + vType[0] + "2CCV" v = getattr(self, aveOp) * v # average to cell centers (might be a vector) xORy = {"x": 0, "y": 1}[vType[1]] v = v.reshape((self.nC, -1), order="F")[:, xORy] out = () if view in ["real", "imag", "abs"]: v = self.r(v, "CC", "CC", "M") v = getattr(np, view)(v) # e.g. np.real(v) if clim is None: clim = [v.min(), v.max()] v = np.ma.masked_where(np.isnan(v), v) out += (ax.pcolormesh(self.vectorNx, self.vectorNy, v.T, vmin=clim[0], vmax=clim[1], **pcolorOpts),) elif view in ["vec"]: U, V = self.r(v.reshape((self.nC, -1), order="F"), "CC", "CC", "M") if clim is None: uv = np.sqrt(U ** 2 + V ** 2) clim = [uv.min(), uv.max()] # Matplotlib seems to not support irregular # spaced vectors at the moment. So we will # Interpolate down to a regular mesh at the # smallest mesh size in this 2D slice. nxi = int(self.hx.sum() / self.hx.min()) nyi = int(self.hy.sum() / self.hy.min()) tMi = self.__class__([np.ones(nxi) * self.hx.sum() / nxi, np.ones(nyi) * self.hy.sum() / nyi], self.x0) P = self.getInterpolationMat(tMi.gridCC, "CC", zerosOutside=True) Ui = tMi.r(P * mkvc(U), "CC", "CC", "M") Vi = tMi.r(P * mkvc(V), "CC", "CC", "M") # End Interpolation out += ( ax.pcolormesh( self.vectorNx, self.vectorNy, np.sqrt(U ** 2 + V ** 2).T, vmin=clim[0], vmax=clim[1], **pcolorOpts ), ) out += (ax.streamplot(tMi.vectorCCx, tMi.vectorCCy, Ui.T, Vi.T, **streamOpts),) if grid: xXGrid = np.c_[self.vectorNx, self.vectorNx, np.nan * np.ones(self.nNx)].flatten() xYGrid = np.c_[ self.vectorNy[0] * np.ones(self.nNx), self.vectorNy[-1] * np.ones(self.nNx), np.nan * np.ones(self.nNx) ].flatten() yXGrid = np.c_[ self.vectorNx[0] * np.ones(self.nNy), self.vectorNx[-1] * np.ones(self.nNy), np.nan * np.ones(self.nNy) ].flatten() yYGrid = np.c_[self.vectorNy, self.vectorNy, np.nan * np.ones(self.nNy)].flatten() out += (ax.plot(np.r_[xXGrid, yXGrid], np.r_[xYGrid, yYGrid], **gridOpts)[0],) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_xlim(*self.vectorNx[[0, -1]]) ax.set_ylim(*self.vectorNy[[0, -1]]) if showIt: plt.show() return out
def _plotImage2D(self, v, vType='CC', grid=False, view='real', ax=None, clim=None, showIt=False, pcolorOpts={}, streamOpts={'color':'k'}, gridOpts={'color':'k'} ): vTypeOptsCC = ['N','CC','Fx','Fy','Ex','Ey'] vTypeOptsV = ['CCv','F','E'] vTypeOpts = vTypeOptsCC + vTypeOptsV if view == 'vec': assert vType in vTypeOptsV, "vType must be in ['%s'] when view='vec'" % "','".join(vTypeOptsV) assert vType in vTypeOpts, "vType must be in ['%s']" % "','".join(vTypeOpts) viewOpts = ['real','imag','abs','vec'] assert view in viewOpts, "view must be in ['%s']" % "','".join(viewOpts) if ax is None: fig = plt.figure() ax = plt.subplot(111) else: assert isinstance(ax, matplotlib.axes.Axes), "ax must be an matplotlib.axes.Axes" fig = ax.figure # Reshape to a cell centered variable if vType == 'CC': pass elif vType == 'CCv': assert view == 'vec', 'Other types for CCv not supported' elif vType in ['F', 'E', 'N']: aveOp = 'ave' + vType + ('2CCV' if view == 'vec' else '2CC') v = getattr(self,aveOp)*v # average to cell centers (might be a vector) elif vType in ['Fx','Fy','Ex','Ey']: aveOp = 'ave' + vType[0] + '2CCV' v = getattr(self,aveOp)*v # average to cell centers (might be a vector) xORy = {'x':0,'y':1}[vType[1]] v = v.reshape((self.nC,-1), order='F')[:,xORy] out = () if view in ['real','imag','abs']: v = self.r(v, 'CC', 'CC', 'M') v = getattr(np,view)(v) # e.g. np.real(v) if clim is None: clim = [v.min(),v.max()] v = np.ma.masked_where(np.isnan(v), v) out += (ax.pcolormesh(self.vectorNx, self.vectorNy, v.T, vmin=clim[0], vmax=clim[1], **pcolorOpts),) elif view in ['vec']: U, V = self.r(v.reshape((self.nC,-1), order='F'), 'CC', 'CC', 'M') if clim is None: uv = np.sqrt(U**2 + V**2) clim = [uv.min(),uv.max()] # Matplotlib seems to not support irregular # spaced vectors at the moment. So we will # Interpolate down to a regular mesh at the # smallest mesh size in this 2D slice. nxi = int(self.hx.sum()/self.hx.min()) nyi = int(self.hy.sum()/self.hy.min()) tMi = self.__class__([np.ones(nxi)*self.hx.sum()/nxi, np.ones(nyi)*self.hy.sum()/nyi], self.x0) P = self.getInterpolationMat(tMi.gridCC,'CC',zerosOutside=True) Ui = tMi.r(P*mkvc(U), 'CC', 'CC', 'M') Vi = tMi.r(P*mkvc(V), 'CC', 'CC', 'M') # End Interpolation out += (ax.pcolormesh(self.vectorNx, self.vectorNy, np.sqrt(U**2+V**2).T, vmin=clim[0], vmax=clim[1], **pcolorOpts),) out += (ax.streamplot(tMi.vectorCCx, tMi.vectorCCy, Ui.T, Vi.T, **streamOpts),) if grid: xXGrid = np.c_[self.vectorNx,self.vectorNx,np.nan*np.ones(self.nNx)].flatten() xYGrid = np.c_[self.vectorNy[0]*np.ones(self.nNx),self.vectorNy[-1]*np.ones(self.nNx),np.nan*np.ones(self.nNx)].flatten() yXGrid = np.c_[self.vectorNx[0]*np.ones(self.nNy),self.vectorNx[-1]*np.ones(self.nNy),np.nan*np.ones(self.nNy)].flatten() yYGrid = np.c_[self.vectorNy,self.vectorNy,np.nan*np.ones(self.nNy)].flatten() out += (ax.plot(np.r_[xXGrid,yXGrid],np.r_[xYGrid,yYGrid],**gridOpts)[0],) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_xlim(*self.vectorNx[[0,-1]]) ax.set_ylim(*self.vectorNy[[0,-1]]) if showIt: plt.show() return out
def plotGrid(self, ax=None, nodes=False, faces=False, centers=False, edges=False, lines=True, showIt=False): """Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions. :param bool nodes: plot nodes :param bool faces: plot faces :param bool centers: plot centers :param bool edges: plot edges :param bool lines: plot lines connecting nodes :param bool showIt: call plt.show() .. plot:: :include-source: from SimPEG import Mesh, np h1 = np.linspace(.1,.5,3) h2 = np.linspace(.1,.5,5) mesh = Mesh.TensorMesh([h1, h2]) mesh.plotGrid(nodes=True, faces=True, centers=True, lines=True, showIt=True) .. plot:: :include-source: from SimPEG import Mesh, np h1 = np.linspace(.1,.5,3) h2 = np.linspace(.1,.5,5) h3 = np.linspace(.1,.5,3) mesh = Mesh.TensorMesh([h1,h2,h3]) mesh.plotGrid(nodes=True, faces=True, centers=True, lines=True, showIt=True) """ axOpts = {'projection':'3d'} if self.dim == 3 else {} if ax is None: fig = plt.figure() ax = plt.subplot(111, **axOpts) else: assert isinstance(ax, matplotlib.axes.Axes), "ax must be an matplotlib.axes.Axes" fig = ax.figure if self.dim == 1: if nodes: ax.plot(self.gridN, np.ones(self.nN), 'bs') if centers: ax.plot(self.gridCC, np.ones(self.nC), 'ro') if lines: ax.plot(self.gridN, np.ones(self.nN), 'b.-') ax.set_xlabel('x1') elif self.dim == 2: if nodes: ax.plot(self.gridN[:, 0], self.gridN[:, 1], 'bs') if centers: ax.plot(self.gridCC[:, 0], self.gridCC[:, 1], 'ro') if faces: ax.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'g>') ax.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'g^') if edges: ax.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'c>') ax.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'c^') # Plot the grid lines if lines: NN = self.r(self.gridN, 'N', 'N', 'M') X1 = np.c_[mkvc(NN[0][0, :]), mkvc(NN[0][self.nCx, :]), mkvc(NN[0][0, :])*np.nan].flatten() Y1 = np.c_[mkvc(NN[1][0, :]), mkvc(NN[1][self.nCx, :]), mkvc(NN[1][0, :])*np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, 0]), mkvc(NN[0][:, self.nCy]), mkvc(NN[0][:, 0])*np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, 0]), mkvc(NN[1][:, self.nCy]), mkvc(NN[1][:, 0])*np.nan].flatten() X = np.r_[X1, X2] Y = np.r_[Y1, Y2] ax.plot(X, Y, 'b-') ax.set_xlabel('x1') ax.set_ylabel('x2') elif self.dim == 3: if nodes: ax.plot(self.gridN[:, 0], self.gridN[:, 1], 'bs', zs=self.gridN[:, 2]) if centers: ax.plot(self.gridCC[:, 0], self.gridCC[:, 1], 'ro', zs=self.gridCC[:, 2]) if faces: ax.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'g>', zs=self.gridFx[:, 2]) ax.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'g<', zs=self.gridFy[:, 2]) ax.plot(self.gridFz[:, 0], self.gridFz[:, 1], 'g^', zs=self.gridFz[:, 2]) if edges: ax.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'k>', zs=self.gridEx[:, 2]) ax.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'k<', zs=self.gridEy[:, 2]) ax.plot(self.gridEz[:, 0], self.gridEz[:, 1], 'k^', zs=self.gridEz[:, 2]) # Plot the grid lines if lines: NN = self.r(self.gridN, 'N', 'N', 'M') X1 = np.c_[mkvc(NN[0][0, :, :]), mkvc(NN[0][self.nCx, :, :]), mkvc(NN[0][0, :, :])*np.nan].flatten() Y1 = np.c_[mkvc(NN[1][0, :, :]), mkvc(NN[1][self.nCx, :, :]), mkvc(NN[1][0, :, :])*np.nan].flatten() Z1 = np.c_[mkvc(NN[2][0, :, :]), mkvc(NN[2][self.nCx, :, :]), mkvc(NN[2][0, :, :])*np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, 0, :]), mkvc(NN[0][:, self.nCy, :]), mkvc(NN[0][:, 0, :])*np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, 0, :]), mkvc(NN[1][:, self.nCy, :]), mkvc(NN[1][:, 0, :])*np.nan].flatten() Z2 = np.c_[mkvc(NN[2][:, 0, :]), mkvc(NN[2][:, self.nCy, :]), mkvc(NN[2][:, 0, :])*np.nan].flatten() X3 = np.c_[mkvc(NN[0][:, :, 0]), mkvc(NN[0][:, :, self.nCz]), mkvc(NN[0][:, :, 0])*np.nan].flatten() Y3 = np.c_[mkvc(NN[1][:, :, 0]), mkvc(NN[1][:, :, self.nCz]), mkvc(NN[1][:, :, 0])*np.nan].flatten() Z3 = np.c_[mkvc(NN[2][:, :, 0]), mkvc(NN[2][:, :, self.nCz]), mkvc(NN[2][:, :, 0])*np.nan].flatten() X = np.r_[X1, X2, X3] Y = np.r_[Y1, Y2, Y3] Z = np.r_[Z1, Z2, Z3] ax.plot(X, Y, 'b-', zs=Z) ax.set_xlabel('x1') ax.set_ylabel('x2') ax.set_zlabel('x3') ax.grid(True) if showIt: plt.show()
zOffset = 0 # Cycle through the first 3 octree levels for ii in range(3): dx = mesh.hx.min()*2**ii nCx = int((limx[0]-limx[1]) / dx) nCy = int((limy[0]-limy[1]) / dx) # Create a grid at the octree level in xy CCx, CCy = np.meshgrid( np.linspace(limx[1], limx[0], nCx), np.linspace(limy[1], limy[0], nCy) ) z = F(mkvc(CCx), mkvc(CCy)) # level means number of layers in current OcTree level for level in range(int(nCpad[ii])): mesh.insert_cells( np.c_[mkvc(CCx), mkvc(CCy), z-zOffset], np.ones_like(z)*maxLevel-ii, finalize=False ) zOffset += dx mesh.finalize() # Define an active cells from topo
def get_dist_wgt(mesh, rxLoc, actv, R, R0): """ get_dist_wgt(xn,yn,zn,rxLoc,R,R0) Function creating a distance weighting function required for the magnetic inverse problem. INPUT xn, yn, zn : Node location rxLoc : Observation locations [obsx, obsy, obsz] actv : Active cell vector [0:air , 1: ground] R : Decay factor (mag=3, grav =2) R0 : Small factor added (default=dx/4) OUTPUT wr : [nC] Vector of distance weighting Created on Dec, 20th 2015 @author: dominiquef """ # Find non-zero cells if actv.dtype == 'bool': inds = np.where(actv)[0] else: inds = actv nC = len(inds) # Create active cell projector P = sp.csr_matrix((np.ones(nC), (inds, range(nC))), shape=(mesh.nC, nC)) # Geometrical constant p = 1 / np.sqrt(3) # Create cell center location Ym, Xm, Zm = np.meshgrid(mesh.vectorCCy, mesh.vectorCCx, mesh.vectorCCz) hY, hX, hZ = np.meshgrid(mesh.hy, mesh.hx, mesh.hz) # Remove air cells Xm = P.T * mkvc(Xm) Ym = P.T * mkvc(Ym) Zm = P.T * mkvc(Zm) hX = P.T * mkvc(hX) hY = P.T * mkvc(hY) hZ = P.T * mkvc(hZ) V = P.T * mkvc(mesh.vol) wr = np.zeros(nC) ndata = rxLoc.shape[0] count = -1 print("Begin calculation of distance weighting for R= " + str(R)) for dd in range(ndata): nx1 = (Xm - hX * p - rxLoc[dd, 0])**2 nx2 = (Xm + hX * p - rxLoc[dd, 0])**2 ny1 = (Ym - hY * p - rxLoc[dd, 1])**2 ny2 = (Ym + hY * p - rxLoc[dd, 1])**2 nz1 = (Zm - hZ * p - rxLoc[dd, 2])**2 nz2 = (Zm + hZ * p - rxLoc[dd, 2])**2 R1 = np.sqrt(nx1 + ny1 + nz1) R2 = np.sqrt(nx1 + ny1 + nz2) R3 = np.sqrt(nx2 + ny1 + nz1) R4 = np.sqrt(nx2 + ny1 + nz2) R5 = np.sqrt(nx1 + ny2 + nz1) R6 = np.sqrt(nx1 + ny2 + nz2) R7 = np.sqrt(nx2 + ny2 + nz1) R8 = np.sqrt(nx2 + ny2 + nz2) temp = (R1 + R0)**-R + (R2 + R0)**-R + (R3 + R0)**-R + \ (R4 + R0)**-R + (R5 + R0)**-R + (R6 + R0)**-R + \ (R7 + R0)**-R + (R8 + R0)**-R wr = wr + (V * temp / 8.)**2. count = progress(dd, count, ndata) wr = np.sqrt(wr) / V wr = mkvc(wr) wr = np.sqrt(wr / (np.max(wr))) print("Done 100% ...distance weighting completed!!\n") return wr
def plotGrid(self, ax=None, nodes=False, faces=False, centers=False, edges=False, lines=True, showIt=False): """Plot the nodal, cell-centered and staggered grids for 1,2 and 3 dimensions. :param bool nodes: plot nodes :param bool faces: plot faces :param bool centers: plot centers :param bool edges: plot edges :param bool lines: plot lines connecting nodes :param bool showIt: call plt.show() .. plot:: :include-source: from SimPEG import Mesh, np h1 = np.linspace(.1,.5,3) h2 = np.linspace(.1,.5,5) mesh = Mesh.TensorMesh([h1, h2]) mesh.plotGrid(nodes=True, faces=True, centers=True, lines=True, showIt=True) .. plot:: :include-source: from SimPEG import Mesh, np h1 = np.linspace(.1,.5,3) h2 = np.linspace(.1,.5,5) h3 = np.linspace(.1,.5,3) mesh = Mesh.TensorMesh([h1,h2,h3]) mesh.plotGrid(nodes=True, faces=True, centers=True, lines=True, showIt=True) """ axOpts = {'projection': '3d'} if self.dim == 3 else {} if ax is None: fig = plt.figure() ax = plt.subplot(111, **axOpts) else: assert isinstance( ax, matplotlib.axes.Axes), "ax must be an matplotlib.axes.Axes" fig = ax.figure if self.dim == 1: if nodes: ax.plot(self.gridN, np.ones(self.nN), 'bs') if centers: ax.plot(self.gridCC, np.ones(self.nC), 'ro') if lines: ax.plot(self.gridN, np.ones(self.nN), 'b.-') ax.set_xlabel('x1') elif self.dim == 2: if nodes: ax.plot(self.gridN[:, 0], self.gridN[:, 1], 'bs') if centers: ax.plot(self.gridCC[:, 0], self.gridCC[:, 1], 'ro') if faces: ax.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'g>') ax.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'g^') if edges: ax.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'c>') ax.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'c^') # Plot the grid lines if lines: NN = self.r(self.gridN, 'N', 'N', 'M') X1 = np.c_[mkvc(NN[0][0, :]), mkvc(NN[0][self.nCx, :]), mkvc(NN[0][0, :]) * np.nan].flatten() Y1 = np.c_[mkvc(NN[1][0, :]), mkvc(NN[1][self.nCx, :]), mkvc(NN[1][0, :]) * np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, 0]), mkvc(NN[0][:, self.nCy]), mkvc(NN[0][:, 0]) * np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, 0]), mkvc(NN[1][:, self.nCy]), mkvc(NN[1][:, 0]) * np.nan].flatten() X = np.r_[X1, X2] Y = np.r_[Y1, Y2] ax.plot(X, Y, 'b-') ax.set_xlabel('x1') ax.set_ylabel('x2') elif self.dim == 3: if nodes: ax.plot(self.gridN[:, 0], self.gridN[:, 1], 'bs', zs=self.gridN[:, 2]) if centers: ax.plot(self.gridCC[:, 0], self.gridCC[:, 1], 'ro', zs=self.gridCC[:, 2]) if faces: ax.plot(self.gridFx[:, 0], self.gridFx[:, 1], 'g>', zs=self.gridFx[:, 2]) ax.plot(self.gridFy[:, 0], self.gridFy[:, 1], 'g<', zs=self.gridFy[:, 2]) ax.plot(self.gridFz[:, 0], self.gridFz[:, 1], 'g^', zs=self.gridFz[:, 2]) if edges: ax.plot(self.gridEx[:, 0], self.gridEx[:, 1], 'k>', zs=self.gridEx[:, 2]) ax.plot(self.gridEy[:, 0], self.gridEy[:, 1], 'k<', zs=self.gridEy[:, 2]) ax.plot(self.gridEz[:, 0], self.gridEz[:, 1], 'k^', zs=self.gridEz[:, 2]) # Plot the grid lines if lines: NN = self.r(self.gridN, 'N', 'N', 'M') X1 = np.c_[mkvc(NN[0][0, :, :]), mkvc(NN[0][self.nCx, :, :]), mkvc(NN[0][0, :, :]) * np.nan].flatten() Y1 = np.c_[mkvc(NN[1][0, :, :]), mkvc(NN[1][self.nCx, :, :]), mkvc(NN[1][0, :, :]) * np.nan].flatten() Z1 = np.c_[mkvc(NN[2][0, :, :]), mkvc(NN[2][self.nCx, :, :]), mkvc(NN[2][0, :, :]) * np.nan].flatten() X2 = np.c_[mkvc(NN[0][:, 0, :]), mkvc(NN[0][:, self.nCy, :]), mkvc(NN[0][:, 0, :]) * np.nan].flatten() Y2 = np.c_[mkvc(NN[1][:, 0, :]), mkvc(NN[1][:, self.nCy, :]), mkvc(NN[1][:, 0, :]) * np.nan].flatten() Z2 = np.c_[mkvc(NN[2][:, 0, :]), mkvc(NN[2][:, self.nCy, :]), mkvc(NN[2][:, 0, :]) * np.nan].flatten() X3 = np.c_[mkvc(NN[0][:, :, 0]), mkvc(NN[0][:, :, self.nCz]), mkvc(NN[0][:, :, 0]) * np.nan].flatten() Y3 = np.c_[mkvc(NN[1][:, :, 0]), mkvc(NN[1][:, :, self.nCz]), mkvc(NN[1][:, :, 0]) * np.nan].flatten() Z3 = np.c_[mkvc(NN[2][:, :, 0]), mkvc(NN[2][:, :, self.nCz]), mkvc(NN[2][:, :, 0]) * np.nan].flatten() X = np.r_[X1, X2, X3] Y = np.r_[Y1, Y2, Y3] Z = np.r_[Z1, Z2, Z3] ax.plot(X, Y, 'b-', zs=Z) ax.set_xlabel('x1') ax.set_ylabel('x2') ax.set_zlabel('x3') ax.grid(True) if showIt: plt.show()
vtem = TDEM.Src.VTEMWaveform() trapezoid = TDEM.Src.TrapezoidWaveform( ramp_on=np.r_[0., 1.5e-3], ramp_off=max_t-np.r_[1.5e-3, 0] ) quarter_sine = TDEM.Src.QuarterSineRampOnWaveform( ramp_on=np.r_[0., 1.5e-3], ramp_off=max_t-np.r_[1.5e-3, 0] ) waveforms = dict(zip( [ 'RampOffWaveform', 'VTEMWaveform', 'TrapezoidWaveform', 'QuarterSineRampOnWaveform' ], [ramp_off, vtem, trapezoid, quarter_sine] )) # plot the waveforms fig, ax = plt.subplots(2, 2, figsize=(7, 7)) ax = mkvc(ax) for a, key in zip(ax, waveforms): wave = waveforms[key] wave_plt = [wave.eval(t) for t in times] a.plot(times, wave_plt) a.set_title(key) a.set_xlabel('time (s)') plt.tight_layout() plt.show()
def checkDerivative(fctn, x0, num=7, plotIt=True, dx=None, expectedOrder=2, tolerance=0.85, eps=1e-10, ax=None): """ Basic derivative check Compares error decay of 0th and 1st order Taylor approximation at point x0 for a randomized search direction. :param lambda fctn: function handle :param numpy.array x0: point at which to check derivative :param int num: number of times to reduce step length, h :param bool plotIt: if you would like to plot :param numpy.array dx: step direction :param int expectedOrder: The order that you expect the derivative to yield. :param float tolerance: The tolerance on the expected order. :param float eps: What is zero? :rtype: bool :return: did you pass the test?! .. plot:: :include-source: from SimPEG import Tests, Utils, np def simplePass(x): return np.sin(x), Utils.sdiag(np.cos(x)) Tests.checkDerivative(simplePass, np.random.randn(5)) """ print "%s checkDerivative %s" % ('='*20, '='*20) print "iter h |ft-f0| |ft-f0-h*J0*dx| Order\n%s" % ('-'*57) f0, J0 = fctn(x0) x0 = mkvc(x0) if dx is None: dx = np.random.randn(len(x0)) h = np.logspace(-1, -num, num) E0 = np.ones(h.shape) E1 = np.ones(h.shape) def l2norm(x): # because np.norm breaks if they are scalars? return np.sqrt(np.real(np.vdot(x, x))) for i in range(num): # Evaluate at test point ft, Jt = fctn( x0 + h[i]*dx ) # 0th order Taylor E0[i] = l2norm( ft - f0 ) # 1st order Taylor if inspect.isfunction(J0): E1[i] = l2norm( ft - f0 - h[i]*J0(dx) ) else: # We assume it is a numpy.ndarray E1[i] = l2norm( ft - f0 - h[i]*J0.dot(dx) ) order0 = np.log10(E0[:-1]/E0[1:]) order1 = np.log10(E1[:-1]/E1[1:]) print " %d %1.2e %1.3e %1.3e %1.3f" % (i, h[i], E0[i], E1[i], np.nan if i == 0 else order1[i-1]) # Ensure we are about precision order0 = order0[E0[1:] > eps] order1 = order1[E1[1:] > eps] belowTol = (order1.size == 0 and order0.size >= 0) # Make sure we get the correct order correctOrder = order1.size > 0 and np.mean(order1) > tolerance * expectedOrder passTest = belowTol or correctOrder if passTest: print "%s PASS! %s" % ('='*25, '='*25) print happiness[np.random.randint(len(happiness))]+'\n' else: print "%s\n%s FAIL! %s\n%s" % ('*'*57, '<'*25, '>'*25, '*'*57) print sadness[np.random.randint(len(sadness))]+'\n' if plotIt: ax = ax or plt.subplot(111) ax.loglog(h, E0, 'b') ax.loglog(h, E1, 'g--') ax.set_title('Check Derivative - %s' % ('PASSED :)' if passTest else 'FAILED :(')) ax.set_xlabel('h') ax.set_ylabel('Error') leg = ax.legend(['$\mathcal{O}(h)$', '$\mathcal{O}(h^2)$'], loc='best', title="$f(x + h\Delta x) - f(x) - h g(x) \Delta x - \mathcal{O}(h^2) = 0$", frameon=False) plt.setp(leg.get_title(),fontsize=15) plt.show() return passTest
def Jtvec(self, m, v, u=None): """ Computing Jacobian^T multiplied by vector. .. math :: (\\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}})^{T} = \left[ \mathbf{P}_{deriv}\\frac{\partial \mathbf{\mu} } {\partial \mathbf{m} } \left[ \diag(\M^f_{\mu_{0}^{-1} } \mathbf{B}_0) \dMfMuI \\ - \diag (\Div^T\mathbf{u})\dMfMuI \\right ]\\right]^{T} - \left[\mathbf{P}_{deriv}(\MfMui)^{-1}\Div^T\\frac{\delta\mathbf{u}}{\delta \mathbf{m}} \\right]^{T} where .. math :: \mathbf{P}_{derv} = \\frac{\partial \mathbf{P}}{\partial\mathbf{B}} .. note :: Here we only want to compute .. math :: \mathbf{J}^{T}\mathbf{v} = (\\frac{\delta \mathbf{P}\mathbf{B}} {\delta \mathbf{m}})^{T} \mathbf{v} """ if u is None: u = self.fields(m) B, u = u['B'], u['u'] mu = self.mapping * (m) dmudm = self.mapping.deriv(m) # dchidmu = sdiag(1 / mu_0 * np.ones(self.mesh.nC)) vol = self.mesh.vol Div = self._Div Dface = self.mesh.faceDiv P = self.survey.projectFieldsDeriv( B) # Projection matrix B0 = self.getB0() MfMuIvec = 1 / self.MfMui.diagonal() dMfMuI = sdiag(MfMuIvec**2) * \ self.mesh.aveF2CC.T * sdiag(vol * 1. / mu**2) # A = self._Div*self.MfMuI*self._Div.T # RHS = Div*MfMuI*MfMu0*B0 - Div*B0 + Mc*Dface*Pout.T*Bbc # C(m,u) = A*m-rhs # dudm = -(dCdu)^(-1)dCdm dCdu = self.getA(m) s = Div * (self.MfMuI.T * (P.T * v)) m1 = sp.linalg.interface.aslinearoperator( sdiag(1 / (dCdu.T).diagonal()) ) sol, info = sp.linalg.bicgstab(dCdu.T, s, tol=1e-6, maxiter=1000, M=m1) if info > 0: print("Iterative solver did not work well (Jtvec)") # raise Exception ("Iterative solver did not work well") # dCdm_A = Div * ( sdiag( Div.T * u )* dMfMuI *dmudm ) # dCdm_Atsol = ( dMfMuI.T*( sdiag( Div.T * u ) * (Div.T * dmudm)) ) * sol dCdm_Atsol = (dmudm.T * dMfMuI.T * (sdiag(Div.T * u) * Div.T)) * sol # dCdm_RHS1 = Div * (sdiag( self.MfMu0*B0 ) * dMfMuI) # dCdm_RHS1tsol = (dMfMuI.T*( sdiag( self.MfMu0*B0 ) ) * Div.T * dmudm) * sol dCdm_RHS1tsol = ( dmudm.T * dMfMuI.T * (sdiag(self.MfMu0 * B0)) * Div.T ) * sol # temp1 = (Dface*(self._Pout.T*self.Bbc_const*self.Bbc)) # temp1sol = (Dface.T * (sdiag(vol) * sol)) # temp2 = self.Bbc_const * (self._Pout.T * self.Bbc).T # dCdm_RHS2v = (sdiag(vol)*temp1)*np.inner(vol, dchidmu*dmudm*v) # dCdm_RHS2tsol = (dmudm.T * dchidmu.T * vol) * np.inner(temp2, temp1sol) # dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v # temporary fix # dCdm_RHStsol = dCdm_RHS1tsol - dCdm_RHS2tsol dCdm_RHStsol = dCdm_RHS1tsol # dCdm_RHSv = dCdm_RHS1*(dmudm*v) + dCdm_RHS2v # dCdm_v = dCdm_A*v - dCdm_RHSv Ctv = dCdm_Atsol - dCdm_RHStsol # B = self.MfMuI*self.MfMu0*B0-B0-self.MfMuI*self._Div.T*u # dBdm = d\mudm*dBd\mu # dPBdm^T*v = Atemp^T*P^T*v - Btemp^T*P^T*v - Ctv Atemp = sdiag(self.MfMu0 * B0) * (dMfMuI * (dmudm)) Btemp = sdiag(Div.T * u) * (dMfMuI * (dmudm)) Jtv = Atemp.T * (P.T * v) - Btemp.T * (P.T * v) - Ctv return mkvc(Jtv)