Beispiel #1
0
    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)
Beispiel #2
0
def test_solver_homogeneous_laplace():
    # Regression test for homogeneous halfspace in Laplace domain.
    # Not very sophisticated; replace/extend by more detailed tests.
    dat = REGRES['lap'][()]

    grid = utils.TensorMesh(**dat['input_grid'])
    model = utils.Model(**dat['input_model'])
    sfield = utils.get_source_field(**dat['input_source'])

    # F-cycle
    efield = solver.solve(grid, model, sfield, verb=1)

    # Check all fields (ex, ey, and ez)
    assert_allclose(dat['Fresult'], efield)

    # BiCGSTAB with some print checking.
    efield = solver.solve(grid, model, sfield, verb=1, sslsolver=True)

    # Check all fields (ex, ey, and ez)
    assert_allclose(dat['bicresult'], efield)

    # If efield is complex, assert it fails.
    efield = utils.Field(grid, dtype=complex)

    with pytest.raises(ValueError):
        efield = solver.solve(grid, model, sfield, efield=efield, verb=1)
Beispiel #3
0
    def test_log(self, capsys):
        dat = REGRES['res']

        model = emg3d.Model(**dat['input_model'])
        sfield = emg3d.get_source_field(**dat['input_source'])
        inp = {'model': model, 'sfield': sfield, 'plain': True, 'maxit': 1}

        efield, info = solver.solve(return_info=True, log=-1, verb=3, **inp)
        out, _ = capsys.readouterr()
        assert out == ""
        assert ' emg3d START ::' in info['log']

        efield = solver.solve(return_info=True, log=0, verb=3, **inp)
        out, _ = capsys.readouterr()
        assert ' emg3d START ::' in out

        efield, info = solver.solve(return_info=True, log=1, verb=3, **inp)
        out, _ = capsys.readouterr()
        assert ' emg3d START ::' in out
        assert ' emg3d START ::' in info['log']

        efield, info = solver.solve(return_info=True, log=1, verb=1, **inp)
        out, _ = capsys.readouterr()
        assert 'MAX. ITERATION REACHED, NOT CONVERGED' in out
        assert 'MAX. ITERATION REACHED, NOT CONVERGED' in info['log']
Beispiel #4
0
def test_solver_heterogeneous(capsys):
    # Regression test for heterogeneous case.
    dat = REGRES['reg_2'][()]
    grid = dat['grid']
    model = dat['model']
    sfield = dat['sfield']
    inp = dat['inp']
    inp['verb'] = 4

    efield = solver.solve(grid, model, sfield, **inp)

    assert_allclose(dat['result'], efield.field)

    # Check with provided e-field; 2x2 iter should yield the same as 4 iter.
    efield2 = solver.solve(grid, model, sfield, maxit=4, verb=1)
    efield3 = solver.solve(grid, model, sfield, maxit=2, verb=1)
    solver.solve(grid, model, sfield, efield3, maxit=2, verb=1)

    assert_allclose(efield2, efield3)

    out, _ = capsys.readouterr()  # Clean up

    # One test without post-smoothing to check if it runs.
    efield4 = solver.solve(grid,
                           model,
                           sfield,
                           sslsolver=True,
                           semicoarsening=True,
                           linerelaxation=True,
                           maxit=20,
                           nu_pre=0,
                           nu_post=4,
                           verb=3)
    efield5 = solver.solve(grid,
                           model,
                           sfield,
                           sslsolver=True,
                           semicoarsening=True,
                           linerelaxation=True,
                           maxit=20,
                           nu_pre=4,
                           nu_post=0,
                           verb=3)
    # They don't converge, and hence don't agree. Just a lazy test.
    assert_allclose(efield4, efield5, atol=1e-15, rtol=1e-5)

    # Check the QC plot if it is too long.
    # Coincidently, this one also diverges if nu_pre=0!
    # Mesh: 2-cells in y- and z-direction; 2**9 in x-direction
    mesh = utils.TensorMesh(
        [np.ones(2**9) / np.ones(2**9).sum(),
         np.ones(2),
         np.ones(2)],
        x0=np.array([-0.5, -1, -1]))
    sfield = utils.get_source_field(mesh, [0, 0, 0, 0, 0], 1)
    model = utils.Model(mesh)
    _ = solver.solve(mesh, model, sfield, verb=3, nu_pre=0)
    out, _ = capsys.readouterr()
    assert "(Cycle-QC restricted to first 70 steps of 72 steps.)" in out
    assert "DIVERGED" in out
