コード例 #1
0
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)
コード例 #2
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
    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)
コード例 #3
0
    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')
コード例 #4
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
    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
コード例 #5
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
    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
コード例 #6
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
    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
コード例 #7
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
    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)
コード例 #8
0
    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')
コード例 #9
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)
コード例 #10
0
ファイル: test_simulations.py プロジェクト: emsig/emg3d
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
コード例 #11
0
ファイル: alternatives.py プロジェクト: emsig/emg3d
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
コード例 #12
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
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)
コード例 #13
0
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
コード例 #14
0
ファイル: test_models.py プロジェクト: emsig/emg3d
    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)
コード例 #15
0
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, :])
コード例 #16
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
    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
コード例 #17
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'))
コード例 #18
0
ファイル: test_solver.py プロジェクト: emsig/emg3d
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
コード例 #19
0
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')