def test_errors(self): mesh = emg3d.TensorMesh([[2, 2], [2, 2], [2, 2]], origin=(-1, -1, -1)) survey = emg3d.Survey( sources=emg3d.TxElectricDipole((-1.5, 0, 0, 0, 0)), receivers=emg3d.RxElectricPoint((1.5, 0, 0, 0, 0)), frequencies=1.0, relative_error=0.01, ) sim_inp = { 'survey': survey, 'gridding': 'same', 'receiver_interpolation': 'linear' } # Anisotropic models. simulation = simulations.Simulation(model=emg3d.Model(mesh, 1, 2, 3), **sim_inp) with pytest.raises(NotImplementedError, match='for isotropic models'): simulation.gradient # Model with electric permittivity. simulation = simulations.Simulation(model=emg3d.Model(mesh, epsilon_r=3), **sim_inp) with pytest.raises(NotImplementedError, match='for el. permittivity'): simulation.gradient # Model with magnetic permeability. simulation = simulations.Simulation(model=emg3d.Model( mesh, mu_r=np.ones(mesh.shape_cells) * np.pi), **sim_inp) with pytest.raises(NotImplementedError, match='for magn. permeabili'): simulation.gradient
def test__solve(): # Has keys [model, sfield, efield, solver_opts] dat = REGRES['res'] inp = { 'model': emg3d.Model(**dat['input_model']), 'sfield': emg3d.get_source_field(**dat['input_source']), 'efield': None, 'solver_opts': { 'plain': True } } efield, info = solver._solve(inp) assert_allclose(dat['Fresult'].field, efield.field) # Has keys [model, grid, source, frequency, efield, solver_opts] dat = REGRES['res'] model = model = emg3d.Model(**dat['input_model']) inp = { 'model': model, 'grid': model.grid, 'source': dat['input_source']['source'], 'frequency': dat['input_source']['frequency'], 'efield': None, 'solver_opts': { 'plain': True } } efield, info = solver._solve(inp) assert_allclose(dat['Fresult'].field, efield.field)
def test_get_magnetic_field(): # Check it does still the same (pure regression). dat = REGRES['reg_2'] model = dat['model'] efield = dat['result'] hfield = dat['hresult'] hout = fields.get_magnetic_field(model, efield) assert_allclose(hfield.field, hout.field) # Add some mu_r - Just 1, to trigger, and compare. dat = REGRES['res'] efield = dat['Fresult'] model1 = emg3d.Model(**dat['input_model']) model2 = emg3d.Model(**dat['input_model'], mu_r=1.) hout1 = fields.get_magnetic_field(model1, efield) hout2 = fields.get_magnetic_field(model2, efield) assert_allclose(hout1.field, hout2.field) # Test division by mu_r. model3 = emg3d.Model(**dat['input_model'], mu_r=2.) hout3 = fields.get_magnetic_field(model3, efield) assert_allclose(hout1.field, hout3.field * 2) # Comparison to alternative. # Using very unrealistic value, unrealistic stretching, to test. grid = emg3d.TensorMesh(h=[[1, 100, 25, 33], [1, 1, 33.3, 0.3, 1, 1], [2, 4, 8, 16]], origin=(88, 20, 9)) model = emg3d.Model(grid, mu_r=np.arange(1, grid.n_cells + 1) / 10) new = 10**np.arange(grid.n_edges) - grid.n_edges / 2 efield = fields.Field(grid, data=new, frequency=np.pi) hfield_nb = fields.get_magnetic_field(model, efield) hfield_np = alternatives.alt_get_magnetic_field(model, efield) assert_allclose(hfield_nb.fx, hfield_np.fx) assert_allclose(hfield_nb.fy, hfield_np.fy) assert_allclose(hfield_nb.fz, hfield_np.fz) # Test using discretize if discretize: h = np.ones(4) grid = emg3d.TensorMesh([h * 200, h * 300, h * 400], (0, 0, 0)) model = emg3d.Model(grid, property_x=3.24) sfield = fields.get_source_field(grid, (350, 550, 750, 30, 30), frequency=10) efield = emg3d.solve(model, sfield, plain=True, verb=0) mfield = fields.get_magnetic_field(model, efield).field dfield = grid.edge_curl * efield.field / sfield.smu0 assert_allclose(mfield, dfield)
def test_cycle_gcrotmk(self, capsys): # Load any case. dat = REGRES['res'] model = emg3d.Model(**dat['input_model']) grid = model.grid sfield = emg3d.get_source_field(**dat['input_source']) vmodel = emg3d.models.VolumeModel(model, sfield) efield = emg3d.Field(grid) # Initiate e-field. # Get var-instance var = solver.MGParameters( cycle='F', sslsolver='gcrotmk', semicoarsening=False, linerelaxation=False, shape_cells=grid.shape_cells, verb=4, maxit=5, ) var.l2_refe = sl.norm(sfield.field, check_finite=False) # Call krylov and ensure it fails properly. solver.krylov(vmodel, sfield, efield, var) out, _ = capsys.readouterr() assert 'DIVERGED' in out
def test_bicgstab_error(self, capsys): # Load any case. dat = REGRES['res'] model = emg3d.Model(**dat['input_model']) grid = model.grid model.property_x *= 100000 # Set stupid input to make bicgstab fail. model.property_y /= 100000 # Set stupid input to make bicgstab fail. sfield = emg3d.get_source_field(**dat['input_source']) vmodel = emg3d.models.VolumeModel(model, sfield) efield = emg3d.Field(grid) # Initiate e-field. # Get var-instance var = solver.MGParameters( cycle=None, sslsolver=True, semicoarsening=False, linerelaxation=False, shape_cells=grid.shape_cells, verb=3, maxit=-1, ) var.l2_refe = sl.norm(sfield.field, check_finite=False) # Call krylov and ensure it fails properly. solver.krylov(vmodel, sfield, efield, var) out, _ = capsys.readouterr() assert '* ERROR :: Error in bicgstab' in out
def test_basic(self, capsys): # This should reach every line of solver.multigrid. dat = REGRES['res'] model = emg3d.Model(**dat['input_model']) grid = model.grid sfield = emg3d.get_source_field(**dat['input_source']) vmodel = emg3d.models.VolumeModel(model, sfield) efield = emg3d.Field(grid) # Initiate e-field. # Get var-instance var = solver.MGParameters( cycle='F', sslsolver=False, semicoarsening=True, linerelaxation=True, shape_cells=grid.shape_cells, verb=5, nu_init=2, maxit=-1, ) var.l2_refe = sl.norm(sfield.field, check_finite=False) # Call multigrid. solver.multigrid(vmodel, sfield, efield, var) out, _ = capsys.readouterr() assert '> CONVERGED' in out
def test_laplace(self, ): # Regression test for homogeneous halfspace in Laplace domain. # Not very sophisticated; replace/extend by more detailed tests. dat = REGRES['lap'] model = emg3d.Model(**dat['input_model']) grid = model.grid sfield = emg3d.get_source_field(**dat['input_source']) # F-cycle efield = solver.solve(model, sfield, plain=True) # Check all fields (ex, ey, and ez) assert_allclose(dat['Fresult'].field, efield.field, atol=1e-14) # BiCGSTAB with some print checking. efield = solver.solve(model, sfield, semicoarsening=False, linerelaxation=False) # Check all fields (ex, ey, and ez) assert_allclose(dat['bicresult'].field, efield.field, atol=1e-14) # If efield is complex, assert it fails. efield = emg3d.Field(grid, dtype=np.complex128) with pytest.raises(ValueError, match='Source field and electric fiel'): efield = solver.solve(model, sfield, plain=True, efield=efield)
def test_log(self, capsys): dat = REGRES['res'] model = emg3d.Model(**dat['input_model']) sfield = emg3d.get_source_field(**dat['input_source']) inp = {'model': model, 'sfield': sfield, 'plain': True, 'maxit': 1} efield, info = solver.solve(return_info=True, log=-1, verb=3, **inp) out, _ = capsys.readouterr() assert out == "" assert ' emg3d START ::' in info['log'] efield = solver.solve(return_info=True, log=0, verb=3, **inp) out, _ = capsys.readouterr() assert ' emg3d START ::' in out efield, info = solver.solve(return_info=True, log=1, verb=3, **inp) out, _ = capsys.readouterr() assert ' emg3d START ::' in out assert ' emg3d START ::' in info['log'] efield, info = solver.solve(return_info=True, log=1, verb=1, **inp) out, _ = capsys.readouterr() assert 'MAX. ITERATION REACHED, NOT CONVERGED' in out assert 'MAX. ITERATION REACHED, NOT CONVERGED' in info['log']
def test_2d_arrays(self): hx = [1, 1, 1, 2, 4, 8] grid = emg3d.TensorMesh([hx, hx, hx], (0, 0, 0)) field = emg3d.Field(grid) field.fx = np.arange(1, field.fx.size+1).reshape( field.fx.shape, order='F') model = emg3d.Model(grid, 1, 2, 3) model.property_x[1, :, :] = 2 model.property_x[2, :, :] = 3 model.property_x[3, :, :] = 4 model.property_x[4, :, :] = np.arange(1, 37).reshape((6, 6), order='F') model.property_x[5, :, :] = 200 xi = (np.ones((3, 2)), 5, np.ones((3, 2))) # == NEAREST == # property - points _ = maps.interpolate(grid, model.property_x, xi, method='nearest') # field - points _ = maps.interpolate(grid, field.fx, xi, method='nearest') # == LINEAR == # property - points _ = maps.interpolate(grid, model.property_x, xi, method='linear') # field - points _ = maps.interpolate(grid, field.fx, xi, method='linear') # == CUBIC == # property - points _ = maps.interpolate(grid, model.property_x, xi, method='cubic') # field - points _ = maps.interpolate(grid, field.fx, xi, method='cubic')
def test_all_run(self): hx = [1, 1, 1, 2, 4, 8] grid = emg3d.TensorMesh([hx, hx, hx], (0, 0, 0)) grid2 = emg3d.TensorMesh([[2, 4, 5], [1, 1], [4, 5]], (0, 1, 0)) field = emg3d.Field(grid) field.fx = np.arange(1, field.fx.size+1).reshape( field.fx.shape, order='F') model = emg3d.Model(grid, 1, 2, 3) model.property_x[1, :, :] = 2 model.property_x[2, :, :] = 3 model.property_x[3, :, :] = 4 model.property_x[4, :, :] = np.arange(1, 37).reshape((6, 6), order='F') model.property_x[5, :, :] = 200 xi = (1, [8, 7, 6, 8, 9], [1]) # == NEAREST == # property - grid _ = maps.interpolate(grid, model.property_x, grid2, method='nearest') # field - grid _ = maps.interpolate(grid, field.fx, grid2, method='nearest') # property - points _ = maps.interpolate(grid, model.property_x, xi, method='nearest') # field - points _ = maps.interpolate(grid, field.fx, xi, method='nearest') # == LINEAR == # property - grid _ = maps.interpolate(grid, model.property_x, grid2, method='linear') # field - grid _ = maps.interpolate(grid, field.fx, grid2, method='linear') # property - points _ = maps.interpolate(grid, model.property_x, xi, method='linear') # field - points _ = maps.interpolate(grid, field.fx, xi, method='linear') # == CUBIC == # property - grid _ = maps.interpolate(grid, model.property_x, grid2, method='cubic') # field - grid _ = maps.interpolate(grid, field.fx, grid2, method='cubic') # property - points _ = maps.interpolate(grid, model.property_x, xi, method='cubic') # field - points _ = maps.interpolate(grid, field.fx, xi, method='cubic') # == VOLUME == # property - grid _ = maps.interpolate(grid, model.property_x, grid2, method='volume') # field - grid with pytest.raises(ValueError, match="for cell-centered properties"): maps.interpolate(grid, field.fx, grid2, method='volume') # property - points with pytest.raises(ValueError, match="only implemented for TensorM"): maps.interpolate(grid, model.property_x, xi, method='volume') # field - points with pytest.raises(ValueError, match="only implemented for TensorM"): maps.interpolate(grid, field.fx, xi, method='volume')
def test_solve_source(): dat = REGRES['res'] model = emg3d.Model(**dat['input_model']) efield = solver.solve_source(model=model, source=dat['input_source']['source'], frequency=dat['input_source']['frequency'], plain=True) assert_allclose(dat['Fresult'].field, efield.field)
def test_amat_x(njit): if njit: amat_x = core.amat_x else: amat_x = core.amat_x.py_func # 1. Compare to alternative amat_x # Create a grid src = [200, 300, -50., 5, 60] hx = helpers.widths(8, 4, 100, 1.2) hy = np.ones(8) * 800 hz = np.ones(4) * 500 grid = emg3d.TensorMesh(h=[hx, hy, hz], origin=np.array( [-hx.sum() / 2, -hy.sum() / 2, -hz.sum() / 2])) # Create some resistivity model x = np.arange(1, grid.shape_cells[0] + 1) * 2 y = 1 / np.arange(1, grid.shape_cells[1] + 1) z = np.arange(1, grid.shape_cells[2] + 1)[::-1] / 10 property_x = np.outer(np.outer(x, y), z).ravel() freq = 0.319 model = emg3d.Model(grid=grid, property_x=property_x, property_y=0.8 * property_x, property_z=2 * property_x) # Create a source field sfield = emg3d.get_source_field(grid=grid, source=src, frequency=freq) # Get volume-averaged model parameters. vmodel = emg3d.models.VolumeModel(model, sfield) # Run two iterations to get a e-field efield = emg3d.solve(model=model, sfield=sfield, sslsolver=False, semicoarsening=False, linerelaxation=False, maxit=2, verb=1) # amat_x rr1 = emg3d.Field(grid) amat_x(rr1.fx, rr1.fy, rr1.fz, efield.fx, efield.fy, efield.fz, vmodel.eta_x, vmodel.eta_y, vmodel.eta_z, vmodel.zeta, grid.h[0], grid.h[1], grid.h[2]) # amat_x - alternative rr2 = emg3d.Field(grid) alternatives.alt_amat_x(rr2.fx, rr2.fy, rr2.fz, efield.fx, efield.fy, efield.fz, vmodel.eta_x, vmodel.eta_y, vmodel.eta_z, vmodel.zeta, grid.h[0], grid.h[1], grid.h[2]) # Check all fields (ex, ey, and ez) assert_allclose(-rr1.field, rr2.field, atol=1e-23)
def test_rel_abs_rec(self): # Sources sources = emg3d.surveys.txrx_coordinates_to_dict( emg3d.TxElectricDipole, ([0, 100, 200], 0, 0, 0, 0)) # Abs and rel Receivers a_e_rec = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, (1000 + np.arange(3) * 100, 0, -100, 0, 0)) r_e_rec = emg3d.surveys.txrx_coordinates_to_dict(emg3d.RxElectricPoint, (1000, 0, -100, 0, 0), relative=True) a_h_rec = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxMagneticPoint, (1000 + np.arange(3) * 100, 0, -100, 0, 0)) r_h_rec = emg3d.surveys.txrx_coordinates_to_dict(emg3d.RxMagneticPoint, (1000, 0, -100, 0, 0), relative=True) receivers = emg3d.surveys.txrx_lists_to_dict( [a_e_rec, r_e_rec, a_h_rec, r_h_rec]) # Frequencies frequencies = (1.0) survey = emg3d.Survey(sources, receivers, frequencies, name='TestSurv', noise_floor=1e-15, relative_error=0.05) # Create a simple grid and model grid = emg3d.TensorMesh( [np.ones(32) * 250, np.ones(16) * 500, np.ones(16) * 500], np.array([-1250, -1250, -2250])) model = emg3d.Model(grid, 1) # Create a simulation, compute all fields. simulation = simulations.Simulation(survey, model, name='TestSim', max_workers=1, solver_opts={ 'maxit': 1, 'verb': 0, 'plain': True }, gridding='same') simulation.compute() # Relative receivers must be same as corresponding absolute receivers assert_allclose( [simulation.data.synthetic[i, i, 0].data for i in range(3)], simulation.data.synthetic[:, 3, 0].data) assert_allclose( [simulation.data.synthetic[i, i + 4, 0].data for i in range(3)], simulation.data.synthetic[:, 7, 0].data)
def test_sc_0(self): sc = 0 # Simple test with restriction followed by prolongation. src = [150, 150, 150, 0, 45] grid = emg3d.TensorMesh( [np.ones(4) * 100, np.ones(4) * 100, np.ones(4) * 100], origin=np.zeros(3)) # Create dummy model and fields, parameters don't matter. model = emg3d.Model(grid, 1, 1, 1, 1) sfield = emg3d.get_source_field(grid, src, 1) # Get volume-averaged model parameters. vmodel = emg3d.models.VolumeModel(model, sfield) rx = np.arange(sfield.fx.size, dtype=np.complex128).reshape(sfield.fx.shape) ry = np.arange(sfield.fy.size, dtype=np.complex128).reshape(sfield.fy.shape) rz = np.arange(sfield.fz.size, dtype=np.complex128).reshape(sfield.fz.shape) field = np.r_[rx.ravel('F'), ry.ravel('F'), rz.ravel('F')] rr = emg3d.Field(grid, field) # Restrict it cmodel, csfield, cefield = solver.restriction(vmodel, sfield, rr, sc_dir=sc) assert_allclose(csfield.fx[:, 1:-1, 1], np.array([[196. + 0.j], [596. + 0.j]])) assert_allclose(csfield.fy[1:-1, :, 1], np.array([[356. + 0.j, 436. + 0.j]])) assert_allclose(csfield.fz[1:-1, 1:-1, :], np.array([[[388. + 0.j, 404. + 0.j]]])) assert cmodel.grid.shape_nodes[0] == cmodel.grid.shape_nodes[1] == 3 assert cmodel.grid.shape_nodes[2] == 3 assert cmodel.eta_x[0, 0, 0] / 8. == vmodel.eta_x[0, 0, 0] assert np.sum(grid.h[0]) == np.sum(cmodel.grid.h[0]) assert np.sum(grid.h[1]) == np.sum(cmodel.grid.h[1]) assert np.sum(grid.h[2]) == np.sum(cmodel.grid.h[2]) # Add pi to the coarse e-field efield = emg3d.Field(grid) cefield.field += np.pi # Prolong it solver.prolongation(efield, cefield, sc_dir=sc) assert np.all(efield.fx[:, 1:-1, 1:-1] == np.pi) assert np.all(efield.fy[1:-1, :, 1:-1] == np.pi) assert np.all(efield.fz[1:-1, 1:-1, :] == np.pi)
def test_reciprocity(): frequency = 1 center = (1_000, 10_000, 100_000) grid = emg3d.construct_mesh( center=center, frequency=frequency, properties=frequency, distance=[-400, 800], ) # Random model parameters model = emg3d.Model(grid, (np.random.rand(grid.n_cells) + 1) * 10) c = (0, 0, 0, 0, 0) # Random angles azm0, azm1 = np.random.randint(91), np.random.randint(91) ele0, ele1 = np.random.randint(91), np.random.randint(91) srcrec0 = [[emg3d.TxElectricPoint, emg3d.RxElectricPoint], [emg3d.TxMagneticPoint, emg3d.RxMagneticPoint]] srcrec1 = [[emg3d.RxElectricPoint, emg3d.TxElectricPoint], [emg3d.RxMagneticPoint, emg3d.TxMagneticPoint]] # print(f" loc1 / loc2 : azm / ele : NMRSD (%)\n{98*'-'}") for loc0 in srcrec0: for loc1 in srcrec1: coo1 = (center[0] + 300, center[1] + 200, center[2] + 400, azm0, ele0) coo2 = (center[0] + 800, center[1] + 700, center[2] + 500, azm1, ele1) field1 = emg3d.solve_source(model=model, source=loc0[0](coo1), frequency=frequency) field2 = emg3d.solve_source(model=model, source=loc1[1](coo2), frequency=frequency) if loc1[0](c).xtype == 'magnetic': field1 = fields.get_magnetic_field(model, field1) if loc0[1](c).xtype == 'magnetic': field2 = fields.get_magnetic_field(model, field2) resp1 = field1.get_receiver(loc1[0](coo2), 'linear')[0] resp2 = field2.get_receiver(loc0[1](coo1), 'linear')[0] nrmsd = 200.0 * abs(resp1 - resp2) / (abs(resp1) + abs(resp2)) # print(f" {str(loc0[0])[25:28]}-{str(loc1[0])[25:28]} /" # f" {str(loc1[1])[25:28]}-{str(loc0[1])[25:28]}" # f" : {azm0:03d};{azm1:03d}/{ele0:03d};{ele1:03d}" # f" : {nrmsd:6.2f} {resp1:+.4e}; {resp2:+.4e}") assert nrmsd < 1.0
def test_dict_serialize_deserialize(): frequency = 1.0 grid = emg3d.TensorMesh([[2, 2], [3, 4], [0.5, 2]], (0, 0, 0)) field = emg3d.Field(grid) model = emg3d.Model(grid, 1) tx_e_d = emg3d.TxElectricDipole((0, 1000, 0, 0, -900, -950)) tx_m_d = emg3d.TxMagneticDipole([[0, 0, -900], [1000, 0, -950]]) tx_e_w = emg3d.TxElectricWire(([[0, 0, 0], [1, 1, 1], [1, 0, 1]])) rx_e_p = emg3d.RxElectricPoint((0, 1000, -950, 0, 20)) rx_m_p = emg3d.RxMagneticPoint((0, 1000, -950, 20, 0)) data = { 'Grid': grid, 'Model': model, 'Field': field, } if xarray: survey = emg3d.Survey( emg3d.surveys.txrx_lists_to_dict([tx_e_d, tx_m_d, tx_e_w]), emg3d.surveys.txrx_lists_to_dict([rx_e_p, rx_m_p]), frequency ) simulation = emg3d.Simulation(survey, model, gridding='same') data['Survey'] = survey data['Simulation'] = simulation # Get everything into a serialized dict. out = io._dict_serialize(data) # Get everything back. io._nonetype_to_none(out) keep = deepcopy(out) io._dict_deserialize(out) assert data.keys() == out.keys() assert out['Field'] == field assert out['Grid'] == grid assert out['Model'] == model if xarray: assert out['Survey'].sources == survey.sources assert (out['Simulation'].survey.receivers == simulation.survey.receivers) del keep['Grid']['hx'] with pytest.warns(UserWarning, match="Could not de-serialize"): io._dict_deserialize(keep)
def test_resistivity(self): model = emg3d.Model(self.mesh, 1/self.values, mapping='Resistivity') # Forward forward = model.map.forward(self.values) assert_allclose(forward, 1/self.values) # Backward backward = model.map.backward(forward) assert_allclose(backward, self.values) # Derivative gradient = 2*np.ones(model.property_x.shape) derivative = gradient.copy() model.map.derivative_chain(gradient, model.property_x) assert_allclose(gradient, -derivative*(1/model.property_x)**2)
def test_lgresistivity(self): model = emg3d.Model(self.mesh, np.log10(1/self.values), mapping='LgResistivity') # Forward forward = model.map.forward(self.values) assert_allclose(forward, np.log10(1/self.values)) # Backward backward = model.map.backward(forward) assert_allclose(backward, self.values) # Derivative gradient = 2*np.ones(model.property_x.shape) derivative = gradient.copy() model.map.derivative_chain(gradient, model.property_x) assert_allclose(gradient, -derivative*10**-model.property_x*np.log(10))
def test_lnconductivity(self): model = emg3d.Model(self.mesh, np.log(self.values), mapping='LnConductivity') # Forward forward = model.map.forward(self.values) assert_allclose(forward, np.log(self.values)) # Backward backward = model.map.backward(forward) assert_allclose(backward, self.values) # Derivative gradient = 2*np.ones(model.property_x.shape) derivative = gradient.copy() model.map.derivative_chain(gradient, model.property_x) assert_allclose(gradient, derivative*np.exp(model.property_x))
def test_residual(): # The only thing to test here is that the residual returns the same as # sfield-amat_x. Basically a copy of the function itself. # Create a grid src = [90, 1600, 25., 45, 45] grid = emg3d.TensorMesh( [helpers.widths(4, 2, 20, 1.2), np.ones(16) * 200, np.ones(2) * 25], origin=np.zeros(3)) # Create some resistivity model x = np.arange(1, grid.shape_cells[0] + 1) * 2 y = 1 / np.arange(1, grid.shape_cells[1] + 1) z = np.arange(1, grid.shape_cells[2] + 1)[::-1] / 10 property_x = np.outer(np.outer(x, y), z).ravel() freq = 0.319 model = emg3d.Model(grid, property_x, 0.8 * property_x, 2 * property_x) # Create a source field sfield = emg3d.get_source_field(grid=grid, source=src, frequency=freq) # Get volume-averaged model parameters. vmodel = emg3d.models.VolumeModel(model, sfield) # Run two iterations to get an e-field efield = solver.solve(model, sfield, maxit=2) # Use directly amat_x rfield = sfield.copy() emg3d.core.amat_x(rfield.fx, rfield.fy, rfield.fz, efield.fx, efield.fy, efield.fz, vmodel.eta_x, vmodel.eta_y, vmodel.eta_z, vmodel.zeta, grid.h[0], grid.h[1], grid.h[2]) # Compute residual out = solver.residual(vmodel, sfield, efield) outnorm = solver.residual(vmodel, sfield, efield, True) # Compare assert_allclose(out.field, rfield.field) assert_allclose(outnorm, np.linalg.norm(out.field))
def test_misfit(): data = 1 syn = 5 rel_err = 0.05 sources = emg3d.TxElectricDipole((0, 0, 0, 0, 0)) receivers = emg3d.RxElectricPoint((5, 0, 0, 0, 0)) survey = emg3d.Survey( sources=sources, receivers=receivers, frequencies=100, data=np.zeros((1, 1, 1)) + data, relative_error=0.05, ) grid = emg3d.TensorMesh([np.ones(10) * 2, [2, 2], [2, 2]], (-10, -2, -2)) model = emg3d.Model(grid, 1) simulation = simulations.Simulation(survey=survey, model=model) field = emg3d.Field(grid, dtype=np.float64) field.field += syn simulation._dict_efield['TxED-1']['f-1'] = field simulation.data['synthetic'] = simulation.data['observed'] * 0 + syn misfit = 0.5 * ((syn - data) / (rel_err * data))**2 def dummy(): pass simulation.compute = dummy # => switch of compute() assert_allclose(simulation.misfit, misfit) # Missing noise_floor / std. survey = emg3d.Survey(sources, receivers, 100) simulation = simulations.Simulation(survey=survey, model=model) with pytest.raises(ValueError, match="Either `noise_floor` or"): simulation.misfit
def test_expand_grid_model(): grid = emg3d.TensorMesh([[4, 2, 2, 4], [2, 2, 2, 2], [1, 1]], (0, 0, 0)) model = emg3d.Model(grid, 1, np.ones(grid.shape_cells) * 2, mu_r=3, epsilon_r=5) o_model = models.expand_grid_model(model, [2, 3], 5) # Grid. assert_allclose(grid.nodes_z, o_model.grid.nodes_z[:-2]) assert o_model.grid.nodes_z[-2] == 5 assert o_model.grid.nodes_z[-1] == 105 # Property x (from float). assert_allclose(o_model.property_x[:, :, :-2], 1) assert_allclose(o_model.property_x[:, :, -2], 2) assert_allclose(o_model.property_x[:, :, -1], 3) # Property y (from shape_cells). assert_allclose(o_model.property_y[:, :, :-2], model.property_y) assert_allclose(o_model.property_y[:, :, -2], 2) assert_allclose(o_model.property_y[:, :, -1], 3) # Property z. assert o_model.property_z is None # Property mu_r (from float). assert_allclose(o_model.mu_r[:, :, :-2], 3) assert_allclose(o_model.mu_r[:, :, -2], 1) assert_allclose(o_model.mu_r[:, :, -1], 1) # Property epsilon_r (from float). assert_allclose(o_model.epsilon_r[:, :, :-2], 5) assert_allclose(o_model.epsilon_r[:, :, -2], 1) assert_allclose(o_model.epsilon_r[:, :, -1], 1)
class TestRun: # Default values for run-tests args_dict = { 'config': '.', 'nproc': 1, 'forward': False, 'misfit': False, 'gradient': True, 'path': None, 'survey': 'survey.npz', 'model': 'model.npz', 'output': 'output.npz', 'save': None, 'load': None, 'verbosity': 0, 'dry_run': True, } if xarray is not None: # Create a tiny dummy survey. data = np.ones((1, 17, 1)) data[0, 8:11, 0] = np.nan sources = emg3d.TxElectricDipole((4125, 4000, 4000, 0, 0)) receivers = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, (np.arange(17) * 250 + 2000, 4000, 3950, 0, 0)) survey = emg3d.Survey( name='CLI Survey', sources=sources, receivers=receivers, frequencies=1, noise_floor=1e-15, relative_error=0.05, data=data, ) # Create a dummy grid and model. xx = np.ones(16) * 500 grid = emg3d.TensorMesh([xx, xx, xx], origin=np.array([0, 0, 0])) model = emg3d.Model(grid, 1.) def test_basic(self, tmpdir, capsys): # Store survey and model. self.survey.to_file(os.path.join(tmpdir, 'survey.npz'), verb=0) emg3d.save(os.path.join(tmpdir, 'model.npz'), model=self.model, mesh=self.grid, verb=0) args_dict = self.args_dict.copy() args_dict['path'] = tmpdir args_dict['verbosity'] = -1 cli.run.simulation(args_dict) args_dict = self.args_dict.copy() args_dict['path'] = tmpdir args_dict['config'] = 'bla' args_dict['verbosity'] = 2 _, _ = capsys.readouterr() with pytest.raises(SystemExit) as e: cli.run.simulation(args_dict) assert e.type == SystemExit assert "* ERROR :: Config file not found: " in e.value.code # Missing survey. args_dict = self.args_dict.copy() args_dict['path'] = tmpdir args_dict['survey'] = 'wrong' with pytest.raises(SystemExit) as e: cli.run.simulation(args_dict) assert e.type == SystemExit assert "* ERROR :: Survey file not found: " in e.value.code assert "wrong" in e.value.code # Missing model. args_dict = self.args_dict.copy() args_dict['path'] = tmpdir args_dict['model'] = 'phantommodel' with pytest.raises(SystemExit) as e: cli.run.simulation(args_dict) assert e.type == SystemExit assert "* ERROR :: Model file not found: " in e.value.code assert "phantommodel" in e.value.code # Missing output directory. args_dict = self.args_dict.copy() args_dict['path'] = tmpdir args_dict['output'] = join('phantom', 'output', 'dir.npz') args_dict['save'] = join('phantom', 'simulation', 'save.npz') with pytest.raises(SystemExit) as e: cli.run.simulation(args_dict) assert e.type == SystemExit assert "* ERROR :: Output directory does not exist: " in e.value.code assert join("phantom", "output") in e.value.code assert join("phantom", "simulation") in e.value.code def test_run(self, tmpdir, capsys): # Write a config file. config = os.path.join(tmpdir, 'emg3d.cfg') with open(config, 'w') as f: f.write("[files]\n") f.write("save=mysim.npz\n") f.write("[solver_opts]\n") f.write("sslsolver=False\n") f.write("semicoarsening=False\n") f.write("linerelaxation=False\n") f.write("maxit=1\n") # Store survey and model. self.survey.to_file(os.path.join(tmpdir, 'survey.npz'), verb=1) emg3d.save(os.path.join(tmpdir, 'model.npz'), model=self.model, mesh=self.grid, verb=1) # Run a dry run (to output.npz). args_dict = self.args_dict.copy() args_dict['config'] = os.path.join(tmpdir, 'emg3d.cfg') args_dict['path'] = tmpdir cli.run.simulation(args_dict) # Actually run one iteration (to output2.npz). args_dict = self.args_dict.copy() args_dict['config'] = os.path.join(tmpdir, 'emg3d.cfg') args_dict['path'] = tmpdir args_dict['dry_run'] = False args_dict['output'] = 'output2.npz' cli.run.simulation(args_dict) # Ensure dry_run returns same shaped data as the real thing. res1 = emg3d.load(os.path.join(tmpdir, 'output.npz')) res2 = emg3d.load(os.path.join(tmpdir, 'output2.npz')) assert_allclose(res1['data'].shape, res2['data'].shape) assert_allclose(res1['misfit'].shape, res2['misfit'].shape) assert_allclose(res1['gradient'].shape, res2['gradient'].shape) # Assert we can load the simulation emg3d.Simulation.from_file(os.path.join(tmpdir, 'mysim.npz')) assert res1['n_observations'] == np.isfinite(self.data).sum() assert res2['n_observations'] == np.isfinite(self.data).sum() # Actually run one iteration (to output2.npz). args_dict = self.args_dict.copy() args_dict['config'] = os.path.join(tmpdir, 'emg3d.cfg') args_dict['path'] = tmpdir args_dict['forward'] = True args_dict['gradient'] = False args_dict['dry_run'] = False args_dict['output'] = 'output3.npz' cli.run.simulation(args_dict) res3 = emg3d.load(os.path.join(tmpdir, 'output3.npz')) assert 'misfit' not in res3 assert 'gradient' not in res3 # Redo for misfit, loading existing simulation. args_dict = self.args_dict.copy() args_dict['config'] = os.path.join(tmpdir, 'emg3d.cfg') args_dict['path'] = tmpdir args_dict['forward'] = False args_dict['misfit'] = True args_dict['gradient'] = False args_dict['dry_run'] = False args_dict['load'] = 'mysim.npz' args_dict['output'] = 'output3.npz' cli.run.simulation(args_dict) res3 = emg3d.load(os.path.join(tmpdir, 'output3.npz')) assert 'misfit' in res3 assert 'gradient' not in res3 def test_data(self, tmpdir, capsys): # Write a config file; remove_empty=False (default) config = os.path.join(tmpdir, 'emg3d.cfg') with open(config, 'w') as f: f.write("[data]\n") f.write("sources=TxED-1\n") f.write("receivers=RxEP-05, RxEP-10, RxEP-02, RxEP-12, RxEP-06\n") f.write("frequencies=f-1") # Store survey and model. self.survey.to_file(os.path.join(tmpdir, 'survey.npz'), verb=1) emg3d.save(os.path.join(tmpdir, 'model.npz'), model=self.model, mesh=self.grid, verb=1) # Run a dry run (to output.npz). args_dict = self.args_dict.copy() args_dict['config'] = os.path.join(tmpdir, 'emg3d.cfg') args_dict['path'] = tmpdir cli.run.simulation(args_dict.copy()) # Ensure dry_run returns same shaped data as the real thing. res = emg3d.load(os.path.join(tmpdir, 'output.npz')) assert_allclose(res['data'].shape, (1, 5, 1)) assert res['n_observations'] == 4 # Append config file with: remove_empty=True with open(config, 'a') as f: f.write("\nremove_empty=True") # Run a dry run (to output.npz). cli.run.simulation(args_dict) # Ensure dry_run returns same shaped data as the real thing. res = emg3d.load(os.path.join(tmpdir, 'output.npz')) assert_allclose(res['data'].shape, (1, 4, 1)) assert res['n_observations'] == 4
class TestGradient: if xarray is not None: # Create a simple mesh. hx = np.ones(64) * 100 mesh = emg3d.TensorMesh([hx, hx, hx], origin=[0, 0, 0]) # Define a simple survey, including 1 el. & 1 magn. receiver survey = emg3d.Survey( sources=emg3d.TxElectricDipole((1680, 3220, 3210, 20, 5)), receivers=[ emg3d.RxElectricPoint((4751, 3280, 3220, 33, 14)), emg3d.RxMagneticPoint((4758, 3230, 3250, 15, 70)), ], frequencies=1.0, relative_error=0.01, ) # Background Model con_init = np.ones(mesh.shape_cells) # Target Model 1: One Block con_true = np.ones(mesh.shape_cells) con_true[27:37, 27:37, 15:25] = 0.001 model_init = emg3d.Model(mesh, con_init, mapping='Conductivity') model_true = emg3d.Model(mesh, con_true, mapping='Conductivity') # mesh.plot_3d_slicer(con_true) # For debug / QC, needs discretize sim_inp = { 'survey': survey, 'solver_opts': { 'plain': True, 'tol': 5e-5 }, # Red. tol 4 speed 'max_workers': 1, 'gridding': 'same', 'verb': 0, 'receiver_interpolation': 'linear', } # Compute data (pre-computed and passed to Survey above) sim_data = simulations.Simulation(model=model_true, **sim_inp) sim_data.compute(observed=True) def test_errors(self): mesh = emg3d.TensorMesh([[2, 2], [2, 2], [2, 2]], origin=(-1, -1, -1)) survey = emg3d.Survey( sources=emg3d.TxElectricDipole((-1.5, 0, 0, 0, 0)), receivers=emg3d.RxElectricPoint((1.5, 0, 0, 0, 0)), frequencies=1.0, relative_error=0.01, ) sim_inp = { 'survey': survey, 'gridding': 'same', 'receiver_interpolation': 'linear' } # Anisotropic models. simulation = simulations.Simulation(model=emg3d.Model(mesh, 1, 2, 3), **sim_inp) with pytest.raises(NotImplementedError, match='for isotropic models'): simulation.gradient # Model with electric permittivity. simulation = simulations.Simulation(model=emg3d.Model(mesh, epsilon_r=3), **sim_inp) with pytest.raises(NotImplementedError, match='for el. permittivity'): simulation.gradient # Model with magnetic permeability. simulation = simulations.Simulation(model=emg3d.Model( mesh, mu_r=np.ones(mesh.shape_cells) * np.pi), **sim_inp) with pytest.raises(NotImplementedError, match='for magn. permeabili'): simulation.gradient def test_as_vs_fd_gradient(self, capsys): # Compute adjoint state misfit and gradient sim = simulations.Simulation(model=self.model_init, **self.sim_inp) data_misfit = sim.misfit grad = sim.gradient # For Debug / QC, needs discretize # from matplotlib.colors import LogNorm, SymLogNorm # mesh.plot_3d_slicer( # grad.ravel('F'), # pcolor_opts={ # 'cmap': 'RdBu_r', # 'norm': SymLogNorm(linthresh=1e-2, base=10, # vmin=-1e1, vmax=1e1)} # ) # We test a random cell from the inline xz slice, where the grad > 3. # # The NRMSD is (should) be below 1 %. However, (a) close to the # boundary, (b) in regions where the gradient is almost zero, and (c) # in regions where the gradient changes sign the NRMSD can become # large. This is mainly due to numerics, our coarse mesh, and the # reduced tolerance (which we reduced for speed). iy = 32 indices = np.argwhere(abs(grad[:, iy, :]) > 3) ix, iz = indices[np.random.randint(indices.shape[0])] nrmsd = alternatives.fd_vs_as_gradient((ix, iy, iz), self.model_init, grad, data_misfit, self.sim_inp) assert nrmsd < 0.3 @pytest.mark.skipif(discretize is None, reason="discretize not installed.") @pytest.mark.skipif(h5py is None, reason="h5py not installed.") def test_adjoint(self, tmpdir): sim = simulations.Simulation(model=self.model_init, file_dir=str(tmpdir), **self.sim_inp) v = np.random.rand(self.mesh.n_cells).reshape(self.mesh.shape_cells) w = np.random.rand(self.survey.size).reshape(self.survey.shape) wtJv = np.vdot(w, sim.jvec(v)).real vtJtw = np.vdot(v, sim.jtvec(w).ravel('F')) assert abs(wtJv - vtJtw) < 1e-10 @pytest.mark.skipif(discretize is None, reason="discretize not installed.") @pytest.mark.skipif(h5py is None, reason="h5py not installed.") def test_misfit(self, tmpdir): sim = simulations.Simulation(model=self.model_init, file_dir=str(tmpdir), **self.sim_inp) m0 = 2 * sim.model.property_x def func2(x): sim.model.property_x[...] = m0 return sim.jvec(x) def func1(x): sim.model.property_x[...] = x.reshape(sim.model.grid.shape_cells) sim.clean('computed') # Quick test that clean() removes the files assert len(os.listdir(tmpdir)) == 0 sim.compute() return sim.data.synthetic.data, func2 assert discretize.tests.check_derivative( func1, m0, plotIt=False, num=3, )
def test_basics(self): # Coarse check with emg3d.solve and empymod. x = np.array([400, 450, 500, 550]) rec = (x, x * 0, 0, 20, 70) res = 0.3 src = (0, 0, 0, 0, 0) freq = 10 grid = emg3d.construct_mesh( frequency=freq, center=(0, 0, 0), properties=res, domain=[[0, 1000], [-25, 25], [-25, 25]], min_width_limits=20, ) model = emg3d.Model(grid, res) sfield = fields.get_source_field(grid, src, freq) efield = emg3d.solve(model, sfield, plain=True, verb=1) # epm = empymod.bipole(src, rec, [], res, freq, verb=1) epm = np.array([ -1.27832028e-11 + 1.21383502e-11j, -1.90064149e-12 + 7.51937145e-12j, 1.09602131e-12 + 3.33066197e-12j, 1.25359248e-12 + 1.02630145e-12j ]) e3d = fields.get_receiver(efield, rec) # 10 % is still OK, grid is very coarse for fast comp (2s) assert_allclose(epm, e3d, rtol=0.1) # Test with a list of receiver instance. rec_inst = [ emg3d.RxElectricPoint((rec[0][i], rec[1][i], *rec[2:])) for i in range(rec[0].size) ] e3d_inst = fields.get_receiver(efield, rec_inst) assert_allclose(e3d_inst, e3d) # Only one receiver e3d_inst = fields.get_receiver(efield, rec_inst[0]) assert_allclose(e3d_inst, e3d[0]) # Ensure cubic and linear are different; and that 'cubic' is default. e3d_inst2 = fields.get_receiver(efield, rec_inst[0], method='linear') assert abs(e3d_inst) != abs(e3d_inst2) # Ensure responses outside and in the last cell are set to NaN. h = np.ones(4) * 100 grid = emg3d.TensorMesh([h, h, h], (-200, -200, -200)) model = emg3d.Model(grid) sfield = fields.get_source_field(grid=grid, source=[0, 0, 0, 0, 0], frequency=10) out = emg3d.solve(model=model, sfield=sfield, plain=True, verb=0) off = np.arange(11) * 50 - 250 resp = out.get_receiver((off, off, off, 0, 0)) assert_allclose(np.isfinite(resp), np.r_[3 * [ False, ], 5 * [ True, ], 3 * [ False, ]]) # Also if linearly interpolated resp = out.get_receiver((off, off, off, 0, 0), method='linear') assert_allclose(np.isfinite(resp), np.r_[3 * [ False, ], 5 * [ True, ], 3 * [ False, ]])
def test_print_solver(self, capsys): grid = emg3d.TensorMesh(h=[[(25, 10, -1.04), (25, 28), (25, 10, 1.04)], [(50, 8, -1.03), (50, 16), (50, 8, 1.03)], [(30, 8, -1.05), (30, 16), (30, 8, 1.05)]], origin='CCC') model = emg3d.Model(grid, property_x=1.5, property_y=1.8, property_z=3.3, mapping='Resistivity') sources = emg3d.TxElectricDipole((0, 0, 0, 0, 0)) receivers = [ emg3d.RxElectricPoint((x, 0, 0, 0, 0)) for x in [-10000, 10000] ] survey = emg3d.Survey( name='Test', sources=sources, receivers=receivers, frequencies=1.0, noise_floor=1e-15, relative_error=0.05, ) inp = { 'name': 'Test', 'survey': survey, 'model': model, 'gridding': 'same' } sol = { 'sslsolver': False, 'semicoarsening': False, 'linerelaxation': False, 'maxit': 1 } # Errors but verb=-1. _, _ = capsys.readouterr() # empty simulation = simulations.Simulation(verb=-1, **inp, solver_opts=sol) simulation.compute() out, _ = capsys.readouterr() assert out == "" # Errors with verb=0. out = simulation.print_solver_info('efield', verb=0, return_info=True) assert "= Source TxED-1; Frequency 1.0 Hz = MAX. ITERATION REAC" in out # Errors with verb=1. _, _ = capsys.readouterr() # empty simulation.print_solver_info('efield', verb=1) out, _ = capsys.readouterr() assert "= Source TxED-1; Frequency 1.0 Hz = 2.6e-02; 1; 0:00:" in out # No errors; solver-verb 3. simulation = simulations.Simulation(verb=1, **inp, solver_opts={'verb': 3}) simulation.compute() out, _ = capsys.readouterr() assert 'MG-cycle' in out assert 'CONVERGED' in out # No errors; solver-verb 0. simulation = simulations.Simulation(verb=1, **inp, solver_opts={'verb': 0}) simulation.compute() out, _ = capsys.readouterr() assert "= Source TxED-1; Frequency 1.0 Hz = CONVERGED" in out # Two sources, only compute 1, assure printing works. sources = [emg3d.TxElectricDipole((x, 0, 0, 0, 0)) for x in [0, 10]] survey = emg3d.Survey( name='Test', sources=sources, receivers=receivers, frequencies=1.0, noise_floor=1e-15, relative_error=0.05, ) inp = { 'name': 'Test', 'survey': survey, 'model': model, 'gridding': 'same' } simulation = simulations.Simulation(**inp, solver_opts={'verb': 0}) _ = simulation.get_efield('TxED-2', 'f-1') simulation.print_solver_info(verb=1) out, _ = capsys.readouterr() assert "= Source TxED-2; Frequency 1.0 Hz = CONVERGED" in out
def test_simulation_automatic(self, capsys): # Create a simple survey sources = emg3d.surveys.txrx_coordinates_to_dict( emg3d.TxElectricDipole, (0, [1000, 3000, 5000], -950, 0, 0)) receivers = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, ([-3000, 0, 3000], [0, 3000, 6000], -1000, 0, 0)) frequencies = (0.1, 1.0, 10.0) survey = emg3d.Survey(sources, receivers, frequencies, name='Test', noise_floor=1e-15, relative_error=0.05) # Create a simple grid and model grid = emg3d.TensorMesh( [np.ones(32) * 250, np.ones(16) * 500, np.ones(4) * 500], np.array([-1250, -1250, -2250])) model = emg3d.Model(grid, 1) # Create a simulation, compute all fields. inp = { 'survey': survey, 'model': model, 'gridding_opts': { 'expand': [1, 0.5], 'seasurface': 0, 'verb': 1 } } b_sim = simulations.Simulation(name='both', gridding='both', **inp) f_sim = simulations.Simulation(name='freq', gridding='frequency', **inp) t_sim = simulations.Simulation(name='src', gridding='source', **inp) s_sim = simulations.Simulation(name='single', gridding='single', **inp) # Quick repr test. assert " 24 x 24 (13,824) - 160 x 160 x 96 (2,457," in b_sim.__repr__() assert " 24 x 24 (13,824) - 160 x 160 x 96 (2,457," in f_sim.__repr__() assert "Source-dependent grids; 64 x 64 x 40 (163," in t_sim.__repr__() assert "ources and frequencies; 64 x 64 x 40 (163," in s_sim.__repr__() # Quick print_grid test: _, _ = capsys.readouterr() # empty b_sim.print_grid_info() out, _ = capsys.readouterr() assert "= Source: TxED-1; Frequency: 10.0 Hz =" in out assert "== GRIDDING IN X ==" in out assert b_sim.get_grid('TxED-1', 1.0).__repr__() in out _, _ = capsys.readouterr() # empty out = f_sim.print_grid_info(return_info=True) out2, _ = capsys.readouterr() assert out2 == "" assert "= Source: all" in out assert "== GRIDDING IN X ==" in out assert f_sim.get_grid('TxED-3', 1.0).__repr__() in out t_sim.print_grid_info() out, _ = capsys.readouterr() assert "; Frequency: all" in out assert "== GRIDDING IN X ==" in out assert t_sim.get_grid('TxED-1', 10.0).__repr__() in out _, _ = capsys.readouterr() # empty out = s_sim.print_grid_info(return_info=True) out2, _ = capsys.readouterr() assert out2 == "" assert "= Source: all; Frequency: all =" in out assert "== GRIDDING IN X ==" in out assert s_sim.get_grid('TxED-3', 0.1).__repr__() in out assert s_sim.print_grid_info(verb=-1) is None # Grids: Middle source / middle frequency should be the same in all. assert f_sim.get_grid('TxED-2', 1.0) == t_sim.get_grid('TxED-2', 1.0) assert f_sim.get_grid('TxED-2', 1.0) == s_sim.get_grid('TxED-2', 1.0) assert f_sim.get_grid('TxED-2', 1.0) == b_sim.get_grid('TxED-2', 1.0) assert f_sim.get_model('TxED-2', 1.0) == t_sim.get_model('TxED-2', 1.0) assert f_sim.get_model('TxED-2', 1.0) == s_sim.get_model('TxED-2', 1.0) assert f_sim.get_model('TxED-2', 1.0) == b_sim.get_model('TxED-2', 1.0) # Copy: f_sim_copy = f_sim.copy() assert (f_sim.get_grid('TxED-1', 1.0) == f_sim_copy.get_grid('TxED-1', 1.0)) assert 'expand' not in f_sim.gridding_opts.keys() assert 'expand' not in f_sim_copy.gridding_opts.keys() s_sim_copy = s_sim.copy() assert (s_sim.get_grid('TxED-1', 1.0) == s_sim_copy.get_grid('TxED-1', 1.0)) assert 'expand' not in s_sim.gridding_opts.keys() assert 'expand' not in s_sim_copy.gridding_opts.keys() t_sim_copy = t_sim.copy() assert (t_sim.get_grid('TxED-1', 1.0) == t_sim_copy.get_grid('TxED-1', 1.0)) assert 'expand' not in t_sim.gridding_opts.keys() assert 'expand' not in t_sim_copy.gridding_opts.keys()
class TestSimulation(): if xarray is not None: # Create a simple survey # Sources: 1 Electric Dipole, 1 Magnetic Dipole, 1 Electric Wire. s1 = emg3d.TxElectricDipole((0, 1000, -950, 0, 0)) s2 = emg3d.TxMagneticDipole((0, 3000, -950, 90, 0)) s3 = emg3d.TxElectricWire(([0, 4900, -950], [-20, 5000, -950], [20, 5100, -950])) sources = emg3d.surveys.txrx_lists_to_dict([s1, s2, s3]) # Receivers: 1 Electric Point, 1 Magnetic Point e_rec = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, (np.arange(6) * 1000, 0, -1000, 0, 0)) m_rec = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxMagneticPoint, (np.arange(6) * 1000, 0, -1000, 90, 0)) receivers = emg3d.surveys.txrx_lists_to_dict([e_rec, m_rec]) # Frequencies frequencies = (1.0, 2.0) survey = emg3d.Survey(sources, receivers, frequencies, name='TestSurv', noise_floor=1e-15, relative_error=0.05) # Create a simple grid and model grid = emg3d.TensorMesh( [np.ones(32) * 250, np.ones(16) * 500, np.ones(16) * 500], np.array([-1250, -1250, -2250])) model = emg3d.Model(grid, 1) # Create a simulation, compute all fields. simulation = simulations.Simulation(survey, model, name='TestSim', max_workers=1, solver_opts={ 'maxit': 1, 'verb': 0, 'sslsolver': False, 'linerelaxation': False, 'semicoarsening': False }, gridding='same') # Do first one single and then all together. simulation.get_efield('TxED-1', 'f-1') simulation.compute(observed=True, min_offset=1100) def test_same(self): assert self.simulation.get_model('TxMD-2', 'f-1') == self.model assert self.simulation.get_grid('TxEW-3', 1.0) == self.grid def test_fields(self, capsys): # Check sfield sfield = emg3d.get_source_field(self.grid, self.survey.sources['TxEW-3'], frequency=1.0) # Check efield efield, info = emg3d.solve(self.model, sfield, **self.simulation.solver_opts) assert self.simulation.get_efield('TxEW-3', 'f-1') == efield # See a single one self.simulation._dict_efield['TxEW-3'][1.0] = None _, _ = capsys.readouterr() self.simulation.get_efield('TxEW-3', 1.0) info = self.simulation.get_efield_info('TxEW-3', 1.0) assert 'MAX. ITERATION REACHED, NOT CONVERGED' in info['exit_message'] # Check hfield hfield = emg3d.get_magnetic_field(self.model, efield) assert self.simulation.get_hfield('TxEW-3', 1.0) == hfield s_hfield = self.simulation.get_hfield('TxEW-3', 1.0) assert s_hfield == hfield assert_allclose( self.simulation._dict_efield_info['TxEW-3']['f-1']['abs_error'], info['abs_error']) assert_allclose( self.simulation._dict_efield_info['TxEW-3']['f-1']['rel_error'], info['rel_error']) exit = self.simulation._dict_efield_info['TxEW-3']['f-1']['exit'] assert exit == info['exit'] == 1 # First hfield, ensure efield/hfield get computed. sim = self.simulation.copy(what='all') sim._dict_efield['TxEW-3']['f-1'] = None sim.get_hfield('TxEW-3', 'f-1') assert sim._dict_efield['TxEW-3']['f-1'] is not None def test_responses(self): # Check min_offset were switched-off assert_allclose(self.simulation.data.observed[0, 0, 0].data, np.nan) assert_allclose(self.simulation.data.observed[0, 6, 0].data, np.nan) # Get efield responses e_resp = self.simulation.get_efield('TxMD-2', 1.0).get_receiver( self.survey.receivers.values()) assert_allclose(self.simulation.data.synthetic[1, :6, 0].data, e_resp[:6], atol=1e-16) # Get hfield responses m_resp = self.simulation.get_hfield('TxMD-2', 1.0).get_receiver( self.survey.receivers.values()) assert_allclose(self.simulation.data.synthetic[1, 6:, 0].data, m_resp[6:], atol=1e-16) def test_errors(self): with pytest.raises(TypeError, match='Unexpected '): simulations.Simulation(self.survey, self.model, unknown=True, name='Test2') # gridding='same' with gridding_opts. with pytest.raises(TypeError, match="`gridding_opts` is not permitt"): simulations.Simulation(self.survey, self.model, name='Test', gridding='same', gridding_opts={'bummer': True}) # expand without seasurface with pytest.raises(KeyError, match="is required if"): simulations.Simulation(self.survey, self.model, name='Test', gridding='single', gridding_opts={'expand': [1, 2]}) def test_reprs(self): test = self.simulation.__repr__() assert "Simulation «TestSim»" in test assert "Survey «TestSurv»: 3 sources; 12 receivers; 2 frequenc" in test assert "Model: resistivity; isotropic; 32 x 16 x 16 (8,192)" in test assert "Gridding: Same grid as for model" in test test = self.simulation._repr_html_() assert "Simulation «TestSim»" in test assert "Survey «TestSurv»: 3 sources; 12 receivers; 2" in test assert "Model: resistivity; isotropic; 32 x 16 x 16 (8,192)" in test assert "Gridding: Same grid as for model" in test def test_copy(self, tmpdir): with pytest.raises(TypeError, match="Unrecognized `what`: nothing"): self.simulation.copy('nothing') sim2 = self.simulation.copy() assert self.simulation.name == sim2.name assert self.simulation.survey.sources == sim2.survey.sources assert_allclose( self.simulation.get_efield('TxED-1', 1.0).field, sim2.get_efield('TxED-1', 1.0).field) # Also check to_file()/from_file(). sim_dict = self.simulation.to_dict('all') sim2 = simulations.Simulation.from_dict(sim_dict.copy()) assert self.simulation.name == sim2.name assert self.simulation.survey.name == sim2.survey.name assert self.simulation.max_workers == sim2.max_workers assert self.simulation.gridding == sim2.gridding assert self.simulation.model == sim2.model del sim_dict['survey'] with pytest.raises(KeyError, match="'survey'"): simulations.Simulation.from_dict(sim_dict) # Also check to_file()/from_file(). self.simulation.to_file(tmpdir + '/test.npz', what='all') sim2 = simulations.Simulation.from_file(tmpdir + '/test.npz') assert self.simulation.name == sim2.name assert self.simulation.survey.name == sim2.survey.name assert self.simulation.max_workers == sim2.max_workers assert self.simulation.gridding == sim2.gridding assert self.simulation.model == sim2.model sim9 = simulations.Simulation.from_file(tmpdir + '/test.npz', verb=-1) assert sim2.name == sim9[0].name assert 'Data loaded from' in sim9[1] # Clean and ensure it is empty sim3 = self.simulation.copy() sim3.clean('all') assert sim3._dict_efield['TxMD-2']['f-1'] is None assert sim3._dict_efield_info['TxMD-2']['f-1'] is None with pytest.raises(TypeError, match="Unrecognized `what`: nothing"): sim3.clean('nothing') def test_dicts_provided(self): grids = self.simulation._dict_grid.copy() # dict sim1 = simulations.Simulation(self.survey, self.model, gridding='dict', gridding_opts=grids, name='Test2') m1 = sim1.get_model('TxEW-3', 1.0) g1 = sim1.get_grid('TxEW-3', 1.0) # provide sim2 = simulations.Simulation(self.survey, self.model, name='Test2', gridding='input', gridding_opts=grids['TxEW-3']['f-1']) m2 = sim2.get_model('TxEW-3', 1.0) g2 = sim2.get_grid('TxEW-3', 1.0) assert m1 == m2 assert g1 == g2 # to/from_dict sim1copy = sim1.copy() sim2copy = sim2.copy() m1c = sim1copy.get_model('TxEW-3', 1.0) g1c = sim1copy.get_grid('TxEW-3', 1.0) m2c = sim2copy.get_model('TxEW-3', 1.0) g2c = sim2copy.get_grid('TxEW-3', 1.0) assert m1 == m1c assert g1 == g1c assert m2 == m2c assert g2 == g2c def test_grid_provided(self): # Check bad grid hx = np.ones(17) * 20 grid = emg3d.TensorMesh([hx, hx, hx], (0, 0, 0)) with pytest.warns(UserWarning, match='optimal for MG solver. Good n'): simulations.Simulation(self.survey, self.model, gridding='input', gridding_opts=grid) def test_synthetic(self): sim = self.simulation.copy() sim._dict_efield = sim._dict_initiate # Reset sim.compute(observed=True, add_noise=False) assert_allclose(sim.data.synthetic, sim.data.observed) assert sim.survey.size == sim.data.observed.size def test_input_gradient(self): # Create another mesh, so there will be a difference. newgrid = emg3d.TensorMesh( [np.ones(16) * 500, np.ones(8) * 1000, np.ones(8) * 1000], np.array([-1250, -1250, -2250])) simulation = simulations.Simulation(self.survey, self.model, max_workers=1, solver_opts={ 'maxit': 1, 'verb': 0, 'sslsolver': False, 'linerelaxation': False, 'semicoarsening': False }, gridding='input', gridding_opts=newgrid, name='TestX') with pytest.warns(UserWarning, match='Receiver responses were obtain'): grad = simulation.gradient with pytest.warns(UserWarning, match='Receiver responses were obtain'): vec = simulation.data.residual.data.copy() vec *= simulation.data.weights.data jtvec = simulation.jtvec(vec) assert_allclose(grad, jtvec) jvec = simulation.jvec(np.ones(newgrid.n_cells)) assert jvec.shape == simulation.data.observed.data.shape # Ensure the gradient has the shape of the model, not of the input. assert grad.shape == self.model.shape sim2 = simulation.to_dict(what='all', copy=True) sim3 = simulation.to_dict(what='plain', copy=True) assert 'residual' in sim2['survey']['data'].keys() assert 'residual' not in sim3['survey']['data'].keys() simulation.clean('all') # Should remove 'residual', 'bfield-dicts' sim5 = simulation.to_dict('all') assert 'residual' not in sim5['survey']['data'].keys() assert '_dict_bfield' not in sim5.keys() def test_simulation_automatic(self, capsys): # Create a simple survey sources = emg3d.surveys.txrx_coordinates_to_dict( emg3d.TxElectricDipole, (0, [1000, 3000, 5000], -950, 0, 0)) receivers = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, ([-3000, 0, 3000], [0, 3000, 6000], -1000, 0, 0)) frequencies = (0.1, 1.0, 10.0) survey = emg3d.Survey(sources, receivers, frequencies, name='Test', noise_floor=1e-15, relative_error=0.05) # Create a simple grid and model grid = emg3d.TensorMesh( [np.ones(32) * 250, np.ones(16) * 500, np.ones(4) * 500], np.array([-1250, -1250, -2250])) model = emg3d.Model(grid, 1) # Create a simulation, compute all fields. inp = { 'survey': survey, 'model': model, 'gridding_opts': { 'expand': [1, 0.5], 'seasurface': 0, 'verb': 1 } } b_sim = simulations.Simulation(name='both', gridding='both', **inp) f_sim = simulations.Simulation(name='freq', gridding='frequency', **inp) t_sim = simulations.Simulation(name='src', gridding='source', **inp) s_sim = simulations.Simulation(name='single', gridding='single', **inp) # Quick repr test. assert " 24 x 24 (13,824) - 160 x 160 x 96 (2,457," in b_sim.__repr__() assert " 24 x 24 (13,824) - 160 x 160 x 96 (2,457," in f_sim.__repr__() assert "Source-dependent grids; 64 x 64 x 40 (163," in t_sim.__repr__() assert "ources and frequencies; 64 x 64 x 40 (163," in s_sim.__repr__() # Quick print_grid test: _, _ = capsys.readouterr() # empty b_sim.print_grid_info() out, _ = capsys.readouterr() assert "= Source: TxED-1; Frequency: 10.0 Hz =" in out assert "== GRIDDING IN X ==" in out assert b_sim.get_grid('TxED-1', 1.0).__repr__() in out _, _ = capsys.readouterr() # empty out = f_sim.print_grid_info(return_info=True) out2, _ = capsys.readouterr() assert out2 == "" assert "= Source: all" in out assert "== GRIDDING IN X ==" in out assert f_sim.get_grid('TxED-3', 1.0).__repr__() in out t_sim.print_grid_info() out, _ = capsys.readouterr() assert "; Frequency: all" in out assert "== GRIDDING IN X ==" in out assert t_sim.get_grid('TxED-1', 10.0).__repr__() in out _, _ = capsys.readouterr() # empty out = s_sim.print_grid_info(return_info=True) out2, _ = capsys.readouterr() assert out2 == "" assert "= Source: all; Frequency: all =" in out assert "== GRIDDING IN X ==" in out assert s_sim.get_grid('TxED-3', 0.1).__repr__() in out assert s_sim.print_grid_info(verb=-1) is None # Grids: Middle source / middle frequency should be the same in all. assert f_sim.get_grid('TxED-2', 1.0) == t_sim.get_grid('TxED-2', 1.0) assert f_sim.get_grid('TxED-2', 1.0) == s_sim.get_grid('TxED-2', 1.0) assert f_sim.get_grid('TxED-2', 1.0) == b_sim.get_grid('TxED-2', 1.0) assert f_sim.get_model('TxED-2', 1.0) == t_sim.get_model('TxED-2', 1.0) assert f_sim.get_model('TxED-2', 1.0) == s_sim.get_model('TxED-2', 1.0) assert f_sim.get_model('TxED-2', 1.0) == b_sim.get_model('TxED-2', 1.0) # Copy: f_sim_copy = f_sim.copy() assert (f_sim.get_grid('TxED-1', 1.0) == f_sim_copy.get_grid('TxED-1', 1.0)) assert 'expand' not in f_sim.gridding_opts.keys() assert 'expand' not in f_sim_copy.gridding_opts.keys() s_sim_copy = s_sim.copy() assert (s_sim.get_grid('TxED-1', 1.0) == s_sim_copy.get_grid('TxED-1', 1.0)) assert 'expand' not in s_sim.gridding_opts.keys() assert 'expand' not in s_sim_copy.gridding_opts.keys() t_sim_copy = t_sim.copy() assert (t_sim.get_grid('TxED-1', 1.0) == t_sim_copy.get_grid('TxED-1', 1.0)) assert 'expand' not in t_sim.gridding_opts.keys() assert 'expand' not in t_sim_copy.gridding_opts.keys() def test_print_solver(self, capsys): grid = emg3d.TensorMesh(h=[[(25, 10, -1.04), (25, 28), (25, 10, 1.04)], [(50, 8, -1.03), (50, 16), (50, 8, 1.03)], [(30, 8, -1.05), (30, 16), (30, 8, 1.05)]], origin='CCC') model = emg3d.Model(grid, property_x=1.5, property_y=1.8, property_z=3.3, mapping='Resistivity') sources = emg3d.TxElectricDipole((0, 0, 0, 0, 0)) receivers = [ emg3d.RxElectricPoint((x, 0, 0, 0, 0)) for x in [-10000, 10000] ] survey = emg3d.Survey( name='Test', sources=sources, receivers=receivers, frequencies=1.0, noise_floor=1e-15, relative_error=0.05, ) inp = { 'name': 'Test', 'survey': survey, 'model': model, 'gridding': 'same' } sol = { 'sslsolver': False, 'semicoarsening': False, 'linerelaxation': False, 'maxit': 1 } # Errors but verb=-1. _, _ = capsys.readouterr() # empty simulation = simulations.Simulation(verb=-1, **inp, solver_opts=sol) simulation.compute() out, _ = capsys.readouterr() assert out == "" # Errors with verb=0. out = simulation.print_solver_info('efield', verb=0, return_info=True) assert "= Source TxED-1; Frequency 1.0 Hz = MAX. ITERATION REAC" in out # Errors with verb=1. _, _ = capsys.readouterr() # empty simulation.print_solver_info('efield', verb=1) out, _ = capsys.readouterr() assert "= Source TxED-1; Frequency 1.0 Hz = 2.6e-02; 1; 0:00:" in out # No errors; solver-verb 3. simulation = simulations.Simulation(verb=1, **inp, solver_opts={'verb': 3}) simulation.compute() out, _ = capsys.readouterr() assert 'MG-cycle' in out assert 'CONVERGED' in out # No errors; solver-verb 0. simulation = simulations.Simulation(verb=1, **inp, solver_opts={'verb': 0}) simulation.compute() out, _ = capsys.readouterr() assert "= Source TxED-1; Frequency 1.0 Hz = CONVERGED" in out # Two sources, only compute 1, assure printing works. sources = [emg3d.TxElectricDipole((x, 0, 0, 0, 0)) for x in [0, 10]] survey = emg3d.Survey( name='Test', sources=sources, receivers=receivers, frequencies=1.0, noise_floor=1e-15, relative_error=0.05, ) inp = { 'name': 'Test', 'survey': survey, 'model': model, 'gridding': 'same' } simulation = simulations.Simulation(**inp, solver_opts={'verb': 0}) _ = simulation.get_efield('TxED-2', 'f-1') simulation.print_solver_info(verb=1) out, _ = capsys.readouterr() assert "= Source TxED-2; Frequency 1.0 Hz = CONVERGED" in out def test_rel_abs_rec(self): # Sources sources = emg3d.surveys.txrx_coordinates_to_dict( emg3d.TxElectricDipole, ([0, 100, 200], 0, 0, 0, 0)) # Abs and rel Receivers a_e_rec = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, (1000 + np.arange(3) * 100, 0, -100, 0, 0)) r_e_rec = emg3d.surveys.txrx_coordinates_to_dict(emg3d.RxElectricPoint, (1000, 0, -100, 0, 0), relative=True) a_h_rec = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxMagneticPoint, (1000 + np.arange(3) * 100, 0, -100, 0, 0)) r_h_rec = emg3d.surveys.txrx_coordinates_to_dict(emg3d.RxMagneticPoint, (1000, 0, -100, 0, 0), relative=True) receivers = emg3d.surveys.txrx_lists_to_dict( [a_e_rec, r_e_rec, a_h_rec, r_h_rec]) # Frequencies frequencies = (1.0) survey = emg3d.Survey(sources, receivers, frequencies, name='TestSurv', noise_floor=1e-15, relative_error=0.05) # Create a simple grid and model grid = emg3d.TensorMesh( [np.ones(32) * 250, np.ones(16) * 500, np.ones(16) * 500], np.array([-1250, -1250, -2250])) model = emg3d.Model(grid, 1) # Create a simulation, compute all fields. simulation = simulations.Simulation(survey, model, name='TestSim', max_workers=1, solver_opts={ 'maxit': 1, 'verb': 0, 'plain': True }, gridding='same') simulation.compute() # Relative receivers must be same as corresponding absolute receivers assert_allclose( [simulation.data.synthetic[i, i, 0].data for i in range(3)], simulation.data.synthetic[:, 3, 0].data) assert_allclose( [simulation.data.synthetic[i, i + 4, 0].data for i in range(3)], simulation.data.synthetic[:, 7, 0].data)
class TestEstimateGriddingOpts(): if xarray is not None: # Create a simple survey sources = emg3d.surveys.txrx_coordinates_to_dict( emg3d.TxElectricDipole, (0, [1000, 3000, 5000], -950, 0, 0)) receivers = emg3d.surveys.txrx_coordinates_to_dict( emg3d.RxElectricPoint, (np.arange(11)*500, 2000, -1000, 0, 0)) frequencies = (0.1, 10.0) survey = emg3d.Survey( sources, receivers, frequencies, noise_floor=1e-15, relative_error=0.05) # Create a simple grid and model grid = meshes.TensorMesh( [np.ones(32)*250, np.ones(16)*500, np.ones(16)*500], np.array([-1250, -1250, -2250])) model = emg3d.Model(grid, 0.1, np.ones(grid.shape_cells)*10) model.property_y[5, 8, 3] = 100000 # Cell at source center def test_empty_dict(self): gdict = meshes.estimate_gridding_opts({}, self.model, self.survey) assert gdict['frequency'] == 1.0 assert gdict['mapping'] == self.model.map.name assert_allclose(gdict['center'], (0, 3000, -950)) assert_allclose(gdict['domain']['x'], (-500, 5500)) assert_allclose(gdict['domain']['y'], (600, 5400)) assert_allclose(gdict['domain']['z'], (-3651, -651)) assert_allclose(gdict['properties'], [100000, 10, 10, 10, 10, 10, 10]) def test_mapping_vector(self): gridding_opts = { 'mapping': "LgConductivity", 'vector': 'xZ', } gdict = meshes.estimate_gridding_opts( gridding_opts, self.model, self.survey) assert_allclose( gdict['properties'], np.log10(1/np.array([100000, 10, 10, 10, 10, 10, 10])), atol=1e-15) assert_allclose(gdict['vector']['x'], self.grid.nodes_x) assert gdict['vector']['y'] is None assert_allclose(gdict['vector']['z'], self.grid.nodes_z) def test_vector_domain_distance(self): gridding_opts = { 'vector': 'Z', 'domain': (None, [-1000, 1000], None), 'distance': [[5, 10], None, None], } gdict = meshes.estimate_gridding_opts( gridding_opts, self.model, self.survey) assert gdict['vector']['x'] == gdict['vector']['y'] is None assert_allclose(gdict['vector']['z'], self.model.grid.nodes_z) assert gdict['domain']['x'] is None assert gdict['domain']['y'] == [-1000, 1000] assert gdict['domain']['z'] == [self.model.grid.nodes_z[0], self.model.grid.nodes_z[-1]] assert gdict['distance']['x'] == [5, 10] assert gdict['distance']['y'] == gdict['distance']['z'] is None # As dict gridding_opts = { 'vector': 'Z', 'domain': {'x': None, 'y': [-1000, 1000], 'z': None}, 'distance': {'x': [5, 10], 'y': None, 'z': None}, } gdict = meshes.estimate_gridding_opts( gridding_opts, self.model, self.survey) assert gdict['vector']['x'] == gdict['vector']['y'] is None assert_allclose(gdict['vector']['z'], self.model.grid.nodes_z) assert gdict['domain']['x'] is None assert gdict['domain']['y'] == [-1000, 1000] assert gdict['domain']['z'] == [self.model.grid.nodes_z[0], self.model.grid.nodes_z[-1]] assert gdict['distance']['x'] == [5, 10] assert gdict['distance']['y'] == gdict['distance']['z'] is None def test_pass_along(self): gridding_opts = { 'vector': {'x': None, 'y': 1, 'z': None}, 'stretching': [1.2, 1.3], 'seasurface': -500, 'cell_numbers': [10, 20, 30], 'lambda_factor': 0.8, 'max_buffer': 10000, 'min_width_limits': ([20, 40], [20, 40], [20, 40]), 'min_width_pps': 4, 'verb': -1, } gdict = meshes.estimate_gridding_opts( gridding_opts.copy(), self.model, self.survey) # Check that all parameters passed unchanged. gdict2 = {k: gdict[k] for k, _ in gridding_opts.items()} # Except the tuple, which should be a dict now gridding_opts['min_width_limits'] = { 'x': gridding_opts['min_width_limits'][0], 'y': gridding_opts['min_width_limits'][1], 'z': gridding_opts['min_width_limits'][2] } assert helpers.compare_dicts(gdict2, gridding_opts) def test_factor(self): sources = emg3d.TxElectricDipole((0, 3000, -950, 0, 0)) receivers = emg3d.RxElectricPoint((0, 3000, -1000, 0, 0)) # Adjusted x-domain. survey = emg3d.Survey( self.sources, receivers, self.frequencies, noise_floor=1e-15, relative_error=0.05) gdict = meshes.estimate_gridding_opts({}, self.model, survey) assert_allclose(gdict['domain']['x'], (-800, 800)) # Adjusted x-domain. survey = emg3d.Survey( sources, self.receivers, self.frequencies, noise_floor=1e-15, relative_error=0.05) gdict = meshes.estimate_gridding_opts({}, self.model, survey) assert_allclose(gdict['domain']['y'], (1500, 3500)) def test_error(self): with pytest.raises(TypeError, match='Unexpected gridding_opts'): _ = meshes.estimate_gridding_opts( {'what': True}, self.model, self.survey)
def test_gauss_seidel(njit): if njit: gauss_seidel = core.gauss_seidel gauss_seidel_x = core.gauss_seidel_x gauss_seidel_y = core.gauss_seidel_y gauss_seidel_z = core.gauss_seidel_z else: gauss_seidel = core.gauss_seidel.py_func gauss_seidel_x = core.gauss_seidel_x.py_func gauss_seidel_y = core.gauss_seidel_y.py_func gauss_seidel_z = core.gauss_seidel_z.py_func # At the moment we only compare `gauss_seidel_x/y/z` to `gauss_seidel`. # Better tests would always be welcomed... # Rotate the source, so we have a strong enough signal in all directions src = [0, 0, 0, 45, 45] freq = 0.9 nu = 2 # One back-and-forth for lr_dir in range(1, 4): # `gauss_seidel`/`_x/y/z` loop over z, then y, then x. Together with # `lr_dir`, we have to keep the dimension at 2 in order that they # agree. nx = [1, 4, 4][lr_dir - 1] ny = [4, 1, 4][lr_dir - 1] nz = [4, 4, 1][lr_dir - 1] # Get this grid. hx = helpers.widths(0, nx, 80, 1.1) hy = helpers.widths(0, ny, 100, 1.3) hz = helpers.widths(0, nz, 200, 1.2) grid = emg3d.TensorMesh( [hx, hy, hz], np.array([-hx.sum() / 2, -hy.sum() / 2, -hz.sum() / 2])) # Initialize model with some resistivities. property_x = np.arange(grid.n_cells) + 1 property_y = 0.5 * np.arange(grid.n_cells) + 1 property_z = 2 * np.arange(grid.n_cells) + 1 model = emg3d.Model(grid, property_x, property_y, property_z) # Initialize source field. sfield = emg3d.get_source_field(grid, src, freq) # Get volume-averaged model parameters. vmodel = emg3d.models.VolumeModel(model, sfield) # Run two iterations to get some e-field. efield = emg3d.solve(model, sfield, sslsolver=False, semicoarsening=False, linerelaxation=False, maxit=2, verb=1) inp = (sfield.fx, sfield.fy, sfield.fz, vmodel.eta_x, vmodel.eta_y, vmodel.eta_z, vmodel.zeta, grid.h[0], grid.h[1], grid.h[2], nu) # Get result from `gauss_seidel`. cfield = emg3d.Field(grid, efield.field.copy(), frequency=efield._frequency) gauss_seidel(cfield.fx, cfield.fy, cfield.fz, *inp) # Get result from `gauss_seidel_x/y/z`. if lr_dir == 1: gauss_seidel_x(efield.fx, efield.fy, efield.fz, *inp) elif lr_dir == 2: gauss_seidel_y(efield.fx, efield.fy, efield.fz, *inp) elif lr_dir == 3: gauss_seidel_z(efield.fx, efield.fy, efield.fz, *inp) # Check the resulting field. assert efield == cfield