Пример #1
0
def test_check_mesh():

    # Bad class name.
    grid = meshes.BaseMesh(h=[2, 2, 2], origin=(0, 0, 0))
    grid.__class__.__name__ = 'Test'
    with pytest.raises(TypeError, match="Mesh must be a TensorMesh."):
        meshes.check_mesh(grid)

    # Wrong dimension.
    if discretize is None:
        grid = meshes.TensorMesh(h=[2, 2, 2], origin=(0, 0, 0))
        grid.origin = (0, 0)
    else:
        grid = meshes.TensorMesh(h=[2, 2], origin=(0, 0))
    with pytest.raises(TypeError, match="Mesh must be a 3D mesh."):
        meshes.check_mesh(grid)

    # Bad cell number.
    grid = meshes.TensorMesh(h=[[2, ], [2, ], [2, 2]], origin=(0, 0, 0))
    with pytest.warns(UserWarning, match='ptimal for MG solver. Good numbers'):
        meshes.check_mesh(grid)

    # A good one, nothing should happen.
    hx = np.ones(16)*20
    grid = meshes.TensorMesh(h=[hx, hx, hx], origin=(0, 0, 0))
    meshes.check_mesh(grid)
Пример #2
0
    def to_dict(self, copy=False):
        """Store the necessary information of the Field in a dict.

        Parameters
        ----------
        copy : bool, default: False
            If True, returns a deep copy of the dict.


        Returns
        -------
        out : dict
            Dictionary containing all information to re-create the Field.

        """
        out = {
            '__class__': self.__class__.__name__,  # v ensure emg3d-TensorMesh
            'grid': meshes.TensorMesh(self.grid.h, self.grid.origin).to_dict(),
            'data': self._field,
            'frequency': self._frequency,
            'electric': self.electric,
        }
        if copy:
            return deepcopy(out)
        else:
            return out
Пример #3
0
def _dict_serialize(inp):
    """Serialize emg3d-classes and other objects in inp-dict.

    Returns a serialized dictionary <out> of <inp>, where all members of
    `emg3d.utils._KNOWN_CLASSES` are serialized with their respective
    `to_dict()` methods.

    Any other (non-emg3d) object can be added too, as long as it knows how to
    serialize itself.

    There are some limitations:

    1. Key names are converted to strings.
    2. None values are converted to 'NoneType'.
    3. TensorMesh instances from discretize will be stored as if they would be
       simpler emg3d.TensorMesh instances.


    Parameters
    ----------
    inp : dict
        Input dictionary to serialize.


    Returns
    -------
    out : dict
        Serialized <inp>-dict.

    """

    # Initiate output dictionary.
    out = {}

    # Loop over items.
    for key, value in inp.items():

        # Serialize known classes.
        if isinstance(value, tuple(utils._KNOWN_CLASSES.values())):

            # Workaround for discretize.TensorMesh (store as emg3d.TensorMesh)
            if hasattr(value, 'face_areas'):
                value = meshes.TensorMesh(value.h, value.origin)

            # Serialize.
            value = value.to_dict()

        # If value is a dict we use recursion
        if isinstance(value, dict):
            value = _dict_serialize(value)

        # Limitation 1: None -> 'NoneType'
        elif value is None:
            value = 'NoneType'

        # Store value
        # Limitation 2: Cast keys -> str(key)
        out[str(key)] = value

    return out
Пример #4
0
    def to_dict(self, copy=False):
        """Store the necessary information in a dict for serialization.

        Parameters
        ----------
        copy : bool, default: False
            If True, returns a deep copy of the dict.


        Returns
        -------
        out : dict
            Dictionary containing all information to re-create the Model.

        """
        out = {
            '__class__': self.__class__.__name__,  # v ensure emg3d-TensorMesh
            'grid': meshes.TensorMesh(self.grid.h, self.grid.origin).to_dict(),
            **{prop: getattr(self, prop)
               for prop in self._properties},
            'mapping': self.map.name,
        }
        if copy:
            return deepcopy(out)
        else:
            return out
Пример #5
0
    def test_TensorMesh_repr(self):
        # Create some dummy data
        grid = meshes.TensorMesh(
                [np.ones(2), np.ones(2), np.ones(2)], np.zeros(3))

        # Check representation of TensorMesh.
        if discretize is None:
            assert 'TensorMesh: 2 x 2 x 2 (8)' in grid.__repr__()
            assert not hasattr(grid, '_repr_html_')
        else:
            assert 'TensorMesh: 8 cells' in grid.__repr__()
            assert hasattr(grid, '_repr_html_')