Beispiel #5
0
def test_one_liner(capsys):
    grid = utils.TensorMesh(
        [np.ones(8), np.ones(8), np.ones(8)], x0=np.array([0, 0, 0]))
    model = utils.Model(grid, res_x=1.5, res_y=1.8, res_z=3.3)
    sfield = utils.get_source_field(grid, src=[4, 4, 4, 0, 0], freq=10.0)

    out, _ = capsys.readouterr()
    _ = solver.solve(grid, model, sfield, verb=-1)
    out, _ = capsys.readouterr()
    assert '6; 0:00:' in out
    assert '; CONVERGED' in out

    out, _ = capsys.readouterr()
    _ = solver.solve(grid, model, sfield, sslsolver=True, verb=-1)
    out, _ = capsys.readouterr()
    assert '3(5); 0:00:' in out
    assert '; CONVERGED' in out
Beispiel #6
0
    def time_solver(self, data, cycle):
        grid = data['grid']
        if INFO > (1, 0, 0, 0):
            sfield = Field(grid, data['sfield'].field,
                           data['sfield'].frequency)
        else:
            sfield = Field(grid, data['sfield'])
        inp = {
            'model': data['model'],
            'sfield': sfield,
            'cycle': cycle,
            'sslsolver': False,
            'semicoarsening': True,
            'linerelaxation': True,
            'verb': VERB
        }

        if INFO < (0, 17, 1, 7):
            inp['grid'] = grid

        solve(**inp)
Beispiel #7
0
    def peakmem_solver(self, data, sslsolver, anisotropy):
        grid = data[anisotropy]['grid']

        if INFO > (1, 0, 0, 0):
            sfield = Field(grid, data[anisotropy]['sfield'].field,
                           data[anisotropy]['sfield'].frequency)
        else:
            sfield = Field(grid, data[anisotropy]['sfield'])

        inp = {
            'model': data[anisotropy]['model'],
            'sfield': sfield,
            'cycle': 'F',
            'sslsolver': sslsolver,
            'semicoarsening': True,
            'linerelaxation': True,
            'verb': VERB
        }

        if INFO < (0, 17, 1, 7):
            inp['grid'] = grid

        solve(**inp)
Beispiel #8
0
def test_amat_x(njit):
    if njit:
        amat_x = njitted.amat_x
    else:
        amat_x = njitted.amat_x.py_func

    # 1. Compare to alternative amat_x

    # Create a grid
    src = [200, 300, -50., 5, 60]
    hx = get_h(8, 4, 100, 1.2)
    hy = np.ones(8) * 800
    hz = np.ones(4) * 500
    grid = utils.TensorMesh([hx, hy, hz],
                            np.array(
                                [-hx.sum() / 2, -hy.sum() / 2, -hz.sum() / 2]))

    # Create some resistivity model
    x = np.arange(1, grid.nCx + 1) * 2
    y = 1 / np.arange(1, grid.nCy + 1)
    z = np.arange(1, grid.nCz + 1)[::-1] / 10
    res_x = np.outer(np.outer(x, y), z).ravel()
    freq = 0.319
    model = utils.Model(grid, res_x, 0.8 * res_x, 2 * res_x)

    # Create a source field
    sfield = utils.get_source_field(grid=grid, src=src, freq=freq)

    # Get volume-averaged model parameters.
    vmodel = utils.VolumeModel(grid, model, sfield)

    # Run two iterations to get a e-field
    efield = solver.solve(grid, model, sfield, maxit=2, verb=1)

    # amat_x
    rr1 = utils.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.hx,
           grid.hy, grid.hz)

    # amat_x - alternative
    rr2 = utils.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.hx, grid.hy,
                            grid.hz)

    # Check all fields (ex, ey, and ez)
    assert_allclose(-rr1, rr2, atol=1e-23)
