Releases: emsig/emg3d
Survey & Simulation
This is a big release with many new features, and unfortunately not completely
backwards compatible. The main new features are the new Survey and
Simulation classes, as well as some initial work for optimization
(misfit, gradient). Also, a Model can now be a resistivity model, a
conductivity model, or the logarithm (natural or base 10) therefore. Receivers
can now be arbitrarily rotated, just as the sources. In addition to the
existing soft-dependencies empymod
, discretize
, and h5py
there are
the new soft-dependencies xarray
and tqm
; discretize
is now much tighter
integrated. For the new survey and simulation classes xarray
is a required
dependency. However, the only hard dependency remain scipy
and numba
, if
you use emg3d
purely as a solver. Data reading and writing has new a
JSON-backend, in addition to the existing HDF5 and NumPy-backends.
In more detail:
-
Modules:
-
surveys
(new; requiresxarray
):- Class
surveys.Survey
, which combines sources, receivers, and data. - Class
surveys.Dipole
, which defines electric or magnetic point dipoles
and finite length dipoles.
- Class
-
simulations
(new; requiresxarray
; soft-dependencytqdm
):- Class
simulations.Simulation
, which combines a survey with a model. A
simulation computes the e-field (and h-field) asynchronously using
concurrent.futures
. This class will include automatic, source- and
frequency-dependent gridding in the future. Iftqdm
is installed it
displays a progress bar for the asynchronous computation. Note that the
simulation class has still some limitations, consult the class
documentation.
- Class
-
models
:- Model instances take new the parameters
property_{x;y;z}
instead of
res_{x;y;z}
. The properties can be either resistivity, conductivity, or
log_{e;10} thereof. What is actually provided has to be defined with the
parametermapping
. By default, it remains resistivity, as it was until
now. The keywordsres_{x;y;z}
are deprecated, but still accepted at
the moment. The attributesmodel.res_{x;y;z}
are still available too,
but equally deprecated. However, it is no longer possible to
assign values to these attributes, which is a backwards
incompatible change. - A model knows now how to interpolate itself from its grid to another grid
(interpolate2grid
).
- Model instances take new the parameters
-
maps
:- New mappings for
models.Model
instances: The mappings take care of
how to transform the investigation variable to conductivity and back, and
how it affects its derivative. - New interpolation routine
edges2cellaverages
.
- New mappings for
-
fields
:-
Function
get_receiver_response
(new), which returns the response
for arbitrarily rotated receivers. -
Improvements to
Field
andSourceField
:_sval
and_smu0
not stored any longer, derived from_freq
.SourceField
is now using thecopy()
andfrom_dict()
from its
parents classField
.
-
-
io
:- File-format
json
(new), writes to a hierarchical, plain json file. - Deprecated the use of
backend
, it uses the file extension of
fname
instead. - This means
.npz
(instead ofnumpy
),.h5
(instead ofh5py
), and
new.json
. - New parameter
collect_classes
, which can be used to switch-on
collection of the main classes in root-level dictionaries. By default,
they are no longer collected (changed).
- File-format
-
meshes
:meshes.TensorMesh
new inherits fromdiscretize
if installed.- Added
__eq__
tomodels.TensorMesh
to compare meshes.
-
optimize
(new)- Functionalities related to inversion (data misfit, gradient, data
weighting, and depth weighting). This module is in an early stage, and
the API will likely change in the future. Current functions aremisfit
,
gradient
(using the adjoint-state method), anddata_weighting
. These
functionalities are best accessed through theSimulation
class.
- Functionalities related to inversion (data misfit, gradient, data
-
-
Dependencies:
empymod
is now a soft dependency (no longer a hard dependency), only
required forutils.Fourier
(time-domain modelling).- Existing soft dependency
discretize
is now baked straight intomeshes
. - New soft dependency
xarray
for theSurvey
class (and therefore also for
theSimulation
class and theoptimize
module). - New soft dependency
tqdm
for nice progress bars in asynchronous
computation.
-
Deprecations and removals:
- Removed deprecated functions
data_write
anddata_read
. - Removed all deprecated functions from
utils
.
- Removed deprecated functions
-
Miscellaneous:
- Re-organise API-docs.
- Much bookkeeping (improve error raising and checking; chaining errors,
numpy types, etc).
Refactor
Grand refactor with new internal layout. Mainly splitting-up utils
into
smaller bits. Most functionalities (old names) are currently retained in
utils
and it should be mostly backwards compatible for now, but they are
deprecated and will eventually be removed. Some previously deprecated functions
were removed, however.
-
Removed deprecated functions:
emg3d.solver.solver
(useemg3d.solver.solve
instead).- Aliases of
emg3d.io.data_write
andemg3d.io.data_read
inemg3d.utils
.
-
Changes:
-
SourceField
has now the same signature asField
(this might break your
code if you calledSourceField
directly, with positional arguments, and
not throughget_source_field
). -
More functions and classes in the top namespace.
-
Replaced
core.l2norm
withscipy.linalg.norm
, as SciPy 1.4 got the
following PR: scipy/scipy#10397 (reason to raise
minimum SciPy to 1.4). -
Increased minimum required versions of dependencies to
scipy>=1.4.0
(raised from 1.1, see note above)empymod>=2.0.0
(no min requirement before)numba>=0.45.0
(raised from 0.40)
-
-
New layout
njitted
->core
.utils
split infields
,meshes
,models
,maps
, andutils
.
-
Bugfixes:
- Fixed
to_dict
,from_dict
, andcopy
for theSourceField
. - Fixed
io
forSourceField
, that was not implemented properly.
- Fixed
Zero Source
-
Bug fixes:
- Checks now if provided source-field is zero, and exists gracefully if so, returning a zero electric field. Until now it failed with a division-by-zero error.
-
Improvements:
- Warnings: If
verb=1
it prints a warning in case it did not converge (it finished silently until now). - Improvements to docs (figures-scaling; intersphinx).
- Adjust
Fields.pha
andFields.amp
in accordance withempymod v2
:.pha
and.amp
are now methods; uses directlyempymod.utils.EMArray
. - Adjust tests for
empymod v2
(Fields, Fourier).
- Warnings: If
Data persistence
-
New:
- New functions
emg3d.save
andemg3d.load
to save and load all sort ofemg3d
instances. The currently implemented backends areh5py
for.h5
-files (default, but requiresh5py
to be installed) andnumpy
for.npz
-files. - Classes
emg3d.utils.Field
,emg3d.utils.Model
, andemg3d.utils.TensorMesh
have new methods.copy()
,.to_dict()
, and.from_dict()
. emg3d.utils.Model
: Possible to create new models by adding or subtracting existing models, and comparing two models (+
,-
,==
and!=
). New attributesshape
andsize
.emg3d.utils.Model
does not store the volume any longer (justvnC
).
- New functions
-
Deprecations:
- Deprecated
data_write
anddata_read
.
- Deprecated
-
Internal and bug fixes:
- All I/O-related stuff moved to its own file
io.py
. - Change from
NUMBA_DISABLE_JIT
to usepy_func
for testing and coverage. - Bugfix:
emg3d.njitted.restrict
did not store the {x;y;z}-field ifsc_dir
was {4;5;6}, respectively.
- All I/O-related stuff moved to its own file
Sphinx gallery
- Rename
solver.solver
tosolver.solve
; loadsolve
also into the main namespace asemg3d.solve
. - Adjustment to termination criterion for STAGNATION: The current error is now compared to the last error of the same cycle type. Together with this the workaround for sslsolver when called with an initial efield introduced in v0.8.0 was removed.
- Adjustment to
utils.get_hx_h0
(this might change your boundaries): The calculation domain is now calculated so that the distance for the signal travelling from the source to the boundary and back to the most remote receiver is at least two wavelengths away. If this is within the provided domain, then now extra buffer is added around the domain. Additionally, the function has a new parametermax_domain
, which is the maximum distance from the center to the boundary; defaults to 100 km. - New parameter
log
forutils.grid2grid
; ifTrue
, then the interpolation is carried out on a log10-scale. - Change from the notebook-based
emg3d-examples
-repo to thesphinx
-basedemg3d-gallery
-repo.
Complex sources
-
Strength input for
get_source_field
can now be complex; it also stores now the source location and its strength and moment. -
get_receiver
can now take entireField
instances, and returns in that case (fx
,fy
,fz
) at receiver locations. -
Krylov subspace solvers:
- Solver now finishes in the middle of preconditioning cycles if tolerance is reached.
- Solver now aborts if solution diverges or stagnates also for the SSL solvers; it fails and returns a zero field.
- Removed
gmres
andlgmres
from the supported SSL solvers; they do not work nice for this problem. Supported remainbicgstab
(default),cgs
, andgcrotmk
.
-
Various small things:
-
New attribute
Field.is_electric
, so the field knows if it is electric or magnetic. -
New
verb
-possibility:verb=-1
is a continuously updated one-liner, ideal to monitor large sets of calculations or in inversions. -
The returned
info
dictionary contains new keys:runtime_at_cycle
: accumulated total runtime at each cycle;error_at_cycle
: absolute error at each cycle.
-
Simple
__repr__
forTensorMesh
,Model
,Fourier
,Time
.
-
-
Bugfixes:
- Related to
get_hx_h0
,data_write
, printing inFourier
.
- Related to
VolumeModel
-
New class
VolumeModel
; changes inModel
:Model
now only contains resistivity, magnetic permeability, and electric permittivity.VolumeModel
contains the volume-averaged values eta and zeta; called from withinemg3d.solver.solver
.- Full wave equation is enabled again, via
epsilon_r
; by default it is set to None, hence diffusive approximation. - Model parameters are now internally stored as 1D arrays.
- An {isotropic, VTI, HTI} initiated model can be changed by providing the missing resistivities.
-
Bugfix: Up and till version 0.8.1 there was a bug. If resistivity was set with slices, e.g.,
model.res[:, :, :5]=1e10
, it DID NOT update the corresponding eta. This bug was unintentionally fixed in 0.9.0, but only realised now. -
Various:
- The log now lists the version of emg3d.
- PEP8: internal imports now use absolute paths instead of relative ones.
- Move from conda-channel
prisae
toconda-forge
. - Automatic deploy for PyPi and conda-forge.
Fourier
-
New routine:
emg3d.utils.Fourier
, a class to handle Fourier-transform related stuff for time-domain modelling. See the example notebooks for its usage.
-
Utilities:
Fields
and returned receiver-arrays (EMArray
) both have amplitude (.amp
) and phase (.pha
) attributes.Fields
have attributes containing frequency-information (freq
,smu0
).- New class
SourceField
; a subclass ofField
, addingvector
andv{x,y,z}
attributes for the real valued source vectors. - The
Model
is not frequency-dependent any longer and does NOT take afreq
-parameter any more (currently it still takes it, but it is deprecated and will be removed in the future). data_write
automatically removes_vol
fromTensorMesh
instances and_eta_{x,y,z}
,_zeta
fromModel
instances. This makes the archives smaller, and they are not required, as they are simply reconstructed if needed.
-
Internal changes:
- The multigrid method, as implemented, only works for the diffusive approximation. Nevertheless, we always used
\sigma-i\omega\epsilon
, hence a complex number. This is now changed and\epsilon
set to 0,
leaving only\sigma
. - Change time convention from
exp(-iwt)
toexp(iwt)
, as used inempymod
and commonly in CSEM. Removed the parameterconjugate
from the solver, to simplify. - Change own private class variables from
__
to_
. res
andmu_r
are now checked to ensure they are >0;freq
is checked to ensure !=0.
- The multigrid method, as implemented, only works for the diffusive approximation. Nevertheless, we always used
-
New dependencies and maintenance:
empymod
is a new dependency.- Travis now checks all the url's in the documentation, so there should be no
broken links down the road. (Check is allowed to fail, it is visual QC.)
-
Bugfixes:
- Fixes to the
setuptools_scm
-implementation (MANIFEST.in
).
- Fixes to the
setuptools_scm
- Implement
setuptools_scm
for versioning (adds git hashes for dev-versions).
Laplace
-
Laplace-domain calculation: By providing a negative
freq
-value toutils.get_source_field
andutils.Model
, the calculation is carried out in the real Laplace domains = freq
instead of the complex frequency
domains = 2i*pi*freq
. -
New meshing helper routines (particularly useful for transient modelling where frequency-dependent/adaptive meshes are inevitable):
utils.get_hx_h0
to get cell widths and origin for given parameters including a few fixed interfaces (center plus two, e.g. top anomaly, sea-floor, and sea-surface).utils.get_cell_numbers
to get good values of number of cells for given primes.
-
Speed-up
njitted.volume_average
significantly thanks to @jcapriot. -
Bugfixes and other minor things:
- Abort if l2-norm is NaN (only works for MG).
- Workaround for the case where a
sslsolver
is used together with a provided initialefield
. - Changed parameter
rho
tores
for consistency reasons inutils.get_domain
. - Changed parameter
h_min
tomin_width
for consistency reasons inutils.get_stretched_h
.