Skip to content

Commit

Permalink
Merge 2e59b0c into cbff118
Browse files Browse the repository at this point in the history
  • Loading branch information
prisae committed Dec 8, 2020
2 parents cbff118 + 2e59b0c commit e7675f2
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 9 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ recent versions
*latest*
--------

- All data is stored in the ``Survey``, not partly in ``Survey`` and partly
in ``Simulation``.
- New parameter ``distance`` for ``get_origin_widths``, as an alternative for
``domain`` and ``vector``: distance defines the survey domain as distance
from the center. This is then also available in ``construct_mesh`` and
``Simulation``, including the CLI.
- Removed ``precision`` from ``skin_depth``, ``wavelength``,
``min_cell_width``; all in ``meshes``. It caused problems for high
frequencies.
- All data is stored in the ``Survey``, not partly in ``Survey`` and partly
in ``Simulation``.
- Deprecated ``collect_classes`` in ``io``.
- Expanded the ``what``-parameter in the ``Simulation``-class to include
properties related to the gradient.
Expand Down
2 changes: 1 addition & 1 deletion emg3d/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def parse_config_file(args_dict):
cfg.get('gridding_opts', key).split(',')]

# Check for list of lists.
for key in ['domain', 'stretching', 'min_width_limits']:
for key in ['domain', 'distance', 'stretching', 'min_width_limits']:
if cfg.has_option('gridding_opts', key):
_ = all_grid.pop(key)
out = []
Expand Down
26 changes: 21 additions & 5 deletions emg3d/meshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,13 @@ def construct_mesh(frequency, properties, center, domain=None, vector=None,
is then assumed to span exactly the domain. If only one list is
provided it is applied to all dimensions.
distance : tuple of lists, list, or None, optional
An alternative to ``domain``: Instead of defining the domain in
absolute values, they are defined here as distance from the center.
Format: ``([xl, xr], [yl, yr], [zd, zu])``. From this the domain is
given as ``([cx-xl, cx+xr], [cy-yl, cy+yr], [cz-zd, cz+zu])``, where
``center=(cx, cy, cz)``.
vector : tuple of three ndarrays, ndarray, or None, optional
Contains vectors of mesh-edges that should be used. If provided, the
vector MUST at least include all of the survey domain. If ``domain``
Expand Down Expand Up @@ -469,6 +476,7 @@ def construct_mesh(frequency, properties, center, domain=None, vector=None,
"""
verb = kwargs.get('verb', 0)
distance = kwargs.pop('distance', None)

# Initiate direction-specific dicts, add unambiguous args.
kwargs['frequency'] = frequency
Expand All @@ -491,7 +499,8 @@ def construct_mesh(frequency, properties, center, domain=None, vector=None,
kwargs['properties'] = properties

# Add optionally direction specific args.
for name, value in zip(['domain', 'vector'], [domain, vector]):
for name, value in zip(['domain', 'vector', 'distance'],
[domain, vector, distance]):
if (value is not None and len(value) == 3 and not
isinstance(value, np.ndarray)):
if value[0] is not None:
Expand Down Expand Up @@ -569,6 +578,7 @@ def get_origin_widths(frequency, properties, center, domain=None, vector=None,
"""
# Get all kwargs.
distance = kwargs.pop('distance', None)
stretching = kwargs.pop('stretching', [1.0, 1.5])
min_width_limits = kwargs.pop('min_width_limits', None)
min_width_pps = kwargs.pop('min_width_pps', 3)
Expand Down Expand Up @@ -599,12 +609,18 @@ def get_origin_widths(frequency, properties, center, domain=None, vector=None,
# Minimum cell width.
dmin = min_cell_width(skind[0], min_width_pps, min_width_limits)

# Survey domain: if not provided get from vector.
if domain is None and vector is None:
# Survey domain: if not provided get from vector or distance.
# Priority: domain > vector > distance.
if domain is None and vector is None and distance is None:
raise ValueError(
"At least one of `domain` and `vector` must be provided.")
"At least one of `domain`, `distance, and `vector` "
"must be provided.")
elif domain is None:
domain = np.array([vector.min(), vector.max()], dtype=float)
if vector is None:
domain = np.array([center-abs(distance[0]),
center+abs(distance[1])])
else:
domain = np.array([vector.min(), vector.max()], dtype=float)
else:
domain = np.array(domain, dtype=np.float64)
if vector is not None:
Expand Down
12 changes: 12 additions & 0 deletions emg3d/simulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,7 @@ def estimate_gridding_opts(gridding_opts, grid, model, survey, input_nCz=None):
nothing is done otherwise:
- ``vector``
- ``distance``
- ``stretching``
- ``seasurface``
- ``cell_numbers``
Expand Down Expand Up @@ -1318,6 +1319,11 @@ def estimate_gridding_opts(gridding_opts, grid, model, survey, input_nCz=None):
# In this case vector was provided, and we include it like this.
gopts['vector'] = vector

# Distance.
distance = gridding_opts.pop('distance', None)
if distance is not None:
gopts['distance'] = distance

# Properties defaults to model averages (AFTER model expansion).
properties = gridding_opts.pop('properties', None)
if properties is None:
Expand Down Expand Up @@ -1390,6 +1396,12 @@ def get_dim_diff(i):
diff = np.diff(dim)[0]
get_it = False

elif distance is not None and distance[i] is not None:
# distance is provided.
dim = None
diff = abs(distance[i][0]) + abs(distance[i][1])
get_it = False

else:
# Get it from survey, add 5 % on each side.
inp = np.r_[survey.src_coords[i], survey.rec_coords[i]]
Expand Down
7 changes: 6 additions & 1 deletion tests/test_meshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def test_errors(self, capsys):
with pytest.raises(TypeError, match='Unexpected '):
meshes.get_origin_widths(1, 1, 0, [-1, 1], unknown=True)

with pytest.raises(ValueError, match="At least one of `domain` and"):
with pytest.raises(ValueError, match="At least one of `domain`, `d"):
meshes.get_origin_widths(1, 1, 0)

with pytest.raises(ValueError, match="Provided vector MUST at least"):
Expand Down Expand Up @@ -404,6 +404,11 @@ def test_domain_vector(self):
assert_allclose(x01, x02)
assert_allclose(hx1, hx2)

x03, hx3 = meshes.get_origin_widths(
1/np.pi, 9*mu_0, 0.0, distance=[1, 1], stretching=[1, 1])
assert_allclose(x01, x03)
assert_allclose(hx1, hx3)

def test_seasurface(self):
x01, hx1 = meshes.get_origin_widths(
1/np.pi, 9*mu_0, 0.0, [-1, 1], stretching=[1, 1])
Expand Down
8 changes: 8 additions & 0 deletions tests/test_simulations.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,14 @@ def test_mapping_vector(self):
assert gdict['vector'][1] is None
assert_allclose(gdict['vector'][2], self.grid.nodes_z)

def test_vector_distance(self):
gridding_opts = {'vector': 'Z', 'distance': [[5, 10], None, None]}
gdict = simulations.estimate_gridding_opts(
gridding_opts, self.grid, self.model, self.survey)

assert gdict['distance'][0] == [5, 10]
assert gdict['distance'][1] is None

def test_pass_along(self):
gridding_opts = {
'vector': (None, 1, None),
Expand Down

0 comments on commit e7675f2

Please sign in to comment.