Beispiel #9
0
def test_residual():
    # The only thing to test here is that the residual returns the same as
    # sfield-amat_x. Basically a copy of the function itself.

    # Create a grid
    src = [90, 1600, 25., 45, 45]
    grid = emg3d.TensorMesh(
        [helpers.widths(4, 2, 20, 1.2),
         np.ones(16) * 200,
         np.ones(2) * 25],
        origin=np.zeros(3))

    # Create some resistivity model
    x = np.arange(1, grid.shape_cells[0] + 1) * 2
    y = 1 / np.arange(1, grid.shape_cells[1] + 1)
    z = np.arange(1, grid.shape_cells[2] + 1)[::-1] / 10
    property_x = np.outer(np.outer(x, y), z).ravel()
    freq = 0.319
    model = emg3d.Model(grid, property_x, 0.8 * property_x, 2 * property_x)

    # Create a source field
    sfield = emg3d.get_source_field(grid=grid, source=src, frequency=freq)

    # Get volume-averaged model parameters.
    vmodel = emg3d.models.VolumeModel(model, sfield)

    # Run two iterations to get an e-field
    efield = solver.solve(model, sfield, maxit=2)

    # Use directly amat_x
    rfield = sfield.copy()
    emg3d.core.amat_x(rfield.fx, rfield.fy, rfield.fz, efield.fx, efield.fy,
                      efield.fz, vmodel.eta_x, vmodel.eta_y, vmodel.eta_z,
                      vmodel.zeta, grid.h[0], grid.h[1], grid.h[2])

    # Compute residual
    out = solver.residual(vmodel, sfield, efield)
    outnorm = solver.residual(vmodel, sfield, efield, True)

    # Compare
    assert_allclose(out.field, rfield.field)
    assert_allclose(outnorm, np.linalg.norm(out.field))
Beispiel #10
0
def test_residual():
    # The only thing to test here is that residual returns the same as
    # sfield-amat_x. Basically a copy of the function itself.

    # Create a grid
    src = [90, 1600, 25., 45, 45]
    grid = utils.TensorMesh(
        [get_h(4, 2, 20, 1.2),
         np.ones(16) * 200,
         np.ones(2) * 25],
        x0=np.zeros(3))

    # Create some resistivity model
    x = np.arange(1, grid.nCx + 1) * 2
    y = 1 / np.arange(1, grid.nCy + 1)
    z = np.arange(1, grid.nCz + 1)[::-1] / 10
    res_x = np.outer(np.outer(x, y), z).ravel()
    freq = 0.319
    model = utils.Model(grid, res_x, 0.8 * res_x, 2 * res_x)

    # Create a source field
    sfield = utils.get_source_field(grid=grid, src=src, freq=freq)

    # Get volume-averaged model parameters.
    vmodel = utils.VolumeModel(grid, model, sfield)

    # Run two iterations to get an e-field
    efield = solver.solve(grid, model, sfield, maxit=2, verb=1)

    # Use directly amat_x
    rfield = sfield.copy()
    njitted.amat_x(rfield.fx, rfield.fy, rfield.fz, efield.fx, efield.fy,
                   efield.fz, vmodel.eta_x, vmodel.eta_y, vmodel.eta_z,
                   vmodel.zeta, grid.hx, grid.hy, grid.hz)

    # Calculate residual
    out = solver.residual(grid, vmodel, sfield, efield)
    outnorm = solver.residual(grid, vmodel, sfield, efield, True)

    # Compare
    assert_allclose(out, rfield)
    assert_allclose(outnorm, np.linalg.norm(out))