Пример #6
0
    def test_TensorMesh(self):
        # Load mesh created with discretize.TensorMesh.
        grid = REGRES['grid']
        grid['h'] = [grid.pop('hx'), grid.pop('hy'), grid.pop('hz')]

        mesh = meshes.BaseMesh(grid['h'], origin=grid['origin'])

        # Use this grid instance to create emg3d equivalent.
        emg3dgrid = meshes.TensorMesh(grid['h'], origin=grid['origin'])

        # Ensure they are the same.
        for key, value in grid.items():
            if key == 'h':
                for i in range(3):
                    assert_allclose(value[i], getattr(emg3dgrid, key)[i])
            else:
                assert_allclose(value, getattr(emg3dgrid, key))

        # Copy
        cgrid = emg3dgrid.copy()
        assert_allclose(cgrid.cell_volumes, emg3dgrid.cell_volumes)
        dgrid = emg3dgrid.to_dict()
        cdgrid = meshes.TensorMesh.from_dict(dgrid.copy())
        assert_allclose(cdgrid.cell_volumes, emg3dgrid.cell_volumes)
        del dgrid['hx']
        with pytest.raises(KeyError, match="'hx'"):
            meshes.TensorMesh.from_dict(dgrid)

        # Check __eq__.
        assert emg3dgrid == cgrid
        newgrid = meshes.TensorMesh(
                [np.ones(3), np.ones(3), np.ones(3)], np.zeros(3))
        assert emg3dgrid != newgrid

        assert 'TensorMesh: 40 x 30 x 1 (1,200)' in mesh.__repr__()
        assert not hasattr(mesh, '_repr_html_')

        assert mesh.cell_volumes.sum() > 69046392
Пример #7
0
class TestEstimateGriddingOpts():
    if xarray is not None:
        # Create a simple survey
        sources = emg3d.surveys.txrx_coordinates_to_dict(
                emg3d.TxElectricDipole,
                (0, [1000, 3000, 5000], -950, 0, 0))
        receivers = emg3d.surveys.txrx_coordinates_to_dict(
                emg3d.RxElectricPoint,
                (np.arange(11)*500, 2000, -1000, 0, 0))
        frequencies = (0.1, 10.0)

        survey = emg3d.Survey(
                sources, receivers, frequencies, noise_floor=1e-15,
                relative_error=0.05)

        # Create a simple grid and model
        grid = meshes.TensorMesh(
                [np.ones(32)*250, np.ones(16)*500, np.ones(16)*500],
                np.array([-1250, -1250, -2250]))
        model = emg3d.Model(grid, 0.1, np.ones(grid.shape_cells)*10)
        model.property_y[5, 8, 3] = 100000  # Cell at source center

    def test_empty_dict(self):
        gdict = meshes.estimate_gridding_opts({}, self.model, self.survey)

        assert gdict['frequency'] == 1.0
        assert gdict['mapping'] == self.model.map.name
        assert_allclose(gdict['center'], (0, 3000, -950))
        assert_allclose(gdict['domain']['x'], (-500, 5500))
        assert_allclose(gdict['domain']['y'], (600, 5400))
        assert_allclose(gdict['domain']['z'], (-3651, -651))
        assert_allclose(gdict['properties'], [100000, 10, 10, 10, 10, 10, 10])

    def test_mapping_vector(self):
        gridding_opts = {
            'mapping': "LgConductivity",
            'vector': 'xZ',
            }
        gdict = meshes.estimate_gridding_opts(
                gridding_opts, self.model, self.survey)

        assert_allclose(
                gdict['properties'],
                np.log10(1/np.array([100000, 10, 10, 10, 10, 10, 10])),
                atol=1e-15)
        assert_allclose(gdict['vector']['x'], self.grid.nodes_x)
        assert gdict['vector']['y'] is None
        assert_allclose(gdict['vector']['z'], self.grid.nodes_z)

    def test_vector_domain_distance(self):
        gridding_opts = {
                'vector': 'Z',
                'domain': (None, [-1000, 1000], None),
                'distance': [[5, 10], None, None],
                }
        gdict = meshes.estimate_gridding_opts(
                gridding_opts, self.model, self.survey)

        assert gdict['vector']['x'] == gdict['vector']['y'] is None
        assert_allclose(gdict['vector']['z'], self.model.grid.nodes_z)

        assert gdict['domain']['x'] is None
        assert gdict['domain']['y'] == [-1000, 1000]
        assert gdict['domain']['z'] == [self.model.grid.nodes_z[0],
                                        self.model.grid.nodes_z[-1]]
        assert gdict['distance']['x'] == [5, 10]
        assert gdict['distance']['y'] == gdict['distance']['z'] is None

        # As dict
        gridding_opts = {
                'vector': 'Z',
                'domain': {'x': None, 'y': [-1000, 1000], 'z': None},
                'distance': {'x': [5, 10], 'y': None, 'z': None},
                }
        gdict = meshes.estimate_gridding_opts(
                gridding_opts, self.model, self.survey)

        assert gdict['vector']['x'] == gdict['vector']['y'] is None
        assert_allclose(gdict['vector']['z'], self.model.grid.nodes_z)

        assert gdict['domain']['x'] is None
        assert gdict['domain']['y'] == [-1000, 1000]
        assert gdict['domain']['z'] == [self.model.grid.nodes_z[0],
                                        self.model.grid.nodes_z[-1]]
        assert gdict['distance']['x'] == [5, 10]
        assert gdict['distance']['y'] == gdict['distance']['z'] is None

    def test_pass_along(self):
        gridding_opts = {
            'vector': {'x': None, 'y': 1, 'z': None},
            'stretching': [1.2, 1.3],
            'seasurface': -500,
            'cell_numbers': [10, 20, 30],
            'lambda_factor': 0.8,
            'max_buffer': 10000,
            'min_width_limits': ([20, 40], [20, 40], [20, 40]),
            'min_width_pps': 4,
            'verb': -1,
            }

        gdict = meshes.estimate_gridding_opts(
                gridding_opts.copy(), self.model, self.survey)

        # Check that all parameters passed unchanged.
        gdict2 = {k: gdict[k] for k, _ in gridding_opts.items()}
        # Except the tuple, which should be a dict now
        gridding_opts['min_width_limits'] = {
                'x': gridding_opts['min_width_limits'][0],
                'y': gridding_opts['min_width_limits'][1],
                'z': gridding_opts['min_width_limits'][2]
        }
        assert helpers.compare_dicts(gdict2, gridding_opts)

    def test_factor(self):
        sources = emg3d.TxElectricDipole((0, 3000, -950, 0, 0))
        receivers = emg3d.RxElectricPoint((0, 3000, -1000, 0, 0))

        # Adjusted x-domain.
        survey = emg3d.Survey(
                self.sources, receivers, self.frequencies, noise_floor=1e-15,
                relative_error=0.05)

        gdict = meshes.estimate_gridding_opts({}, self.model, survey)

        assert_allclose(gdict['domain']['x'], (-800, 800))

        # Adjusted x-domain.
        survey = emg3d.Survey(
                sources, self.receivers, self.frequencies, noise_floor=1e-15,
                relative_error=0.05)

        gdict = meshes.estimate_gridding_opts({}, self.model, survey)

        assert_allclose(gdict['domain']['y'], (1500, 3500))

    def test_error(self):
        with pytest.raises(TypeError, match='Unexpected gridding_opts'):
            _ = meshes.estimate_gridding_opts(
                    {'what': True}, self.model, self.survey)
