def generate_forward_data(): """Generate synthetic forward data that we then invert""" scheme = get_scheme() mesh = get_fwd_mesh() rhomap = [ [1, pg.utils.complex.toComplex(100, 0 / 1000)], # Magnitude: 50 ohm m, Phase: -50 mrad [2, pg.utils.complex.toComplex(50, 0 / 1000)], [3, pg.utils.complex.toComplex(100, -50 / 1000)], ] rho = pg.solver.parseArgToArray(rhomap, mesh.cellCount(), mesh) fig, axes = plt.subplots(2, 1, figsize=(16 / 2.54, 16 / 2.54)) pg.show( mesh, data=np.log(np.abs(rho)), ax=axes[0], label=r"$log_{10}(|\rho|~[\Omega m])$" ) pg.show(mesh, data=np.abs(rho), ax=axes[1], label=r"$|\rho|~[\Omega m]$") pg.show( mesh, data=np.arctan2(np.imag(rho), np.real(rho)) * 1000, ax=axes[1], label=r"$\phi$ [mrad]", cMap='jet_r' ) data = ert.simulate( mesh, res=rhomap, scheme=scheme, # noiseAbs=0.0, # noiseLevel=0.0, ) r_complex = data['rhoa'].array() * np.exp(1j * data['phia'].array()) # Please note the apparent negative (resistivity) phases! fig, axes = plt.subplots(2, 2, figsize=(16 / 2.54, 16 / 2.54)) ert.showERTData(data, vals=data['rhoa'], ax=axes[0, 0]) # phia is stored in radians, but usually plotted in milliradians ert.showERTData( data, vals=data['phia'] * 1000, label=r'$\phi$ [mrad]', ax=axes[0, 1]) ert.showERTData( data, vals=np.real(r_complex), ax=axes[1, 0], label=r"$Z'$~[$\Omega$m" ) ert.showERTData( data, vals=np.imag(r_complex), ax=axes[1, 1], label=r"$Z''$~[$\Omega$]" ) fig.tight_layout() fig.show() return r_complex
def calculate_current_flow(self, time=False, verbose=False): """ Perform the simulation based on the mesh, data and scheme Returns: RMatrix and RVector """ if time: pg.tic() self.sim = ert.simulate(self.mesh, res=self.data, scheme=self.scheme, sr=False, calcOnly=True, verbose=verbose, returnFields=True) if time: pg.toc("Current flow", box=True) self.pot = pg.utils.logDropTol(self.sim[0] - self.sim[1], 10) return self.sim, self.pot
def runSim(mesh, scheme, rhomap, outfile): data = ert.simulate(mesh, scheme=scheme, res=rhomap, noiseLevel=1, noiseAbs=1e-6, seed=1337, calcOnly=True) data.set('r', data('u') / data('i')) data.set('rhoa', data('k') * data('u') / data('i')) # pg.info('Simulated data', data) # pg.info('The data contains:', data.dataMap().keys()) # pg.info('Simulated rhoa (min/max)', min(data['rhoa']), max(data['rhoa'])) # pg.info('Selected data noise %(min/max)', min(data['err'])*100, max(data['err'])*100) if outfile is not None: data.save(outfile) return data
pg.show(plc, markers=True) pg.show(mesh) ############################################################################### # Prepare the model parameterization # We have two markers here: 1: background 2: circle anomaly # Parameters must be specified as a complex number, here converted by the # utility function :func:`pygimli.utils.complex.toComplex`. rhomap = [ [1, pg.utils.complex.toComplex(100, 0 / 1000)], # Magnitude: 50 ohm m, Phase: -50 mrad [2, pg.utils.complex.toComplex(50, 0 / 1000)], [3, pg.utils.complex.toComplex(100, -50 / 1000)], ] ############################################################################### # Do the actual forward modeling data = ert.simulate( mesh, res=rhomap, scheme=scheme, # noiseAbs=0.0, # noiseLevel=0.0, ) ############################################################################### # Visualize the modeled data # Convert magnitude and phase into a complex apparent resistivity rho_a_complex = data['rhoa'].array() * np.exp(1j * data['phia'].array()) np.savetxt('data_rre_rim.dat', np.hstack((rho_a_complex.real, rho_a_complex.imag)))
# Take a look at the mesh and the resistivity distribution pg.show(mesh, data=rhomap, label=pg.unit('res'), showMesh=True) # %% ############################################################################### # Perform the modeling with the mesh and the measuring scheme itself # and return a data container with apparent resistivity values, # geometric factors and estimated data errors specified by the noise setting. # The noise is also added to the data. Here 1% plus 1µV. # Note, we force a specific noise seed as we want reproducable results for # testing purposes. data = ert.simulate(mesh, scheme=scheme, res=rhomap, noiseLevel=1, noiseAbs=1e-6, seed=1337) pg.info('Simulated data', data) pg.info('The data contains:', data.dataMap().keys()) pg.info('Simulated rhoa (min/max)', min(data['rhoa']), max(data['rhoa'])) pg.info('Selected data noise %(min/max)', min(data['err']) * 100, max(data['err']) * 100) ############################################################################### # Optional: you can filter all values and tokens in the data container. # Its possible that there are some negative data values due to noise and # huge geometric factors. So we need to remove them.
# first two measurements have reversed geometric factor! scheme.set('a', [0, 0, 3]) scheme.set('b', [1, 1, 2]) scheme.set('m', [3, 2, 1]) scheme.set('n', [2, 3, 0]) for pos in scheme.sensorPositions(): world.createNode(pos) # world.createNode(pos + pg.RVector3(0, -0.1)) mesh = mt.createMesh(world, quality=34) rhomap = [[1, 99.595 + 8.987j], [2, 99.595 + 8.987j], [3, 59.595 + 8.987j]] # mgr = pg.physics.ERTManager() # not necessary anymore data = ert.simulate(mesh, res=rhomap, scheme=scheme, verbose=True) rhoa = data.get('rhoa').array() phia = data.get('phia').array() # make sure all computed responses are equal, especially the first two, which # only differ in the sign of their geometrical factor np.testing.assert_allclose(rhoa, rhoa[0]) np.testing.assert_allclose(phia, phia[0]) # make sure the phases are positive (for positive input) assert np.all(phia > 0) # make sure rhoa is also positive assert np.all(rhoa > 0)
# You usually want to keep full control about this calculation because you want # the accuracy as high as possible by providing a special mesh with # higher quality, lower max cell area, finer local mesh refinement, # or quadratic base functions (p2). # # We don't want the automatic k generation here because we want also to # demonstrate how you can solve this task yourself. # The argument 'calcOnly=True' omits the check for valid k factors # and will add the simulated voltages (u) in the returned DataContainerERT. # The simulation current (i) is 1 A by default. In addition, the flag # 'sr=False' omits the singularity removal technique (default) which not # applicable in absence of (analytic) primary potential. hom = ert.simulate(mesh, res=1.0, scheme=shm, sr=False, calcOnly=True, verbose=True) hom.save('homogeneous.ohm', 'a b m n u') ############################################################################### # We now create an inhomogeneity (cube) and merge it with the above PLC. # marker=2 ensures all cells of the cube being associated with a cell marker 2. cube = mt.createCube(size=[0.3, 0.2, 0.8], pos=[0.7, 0.2], marker=2) plc += cube mesh = mt.createMesh(plc) print(mesh)
mesh = mt.createMesh(plc, quality=33) pg.show(mesh, data=mesh.cellMarkers(), label='Marker', showMesh=True) ############################################################################### # It is usually a good idea to calculate with a p2-refined mesh. # However, you should be careful for larger meshes since the numerical efford # will be highly increased. mesh = mesh.createP2() ############################################################################### # Perform the modeling using the static convenience call for ERT. # Res is the resistivity mapping regarding the regions of the given geometry. # Region with marker 1 is the upper layer, maker 2 is the background data = ert.simulate(mesh, res=[[1, 100.0], [2, 1.0]], scheme=scheme, verbose=False) ############################################################################### # 1D VES x = pg.x(scheme) ab2 = (x[scheme('b')] - x[scheme('a')]) / 2 mn2 = (x[scheme('n')] - x[scheme('m')]) / 2 ves = VESModelling(ab2=ab2, mn2=mn2) ############################################################################### # Plot results fig, ax = pg.plt.subplots(1, 1) ax.plot(ab2, data('rhoa'), '-o', label='2D (FEM)') ax.plot(ab2, ves.response([10.0, 100.0, 1.0]), '-x', label='1D (VES)') ax.set_xlabel('AB/2 (m)')