Beispiel #11
0
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
Beispiel #12
0
def test_print_one_liner(capsys):
    var = solver.MGParameters(verb=5,
                              cycle='F',
                              sslsolver=False,
                              linerelaxation=False,
                              semicoarsening=False,
                              shape_cells=(16, 8, 2))

    solver._print_one_liner(var, 1e-2, False)
    out, _ = capsys.readouterr()
    assert ":: emg3d :: 1.0e-02; 0; 0:00:0" in out

    var = solver.MGParameters(verb=5,
                              cycle='F',
                              sslsolver=True,
                              linerelaxation=False,
                              semicoarsening=False,
                              shape_cells=(16, 8, 2))
    var.exit_message = "TEST"

    solver._print_one_liner(var, 1e-2, True)
    out, _ = capsys.readouterr()
    assert ":: emg3d :: 1.0e-02; 0(0); 0:00:0" in out
    assert "TEST" in out

    grid = emg3d.TensorMesh(
        [np.ones(8), np.ones(8), np.ones(8)], origin=np.array([0, 0, 0]))
    model = emg3d.Model(grid, property_x=1.5, property_y=1.8, property_z=3.3)
    sfield = emg3d.get_source_field(grid,
                                    source=[4, 4, 4, 0, 0],
                                    frequency=10.0)

    # Dynamic one-liner.
    out, _ = capsys.readouterr()
    _ = solver.solve(model,
                     sfield,
                     sslsolver=False,
                     semicoarsening=False,
                     linerelaxation=False,
                     verb=1)
    out, _ = capsys.readouterr()
    assert '6; 0:00:' in out
    assert '; CONVERGED' in out

    out, _ = capsys.readouterr()
    _ = solver.solve(model,
                     sfield,
                     sslsolver=True,
                     semicoarsening=False,
                     linerelaxation=False,
                     verb=1)
    out, _ = capsys.readouterr()
    assert '3(5); 0:00:' in out
    assert '; CONVERGED' in out

    # One-liner.
    out, _ = capsys.readouterr()
    _ = solver.solve(model,
                     sfield,
                     sslsolver=True,
                     semicoarsening=False,
                     linerelaxation=False,
                     verb=1)
    out, _ = capsys.readouterr()
    assert '3(5); 0:00:' in out
    assert '; CONVERGED' in out
Beispiel #13
0
    'res_y': 2.0,
    'res_z': 3.3,
}
model = utils.Model(**input_model)

input_source = {
    'grid': grid,
    'src': [0, 0, 250., 30, 10],  # A rotated source to include all
    'freq': freq
}

# Fields
sfield = utils.get_source_field(**input_source)

# F-cycle
fefield = solver.solve(grid, model, sfield)

# W-cycle
wefield = solver.solve(grid, model, sfield, cycle='W')

# V-cycle
vefield = solver.solve(grid, model, sfield, cycle='V')

# BiCGSTAB; F-cycle
bicefield = solver.solve(grid, model, sfield, sslsolver=True)

