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_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_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_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_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_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_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 alt_get_magnetic_field(model, efield): r"""Return magnetic field corresponding to provided electric field. Retrieve the magnetic field :math:`\mathbf{H}` from the electric field :math:`\mathbf{E}` using Farady's law, given by .. math:: \nabla \times \mathbf{E} = \rm{i}\omega\mu\mathbf{H} . Note that the magnetic field is defined on the faces of the grid, or on the edges of the so-called dual grid. The grid of the returned magnetic field is the dual grid and has therefore one cell less in each direction. Parameters ---------- model : Model The model; a :class:`emg3d.models.Model` instance. efield : Field The electric field; a :class:`emg3d.fields.Field` instance. Returns ------- hfield : Field The magnetic field; a :class:`emg3d.fields.Field` instance. """ grid = efield.grid # Carry out the curl (^ corresponds to differentiation axis): # H_x = (E_z^1 - E_y^2) e3d_hx = (np.diff(efield.fz, axis=1) / efield.grid.h[1][None, :, None] - np.diff(efield.fy, axis=2) / efield.grid.h[2][None, None, :]) e3d_hx[0, :, :] = e3d_hx[-1, :, :] = 0 # H_y = (E_x^2 - E_z^0) e3d_hy = (np.diff(efield.fx, axis=2) / efield.grid.h[2][None, None, :] - np.diff(efield.fz, axis=0) / efield.grid.h[0][:, None, None]) e3d_hy[:, 0, :] = e3d_hy[:, -1, :] = 0 # H_z = (E_y^0 - E_x^1) e3d_hz = (np.diff(efield.fy, axis=0) / efield.grid.h[0][:, None, None] - np.diff(efield.fx, axis=1) / efield.grid.h[1][None, :, None]) e3d_hz[:, :, 0] = e3d_hz[:, :, -1] = 0 # Divide by averaged relative magnetic permeability, if not not None. if model.mu_r is not None: # Get volume-averaged values. vmodel = emg3d.models.VolumeModel(model, efield) # Plus and minus indices. ixm = np.r_[0, np.arange(grid.shape_cells[0])] ixp = np.r_[np.arange(grid.shape_cells[0]), grid.shape_cells[0] - 1] iym = np.r_[0, np.arange(grid.shape_cells[1])] iyp = np.r_[np.arange(grid.shape_cells[1]), grid.shape_cells[1] - 1] izm = np.r_[0, np.arange(grid.shape_cells[2])] izp = np.r_[np.arange(grid.shape_cells[2]), grid.shape_cells[2] - 1] # Average mu_r for dual-grid. zeta_x = (vmodel.zeta[ixm, :, :] + vmodel.zeta[ixp, :, :]) / 2. zeta_y = (vmodel.zeta[:, iym, :] + vmodel.zeta[:, iyp, :]) / 2. zeta_z = (vmodel.zeta[:, :, izm] + vmodel.zeta[:, :, izp]) / 2. hvx = grid.h[0][:, None, None] hvy = grid.h[1][None, :, None] hvz = grid.h[2][None, None, :] # Define the widths of the dual grid. dx = (np.r_[0., grid.h[0]] + np.r_[grid.h[0], 0.]) / 2. dy = (np.r_[0., grid.h[1]] + np.r_[grid.h[1], 0.]) / 2. dz = (np.r_[0., grid.h[2]] + np.r_[grid.h[2], 0.]) / 2. # Multiply fields by mu_r. e3d_hx *= zeta_x / (dx[:, None, None] * hvy * hvz) e3d_hy *= zeta_y / (hvx * dy[None, :, None] * hvz) e3d_hz *= zeta_z / (hvx * hvy * dz[None, None, :]) new = np.r_[e3d_hx.ravel('F'), e3d_hy.ravel('F'), e3d_hz.ravel('F')] hfield = emg3d.Field(efield.grid, data=new, frequency=efield._frequency, electric=False) hfield.field /= efield.smu0 # Return. return hfield
def test_RegularGridProlongator(): def prolon_scipy(grid, cgrid, efield, cefield): CZ, CY = np.broadcast_arrays(grid.nodes_z, grid.nodes_y[:, None]) yz = np.r_[CY.ravel('F'), CZ.ravel('F')].reshape(-1, 2, order='F') """Compute SciPy alternative.""" for ixc in range(cgrid.shape_cells[0]): # Bilinear interpolation in the y-z plane fn = si.RegularGridInterpolator((cgrid.nodes_y, cgrid.nodes_z), cefield.fx[ixc, :, :], bounds_error=False, fill_value=None) hh = fn(yz).reshape(grid.shape_edges_x[1:], order='F') # Piecewise constant interpolation in x-direction efield[2 * ixc, :, :] += hh efield[2 * ixc + 1, :, :] += hh return efield def prolon_emg3d(grid, cgrid, efield, cefield): """Compute emg3d alternative.""" fn = solver.RegularGridProlongator(cgrid.nodes_y, cgrid.nodes_z, grid.nodes_y, grid.nodes_z) for ixc in range(cgrid.shape_cells[0]): # Bilinear interpolation in the y-z plane hh = fn(cefield.fx[ixc, :, :]).reshape(grid.shape_edges_x[1:], order='F') # Piecewise constant interpolation in x-direction efield[2 * ixc, :, :] += hh efield[2 * ixc + 1, :, :] += hh return efield # Create fine grid. nx = 2**7 hx = 50 * np.ones(nx) hx = np.array([4, 1.1, 2, 3]) hy = np.array([2, 0.1, 20, np.pi]) hz = np.array([1, 2, 5, 1]) grid = emg3d.TensorMesh([hx, hy, hz], origin=np.array([0, 0, 0])) # Create coarse grid. chx = np.diff(grid.nodes_x[::2]) cgrid = emg3d.TensorMesh([chx, chx, chx], origin=np.array([0, 0, 0])) # Create empty fine grid fields. efield1 = emg3d.Field(grid) efield2 = emg3d.Field(grid) # Create coarse grid field with some values. cefield = emg3d.Field(cgrid) cefield.fx = np.arange(cefield.fx.size) cefield.fx = 1j * np.arange(cefield.fx.size) / 10 # Compare out1 = prolon_scipy(grid, cgrid, efield1.fx, cefield) out2 = prolon_emg3d(grid, cgrid, efield2.fx, cefield) assert_allclose(out1, out2)
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
def test_regression(self, capsys): # Mainly regression tests # Create some dummy data grid = emg3d.TensorMesh( [np.array([2, 2]), np.array([3, 4]), np.array([0.5, 2])], np.zeros(3)) property_x = helpers.dummy_field(*grid.shape_cells, False) property_y = property_x / 2.0 property_z = property_x * 1.4 mu_r = property_x * 1.11 _, _ = capsys.readouterr() # Clean-up # Using defaults; check backwards compatibility for freq. sfield = emg3d.Field(grid, frequency=1) model1 = models.Model(grid) # Check representation of Model. assert 'Model: resistivity; isotropic' in model1.__repr__() vmodel1 = models.VolumeModel(model1, sfield) assert_allclose(model1.size, grid.n_cells) assert_allclose(model1.shape, grid.shape_cells) assert_allclose(vmodel1.eta_z, vmodel1.eta_y) assert model1.property_y is None assert model1.property_z is None assert model1.mu_r is None assert model1.epsilon_r is None # Using ints model2 = models.Model(grid, 2., 3., 4.) vmodel2 = models.VolumeModel(model2, sfield) assert_allclose(model2.property_x * 1.5, model2.property_y) assert_allclose(model2.property_x * 2, model2.property_z) # VTI: Setting property_x and property_z, not property_y model2b = models.Model(grid, 2., property_z=4., epsilon_r=1) vmodel2b = models.VolumeModel(model2b, sfield) assert model1.property_y is None assert_allclose(vmodel2b.eta_y, vmodel2b.eta_x) model2b.property_z = model2b.property_x model2c = models.Model(grid, 2., property_z=model2b.property_z.copy()) vmodel2c = models.VolumeModel(model2c, sfield) assert_allclose(model2c.property_x, model2c.property_z) assert_allclose(vmodel2c.eta_z, vmodel2c.eta_x) # HTI: Setting property_x and property_y, not property_z model2d = models.Model(grid, 2., 4.) vmodel2d = models.VolumeModel(model2d, sfield) assert model1.property_z is None assert_allclose(vmodel2d.eta_z, vmodel2d.eta_x) # Pure air, epsilon_r init with 0 => should be 1! model6 = models.Model(grid, 2e14) assert model6.epsilon_r is None # Check wrong shape with pytest.raises(ValueError, match='could not be broadcast'): models.Model(grid, np.arange(1, 11)) with pytest.raises(ValueError, match='could not be broadcast'): models.Model(grid, property_y=np.ones((2, 5, 6))) # Actual broadcasting. models.Model(grid, property_z=np.array([1, 3])) models.Model(grid, mu_r=np.array([[ 1, ], [ 3, ]])) # Check with all inputs gridvol = grid.cell_volumes.reshape(grid.shape_cells, order='F') model3 = models.Model(grid, property_x, property_y, property_z, mu_r=mu_r) vmodel3 = models.VolumeModel(model3, sfield) assert_allclose(model3.property_x, model3.property_y * 2) assert_allclose(model3.property_x.shape, grid.shape_cells) assert_allclose(model3.property_x, model3.property_z / 1.4) assert_allclose(gridvol / mu_r, vmodel3.zeta) # Check with all inputs model3b = models.Model(grid, property_x.ravel('F'), property_y.ravel('F'), property_z.ravel('F'), mu_r=mu_r.ravel('F')) vmodel3b = models.VolumeModel(model3b, sfield) assert_allclose(model3b.property_x, model3b.property_y * 2) assert_allclose(model3b.property_x.shape, grid.shape_cells) assert_allclose(model3b.property_x, model3b.property_z / 1.4) assert_allclose(gridvol / mu_r, vmodel3b.zeta) # Check setters shape_cells tres = np.ones(grid.shape_cells) model3.property_x[:, :, :] = tres * 2.0 model3.property_y[:, :1, :] = tres[:, :1, :] * 3.0 model3.property_y[:, 1:, :] = tres[:, 1:, :] * 3.0 model3.property_z = tres * 4.0 model3.mu_r = tres * 5.0 assert_allclose(tres * 2., model3.property_x) assert_allclose(tres * 3., model3.property_y) assert_allclose(tres * 4., model3.property_z) # Check eta iomep = sfield.sval * models.epsilon_0 eta_x = -sfield.smu0 * (1. / model3.property_x - iomep) * gridvol eta_y = -sfield.smu0 * (1. / model3.property_y - iomep) * gridvol eta_z = -sfield.smu0 * (1. / model3.property_z - iomep) * gridvol vmodel3 = models.VolumeModel(model3, sfield) assert_allclose(vmodel3.eta_x, eta_x) assert_allclose(vmodel3.eta_y, eta_y) assert_allclose(vmodel3.eta_z, eta_z) # Check volume assert_allclose(grid.cell_volumes.reshape(grid.shape_cells, order='F'), vmodel2.zeta) model4 = models.Model(grid, 1) vmodel4 = models.VolumeModel(model4, sfield) assert_allclose(vmodel4.zeta, grid.cell_volumes.reshape(grid.shape_cells, order='F')) # Check a couple of out-of-range failures with pytest.raises(ValueError, match='`property_x` must be all'): with np.errstate(all='ignore'): _ = models.Model(grid, property_x=property_x * 0) Model = models.Model(grid, property_x=property_x) with pytest.raises(ValueError, match='`property_x` must be all'): with np.errstate(all='ignore'): Model._check_positive_finite(property_x * 0, 'property_x') with pytest.raises(ValueError, match='`property_x` must be all'): Model._check_positive_finite(-1.0, 'property_x') with pytest.raises(ValueError, match='`property_y` must be all'): _ = models.Model(grid, property_y=np.inf) with pytest.raises(ValueError, match='`property_z` must be all'): _ = models.Model(grid, property_z=property_z * np.inf) with pytest.raises(ValueError, match='`mu_r` must be all'): _ = models.Model(grid, mu_r=-1)
def test_restrict(njit): if njit: restrict = core.restrict restrict_weights = core.restrict_weights else: restrict = core.restrict.py_func restrict_weights = core.restrict_weights.py_func # Simple comparison using the most basic mesh. h = np.array([1, 1, 1, 1, 1, 1]) # Fine grid. fgrid = emg3d.TensorMesh([h, h, h], origin=np.array([-3, -3, -3])) # Create fine field. ffield = emg3d.Field(fgrid) # Put in values. ffield.fx[:, 1:-1, 1:-1] = 1 ffield.fy[1:-1, :, 1:-1] = 2 ffield.fz[1:-1, 1:-1, :] = 4 # Get weigths wlr = np.zeros(fgrid.shape_nodes[0], dtype=np.float64) w0 = np.ones(fgrid.shape_nodes[0], dtype=np.float64) fw = (wlr, w0, wlr) # # CASE 0 -- regular # # # Coarse grid. cgrid = emg3d.TensorMesh([ np.diff(fgrid.nodes_x[::2]), np.diff(fgrid.nodes_y[::2]), np.diff(fgrid.nodes_z[::2]) ], fgrid.origin) # Regular grid, so all weights (wx, wy, wz) are the same... w = restrict_weights(fgrid.nodes_x, fgrid.cell_centers_x, fgrid.h[0], cgrid.nodes_x, cgrid.cell_centers_x, cgrid.h[0]) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict it. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, w, w, w, 0) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fx[0, :, :] * 2, cfield.fy[:, 0, :]) assert_allclose(cfield.fy[:, 0, :] * 2, cfield.fz[:, :, 0]) # # CASE 1 -- y & z # # # Coarse grid. cgrid = emg3d.TensorMesh( [fgrid.h[0], np.diff(fgrid.nodes_y[::2]), np.diff(fgrid.nodes_z[::2])], fgrid.origin) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict field. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, fw, w, w, 1) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fy[:, 0, :] * 2, cfield.fz[:, :, 0]) # # CASE 2 -- x & z # # # Coarse grid. cgrid = emg3d.TensorMesh( [np.diff(fgrid.nodes_x[::2]), fgrid.h[1], np.diff(fgrid.nodes_z[::2])], fgrid.origin) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict field. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, w, fw, w, 2) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fx[0, :, :].T * 4, cfield.fz[:, :, 0]) # # CASE 3 -- x & y # # # Coarse grid. cgrid = emg3d.TensorMesh( [np.diff(fgrid.nodes_x[::2]), np.diff(fgrid.nodes_y[::2]), fgrid.h[2]], fgrid.origin) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict field. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, w, w, fw, 3) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fx[0, :, :] * 2, cfield.fy[:, 0, :]) # # CASE 4 -- x # # # Coarse grid. cgrid = emg3d.TensorMesh( [np.diff(fgrid.nodes_x[::2]), fgrid.h[1], fgrid.h[2]], fgrid.origin) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict field. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, w, fw, fw, 4) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fy[:, 0, :] * 2, cfield.fz[:, :, 0]) # # CASE 5 -- y # # # Coarse grid. cgrid = emg3d.TensorMesh( [fgrid.h[0], np.diff(fgrid.nodes_y[::2]), fgrid.h[2]], fgrid.origin) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict field. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, fw, w, fw, 5) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fx[0, :, :].T * 4, cfield.fz[:, :, 0]) # # CASE 6 -- z # # # Coarse grid. cgrid = emg3d.TensorMesh( [fgrid.h[0], fgrid.h[1], np.diff(fgrid.nodes_z[::2])], fgrid.origin) # Create coarse field. cfield = emg3d.Field(cgrid) # Restrict field. restrict(cfield.fx, cfield.fy, cfield.fz, ffield.fx, ffield.fy, ffield.fz, fw, fw, w, 6) # Check sum of fine and coarse fields. assert cfield.fx.sum() == ffield.fx.sum() assert cfield.fy.sum() == ffield.fy.sum() assert cfield.fz.sum() == ffield.fz.sum() # Assert fields are multiples from each other. assert_allclose(cfield.fx[0, :, :] * 2, cfield.fy[:, 0, :])
def test_homogeneous(self, capsys): # Regression test for homogeneous halfspace. dat = REGRES['res'] model = emg3d.Model(**dat['input_model']) grid = model.grid sfield = emg3d.get_source_field(**dat['input_source']) # F-cycle efield = solver.solve(model=model, sfield=sfield, plain=True, verb=4) out, _ = capsys.readouterr() assert ' emg3d START ::' in out assert ' [hh:mm:ss] ' in out assert ' MG cycles ' in out assert ' Final rel. error ' in out assert ' emg3d END :: ' in out # Experimental: # Check if norms are also the same, at least for first two cycles. assert "3.399e-02 after 1 F-cycles [1.830e-07, 0.034] 0 " in out assert "3.535e-03 after 2 F-cycles [1.903e-08, 0.104] 0 " in out # Check all fields (ex, ey, and ez) assert_allclose(dat['Fresult'].field, efield.field) # W-cycle wfield = solver.solve(model, sfield, plain=True, cycle='W') # Check all fields (ex, ey, and ez) assert_allclose(dat['Wresult'].field, wfield.field) # V-cycle vfield = solver.solve(model, sfield, plain=True, cycle='V') _, _ = capsys.readouterr() # clear output # Check all fields (ex, ey, and ez) assert_allclose(dat['Vresult'].field, vfield.field) # BiCGSTAB with some print checking. efield = solver.solve(model, sfield, verb=4, sslsolver='bicgstab', plain=True) out, _ = capsys.readouterr() assert ' emg3d START ::' in out assert ' [hh:mm:ss] ' in out assert ' CONVERGED' in out assert ' Solver steps ' in out assert ' MG prec. steps ' in out assert ' Final rel. error ' in out assert ' emg3d END :: ' in out # Check all fields (ex, ey, and ez) assert_allclose(dat['bicresult'].field, efield.field) # Same as previous, without BiCGSTAB, but some print checking. efield = solver.solve(model, sfield, plain=True, verb=4) out, _ = capsys.readouterr() assert ' emg3d START ::' in out assert ' [hh:mm:ss] ' in out assert ' CONVERGED' in out assert ' MG cycles ' in out assert ' Final rel. error ' in out assert ' emg3d END :: ' in out # Max it maxit = 2 _, info = solver.solve(model, sfield, plain=True, verb=3, maxit=maxit, return_info=True) out, _ = capsys.readouterr() assert ' MAX. ITERATION REACHED' in out assert maxit == info['it_mg'] assert info['exit'] == 1 assert 'MAX. ITERATION REACHED' in info['exit_message'] # BiCGSTAB with lower verbosity, print checking. _ = solver.solve(model, sfield, sslsolver='bicgstab', plain=True, verb=3, maxit=1) out, _ = capsys.readouterr() assert ' MAX. ITERATION REACHED' in out # Just check if it runs without failing for other solvers. _ = solver.solve(model, sfield, sslsolver='gcrotmk', plain=True, verb=5, maxit=1) # Provide initial field. _, _ = capsys.readouterr() # empty efield_copy = efield.copy() outarray = solver.solve(model, sfield, plain=True, efield=efield_copy, verb=3) out, _ = capsys.readouterr() # Ensure there is no output. assert outarray is None assert "NOTHING DONE (provided efield already good enough)" in out # Ensure the field did not change. assert_allclose(efield.field, efield_copy.field) # Provide initial field and return info. info = solver.solve(model, sfield, plain=True, efield=efield_copy, return_info=True) assert info['it_mg'] == 0 assert info['it_ssl'] == 0 assert info['exit'] == 0 assert info['exit_message'] == 'CONVERGED' # Provide initial field, ensure one initial multigrid is carried out # without linerelaxation nor semicoarsening. _, _ = capsys.readouterr() # empty efield = emg3d.Field(grid) outarray = solver.solve(model, sfield, efield=efield, maxit=2, verb=4) out, _ = capsys.readouterr() assert "after 1 F-cycles 4 1" in out assert "after 2 F-cycles 5 2" in out # Provide an initial source-field without frequency information. wrong_sfield = emg3d.Field(grid) wrong_sfield.field = sfield.field with pytest.raises(ValueError, match="Source field is missing frequ"): solver.solve(model, wrong_sfield, plain=True, efield=efield, verb=1) # Check stagnation by providing an almost zero source field. sfield.field = 1e-10 _ = solver.solve(model, sfield, plain=True, maxit=100) out, _ = capsys.readouterr() assert "STAGNATED" in out # Check a zero field is returned for a zero source field. sfield.field = 0 efield = solver.solve(model, sfield, plain=True, maxit=100, verb=3) out, _ = capsys.readouterr() assert "RETURN ZERO E-FIELD (provided sfield is zero)" in out assert np.linalg.norm(efield.field) == 0.0
def test_interp_edges_to_vol_averages(njit): if njit: edges_to_vol_averages = maps.interp_edges_to_vol_averages else: edges_to_vol_averages = maps.interp_edges_to_vol_averages.py_func # To test it, we create a mesh 2x2x2 cells, # where all hx/hy/hz have distinct lengths. x0, x1 = 2, 3 y0, y1 = 4, 5 z0, z1 = 6, 7 grid = emg3d.TensorMesh([[x0, x1], [y0, y1], [z0, z1]], [0, 0, 0]) field = emg3d.Field(grid) # Only three edges have a value, one in each direction. fx = 1.23+9.87j fy = 2.68-5.48j fz = 1.57+7.63j field.fx[0, 1, 1] = fx field.fy[1, 1, 1] = fy field.fz[1, 1, 0] = fz # Initiate gradient. grad_x = np.zeros(grid.shape_cells, order='F', dtype=complex) grad_y = np.zeros(grid.shape_cells, order='F', dtype=complex) grad_z = np.zeros(grid.shape_cells, order='F', dtype=complex) cell_volumes = grid.cell_volumes.reshape(grid.shape_cells, order='F') # Call function. edges_to_vol_averages(ex=field.fx, ey=field.fy, ez=field.fz, volumes=cell_volumes, ox=grad_x, oy=grad_y, oz=grad_z) grad = grad_x + grad_y + grad_z # Check all eight cells explicitly by # - computing the volume of the cell; # - multiplying with the present fields in that cell. assert_allclose(x0*y0*z0*(fx+fz)/4, grad[0, 0, 0]) assert_allclose(x1*y0*z0*fz/4, grad[1, 0, 0]) assert_allclose(x0*y1*z0*(fx+fy+fz)/4, grad[0, 1, 0]) assert_allclose(x1*y1*z0*(fy+fz)/4, grad[1, 1, 0]) assert_allclose(x0*y0*z1*fx/4, grad[0, 0, 1]) assert_allclose(0j, grad[1, 0, 1]) assert_allclose(x0*y1*z1*(fx+fy)/4, grad[0, 1, 1]) assert_allclose(x1*y1*z1*fy/4, grad[1, 1, 1]) # Separately. assert_allclose(x0*y0*z0*fx/4, grad_x[0, 0, 0]) assert_allclose(x0*y0*z0*fz/4, grad_z[0, 0, 0]) assert_allclose(x0*y1*z0*fx/4, grad_x[0, 1, 0]) assert_allclose(x0*y1*z0*fy/4, grad_y[0, 1, 0]) assert_allclose(x0*y1*z0*fz/4, grad_z[0, 1, 0]) assert_allclose(x1*y1*z0*fy/4, grad_y[1, 1, 0]) assert_allclose(x1*y1*z0*fz/4, grad_z[1, 1, 0]) assert_allclose(x0*y1*z1*fx/4, grad_x[0, 1, 1]) assert_allclose(x0*y1*z1*fy/4, grad_y[0, 1, 1]) if discretize is not None: def volume_disc(grid, field): out = grid.average_edge_to_cell*field.field*grid.cell_volumes return out.reshape(grid.shape_cells, order='F') assert_allclose(grad, 3*volume_disc(grid, field)) if discretize is not None: out_x = grid.average_edge_x_to_cell*field.fx.ravel('F') out_x *= grid.cell_volumes out_y = grid.average_edge_y_to_cell*field.fy.ravel('F') out_y *= grid.cell_volumes out_z = grid.average_edge_z_to_cell*field.fz.ravel('F') out_z *= grid.cell_volumes assert_allclose(grad_x, out_x.reshape(grid.shape_cells, order='F')) assert_allclose(grad_y, out_y.reshape(grid.shape_cells, order='F')) assert_allclose(grad_z, out_z.reshape(grid.shape_cells, order='F'))
def test_smoothing(): # 1. The only thing to test here is that smoothing returns the same as # the corresponding jitted functions. Basically a copy of the function # itself. nu = 2 widths = [ np.ones(2) * 100, helpers.widths(10, 27, 10, 1.1), helpers.widths(2, 1, 50, 1.2) ] origin = [-w.sum() / 2 for w in widths] src = [0, -10, -10, 43, 13] # Loop and move the 2-cell dimension (100, 2) from x to y to z. for xyz in range(3): # Create a grid grid = emg3d.TensorMesh( [widths[xyz % 3], widths[(xyz + 1) % 3], widths[(xyz + 2) % 3]], origin=np.array([ origin[xyz % 3], origin[(xyz + 1) % 3], origin[(xyz + 2) % 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 field = solver.solve(model, sfield, maxit=2) # Collect Gauss-Seidel input (same for all routines) 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) func = ['', '_x', '_y', '_z'] for lr_dir in range(8): # Get it directly from core efield = emg3d.Field(grid, field.field) finp = (efield.fx, efield.fy, efield.fz) if lr_dir < 4: getattr(emg3d.core, 'gauss_seidel' + func[lr_dir])(efield.fx, efield.fy, efield.fz, *inp) elif lr_dir == 4: emg3d.core.gauss_seidel_y(*finp, *inp) emg3d.core.gauss_seidel_z(*finp, *inp) elif lr_dir == 5: emg3d.core.gauss_seidel_x(*finp, *inp) emg3d.core.gauss_seidel_z(*finp, *inp) elif lr_dir == 6: emg3d.core.gauss_seidel_x(*finp, *inp) emg3d.core.gauss_seidel_y(*finp, *inp) elif lr_dir == 7: emg3d.core.gauss_seidel_x(*finp, *inp) emg3d.core.gauss_seidel_y(*finp, *inp) emg3d.core.gauss_seidel_z(*finp, *inp) # Use solver.smoothing ofield = emg3d.Field(grid, field.field) solver.smoothing(vmodel, sfield, ofield, nu, lr_dir) # Compare assert efield == ofield
class TestSaveLoad: 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)) a = np.arange(10.) b = 1+5j data = { 'Grid': grid, 'Model': model, 'Field': field, 'a': a, 'b': b, } 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 def test_npz(self, tmpdir, capsys): io.save(tmpdir+'/test.npz', **self.data) outstr, _ = capsys.readouterr() assert 'Data saved to «' in outstr assert emg3d.__version__ in outstr # Save it with other verbosity. _, _ = capsys.readouterr() io.save(tmpdir+'/test.npz', **self.data, verb=0) outstr, _ = capsys.readouterr() assert outstr == "" out = io.save(tmpdir+'/test.npz', **self.data, verb=-1) assert 'Data saved to «' in out # Load it. out_npz = io.load(str(tmpdir+'/test.npz'), allow_pickle=True) outstr, _ = capsys.readouterr() assert 'Data loaded from «' in outstr assert 'test.npz' in outstr assert emg3d.__version__ in outstr assert out_npz['Model'] == self.model assert_allclose(out_npz['a'], self.a) assert out_npz['b'] == self.b assert_allclose(self.field.fx, out_npz['Field'].fx) assert_allclose(self.grid.cell_volumes, out_npz['Grid'].cell_volumes) # Load it with other verbosity. _, _ = capsys.readouterr() out = io.load(tmpdir+'/test.npz', verb=0) outstr, _ = capsys.readouterr() assert outstr == "" out, out_str = io.load(tmpdir+'/test.npz', verb=-1) assert 'Data loaded from «' in out_str def test_h5(self, tmpdir): if h5py: io.save(tmpdir+'/test.h5', **self.data) out_h5 = io.load(str(tmpdir+'/test.h5')) assert out_h5['Model'] == self.model assert_allclose(out_h5['a'], self.a) assert out_h5['b'] == self.b assert_allclose(self.field.fx, out_h5['Field'].fx) assert_allclose(self.grid.cell_volumes, out_h5['Grid'].cell_volumes) else: with pytest.warns(UserWarning, match='emg3d: This feature requir'): io.save(tmpdir+'/test.h5', grid=self.grid) def test_json(self, tmpdir): io.save(tmpdir+'/test.json', **self.data) out_json = io.load(str(tmpdir+'/test.json')) assert out_json['Model'] == self.model assert_allclose(out_json['a'], self.a) assert out_json['b'] == self.b assert_allclose(self.field.fx, out_json['Field'].fx) assert_allclose(self.grid.cell_volumes, out_json['Grid'].cell_volumes) def test_warnings(self, tmpdir, capsys): # Check message from loading another file data = io._dict_serialize({'meshes': self.grid}) fdata = io._dict_flatten(data) np.savez_compressed(tmpdir+'/test2.npz', **fdata) _ = io.load(str(tmpdir+'/test2.npz'), allow_pickle=True) outstr, _ = capsys.readouterr() assert "[version/format/date unknown; not created by emg" in outstr # Unknown keyword. with pytest.raises(TypeError, match="Unexpected "): io.load('ttt.npz', stupidkeyword='a') # Unknown extension. with pytest.raises(ValueError, match="Unknown extension '.abc'"): io.save(tmpdir+'/testwrongextension.abc', something=1) with pytest.raises(ValueError, match="Unknown extension '.abc'"): io.load(tmpdir+'/testwrongextension.abc')