def test_sum(self): M2 = Mesh.TensorMesh([np.ones(10), np.ones(20)], "CC") block = ( Maps.ParametricEllipsoid(M2) * Maps.Projection(7, np.r_[1, 2, 3, 4, 5, 6]) ) background = ( Maps.ExpMap(M2) * Maps.SurjectFull(M2) * Maps.Projection(7, np.r_[0]) ) summap0 = Maps.SumMap([block, background]) summap1 = block + background m0 = np.hstack([ np.random.rand(3), np.r_[M2.x0[0], 2*M2.hx.min()], np.r_[M2.x0[1], 4*M2.hy.min()] ]) self.assertTrue( np.all(summap0 * m0 == summap1 * m0) ) self.assertTrue(summap0.test(m0)) self.assertTrue(summap1.test(m0))
for unit in geoUnits: # if unit!=0: index += [mgeo==unit] nC = len(index) # Create active map to go from reduce set to full actvMap = Maps.InjectActiveCells(mesh, actv, -100) # Creat reduced identity map homogMap = Maps.SurjectUnits(index) # Create a wire map for a second model space wires = Maps.Wires(('h**o', nC), ('hetero', len(actv))) # Create Sum map sumMap = Maps.SumMap([homogMap*wires.h**o, wires.hetero]) #%% Run inversion prob = PF.Gravity.GravityIntegral(mesh, rhoMap=sumMap, actInd=actv) survey.pair(prob) #%% # Load weighting file dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1./survey.std wr = prob.getJtJdiag(np.ones(int(nC + len(actv))), W=dmis.W) wr[wires.h**o.index] /= (np.max((wires.h**o*wr)))
def createLocalProb(rxLoc, wrGlobal, lims, tileID): # Grab the data for current tile ind_t = np.all([rxLoc[:, 0] >= lims[0], rxLoc[:, 0] <= lims[1], rxLoc[:, 1] >= lims[2], rxLoc[:, 1] <= lims[3], surveyMask], axis=0) # Remember selected data in case of tile overlap surveyMask[ind_t] = False # Create new survey rxLoc_t = PF.BaseGrav.RxObs(rxLoc[ind_t, :]) srcField = PF.BaseGrav.SrcField([rxLoc_t]) survey_t = PF.BaseGrav.LinearSurvey(srcField) survey_t.dobs = survey.dobs[ind_t] survey_t.std = survey.std[ind_t] survey_t.ind = ind_t meshLocal = Utils.modelutils.meshBuilder( rxLoc, h, padDist, meshType='TREE', meshGlobal=meshInput, verticalAlignment='center' ) if topo is not None: meshLocal = Utils.modelutils.refineTree( meshLocal, topo, dtype='surface', nCpad=octreeTopo, finalize=False ) # Refine the mesh around loc meshLocal = Utils.modelutils.refineTree( meshLocal, rxLoc[ind_t, :], dtype='surface', nCpad=octreeObs, finalize=True ) actv_t = np.ones(meshLocal.nC, dtype='bool') Mesh.TreeMesh.writeUBC( meshLocal, out_dir + 'OctreeMesh' + str(tt) + '.msh', models={ out_dir + 'Active' + str(tileID) + '.act': actv_t } ) # Create reduced identity map tileMap = Maps.Tile((mesh, actv), (meshLocal, actv_t)) actv_t = tileMap.activeLocal # Interpolate the geo model _, ind = tree.query(meshLocal.gridCC) mgeo_t = ((fullMap * mgeo)[ind])[actv_t] # Build list of indecies for the geounits index = [] for unit in geoUnits: index += [mgeo_t == unit] # Creat reduced identity map homogMap_t = Maps.SurjectUnits(index) # Create Sum map sumMap = Maps.SumMap([homogMap_t*wires.h**o, tileMap*wires.hetero]) # Create the forward model operator prob = PF.Gravity.GravityIntegral( meshLocal, rhoMap=sumMap, actInd=actv_t, parallelized=parallization, Jpath=out_dir + "Tile" + str(tileID) + ".zarr", n_cpu=n_cpu ) survey_t.pair(prob) # Data misfit function dmis = DataMisfit.l2_DataMisfit(survey_t) dmis.W = 1./survey_t.std wrGlobal += prob.getJtJdiag(np.ones(wires.h**o.shape[1]), W=dmis.W) del meshLocal # Create combo misfit function return dmis, wrGlobal
def createLocalProb(rxLoc, wrGlobal, lims, ind): # createLocalProb(rxLoc, wrGlobal, lims, ind) # Generate a problem, calculate/store sensitivities for # given data points # Grab the data for current tile ind_t = np.all([ rxLoc[:, 0] >= lims[0], rxLoc[:, 0] <= lims[1], rxLoc[:, 1] >= lims[2], rxLoc[:, 1] <= lims[3], surveyMask ], axis=0) # Remember selected data in case of tile overlap surveyMask[ind_t] = False # Create new survey rxLoc_t = PF.BaseMag.RxObs(rxLoc[ind_t, :]) srcField = PF.BaseMag.SrcField([rxLoc_t], param=survey.srcField.param) survey_t = PF.BaseMag.LinearSurvey(srcField) survey_t.dobs = survey.dobs[ind_t] survey_t.std = survey.std[ind_t] survey_t.ind = ind_t Utils.io_utils.writeUBCmagneticsObservations( out_dir + 'Tile' + str(tt) + 'dat', survey_t, survey_t.dobs) meshLocal = Utils.modelutils.meshBuilder(newTopo, h, padDist, meshType='TREE', meshGlobal=meshInput, verticalAlignment='center') if topo is not None: meshLocal = Utils.modelutils.refineTree(meshLocal, topo, dtype='surface', octreeLevels=octreeTopo, finalize=False) # Refine the mesh around loc meshLocal = Utils.modelutils.refineTree( meshLocal, newTopo[ind_t, :], dtype='surface', octreeLevels=octreeObs, octreeLevels_XY=octreeObs_XY, finalize=True, ) actv_t = np.ones(meshLocal.nC, dtype='bool') # Create reduced identity map tileMap = Maps.Tile((mesh, actv), (meshLocal, actv_t), nBlock=3) actv_t = tileMap.activeLocal if homogenizeMref: # Interpolate the geo model _, ind = tree.query(meshLocal.gridCC) mgeo_t = ((actvMap * mref)[ind])[actv_t] # Build list of indecies for the geounits index = [] for unit in geoUnits: index += [mgeo_t == unit] # Creat reduced identity map homogMap_t = Maps.SurjectUnits(index) homogMap.nBlock = 3 if modelDecomposition: # Create Sum map mapping = Maps.SumMap( [homogMap_t * wires.h**o, tileMap * wires.hetero]) else: mapping = homogMap_t * wires.h**o else: mapping = tileMap # Create the forward model operator prob = PF.Magnetics.MagneticIntegral(meshLocal, chiMap=mapping, actInd=actv_t, parallelized=parallelized, Jpath=out_dir + "Tile" + str(ind) + ".zarr", maxRAM=maxRAM, modelType='vector', n_cpu=np.ceil(n_cpu / nTiles)) survey_t.pair(prob) # Data misfit function dmis = DataMisfit.l2_DataMisfit(survey_t) dmis.W = 1. / survey_t.std wr = prob.getJtJdiag(np.ones(int(mapping.shape[1])), W=dmis.W) actvMap_t = Maps.InjectActiveCells(meshLocal, actv_t, 1e-8) nC_t = int(actv_t.sum()) Mesh.TreeMesh.writeUBC( meshLocal, out_dir + 'OctreeMesh' + str(tt) + '.msh', models={ out_dir + 'Wr_' + str(tt) + '.act': actvMap_t * np.sum( (tileMap * wr).reshape(nC_t, 3, order='F')**2., axis=1)** 0.5 }) wrGlobal += wr del meshLocal # Create combo misfit function return dmis, wrGlobal
def run(plotIt=True): H0 = (50000., 90., 0.) # Create a mesh dx = 5. hxind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hyind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hzind = [(dx, 5, -1.3), (dx, 10)] mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCC') # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy) zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1] # We would usually load a topofile topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)] # Go from topo to array of indices of active cells actv = Utils.surface2ind_topo(mesh, topo, 'N') actv = np.where(actv)[0] # Create and array of observation points xr = np.linspace(-20., 20., 20) yr = np.linspace(-20., 20., 20) X, Y = np.meshgrid(xr, yr) # Move the observation points 5m above the topo Z = -np.exp((X**2 + Y**2) / 75**2) + mesh.vectorNz[-1] + 5. # Create a MAGsurvey rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)] rxLoc = PF.BaseMag.RxObs(rxLoc) srcField = PF.BaseMag.SrcField([rxLoc], param=H0) survey = PF.BaseMag.LinearSurvey(srcField) # We can now create a susceptibility model and generate data model = np.zeros(mesh.nC) # Change values in half the domain model[mesh.gridCC[:, 0] < 0] = 0.01 # Add a block in half-space model = Utils.ModelBuilder.addBlock(mesh.gridCC, model, np.r_[-10, -10, 20], np.r_[10, 10, 40], 0.05) model = Utils.mkvc(model) model = model[actv] # Create active map to go from reduce set to full actvMap = Maps.InjectActiveCells(mesh, actv, np.nan) # Create reduced identity map idenMap = Maps.IdentityMap(nP=len(actv)) # Create the forward model operator prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap, actInd=actv) # Pair the survey and problem survey.pair(prob) # Compute linear forward operator and compute some data d = prob.fields(model) # Add noise and uncertainties # We add some random Gaussian noise (1nT) data = d + np.random.randn(len(d)) wd = np.ones(len(data)) * 1. # Assign flat uncertainties survey.dobs = data survey.std = wd survey.mtrue = model # Plot the data rxLoc = survey.srcField.rxList[0].locs # Create a homogenous maps for the two domains domains = [mesh.gridCC[actv, 0] < 0, mesh.gridCC[actv, 0] >= 0] homogMap = Maps.SurjectUnits(domains) # Create a wire map for a second model space, voxel based wires = Maps.Wires(('h**o', len(domains)), ('hetero', len(actv))) # Create Sum map sumMap = Maps.SumMap([homogMap * wires.h**o, wires.hetero]) # Create the forward model operator prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=sumMap, actInd=actv) # Pair the survey and problem survey.unpair() survey.pair(prob) # Make depth weighting wr = np.zeros(sumMap.shape[1]) # Take the cell number out of the scaling. # Want to keep high sens for large volumes scale = Utils.sdiag(np.r_[Utils.mkvc(1. / homogMap.P.sum(axis=0)), np.ones_like(actv)]) for ii in range(survey.nD): wr += ((prob.G[ii, :] * prob.chiMap.deriv(np.ones(sumMap.shape[1]) * 1e-4) * scale) / survey.std[ii])**2. # Scale the model spaces independently wr[wires.h**o.index] /= (np.max((wires.h**o * wr))) wr[wires.hetero.index] /= (np.max(wires.hetero * wr)) wr = wr**0.5 ## Create a regularization # For the homogeneous model regMesh = Mesh.TensorMesh([len(domains)]) reg_m1 = Regularization.Sparse(regMesh, mapping=wires.h**o) reg_m1.cell_weights = wires.h**o * wr reg_m1.norms = np.c_[0, 2, 2, 2] reg_m1.mref = np.zeros(sumMap.shape[1]) # Regularization for the voxel model reg_m2 = Regularization.Sparse(mesh, indActive=actv, mapping=wires.hetero) reg_m2.cell_weights = wires.hetero * wr reg_m2.norms = np.c_[0, 1, 1, 1] reg_m2.mref = np.zeros(sumMap.shape[1]) reg = reg_m1 + reg_m2 # Data misfit function dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1 / wd # Add directives to the inversion opt = Optimization.ProjectedGNCG(maxIter=100, lower=0., upper=1., maxIterLS=20, maxIterCG=10, tolCG=1e-3, tolG=1e-3, eps=1e-6) invProb = InvProblem.BaseInvProblem(dmis, reg, opt) betaest = Directives.BetaEstimate_ByEig() # Here is where the norms are applied # Use pick a threshold parameter empirically based on the distribution of # model parameters IRLS = Directives.Update_IRLS(f_min_change=1e-3, minGNiter=1) update_Jacobi = Directives.UpdatePreconditioner() inv = Inversion.BaseInversion(invProb, directiveList=[IRLS, betaest, update_Jacobi]) # Run the inversion m0 = np.ones(sumMap.shape[1]) * 1e-4 # Starting model prob.model = m0 mrecSum = inv.run(m0) if plotIt: mesh.plot_3d_slicer(actvMap * model, aspect="equal", zslice=30, pcolorOpts={"cmap": 'inferno_r'}, transparent='slider') mesh.plot_3d_slicer(actvMap * sumMap * mrecSum, aspect="equal", zslice=30, pcolorOpts={"cmap": 'inferno_r'}, transparent='slider')