out = {
    'input_grid': input_grid,
    'input_model': input_model,
    'input_source': input_source,
    'grid': grid,
Beispiel #14
0
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, get_h(10, 27, 10, 1.1), get_h(2, 1, 50, 1.2)]
    x0 = [-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 = utils.TensorMesh(
            [widths[xyz % 3], widths[(xyz + 1) % 3], widths[(xyz + 2) % 3]],
            x0=np.array([x0[xyz % 3], x0[(xyz + 1) % 3], x0[(xyz + 2) % 3]]))

        # Create some resistivity model
        x = np.arange(1, grid.nCx + 1) * 2
        y = 1 / np.arange(1, grid.nCy + 1)
        z = np.arange(1, grid.nCz + 1)[::-1] / 10
        res_x = np.outer(np.outer(x, y), z).ravel()
        freq = 0.319
        model = utils.Model(grid, res_x, 0.8 * res_x, 2 * res_x)

        # Create a source field
        sfield = utils.get_source_field(grid=grid, src=src, freq=freq)

        # Get volume-averaged model parameters.
        vmodel = utils.VolumeModel(grid, model, sfield)

        # Run two iterations to get an e-field
        field = solver.solve(grid, model, sfield, maxit=2, verb=1)

        # 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.hx, grid.hy, grid.hz, nu)

        func = ['', '_x', '_y', '_z']
        for lr_dir in range(8):
            # Get it directly from njitted
            efield = utils.Field(grid, field)
            if lr_dir < 4:
                getattr(njitted,
                        'gauss_seidel' + func[lr_dir])(efield.fx, efield.fy,
                                                       efield.fz, *inp)
            elif lr_dir == 4:
                njitted.gauss_seidel_y(efield.fx, efield.fy, efield.fz, *inp)
                njitted.gauss_seidel_z(efield.fx, efield.fy, efield.fz, *inp)
            elif lr_dir == 5:
                njitted.gauss_seidel_x(efield.fx, efield.fy, efield.fz, *inp)
                njitted.gauss_seidel_z(efield.fx, efield.fy, efield.fz, *inp)
            elif lr_dir == 6:
                njitted.gauss_seidel_x(efield.fx, efield.fy, efield.fz, *inp)
                njitted.gauss_seidel_y(efield.fx, efield.fy, efield.fz, *inp)
            elif lr_dir == 7:
                njitted.gauss_seidel_x(efield.fx, efield.fy, efield.fz, *inp)
                njitted.gauss_seidel_y(efield.fx, efield.fy, efield.fz, *inp)
                njitted.gauss_seidel_z(efield.fx, efield.fy, efield.fz, *inp)

            # Use solver.smoothing
            ofield = utils.Field(grid, field)
            solver.smoothing(grid, vmodel, sfield, ofield, nu, lr_dir)

            # Compare
            assert_allclose(efield, ofield)
Beispiel #15
0
def test_solver_homogeneous(capsys):
    # Regression test for homogeneous halfspace.
    # Not very sophisticated; replace/extend by more detailed tests.
    dat = REGRES['res'][()]

    grid = utils.TensorMesh(**dat['input_grid'])
    model = utils.Model(**dat['input_model'])
    sfield = utils.get_source_field(**dat['input_source'])

    # F-cycle
    efield = solver.solve(grid, model, sfield, 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 "1.509e-01  after   1 F-cycles   [9.161e-07, 0.151]   0 0" in out
    assert "1.002e-01  after   2 F-cycles   [6.082e-07, 0.664]   0 0" in out

    # Check all fields (ex, ey, and ez)
    assert_allclose(dat['Fresult'], efield)

    # W-cycle
    wfield = solver.solve(grid, model, sfield, cycle='W', verb=1)

    # Check all fields (ex, ey, and ez)
    assert_allclose(dat['Wresult'], wfield)

    # V-cycle
    vfield = solver.solve(grid, model, sfield, cycle='V', verb=1)
    _, _ = capsys.readouterr()  # clear output

    # Check all fields (ex, ey, and ez)
    assert_allclose(dat['Vresult'], vfield)

    # BiCGSTAB with some print checking.
    efield = solver.solve(grid, model, sfield, verb=3, sslsolver=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'], efield)

    # Same as previous, without BiCGSTAB, but some print checking.
    efield = solver.solve(grid, model, sfield, verb=3)
    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(grid,
                           model,
                           sfield,
                           verb=2,
                           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(grid, model, sfield, verb=2, maxit=1, sslsolver=True)
    out, _ = capsys.readouterr()
    assert ' MAX. ITERATION REACHED' in out

    # Just check if it runs without failing for other solvers.
    _ = solver.solve(grid, model, sfield, verb=3, maxit=1, sslsolver='gcrotmk')

    # Provide initial field.
    _, _ = capsys.readouterr()  # empty
    efield_copy = efield.copy()
    outarray = solver.solve(grid, model, sfield, efield_copy)
    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, efield_copy)

    # Provide initial field and return info.
    info = solver.solve(grid, model, sfield, 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 = utils.Field(grid)
    outarray = solver.solve(grid,
                            model,
                            sfield,
                            efield,
                            sslsolver=True,
                            semicoarsening=True,
                            linerelaxation=True,
                            maxit=2,
                            verb=3)
    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 = utils.Field(grid)
    wrong_sfield.field = sfield.field
    with pytest.raises(ValueError):
        solver.solve(grid, model, wrong_sfield, efield=efield, verb=2)
    out, _ = capsys.readouterr()
    assert "ERROR   :: Source field is missing frequency information" in out

    # Check stagnation by providing an almost zero source field.
    _ = solver.solve(grid, model, sfield * 0 + 1e-20, maxit=100)
    out, _ = capsys.readouterr()
    assert "STAGNATED" in out
Beispiel #16
0
    'property_z': 3.3,
    'mapping': 'Resistivity'
}
model = models.Model(**input_model)

input_source = {
    'grid': grid,
    'source': [0, 0, 250., 30, 10],  # A rotated source to include all
    'frequency': freq
}

# Fields
sfield = fields.get_source_field(**input_source)

# F-cycle
fefield = solver.solve(model, sfield, plain=True)

# W-cycle
wefield = solver.solve(model, sfield, cycle='W', plain=True)

# V-cycle
vefield = solver.solve(model, sfield, cycle='V', plain=True)

# BiCGSTAB; F-cycle
bicefield = solver.solve(model, sfield, sslsolver='bicgstab', plain=True)

out = {
    'input_grid': input_grid,
    'input_model': input_model,
    'input_source': input_source,
    'grid': grid,
Beispiel #17
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
Beispiel #18
0
def test_gauss_seidel(njit):
    if njit:
        gauss_seidel = njitted.gauss_seidel
        gauss_seidel_x = njitted.gauss_seidel_x
        gauss_seidel_y = njitted.gauss_seidel_y
        gauss_seidel_z = njitted.gauss_seidel_z
    else:
        gauss_seidel = njitted.gauss_seidel.py_func
        gauss_seidel_x = njitted.gauss_seidel_x.py_func
        gauss_seidel_y = njitted.gauss_seidel_y.py_func
        gauss_seidel_z = njitted.gauss_seidel_z.py_func

    # At the moment we only compare `gauss_seidel_x/y/z` to `gauss_seidel`.
    # Better tests should be implemented.

    # 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 = get_h(0, nx, 80, 1.1)
        hy = get_h(0, ny, 100, 1.3)
        hz = get_h(0, nz, 200, 1.2)
        grid = utils.TensorMesh(
            [hx, hy, hz],
            np.array([-hx.sum() / 2, -hy.sum() / 2, -hz.sum() / 2]))

        # Initialize model with some resistivities.
        res_x = np.arange(grid.nC) + 1
        res_y = 0.5 * np.arange(grid.nC) + 1
        res_z = 2 * np.arange(grid.nC) + 1

        model = utils.Model(grid, res_x, res_y, res_z)

        # Initialize source field.
        sfield = utils.get_source_field(grid, src, freq)

        # Get volume-averaged model parameters.
        vmodel = utils.VolumeModel(grid, model, sfield)

        # Run two iterations to get some e-field.
        efield = solver.solve(grid, model, sfield, maxit=2, verb=1)

        inp = (sfield.fx, sfield.fy, sfield.fz, vmodel.eta_x, vmodel.eta_y,
               vmodel.eta_z, vmodel.zeta, grid.hx, grid.hy, grid.hz, nu)

        # Get result from `gauss_seidel`.
        cfield = utils.Field(grid, efield.copy())
        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_allclose(efield.field, cfield.field)
Beispiel #19
0
    def test_heterogeneous(self, capsys):
        # Regression test for heterogeneous case.
        dat = REGRES['reg_2']
        model = dat['model']
        sfield = dat['sfield']
        inp = dat['inp']
        for n in ['nu_init', 'nu_pre', 'nu_coarse', 'nu_post']:
            inp[n] = int(inp[n])
        inp['verb'] = 5

        efield = solver.solve(model, sfield, sslsolver=False, **inp)

        assert_allclose(dat['result'].field, efield.field)

        _, _ = capsys.readouterr()  # Clean up

        # Check with provided e-field; 2x2 iter should yield the same as 4 iter
        efield2 = solver.solve(model, sfield, plain=True, maxit=4, verb=0)
        out, _ = capsys.readouterr()  # Clean up
        assert "* WARNING :: MAX. ITERATION REACHED, NOT CONVERGED" in out
        efield3 = solver.solve(model, sfield, plain=True, maxit=2, verb=0)
        solver.solve(model,
                     sfield,
                     plain=True,
                     efield=efield3,
                     maxit=2,
                     verb=0)

        assert efield2 == efield3

        _, _ = capsys.readouterr()  # Clean up

        # One test without post-smoothing to check if it runs.
        efield4 = solver.solve(model,
                               sfield,
                               maxit=20,
                               nu_pre=0,
                               nu_post=4,
                               verb=4)
        efield5 = solver.solve(model,
                               sfield,
                               maxit=20,
                               nu_pre=4,
                               nu_post=0,
                               verb=4)
        # They don't converge, and hence don't agree. Just a lazy test.
        assert_allclose(efield4.field, efield5.field, atol=1e-15, rtol=1e-5)

        # Check the QC plot if it is too long.
        # Coincidently, this one also diverges if nu_pre=0!
        # Mesh: 2-cells in y- and z-direction; 2**9 in x-direction
        mesh = emg3d.TensorMesh(
            [np.ones(2**9) / np.ones(2**9).sum(),
             np.ones(2),
             np.ones(2)],
            origin=np.array([-0.5, -1, -1]))
        sfield = alternatives.alt_get_source_field(mesh, [0, 0, 0, 0, 0], 1)
        model = emg3d.Model(mesh)
        _ = solver.solve(model, sfield, plain=True, verb=4, nu_pre=0)
        out, _ = capsys.readouterr()
        assert "(Cycle-QC restricted to first 70 steps of 72 steps.)" in out
        assert "DIVERGED" in out