def run(plotIt=True, n=60): M = Mesh.TreeMesh([[(1, 16)], [(1, 16)]], levels=4) M = Mesh.TreeMesh([[(1, 16)], [(1, 16)]], levels=4) M.insert_cells(np.array([5., 5.]), np.array([3])) M.number() if plotIt: fig, axes = plt.subplots(2, 1, figsize=(10, 10)) M.plotGrid(cells=True, nodes=False, ax=axes[0]) axes[0].axis('off') axes[0].set_title('Simple QuadTree Mesh') axes[0].set_xlim([-1, 17]) axes[0].set_ylim([-1, 17]) for ii, loc in zip(range(M.nC), M.gridCC): axes[0].text(loc[0] + 0.2, loc[1], '{0:d}'.format(ii), color='r') axes[0].plot(M.gridFx[:, 0], M.gridFx[:, 1], 'g>') for ii, loc in zip(range(M.nFx), M.gridFx): axes[0].text(loc[0] + 0.2, loc[1], '{0:d}'.format(ii), color='g') axes[0].plot(M.gridFy[:, 0], M.gridFy[:, 1], 'm^') for ii, loc in zip(range(M.nFy), M.gridFy): axes[0].text(loc[0] + 0.2, loc[1] + 0.2, '{0:d}'.format((ii + M.nFx)), color='m') axes[1].spy(M.faceDiv) axes[1].set_title('Face Divergence') axes[1].set_ylabel('Cell Number') axes[1].set_xlabel('Face Number')
def setUp(self): def topo(x): return np.sin(x * (2. * np.pi)) * 0.3 + 0.5 def function(cell): r = cell.center - np.array([0.5] * len(cell.center)) dist1 = np.sqrt(r.dot(r)) - 0.08 dist2 = np.abs(cell.center[-1] - topo(cell.center[0])) dist = min([dist1, dist2]) # if dist < 0.05: # return 5 if dist < 0.05: return 6 if dist < 0.2: return 5 if dist < 0.3: return 4 if dist < 1.0: return 3 else: return 0 M = Mesh.TreeMesh([64, 64], levels=6) M.refine(function) self.M = M
def run(plotIt=True): """ Mesh: QuadTree: Hanging Nodes ============================= You can give the refine method a function, which is evaluated on every cell of the TreeMesh. Occasionally it is useful to initially refine to a constant level (e.g. 3 in this 32x32 mesh). This means the function is first evaluated on an 8x8 mesh (2^3). """ M = Mesh.TreeMesh([8, 8]) def refine(cell): xyz = cell.center dist = ((xyz - [0.25, 0.25])**2).sum()**0.5 if dist < 0.25: return 3 return 2 M.refine(refine) M.number() if plotIt: M.plotGrid(nodes=True, cells=True, facesX=True) plt.legend(('Grid', 'Cell Centers', 'Nodes', 'Hanging Nodes', 'X faces', 'Hanging X faces'))
def run(plotIt=True): """ Mesh: QuadTree: Creation ======================== You can give the refine method a function, which is evaluated on every cell of the TreeMesh. Occasionally it is useful to initially refine to a constant level (e.g. 3 in this 32x32 mesh). This means the function is first evaluated on an 8x8 mesh (2^3). """ M = Mesh.TreeMesh([32, 32]) M.refine(3) def refine(cell): xyz = cell.center for i in range(3): if np.abs(np.sin(xyz[0] * np.pi * 2) * 0.5 + 0.5 - xyz[1]) < 0.2 * i: return 6 - i return 0 M.refine(refine) if plotIt: M.plotGrid()
def run(plotIt=True): """ Mesh: Basic: Types ================== Here we show SimPEG used to create three different types of meshes. """ sz = [16, 16] tM = Mesh.TensorMesh(sz) qM = Mesh.TreeMesh(sz) qM.refine(lambda cell: 4 if np.sqrt(((np.r_[cell.center] - 0.5)**2).sum()) < 0.4 else 3) rM = Mesh.CurvilinearMesh(Utils.meshutils.exampleLrmGrid(sz, 'rotate')) if plotIt: import matplotlib.pyplot as plt fig, axes = plt.subplots(1, 3, figsize=(14, 5)) opts = {} tM.plotGrid(ax=axes[0], **opts) axes[0].set_title('TensorMesh') qM.plotGrid(ax=axes[1], **opts) axes[1].set_title('TreeMesh') rM.plotGrid(ax=axes[2], **opts) axes[2].set_title('CurvilinearMesh') plt.show()
def test_refine(self): M = Mesh.TreeMesh([4, 4, 4]) M.refine(1) assert M.nC == 8 M.refine(0) assert M.nC == 8 M.corsen(0) assert M.nC == 1
def test_getitem(self): M = Mesh.TreeMesh([4, 4]) M.refine(1) assert M.nC == 4 assert len(M) == M.nC assert np.allclose(M[0].center, [0.25, 0.25]) actual = [[0, 0], [0.5, 0], [0, 0.5], [0.5, 0.5]] for i, n in enumerate(M[0].nodes): assert np.allclose(M._gridN[n, :], actual[i])
def test_VectorIdenties(self): hx, hy, hz = [[(1, 4)], [(1, 4)], [(1, 4)]] M = Mesh.TreeMesh([hx, hy, hz], levels=2) Mr = Mesh.TensorMesh([hx, hy, hz]) assert (M.faceDiv * M.edgeCurl).nnz == 0 assert (Mr.faceDiv * Mr.edgeCurl).nnz == 0 hx, hy, hz = np.r_[1., 2, 3, 4], np.r_[5., 6, 7, 8], np.r_[9., 10, 11, 12] M = Mesh.TreeMesh([hx, hy, hz], levels=2) Mr = Mesh.TensorMesh([hx, hy, hz]) assert np.max(np.abs( (M.faceDiv * M.edgeCurl).todense().flatten())) < TOL assert np.max(np.abs( (Mr.faceDiv * Mr.edgeCurl).todense().flatten())) < TOL
def test_edgeCurl(self): hx, hy, hz = np.r_[1., 2, 3, 4], np.r_[5., 6, 7, 8], np.r_[9., 10, 11, 12] M = Mesh.TreeMesh([hx, hy, hz], levels=2) M.refine(lambda xc: 2) # M.plotGrid(showIt=True) Mr = Mesh.TensorMesh([hx, hy, hz]) # plt.subplot(211).spy(Mr.faceDiv) # plt.subplot(212).spy(M.permuteCC.T*M.faceDiv*M.permuteF) # plt.show() assert (Mr.edgeCurl - M.permuteF * M.edgeCurl * M.permuteE.T).nnz == 0
def run(plotIt=True): M = Mesh.TreeMesh([32, 32]) M.refine(3) def refine(cell): xyz = cell.center for i in range(3): if np.abs(np.sin(xyz[0]*np.pi*2)*0.5 + 0.5 - xyz[1]) < 0.2*i: return 6-i return 0 M.refine(refine) if plotIt: M.plotGrid()
def test_corsen(self): nc = 8 h1 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h2 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h = [hi / np.sum(hi) for hi in [h1, h2]] # normalize M = Mesh.TreeMesh(h) M._refineCell([0, 0, 0]) M._refineCell([0, 0, 1]) self.assertRaises(CellLookUpException, M._refineCell, [0, 0, 1]) assert M._index([0, 0, 1]) not in M assert M._index([0, 0, 2]) in M assert M._index([2, 0, 2]) in M assert M._index([0, 2, 2]) in M assert M._index([2, 2, 2]) in M self.assertRaises(CellLookUpException, M._corsenCell, [0, 0, 1]) M._corsenCell([0, 0, 2]) assert M._index([0, 0, 1]) in M assert M._index([0, 0, 2]) not in M assert M._index([2, 0, 2]) not in M assert M._index([0, 2, 2]) not in M assert M._index([2, 2, 2]) not in M M._refineCell([0, 0, 1]) self.assertRaises(CellLookUpException, M._corsenCell, [0, 0, 1]) M._corsenCell([2, 0, 2]) assert M._index([0, 0, 1]) in M assert M._index([0, 0, 2]) not in M assert M._index([2, 0, 2]) not in M assert M._index([0, 2, 2]) not in M assert M._index([2, 2, 2]) not in M M._refineCell([0, 0, 1]) self.assertRaises(CellLookUpException, M._corsenCell, [0, 0, 1]) M._corsenCell([0, 2, 2]) assert M._index([0, 0, 1]) in M assert M._index([0, 0, 2]) not in M assert M._index([2, 0, 2]) not in M assert M._index([0, 2, 2]) not in M assert M._index([2, 2, 2]) not in M M._refineCell([0, 0, 1]) self.assertRaises(CellLookUpException, M._corsenCell, [0, 0, 1]) M._corsenCell([2, 2, 2]) assert M._index([0, 0, 1]) in M assert M._index([0, 0, 2]) not in M assert M._index([2, 0, 2]) not in M assert M._index([0, 2, 2]) not in M assert M._index([2, 2, 2]) not in M
def test_counts(self): nc = 8 h1 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h2 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h3 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h = [hi / np.sum(hi) for hi in [h1, h2, h3]] # normalize M = Mesh.TreeMesh(h, levels=3) M._refineCell([0, 0, 0, 0]) M._refineCell([0, 0, 0, 1]) M.number() # M.plotGrid(showIt=True) # assert M.nhFx == 2 # assert M.nFx == 9 assert np.allclose(M.vol.sum(), 1.0)
def setUp(self): def function(cell): r = cell.center - np.array([0.5] * len(cell.center)) dist = np.sqrt(r.dot(r)) if dist < 0.2: return 4 if dist < 0.3: return 3 if dist < 1.0: return 2 else: return 0 M = Mesh.TreeMesh([16, 16, 16], levels=4) M.refine(function) # M.plotGrid(showIt=True) self.M = M
def run(plotIt=True): """ Mesh: Basic: PlotImage ====================== You can use M.PlotImage to plot images on all of the Meshes. """ M = Mesh.TensorMesh([32, 32]) v = Utils.ModelBuilder.randomModel(M.vnC, seed=789) v = Utils.mkvc(v) O = Mesh.TreeMesh([32, 32]) O.refine(1) def function(cell): if (cell.center[0] < 0.75 and cell.center[0] > 0.25 and cell.center[1] < 0.75 and cell.center[1] > 0.25): return 5 if (cell.center[0] < 0.9 and cell.center[0] > 0.1 and cell.center[1] < 0.9 and cell.center[1] > 0.1): return 4 return 3 O.refine(function) P = M.getInterpolationMat(O.gridCC, 'CC') ov = P * v if not plotIt: return fig, axes = plt.subplots(1, 2, figsize=(10, 5)) out = M.plotImage(v, grid=True, ax=axes[0]) cb = plt.colorbar(out[0], ax=axes[0]) cb.set_label("Random Field") axes[0].set_title('TensorMesh') out = O.plotImage(ov, grid=True, ax=axes[1], clim=[0, 1]) cb = plt.colorbar(out[0], ax=axes[1]) cb.set_label("Random Field") axes[1].set_title('TreeMesh')
def test_counts(self): nc = 8 h1 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h2 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h = [hi / np.sum(hi) for hi in [h1, h2]] # normalize M = Mesh.TreeMesh(h) M._refineCell([0, 0, 0]) M._refineCell([0, 0, 1]) M.number() # M.plotGrid(showIt=True) print(M) assert M.nhFx == 2 assert M.nFx == 9 assert np.allclose(M.vol.sum(), 1.0) assert np.allclose(np.r_[M._areaFxFull, M._areaFyFull], M._deflationMatrix('F') * M.area)
def doTestFace(self, h, rep, fast, meshType, invProp=False, invMat=False): if meshType == 'Curv': hRect = Utils.exampleLrmGrid(h,'rotate') mesh = Mesh.CurvilinearMesh(hRect) elif meshType == 'Tree': mesh = Mesh.TreeMesh(h, levels=3) mesh.refine(lambda xc: 3) mesh.number(balance=False) elif meshType == 'Tensor': mesh = Mesh.TensorMesh(h) v = np.random.rand(mesh.nF) sig = np.random.rand(1) if rep is 0 else np.random.rand(mesh.nC*rep) def fun(sig): M = mesh.getFaceInnerProduct(sig, invProp=invProp, invMat=invMat) Md = mesh.getFaceInnerProductDeriv(sig, invProp=invProp, invMat=invMat, doFast=fast) return M*v, Md(v) print meshType, 'Face', h, rep, fast, ('harmonic' if invProp and invMat else 'standard') return Tests.checkDerivative(fun, sig, num=5, plotIt=False)
def run(plotIt=True): M = Mesh.TreeMesh([8, 8]) def refine(cell): xyz = cell.center dist = ((xyz - [0.25, 0.25])**2).sum()**0.5 if dist < 0.25: return 3 return 2 M.refine(refine) M.number() if plotIt: M.plotGrid(nodes=True, cells=True, facesX=True) plt.legend(( 'Grid', 'Cell Centers', 'Nodes', 'Hanging Nodes', 'X faces', 'Hanging X faces' ))
def test_faceDiv(self): hx, hy = np.r_[1., 2, 3, 4], np.r_[5., 6, 7, 8] T = Mesh.TreeMesh([hx, hy], levels=2) T.refine(lambda xc: 2) # T.plotGrid(showIt=True) M = Mesh.TensorMesh([hx, hy]) assert M.nC == T.nC assert M.nF == T.nF assert M.nFx == T.nFx assert M.nFy == T.nFy assert M.nE == T.nE assert M.nEx == T.nEx assert M.nEy == T.nEy assert np.allclose(M.area, T.permuteF * T.area) assert np.allclose(M.edge, T.permuteE * T.edge) assert np.allclose(M.vol, T.permuteCC * T.vol) # plt.subplot(211).spy(M.faceDiv) # plt.subplot(212).spy(T.permuteCC*T.faceDiv*T.permuteF.T) # plt.show() assert (M.faceDiv - T.permuteCC * T.faceDiv * T.permuteF.T).nnz == 0
def run(plotIt=True): sz = [16, 16] tM = Mesh.TensorMesh(sz) qM = Mesh.TreeMesh(sz) def refine(cell): if np.sqrt(((np.r_[cell.center] - 0.5)**2).sum()) < 0.4: return 4 return 3 qM.refine(refine) rM = Mesh.CurvilinearMesh(Utils.meshutils.exampleLrmGrid(sz, 'rotate')) if not plotIt: return fig, axes = plt.subplots(1, 3, figsize=(14, 5)) opts = {} tM.plotGrid(ax=axes[0], **opts) axes[0].set_title('TensorMesh') qM.plotGrid(ax=axes[1], **opts) axes[1].set_title('TreeMesh') rM.plotGrid(ax=axes[2], **opts) axes[2].set_title('CurvilinearMesh')
def test_faceInnerProduct(self): hx, hy, hz = np.r_[1., 2, 3, 4], np.r_[5., 6, 7, 8], np.r_[9., 10, 11, 12] # hx, hy, hz = [[(1,4)], [(1,4)], [(1,4)]] M = Mesh.TreeMesh([hx, hy, hz], levels=2) M.refine(lambda xc: 2) # M.plotGrid(showIt=True) Mr = Mesh.TensorMesh([hx, hy, hz]) # plt.subplot(211).spy(Mr.getFaceInnerProduct()) # plt.subplot(212).spy(M.getFaceInnerProduct()) # plt.show() # print(M.nC, M.nF, M.getFaceInnerProduct().shape, M.permuteF.shape) assert np.allclose(Mr.getFaceInnerProduct().todense(), (M.permuteF * M.getFaceInnerProduct() * M.permuteF.T).todense()) assert np.allclose(Mr.getEdgeInnerProduct().todense(), (M.permuteE * M.getEdgeInnerProduct() * M.permuteE.T).todense())
def test_faceDiv(self): hx, hy, hz = np.r_[1., 2, 3, 4], np.r_[5., 6, 7, 8], np.r_[9., 10, 11, 12] M = Mesh.TreeMesh([hx, hy, hz], levels=2) M.refine(lambda xc: 2) # M.plotGrid(showIt=True) Mr = Mesh.TensorMesh([hx, hy, hz]) assert M.nC == Mr.nC assert M.nF == Mr.nF assert M.nFx == Mr.nFx assert M.nFy == Mr.nFy assert M.nE == Mr.nE assert M.nEx == Mr.nEx assert M.nEy == Mr.nEy assert np.allclose(Mr.area, M.permuteF * M.area) assert np.allclose(Mr.edge, M.permuteE * M.edge) assert np.allclose(Mr.vol, M.permuteCC * M.vol) # plt.subplot(211).spy(Mr.faceDiv) # plt.subplot(212).spy(M.permuteCC*M.faceDiv*M.permuteF.T) # plt.show() assert (Mr.faceDiv - M.permuteCC * M.faceDiv * M.permuteF.T).nnz == 0
def plotVectorSectionsOctree(mesh, m, normal='X', ind=0, vmin=None, vmax=None, subFact=2, scale=1., xlim=None, ylim=None, vec='k', title=None, axs=None, actvMap=None, contours=None, fill=True, orientation='vertical', cmap='pink_r'): """ Plot section through a 3D tensor model """ # plot recovered model normalInd = {'X': 0, 'Y': 1, 'Z': 2}[normal] antiNormalInd = {'X': [1, 2], 'Y': [0, 2], 'Z': [0, 1]}[normal] h2d = (mesh.h[antiNormalInd[0]], mesh.h[antiNormalInd[1]]) x2d = (mesh.x0[antiNormalInd[0]], mesh.x0[antiNormalInd[1]]) #: Size of the sliced dimension szSliceDim = len(mesh.h[normalInd]) if ind is None: ind = int(szSliceDim // 2) cc_tensor = [None, None, None] for i in range(3): cc_tensor[i] = np.cumsum(np.r_[mesh.x0[i], mesh.h[i]]) cc_tensor[i] = (cc_tensor[i][1:] + cc_tensor[i][:-1]) * 0.5 slice_loc = cc_tensor[normalInd][ind] # Create a temporary TreeMesh with the slice through temp_mesh = Mesh.TreeMesh(h2d, x2d) level_diff = mesh.max_level - temp_mesh.max_level XS = [None, None, None] XS[antiNormalInd[0]], XS[antiNormalInd[1]] = np.meshgrid( cc_tensor[antiNormalInd[0]], cc_tensor[antiNormalInd[1]]) XS[normalInd] = np.ones_like(XS[antiNormalInd[0]]) * slice_loc loc_grid = np.c_[XS[0].reshape(-1), XS[1].reshape(-1), XS[2].reshape(-1)] inds = np.unique(mesh._get_containing_cell_indexes(loc_grid)) grid2d = mesh.gridCC[inds][:, antiNormalInd] levels = mesh._cell_levels_by_indexes(inds) - level_diff temp_mesh.insert_cells(grid2d, levels) tm_gridboost = np.empty((temp_mesh.nC, 3)) tm_gridboost[:, antiNormalInd] = temp_mesh.gridCC tm_gridboost[:, normalInd] = slice_loc # Interpolate values to mesh.gridCC if not 'CC' mx = (actvMap * m[:, 0]) my = (actvMap * m[:, 1]) mz = (actvMap * m[:, 2]) m = np.c_[mx, my, mz] # Interpolate values from mesh.gridCC to grid2d ind_3d_to_2d = mesh._get_containing_cell_indexes(tm_gridboost) v2d = m[ind_3d_to_2d, :] amp = np.sum(v2d**2., axis=1)**0.5 if axs is None: axs = plt.subplot(111) if fill: temp_mesh.plotImage(amp, ax=axs, clim=[vmin, vmax], grid=True) axs.quiver(temp_mesh.gridCC[:, 0], temp_mesh.gridCC[:, 1], v2d[:, antiNormalInd[0]], v2d[:, antiNormalInd[1]], pivot='mid', scale_units="inches", scale=scale, linewidths=(1, ), edgecolors=(vec), headaxislength=0.1, headwidth=10, headlength=30)
nCy * h[1] + padDist[1, :].sum(), nCz * h[2] + padDist[2, :].sum()]) maxLevel = int(np.log2(extent / h[0])) + 1 # Number of cells at the small octree level # For now equal in 3D nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel) # nCy = 2**(int(np.log2(extent/h[1]))+1) # nCz = 2**(int(np.log2(extent/h[2]))+1) # Define the mesh and origin # For now cubic cells mesh = Mesh.TreeMesh( [np.ones(nCx) * h[0], np.ones(nCx) * h[1], np.ones(nCx) * h[2]]) # Set origin mesh.x0 = np.r_[-nCx * h[0] / 2. + midX, -nCy * h[1] / 2. + midY, -nCz * h[2] / 2. + midZ] # mesh = Utils.modelutils.meshBuilder(topo, h, padDist, # meshType='TREE', # verticalAlignment='center') # Refine the mesh around topography # Get extent of points F = NearestNDInterpolator(topo[:, :2], topo[:, 2]) zOffset = 0 # Cycle through the first 3 octree levels
def meshBuilder(xyz, h, padDist, meshGlobal=None, expFact=1.3, meshType='TENSOR', verticalAlignment='top'): """ Function to quickly generate a Tensor mesh given a cloud of xyz points, finest core cell size and padding distance. If a meshGlobal is provided, the core cells will be centered on the underlaying mesh to reduce interpolation errors. :param numpy.ndarray xyz: n x 3 array of locations [x, y, z] :param numpy.ndarray h: 1 x 3 cell size for the core mesh :param numpy.ndarray padDist: 2 x 3 padding distances [W,E,S,N,Down,Up] [OPTIONAL] :param numpy.ndarray padCore: Number of core cells around the xyz locs :object SimPEG.Mesh: Base mesh used to shift the new mesh for overlap :param float expFact: Expension factor for padding cells [1.3] :param string meshType: Specify output mesh type: "TensorMesh" RETURNS: :object SimPEG.Mesh: Mesh object """ assert meshType in ['TENSOR', 'TREE'], ('Revise meshType. Only ' + ' TENSOR | TREE mesh ' + 'are implemented') # Get extent of points limx = np.r_[xyz[:, 0].max(), xyz[:, 0].min()] limy = np.r_[xyz[:, 1].max(), xyz[:, 1].min()] limz = np.r_[xyz[:, 2].max(), xyz[:, 2].min()] # Get center of the mesh midX = np.mean(limx) midY = np.mean(limy) midZ = np.mean(limz) nCx = int(limx[0] - limx[1]) / h[0] nCy = int(limy[0] - limy[1]) / h[1] nCz = int(limz[0] - limz[1] + int(np.min(np.r_[nCx, nCy]) / 3)) / h[2] if meshType == 'TENSOR': # Make sure the core has odd number of cells for centereing # on global mesh if meshGlobal is not None: nCx += 1 - int(nCx % 2) nCy += 1 - int(nCy % 2) nCz += 1 - int(nCz % 2) # Figure out paddings def expand(dx, pad): L = 0 nC = 0 while L < pad: nC += 1 L = np.sum(dx * expFact**(np.asarray(range(nC)) + 1)) return nC # Figure number of padding cells required to fill the space npadEast = expand(h[0], padDist[0, 0]) npadWest = expand(h[0], padDist[0, 1]) npadSouth = expand(h[1], padDist[1, 0]) npadNorth = expand(h[1], padDist[1, 1]) npadDown = expand(h[2], padDist[2, 0]) npadUp = expand(h[2], padDist[2, 1]) # Create discretization hx = [(h[0], npadWest, -expFact), (h[0], nCx), (h[0], npadEast, expFact)] hy = [(h[1], npadSouth, -expFact), (h[1], nCy), (h[1], npadNorth, expFact)] hz = [(h[2], npadDown, -expFact), (h[2], nCz), (h[2], npadUp, expFact)] # Create mesh mesh = Mesh.TensorMesh([hx, hy, hz], 'CC0') # Re-set the mesh at the center of input locations # Set origin if verticalAlignment == 'center': mesh.x0 = [ midX - np.sum(mesh.hx) / 2., midY - np.sum(mesh.hy) / 2., midZ - np.sum(mesh.hz) / 2. ] elif verticalAlignment == 'top': mesh.x0 = [ midX - np.sum(mesh.hx) / 2., midY - np.sum(mesh.hy) / 2., limz[0] - np.sum(mesh.hz) ] else: assert NotImplementedError( "verticalAlignment must be 'center' | 'top'") elif meshType == 'TREE': # Figure out full extent required from input extent = np.max(np.r_[nCx * h[0] + padDist[0, :].sum(), nCy * h[1] + padDist[1, :].sum(), nCz * h[2] + padDist[2, :].sum()]) maxLevel = int(np.log2(extent / h[0])) + 1 # Number of cells at the small octree level # For now equal in 3D nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel) # nCy = 2**(int(np.log2(extent/h[1]))+1) # nCz = 2**(int(np.log2(extent/h[2]))+1) # Define the mesh and origin # For now cubic cells mesh = Mesh.TreeMesh( [np.ones(nCx) * h[0], np.ones(nCx) * h[1], np.ones(nCx) * h[2]]) # Set origin if verticalAlignment == 'center': mesh.x0 = np.r_[-nCx * h[0] / 2. + midX, -nCy * h[1] / 2. + midY, -nCz * h[2] / 2. + midZ] elif verticalAlignment == 'top': mesh.x0 = np.r_[-nCx * h[0] / 2. + midX, -nCy * h[1] / 2. + midY, -(nCz - 1) * h[2] + limz.max()] else: assert NotImplementedError( "verticalAlignment must be 'center' | 'top'") return mesh
def setUp(self): np.random.seed(0) H0 = (50000., 90., 0.) # The magnetization is set along a different # direction (induced + remanence) M = np.array([45., 90.]) # Create grid of points for topography # Lets create a simple Gaussian topo # and set the active cells [xx, yy] = np.meshgrid( np.linspace(-200, 200, 50), np.linspace(-200, 200, 50) ) b = 100 A = 50 zz = A*np.exp(-0.5*((xx/b)**2. + (yy/b)**2.)) # We would usually load a topofile topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)] # Create and array of observation points xr = np.linspace(-100., 100., 20) yr = np.linspace(-100., 100., 20) X, Y = np.meshgrid(xr, yr) Z = A*np.exp(-0.5*((X/b)**2. + (Y/b)**2.)) + 5 # Create a MAGsurvey xyzLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)] rxLoc = PF.BaseMag.RxObs(xyzLoc) srcField = PF.BaseMag.SrcField([rxLoc], param=H0) survey = PF.BaseMag.LinearSurvey(srcField) # Create a mesh h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 nCpad = [2, 4, 2] # Get extent of points limx = np.r_[topo[:, 0].max(), topo[:, 0].min()] limy = np.r_[topo[:, 1].max(), topo[:, 1].min()] limz = np.r_[topo[:, 2].max(), topo[:, 2].min()] # Get center of the mesh midX = np.mean(limx) midY = np.mean(limy) midZ = np.mean(limz) nCx = int(limx[0]-limx[1]) / h[0] nCy = int(limy[0]-limy[1]) / h[1] nCz = int(limz[0]-limz[1]+int(np.min(np.r_[nCx, nCy])/3)) / h[2] # Figure out full extent required from input extent = np.max(np.r_[nCx * h[0] + padDist[0, :].sum(), nCy * h[1] + padDist[1, :].sum(), nCz * h[2] + padDist[2, :].sum()]) maxLevel = int(np.log2(extent/h[0]))+1 # Number of cells at the small octree level nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel) # Define the mesh and origin # For now cubic cells mesh = Mesh.TreeMesh([np.ones(nCx)*h[0], np.ones(nCx)*h[1], np.ones(nCx)*h[2]]) # Set origin mesh.x0 = np.r_[ -nCx*h[0]/2.+midX, -nCy*h[1]/2.+midY, -nCz*h[2]/2.+midZ ] # Refine the mesh around topography # 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() self.mesh = mesh # Define an active cells from topo actv = Utils.surface2ind_topo(mesh, topo) nC = int(actv.sum()) model = np.zeros((mesh.nC, 3)) # Convert the inclination declination to vector in Cartesian M_xyz = Utils.matutils.dip_azimuth2cartesian(M[0], M[1]) # Get the indicies of the magnetized block ind = Utils.ModelBuilder.getIndicesBlock( np.r_[-20, -20, -10], np.r_[20, 20, 25], mesh.gridCC, )[0] # Assign magnetization values model[ind, :] = np.kron( np.ones((ind.shape[0], 1)), M_xyz*0.05 ) # Remove air cells self.model = model[actv, :] # Create active map to go from reduce set to full self.actvMap = Maps.InjectActiveCells(mesh, actv, np.nan) # Creat reduced identity map idenMap = Maps.IdentityMap(nP=nC*3) # Create the forward model operator prob = PF.Magnetics.MagneticIntegral( mesh, chiMap=idenMap, actInd=actv, modelType='vector' ) # Pair the survey and problem survey.pair(prob) # Compute some data and add some random noise data = prob.fields(Utils.mkvc(self.model)) std = 5 # nT data += np.random.randn(len(data))*std wd = np.ones(len(data))*std # Assigne data and uncertainties to the survey survey.dobs = data survey.std = wd # Create an projection matrix for plotting later actvPlot = Maps.InjectActiveCells(mesh, actv, np.nan) # Create sensitivity weights from our linear forward operator rxLoc = survey.srcField.rxList[0].locs # This Mapping connects the regularizations for the three-component # vector model wires = Maps.Wires(('p', nC), ('s', nC), ('t', nC)) # Create sensitivity weights from our linear forward operator # so that all cells get equal chance to contribute to the solution wr = np.sum(prob.G**2., axis=0)**0.5 wr = (wr/np.max(wr)) # Create three regularization for the different components # of magnetization reg_p = Regularization.Sparse(mesh, indActive=actv, mapping=wires.p) reg_p.mref = np.zeros(3*nC) reg_p.cell_weights = (wires.p * wr) reg_s = Regularization.Sparse(mesh, indActive=actv, mapping=wires.s) reg_s.mref = np.zeros(3*nC) reg_s.cell_weights = (wires.s * wr) reg_t = Regularization.Sparse(mesh, indActive=actv, mapping=wires.t) reg_t.mref = np.zeros(3*nC) reg_t.cell_weights = (wires.t * wr) reg = reg_p + reg_s + reg_t reg.mref = np.zeros(3*nC) # Data misfit function dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1./survey.std # Add directives to the inversion opt = Optimization.ProjectedGNCG(maxIter=30, lower=-10, upper=10., maxIterLS=20, maxIterCG=20, tolCG=1e-4) invProb = InvProblem.BaseInvProblem(dmis, reg, opt) # A list of directive to control the inverson betaest = Directives.BetaEstimate_ByEig() # Here is where the norms are applied # Use pick a treshold parameter empirically based on the distribution of # model parameters IRLS = Directives.Update_IRLS( f_min_change=1e-3, maxIRLSiter=0, beta_tol=5e-1 ) # Pre-conditioner update_Jacobi = Directives.UpdatePreconditioner() inv = Inversion.BaseInversion(invProb, directiveList=[IRLS, update_Jacobi, betaest]) # Run the inversion m0 = np.ones(3*nC) * 1e-4 # Starting model mrec_MVIC = inv.run(m0) self.mstart = Utils.matutils.cartesian2spherical(mrec_MVIC.reshape((nC, 3), order='F')) beta = invProb.beta dmis.prob.coordinate_system = 'spherical' dmis.prob.model = self.mstart # Create a block diagonal regularization wires = Maps.Wires(('amp', nC), ('theta', nC), ('phi', nC)) # Create a Combo Regularization # Regularize the amplitude of the vectors reg_a = Regularization.Sparse(mesh, indActive=actv, mapping=wires.amp) reg_a.norms = np.c_[0., 0., 0., 0.] # Sparse on the model and its gradients reg_a.mref = np.zeros(3*nC) # Regularize the vertical angle of the vectors reg_t = Regularization.Sparse(mesh, indActive=actv, mapping=wires.theta) reg_t.alpha_s = 0. # No reference angle reg_t.space = 'spherical' reg_t.norms = np.c_[2., 0., 0., 0.] # Only norm on gradients used # Regularize the horizontal angle of the vectors reg_p = Regularization.Sparse(mesh, indActive=actv, mapping=wires.phi) reg_p.alpha_s = 0. # No reference angle reg_p.space = 'spherical' reg_p.norms = np.c_[2., 0., 0., 0.] # Only norm on gradients used reg = reg_a + reg_t + reg_p reg.mref = np.zeros(3*nC) Lbound = np.kron(np.asarray([0, -np.inf, -np.inf]), np.ones(nC)) Ubound = np.kron(np.asarray([10, np.inf, np.inf]), np.ones(nC)) # Add directives to the inversion opt = Optimization.ProjectedGNCG(maxIter=20, lower=Lbound, upper=Ubound, maxIterLS=20, maxIterCG=30, tolCG=1e-3, stepOffBoundsFact=1e-3, ) opt.approxHinv = None invProb = InvProblem.BaseInvProblem(dmis, reg, opt, beta=beta*10.) # Here is where the norms are applied IRLS = Directives.Update_IRLS(f_min_change=1e-4, maxIRLSiter=20, minGNiter=1, beta_tol=0.5, coolingRate=1, coolEps_q=True, betaSearch=False) # Special directive specific to the mag amplitude problem. The sensitivity # weights are update between each iteration. ProjSpherical = Directives.ProjectSphericalBounds() update_SensWeight = Directives.UpdateSensitivityWeights() update_Jacobi = Directives.UpdatePreconditioner() self.inv = Inversion.BaseInversion( invProb, directiveList=[ ProjSpherical, IRLS, update_SensWeight, update_Jacobi ] )
dh = 10 # minimum cell width (base mesh cell width) dhx = 10 dhy = 1.5 dhz = dh #Dimensao eixo vertical( base 2) nbcx = 2**12 # number of base mesh cells in x nbcy = 2**15 #nbcz =2**15 # Define base mesh (domain and finest discretization) hx = dhx * np.ones(nbcx) hy = dhy * np.ones(nbcy) #hz = dhz*np.ones(nbcz) M = Mesh.TreeMesh([hx, hy]) M.x0 = np.r_[-(nbcx * dhx) / 2, -nbcy * dhy + 15000] #definir a camada xp, yp = np.meshgrid([-(nbcx * dhx) / 2, (nbcx * dhx) / 2], [1., -1.]) #layer xy = np.c_[mkvc(xp), mkvc(yp)] # mkvc creates vectors # Discretize to finest cell size within rectangular box M = refine_tree_xyz(M, xy, octree_levels=[1, 1], method='box', finalize=False) # Define objeto xp, yp = np.meshgrid([-(nbcx * dhx) / 32, (nbcx * dhx) / 32], [-10150, -10650.]) #goal xy = np.c_[mkvc(xp), mkvc(yp)] # mkvc creates vectors
def run(plotIt=True): nFreq = 13 freqs = np.logspace(2, -2, nFreq) # x and y grid parameters # dh = 10 # minimum cell width (base mesh cell width) dx = 15 # minimum cell width (base mesh cell width) in x dy = 15 dz = 10 x_length = 10000. # domain width in x y_length = 10000. z_length = 40000. # Compute number of base mesh cells required in x and y nbcx = 2**int(np.round(np.log(x_length / dx) / np.log(2.))) nbcy = 2**int(np.round(np.log(y_length / dy) / np.log(2.))) nbcz = 2**int(np.round(np.log(z_length / dz) / np.log(2.))) # Define the base mesh hx = [(dx, nbcx)] hy = [(dy, nbcy)] hz = [(dz, nbcz)] M = Mesh.TreeMesh([hx, hy, hz], x0=['C', 'C', -15000]) # camadas xx = M.vectorNx yy = M.vectorNy zz = np.zeros(nbcx + 1) #vetor linha(poderia ser uma função ou pontos) pts = np.c_[matutils.mkvc(xx), matutils.mkvc(yy), matutils.mkvc(zz)] M = meshutils.refine_tree_xyz(M, pts, octree_levels=[1, 1, 1], method='surface', finalize=False) xx = M.vectorNx yy = M.vectorNy zz = np.zeros(nbcx + 1) - 150 #vetor linha(poderia ser uma função ou pontos) pts = np.c_[matutils.mkvc(xx), matutils.mkvc(yy), matutils.mkvc(zz)] M = meshutils.refine_tree_xyz(M, pts, octree_levels=[1, 1, 1], method='surface', finalize=False) xx = M.vectorNx yy = M.vectorNy zz = np.zeros(nbcx + 1) - 350 #vetor linha(poderia ser uma função ou pontos) pts = np.c_[matutils.mkvc(xx), matutils.mkvc(yy), matutils.mkvc(zz)] M = meshutils.refine_tree_xyz(M, pts, octree_levels=[1, 1, 1], method='surface', finalize=False) # M.finalize() print("\n the mesh has {} cells".format(M)) ccMesh = M.gridCC print('indices:', np.size(ccMesh)) ### conds = [1e-2, 1] sig = simpeg.Utils.ModelBuilder.defineBlock(M.gridCC, [-15000, 15000, -350], [15000, 1500, -150], conds) sig[M.gridCC[:, 2] > 0] = 1e-8 sigBG = np.zeros(M.nC) + conds[1] sigBG[M.gridCC[:, 2] > 0] = 1e-8 fig = plt.figure('slice: malha + modelo') ax = fig.add_subplot() collect_obj, = M.plotSlice(np.log(sig), normal='x', ax=ax, grid=True)
def test_vs_mesh_vs_loguniform(self): """ Test to make sure OcTree matches Tensor results and linear vs loguniform match """ h1 = [(2, 4)] h2 = 0.5 * np.ones(16) meshObj_Tensor = Mesh.TensorMesh((h1, h1, h1), x0='000') meshObj_OcTree = Mesh.TreeMesh([h2, h2, h2], x0='000') x, y, z = np.meshgrid(np.c_[1., 3., 5., 7.], np.c_[1., 3., 5., 7.], np.c_[1., 3., 5., 7.]) x = x.reshape((4**3, 1)) y = y.reshape((4**3, 1)) z = z.reshape((4**3, 1)) loc_rx = np.c_[x, y, z] meshObj_OcTree.insert_cells(loc_rx, 2 * np.ones((4**3)), finalize=False) x, y, z = np.meshgrid(np.c_[1., 3., 5., 7.], np.c_[1., 3., 5., 7.], np.c_[5., 7.]) x = x.reshape((32, 1)) y = y.reshape((32, 1)) z = z.reshape((32, 1)) loc_rx = np.c_[x, y, z] meshObj_OcTree.insert_cells(loc_rx, 3 * np.ones((32)), finalize=False) x, y, z = np.meshgrid(np.c_[3.5, 4.0, 4.5, 5.0, 5.5], np.c_[3.5, 4.0, 4.5, 5.0, 5.5], np.c_[6.0, 6.5, 7.0, 7.5]) x = x.reshape((100, 1)) y = y.reshape((100, 1)) z = z.reshape((100, 1)) loc_rx = np.c_[x, y, z] meshObj_OcTree.insert_cells(loc_rx, 4 * np.ones((100)), finalize=True) chi0 = 0. dchi = 0.01 tau1 = 1e-8 tau2 = 1e0 # Tensor Models mod_a = (dchi / np.log(tau2 / tau1)) * np.ones(meshObj_Tensor.nC) mod_chi0_a = chi0 * np.ones(meshObj_Tensor.nC) mod_dchi_a = dchi * np.ones(meshObj_Tensor.nC) mod_tau1_a = tau1 * np.ones(meshObj_Tensor.nC) mod_tau2_a = tau2 * np.ones(meshObj_Tensor.nC) # OcTree Models mod_b = (dchi / np.log(tau2 / tau1)) * np.ones(meshObj_OcTree.nC) mod_chi0_b = chi0 * np.ones(meshObj_OcTree.nC) mod_dchi_b = dchi * np.ones(meshObj_OcTree.nC) mod_tau1_b = tau1 * np.ones(meshObj_OcTree.nC) mod_tau2_b = tau2 * np.ones(meshObj_OcTree.nC) times = np.array([1e-3]) waveObj = VRM.WaveformVRM.SquarePulse(delt=0.02) loc_rx = np.c_[4., 4., 8.25] rxList = [ VRM.Rx.Point(loc_rx, times=times, fieldType='dhdt', fieldComp='z') ] txList = [ VRM.Src.MagDipole(rxList, np.r_[4., 4., 8.25], [0., 0., 1.], waveObj) ] Survey1 = VRM.Survey(txList) Survey2 = VRM.Survey(txList) Survey3 = VRM.Survey(txList) Survey4 = VRM.Survey(txList) Problem1 = VRM.Problem_Linear(meshObj_Tensor, ref_factor=2, ref_radius=[1.9, 3.6]) Problem2 = VRM.Problem_LogUniform(meshObj_Tensor, ref_factor=2, ref_radius=[1.9, 3.6], chi0=mod_chi0_a, dchi=mod_dchi_a, tau1=mod_tau1_a, tau2=mod_tau2_a) Problem3 = VRM.Problem_Linear(meshObj_OcTree, ref_factor=0) Problem4 = VRM.Problem_LogUniform(meshObj_OcTree, ref_factor=0, chi0=mod_chi0_b, dchi=mod_dchi_b, tau1=mod_tau1_b, tau2=mod_tau2_b) Problem1.pair(Survey1) Problem2.pair(Survey2) Problem3.pair(Survey3) Problem4.pair(Survey4) Fields1 = Problem1.fields(mod_a) Fields2 = Problem2.fields() Fields3 = Problem3.fields(mod_b) Fields4 = Problem4.fields() dpred1 = Survey1.dpred(mod_a) dpred2 = Survey2.dpred(mod_a) Err1 = np.abs((Fields1 - Fields2) / Fields1) Err2 = np.abs((Fields2 - Fields3) / Fields2) Err3 = np.abs((Fields3 - Fields4) / Fields3) Err4 = np.abs((Fields4 - Fields1) / Fields4) Err5 = np.abs((dpred1 - dpred2) / dpred1) Test1 = Err1 < 0.01 Test2 = Err2 < 0.01 Test3 = Err3 < 0.01 Test4 = Err4 < 0.01 Test5 = Err5 < 0.01 self.assertTrue(Test1 and Test2 and Test3 and Test4 and Test5)
def setUp(self): # We will assume a vertical inducing field H0 = (50000., 90., 0.) # The magnetization is set along a different direction (induced + remanence) M = np.array([90., 0.]) # Block with an effective susceptibility chi_e = 0.05 # Create grid of points for topography # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(np.linspace(-200, 200, 50), np.linspace(-200, 200, 50)) b = 100 A = 50 zz = A * np.exp(-0.5 * ((xx / b)**2. + (yy / b)**2.)) topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)] # Create and array of observation points xr = np.linspace(-100., 100., 20) yr = np.linspace(-100., 100., 20) X, Y = np.meshgrid(xr, yr) Z = A * np.exp(-0.5 * ((X / b)**2. + (Y / b)**2.)) + 5 # Create a MAGsurvey rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)] Rx = PF.BaseMag.RxObs(rxLoc) srcField = PF.BaseMag.SrcField([Rx], param=H0) survey = PF.BaseMag.LinearSurvey(srcField) # Create a mesh h = [5, 5, 5] padDist = np.ones((3, 2)) * 100 nCpad = [4, 4, 2] # Get extent of points limx = np.r_[topo[:, 0].max(), topo[:, 0].min()] limy = np.r_[topo[:, 1].max(), topo[:, 1].min()] limz = np.r_[topo[:, 2].max(), topo[:, 2].min()] # Get center of the mesh midX = np.mean(limx) midY = np.mean(limy) midZ = np.mean(limz) nCx = int(limx[0] - limx[1]) / h[0] nCy = int(limy[0] - limy[1]) / h[1] nCz = int(limz[0] - limz[1] + int(np.min(np.r_[nCx, nCy]) / 3)) / h[2] # Figure out full extent required from input extent = np.max(np.r_[nCx * h[0] + padDist[0, :].sum(), nCy * h[1] + padDist[1, :].sum(), nCz * h[2] + padDist[2, :].sum()]) maxLevel = int(np.log2(extent / h[0])) + 1 # Number of cells at the small octree level # For now equal in 3D nCx, nCy, nCz = 2**(maxLevel), 2**(maxLevel), 2**(maxLevel) # Define the mesh and origin mesh = Mesh.TreeMesh( [np.ones(nCx) * h[0], np.ones(nCx) * h[1], np.ones(nCx) * h[2]]) # Set origin mesh.x0 = np.r_[-nCx * h[0] / 2. + midX, -nCy * h[1] / 2. + midY, -nCz * h[2] / 2. + midZ] # Refine the mesh around topography # 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()) # Convert the inclination declination to vector in Cartesian M_xyz = Utils.matutils.dip_azimuth2cartesian( np.ones(nC) * M[0], np.ones(nC) * M[1]) # Get the indicies of the magnetized block ind = Utils.ModelBuilder.getIndicesBlock( np.r_[-20, -20, -10], np.r_[20, 20, 25], mesh.gridCC, )[0] # Assign magnetization value, inducing field strength will # be applied in by the :class:`SimPEG.PF.Magnetics` problem model = np.zeros(mesh.nC) model[ind] = chi_e # Remove air cells self.model = model[actv] # Create active map to go from reduce set to full self.actvPlot = Maps.InjectActiveCells(mesh, actv, np.nan) # Creat reduced identity map idenMap = Maps.IdentityMap(nP=nC) # Create the forward model operator prob = PF.Magnetics.MagneticIntegral(mesh, M=M_xyz, chiMap=idenMap, actInd=actv) # Pair the survey and problem survey.pair(prob) # Compute some data and add some random noise data = prob.fields(self.model) # Split the data in components nD = rxLoc.shape[0] std = 5 # nT data += np.random.randn(nD) * std wd = np.ones(nD) * std # Assigne data and uncertainties to the survey survey.dobs = data survey.std = wd ###################################################################### # Equivalent Source # Get the active cells for equivalent source is the top only surf = Utils.modelutils.surface_layer_index(mesh, topo) # Get the layer of cells directyl below topo nC = np.count_nonzero(surf) # Number of active cells # Create active map to go from reduce set to full surfMap = Maps.InjectActiveCells(mesh, surf, np.nan) # Create identity map idenMap = Maps.IdentityMap(nP=nC) # Create static map prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap, actInd=surf, parallelized=False, equiSourceLayer=True) prob.solverOpts['accuracyTol'] = 1e-4 # Pair the survey and problem if survey.ispaired: survey.unpair() survey.pair(prob) # Create a regularization function, in this case l2l2 reg = Regularization.Sparse(mesh, indActive=surf, mapping=Maps.IdentityMap(nP=nC), scaledIRLS=False) reg.mref = np.zeros(nC) # Specify how the optimization will proceed, # set susceptibility bounds to inf opt = Optimization.ProjectedGNCG(maxIter=20, lower=-np.inf, upper=np.inf, maxIterLS=20, maxIterCG=20, tolCG=1e-3) # Define misfit function (obs-calc) dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1. / survey.std # Create the default L2 inverse problem from the above objects invProb = InvProblem.BaseInvProblem(dmis, reg, opt) # Specify how the initial beta is found betaest = Directives.BetaEstimate_ByEig() # Target misfit to stop the inversion, # try to fit as much as possible of the signal, # we don't want to lose anything IRLS = Directives.Update_IRLS(f_min_change=1e-3, minGNiter=1, beta_tol=1e-1) update_Jacobi = Directives.UpdatePreconditioner() # Put all the parts together inv = Inversion.BaseInversion( invProb, directiveList=[betaest, IRLS, update_Jacobi]) # Run the equivalent source inversion mstart = np.ones(nC) * 1e-4 mrec = inv.run(mstart) # Won't store the sensitivity and output 'xyz' data. prob.forwardOnly = True prob.rx_type = 'xyz' prob._G = None prob.modelType = 'amplitude' prob.model = mrec pred = prob.fields(mrec) bx = pred[:nD] by = pred[nD:2 * nD] bz = pred[2 * nD:] bAmp = (bx**2. + by**2. + bz**2.)**0.5 # AMPLITUDE INVERSION # Create active map to go from reduce space to full actvMap = Maps.InjectActiveCells(mesh, actv, -100) nC = int(actv.sum()) # Create identity map idenMap = Maps.IdentityMap(nP=nC) self.mstart = np.ones(nC) * 1e-4 # Create the forward model operator prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap, actInd=actv, modelType='amplitude', rx_type='xyz') prob.model = self.mstart # Change the survey to xyz components surveyAmp = PF.BaseMag.LinearSurvey(survey.srcField) # Pair the survey and problem surveyAmp.pair(prob) # Create a regularization function, in this case l2l2 wr = np.sum(prob.G**2., axis=0)**0.5 wr = (wr / np.max(wr)) # Re-set the observations to |B| surveyAmp.dobs = bAmp surveyAmp.std = wd # Create a sparse regularization reg = Regularization.Sparse(mesh, indActive=actv, mapping=idenMap) reg.norms = np.c_[0, 0, 0, 0] reg.mref = np.zeros(nC) reg.cell_weights = wr # Data misfit function dmis = DataMisfit.l2_DataMisfit(surveyAmp) dmis.W = 1. / surveyAmp.std # Add directives to the inversion opt = Optimization.ProjectedGNCG(maxIter=30, lower=0., upper=1., maxIterLS=20, maxIterCG=20, tolCG=1e-3) invProb = InvProblem.BaseInvProblem(dmis, reg, opt) # Here is the list of directives betaest = Directives.BetaEstimate_ByEig() # Specify the sparse norms IRLS = Directives.Update_IRLS(f_min_change=1e-3, minGNiter=1, coolingRate=1, betaSearch=False) # The sensitivity weights are update between each iteration. update_SensWeight = Directives.UpdateSensitivityWeights() update_Jacobi = Directives.UpdatePreconditioner(threshold=1 - 3) # Put all together self.inv = Inversion.BaseInversion( invProb, directiveList=[betaest, IRLS, update_SensWeight, update_Jacobi]) self.mesh = mesh
def run(plotIt=True): nFreq = 13 freqs = np.logspace(2, -2, nFreq) # x and y grid parameters dh = 10 # minimum cell width (base mesh cell width) dhx = dh dhy = dh dhz = 1.5 #Dimensao eixo vertical( base 2) nbcx = 2**12 # number of base mesh cells in x nbcy = 2**12 nbcz = 2**15 # Define base mesh (domain and finest discretization) hx = dhx * np.ones(nbcx) hy = dhy * np.ones(nbcy) hz = dhz * np.ones(nbcz) M = Mesh.TreeMesh([hx, hy, hz]) #M.x0 = np.r_[-(nbcx*dhx)/2,-(nbcy*dhy)/2,-(nbcz*dhz)/2] M.x0 = np.r_[-(nbcx * dhx) / 2, -(nbcy * dhy) / 2, -nbcz * dhz + 15000] hz = [0] # definir fronteira das camadas n_camadas = len(hz) #========================================= #Criando mais uma área(layer) de dricretização #========================================= for i in range(0, n_camadas, 1): xp, yp, zp = np.meshgrid([-(nbcx * dhx) / 1, (nbcx * dhx) / 1], [-(nbcy * dhy) / 1, (nbcy * dhy) / 1], [hz[i] - 1, hz[i] + 1]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] # mkvc creates vectors M = refine_tree_xyz(M, xyz, octree_levels=[0, 0, 1], method='radial', finalize=False) #========================================= #Criando um objeto(target) #========================================= xp, yp, zp = np.meshgrid([-(nbcx * dhx) / 32, (nbcx * dhx) / 32], [-(nbcy * dhy) / 32, (nbcy * dhy) / 32], [-150, -350]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] #refino M = refine_tree_xyz(M, xyz, octree_levels=[1, 1, 1], method='box', finalize=False) # M.finalize() print("\n the mesh has {} cells".format(M)) ccMesh = M.gridCC print('indices:', np.size(ccMesh)) ## ## ## ## conds = [1e-2, 1] sig = simpeg.Utils.ModelBuilder.defineBlock(M.gridCC, [-20000, -20000, -350], [20000, 20000, -150], conds) sig[M.gridCC[:, 2] > 0] = 1e-8 sigBG = np.zeros(M.nC) + conds[1] sigBG[M.gridCC[:, 2] > 0] = 1e-8 # # A boolean array specifying which cells lie on the boundary bInd = M.cellBoundaryInd ## Cell volumes v = M.vol fig = plt.figure() ax = fig.add_subplot(111) collect_obj, = M.plotSlice(np.log10(sig), normal='x', ax=ax, grid=True) plt.colorbar(collect_obj) ax.set_title('slice')