Пример #8
0
def expand_grid_model(model, expand, interface):
    """Expand model and grid according to provided parameters.

    Expand the grid and corresponding model in positive z-direction from the
    edge of the grid to the interface with property ``expand[0]``, and a 100 m
    thick layer above the interface with property ``expand[1]``.

    The provided properties are taken as isotropic (as is the case in water and
    air); ``mu_r`` and ``epsilon_r`` are expanded with ones, if necessary.

    The ``interface`` is usually the sea-surface, and ``expand`` is therefore
    ``[property_sea, property_air]``.

    Parameters
    ----------
    model : Model
        The model; a :class:`emg3d.models.Model` instance.

    expand : list
        The two properties below and above the interface:
        ``[below_interface, above_interface]``.

    interface : float
        Interface between the two properties in ``expand``.


    Returns
    -------
    exp_grid : TensorMesh
        Expanded grid; a :class:`emg3d.meshes.TensorMesh` instance.

    exp_model : Model
        The expanded model; a :class:`emg3d.models.Model` instance.

    """
    grid = model.grid

    def extend_property(prop, add_values, nadd):
        """Expand property `model.prop`, IF it is not None."""

        if getattr(model, prop) is None:
            prop_ext = None

        else:
            prop_ext = np.zeros((grid.shape_cells[0], grid.shape_cells[1],
                                 grid.shape_cells[2] + nadd))
            prop_ext[:, :, :-nadd] = getattr(model, prop)
            if nadd == 2:
                prop_ext[:, :, -2] = add_values[0]
            prop_ext[:, :, -1] = add_values[1]

        return prop_ext

    # Initiate.
    nzadd = 0
    hz_ext = grid.h[2]

    # Fill-up property_below.
    if grid.nodes_z[-1] < interface - 0.05:  # At least 5 cm.
        hz_ext = np.r_[hz_ext, interface - grid.nodes_z[-1]]
        nzadd += 1

    # Add 100 m of property_above.
    if grid.nodes_z[-1] <= interface + 0.001:  # +1mm
        hz_ext = np.r_[hz_ext, 100]
        nzadd += 1

    if nzadd > 0:
        # Extend properties.
        property_x = extend_property('property_x', expand, nzadd)
        property_y = extend_property('property_y', expand, nzadd)
        property_z = extend_property('property_z', expand, nzadd)
        mu_r = extend_property('mu_r', [1, 1], nzadd)
        epsilon_r = extend_property('epsilon_r', [1, 1], nzadd)

        # Create extended grid and model.
        grid = meshes.TensorMesh([grid.h[0], grid.h[1], hz_ext],
                                 origin=grid.origin)
        model = Model(grid,
                      property_x,
                      property_y,
                      property_z,
                      mu_r,
                      epsilon_r,
                      mapping=model.map.name)

    return model