-------------------
**2021-05-28**
Here it is, three months of hard labour lead to v1.0.0!
There are _many_ changes, and they are listed below for each module.
*Your existing code will break, and I apologize for it. Please do not hesitate
to get in touch if you have troubles updating your code.*
**API**: With version 1.0 the API becomes stable and you can expect that your
code will work fine for the duration of ``emg3d v1.x``.
- Removed all deprecated features.
- Reduced top namespace to principal functions; ``get_receiver`` is not in the
top namespace any longer. It is advised to use directly the field method:
``field.get_receiver``.
- Moved emsig.github.io to emsig.xyz and emsig.readthedocs.io to
emg3d.emsig.xyz.
- Changed principal repo branch from ``master`` to ``main``.
Detailed changes by module
''''''''''''''''''''''''''
**CLI**
- Because frequencies are now dicts as well in a Survey they have to be named
by their key instead of their value when selecting data in the parameter
file.
- Entire configuration is now added to the log file.
**Core**
- ``restrict_weights``: New signature.
**Electrodes**
- New module containing all sources and receivers. Currently implemented are
``TxElectricDipole``, ``TxMagneticDipole``, ``TxElectricWire``,
``RxElectricPoint``, and ``RxMagneticPoint``.
- New class ``TxElectricWire`` for an arbitrary electric wire.
- Receivers can be defined in absolute coordinates, or in coordinates relative
to source position if they move with the source. Latter makes only sense
within a Survey/Simulation.
- ``dip`` is new called ``elevation`` to make it clear that it is the angle
positive upwards (anticlockwise from the horizontal plane).
- Bugfix of the loop area for a magnetic dipole (the area was previously wrong
except for dipoles of length of 1).
- Zero source strength does no longer mean "normalized", it means zero
strength (hence no source).
- Besides the sources and receivers it contains utilities how to move
electrodes in the coordinate system (e.g., ``rotation``).
**Fields**
- ``fields.Field``:
- Is *not* a subclassed ndarray any longer; with all its advantages and
disadvantages. E.g., operations on ``Field`` are not possible any longer
and have to be carried out on ``Field.field``. However, it should be easier
to maintain and expand in the future.
- New signature.
- Knows new its ``grid``. As a consequence, all functions that required
previously the ``grid`` and the ``field`` require new only the ``field``;
e.g., ``emg3d.fields.get_receiver``.
- Has no property ``ensure_pec`` any longer, it is ensured directly in
``solver.prolongation``.
- Has new the methods ``interpolate_to_grid`` and ``get_receiver``.
- Renamed parameters in all functions:
- ``src`` to ``source``;
- ``freq`` to ``frequency``;
- ``rec`` to ``receiver``.
- Removed functions and classes:
- ``SourceField``; it is just a regular ``Field`` now;
- ``get_receiver`` (the name still exists, but it is now what was before
``fields.get_receiver_response``).
- Renamed functions and classes (both do not take a ``grid`` any longer):
- ``get_h_field`` to ``get_magnetic_field``;
- ``fields.get_receiver_response`` to ``fields.get_receiver``.
**I/O**
- ``Model``, ``Field``, ``Survey``, and ``Simulation`` instances saved with an
older version of emg3d will not be able to de-serialize with version 1.0. You
have to update those files, see this gist:
https://gist.github.com/prisae/8345c3798e35f1c73efef617ac495538
**Maps**
- Changed function and class names:
- ``_Map`` to ``BaseMap``;
- ``grid2grid`` to ``interpolate`` (new signature);
- ``edges2cellaverages`` to ``interp_edges_to_vol_averages`` (new signature);
- ``volume_average`` to ``interp_volume_average`` (new signature);
- ``interp3d`` to ``interp_spline_3d`` (new signature).
- ``maps.interpolate``:
- Can now be used to interpolate values living on a grid to another grid or
to points defined either by a tuple or by an ndarray.
- The implemented interpolation methods are 'nearest' (new), 'linear',
'cubic', and 'volume'. Volume averaging ('volume') only works for
grid-to-grid interpolations, not for grid-to-points interpolations.
- Does not accept entire fields any longer. Entire fields can be mapped with
their own ``field.interpolate_to_grid`` method.
- Maps cannot be (de-)serialized any longer (``{to;from_dict}``); simply store
its name, which can be provided to ``models.Model``.
- Function ``rotation`` should be used for anything involving angles to use
the defined coordinate system consistently.
**Meshes**
- Changed function and class names:
- ``_TensorMesh`` to ``BaseMesh``;
- ``min_cell_width`` to ``cell_width``.
- ``get_origin_widths`` to ``origin_and_widths`` (has new finer loops to fine
grid sizes than before).
- ``meshes.BaseMesh``:
- Reduced to the attributes ``origin``, ``h``, ``shape_{cells;nodes}``,
``n_{cells;edges;faces}``, ``n_{edges;faces}_{x;y;z}``,
``{nodes;cell_centers}_{x;y;z}``, ``shape_{edges;faces}_{x;y;z}``, and
``cell_volumes``. These are the only required attributes for ``emg3d``.
- ``meshes.construct_mesh``: ``domain``, ``vector``, ``distance``,
``stretching``, ``min_width_limits``, and ``min_width_pps`` can now also
be provided as a dict containing the three keys ``'{x;y;z}'``.
- ``meshes.skin_depth`` takes new ``mu_r`` instead of ``mu``.
- ``good_mg_cell_nr``: ``max_prime`` is new ``max_lowest``, as it could also
be, e.g., 9, which is not a prime.
**Models**
- ``models.Model``:
- Knows new its ``grid``. As a consequence, all the functions that used to
require the ``grid`` and the ``model`` require new only the ``model``;
e.g., ``emg3d.solver.solve`` or ``emg3d.fields.get_magnetic_field``.
- If ``property_y`` or ``property_z`` are not set they return now ``None``,
not ``property_x``.
- If a float is provided for a property it is new expanded to the shape of
the model, and not kept as a float.
- Has to be initiated with all desired properties; it cannot be changed
afterwards. E.g., if it was initiated without electric permittivity, it
cannot be added afterwards. However, it can be initiated with dummy values
and adjusted later.
- Renamed ``interpolate2grid`` to ``interpolate_to_grid``.
- ``models.VolumeModel``: Does not take a ``grid`` any longer.
**Simulations**
- ``Simulation``:
- Works new for electric and magnetic dipole sources as well as electric wire
sources; electric and magnetic point receivers.
- Works now as well for surveys that contain receivers which are positioned
relatively to the source.
- New signature: no ``grid`` any longer, ``name`` is new an optional keyword
parameter, new optional keyword parameter ``info``.
- Method ``get_sfield`` is removed.
- ``expand_grid_model`` and ``estimate_gridding_opts`` have new signatures and
do not take a ``grid`` any longer.
**Solver**
- ``solver.solve``:
- New signature: no ``grid`` any longer; ``efield`` and ``cycle`` are moved
to keyword arguments.
- The defaults for ``sslsolver``, ``semicoarsening``, and ``linerelaxation``
is new ``True`` (before it was ``False``). This is not necessarily the
fastest setting, but generally the most robust setting.
- New keyword parameter ``plain``, which is by default ``False``. If it is
set to ``True`` it uses plain multigrid, hence ``sslsolver=False``,
``semicoarsening=False``, and ``linerelaxation=False``, unless these
parameters were set to anything different than ``True``.
- Some verbosity levels changed (for consistency reasons throughout emg3d).
The new levels are [old levels in brackets]:
- -1: Nothing [0]
- 0: Warnings [1]
- 1: One-liner at the end [2]
- 2: One-liner (dynamically updated) [-1]
- 3: Runtime and information about the method [same]
- 4: Additional information for each MG-cycle [same]
- 5: Everything (slower due to additional error computations) [same]
Level three updates now dynamically, just as level 2.
- ``solve_source()``: New function, a shortcut for ``solve()``. It takes a
``source`` and a ``frequency`` instead of a ``sfield``, gets the ``sfield``
internally, and forwards everything to ``solver.solve``.
- ``multigrid``, ``krylov``, ``smoothing``, ``restriction``, ``prolongation``,
``residual``, ``RegularGridProlongator``: New signature, mainly not taking a
``grid`` any longer.
**Surveys**
- ``Survey``:
- ``frequencies`` is new a dict just like ``sources`` and ``receivers``.
- ``sources`` and ``receivers`` must be tuples or dicts; lists are no longer
permitted. For this, the module ``surveys`` has new convenience functions
``txrx_coordinates_to_dict`` and ``txrx_lists_to_dict``.
- Has no attribute ``observed`` any longer; access it just like any other
data through ``Survey.data.observed``.
- ``rec_coords`` and ``src_coords`` attributes changed to the methods
``receiver_coordinates`` and ``source_coordinates``.
``receiver_coordinates`` takes an optional source key.
For relatively located receivers, it returns by default all positions of
this receiver for all source position. If a source-key is provided it only
returns the receiver position for this source. This does not affect
absolutely positioned receivers.
- Has no attribute ``rec_types`` any longer.
- ``name`` is new optional.
- New optional keywords ``date`` and ``info``.
- ``noise_floor`` and ``relative_error`` are new stored as data array if they
are not floats.
- The keyword ``fixed`` has been dropped. To simulate fixed surveys define
the receivers with a relative offset to the source, instead of absolute
coordinates.
- ``data`` can be a dict containing many data set.
- Automatic key names start now with 1 and have a hyphen between the prefix
and the number; they also contain the abbreviated electrode name. E.g.,
``Tx0`` becomes ``TxED-1`` or ``TxMD-1`` or ``TxEW-1``. Similar, ``Rx9``
becomes ``RxEP-10`` or ``RxMp-10``, and ``f0`` becomes ``f-1``.
- ``Survey.size`` is now the total number, ``Survey.count`` is the count of
the data that actually has non-NaN values.
- Now completely functional for receivers which are positioned relatively to
the source.
- New functions ``txrx_coordinates_to_dict`` and ``txrx_lists_to_dict`` to
collocate many sources or receivers into dicts (also
``frequencies_to_dict``).
- ``Dipole``: Replaced by the new source and receiver classes in the new module
``electrodes``.
**Time**
- Moved ``Fourier`` from ``emg3d.utils`` to its own module ``emg3d.time``.
- Renamed parameters:
- ``freq_req`` to ``freq_required``;
- ``freq_calc`` to ``freq_compute``;
- ``freq_calc_i`` to ``ifreq_compute``;
- ``freq_inp`` to ``input_freq``;
- ``freq_extrapolate_i`` to ``ifreq_extrapolate``;
- ``freq_interpolate_i`` to ``ifreq_interpolate``;
**Utils**
- Renamed ``Time`` to ``Timer``.
- Moved ``Fourier`` to its own module ``emg3d.time.Fourier``.
- ``_process_map`` new avoids ``concurrent.futures`` if ``max_workers<2``.
0.x-Series
""""""""""