Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-normalize the frequency-domain response in case of a magnetic source #45

Closed
wants to merge 4 commits into from

Conversation

ruboerner
Copy link

With these small changes it seems possible to calculate the time-domain response of a layered half-space due to a magnetic dipole source. The reason for the code change is that prior to the f->t transform, the normalization (by i \omega \mu_0) has to be undone.

@prisae
Copy link
Member

prisae commented Sep 16, 2019

Thanks Ralph-Uwe for your contribution! Improvements to the magnetic-side of things are very welcome, as I hardly ever use that part of the code.

Couple of questions:

  • Just in case: Do you know of any analytical time-domain solution we could use for comparison/tests? The analytical solutions currently implemented are only in the frequency domain (for magnetic sources).
  • I first thought instantly that this should live in model.tem. But model.tem is not aware of the source-type, so you put it into the right place.

Two tests fail currently. The first one is a regression test, so expected to fail. The second one, however, should not fail. I will have to look into that in more detail.

I'll leave some comments in the code too. If you could change that great. Or, if you don't mind, then I'll do it when I get around to adjust the tests (probably after my holidays, so give me two weeks....)

Copy link
Member

@prisae prisae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! As I already mentioned, if you know of an analytical solution that we could use for comparison that would be great!

empymod/model.py Outdated
# back into time-domain has to be carried out.
for kk in range(len(freq)):
EM[kk, :] *= 2j * np.pi * freq[kk] * np.pi * 4e-7

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind changing

for kk in range(len(freq)):
    EM[kk, :] *= 2j * np.pi * freq[kk] * np.pi * 4e-7

to the more pythonic

for kk, kfreq in enumerate(freq):
    EM[kk, :] *= 2j * np.pi * kfreq * np.pi * 4e-7

here and in the other case too?

Thinking about it I think we should actually avoid the loop entirely:

EM *= 2j * np.pi * freq[:, None] * np.pi * 4e-7

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's perfectly ok!

@ruboerner
Copy link
Author

A simple function for checking the impulse response due to a vertical magnetic dipole is:
########################################
import numpy as np
from scipy.constants import mu_0
from scipy.special import erf

def dhzdt(t, sigma, r):
r"""Return the impulse response (i.e., dHz(t)/dt) of a homogeneous isotropic half-space
of electrical conductivity sigma in z>=0 due to a current shut-off in a vertical
magnetic dipole source of unit moment for times t>0.

Source and receiver are both at the plane z=0 and separated by the distance r.
"""
theta = np.sqrt(mu_0 * sigma / 4 / t)
theta_r = theta * r
s = 9 * erf(theta_r)
s -= 2 * theta_r /np.sqrt(np.pi) * (9 + 6 * theta_r**2 + 4 * theta_r**4) * np.exp(-theta_r**2)
s /= (-2 * np.pi * mu_0 * sigma * r**5)
return s

#################################################

@prisae
Copy link
Member

prisae commented Sep 16, 2019

Fantastic, thanks Ralph-Uwe! Do you have a reference for the analytical solution?

I might get time to include it tomorrow and add the relevant tests, but more likely it will have to wait two weeks until I am back. Either way, I will make a new release with the fix pushing it to v1.9.0, including other recent changes I made.

Thanks again for the fix. And a big hooray, you are actually the first contributor (as far as code goes) to empymod! I will include you in the CREDITS file, and probably change the (c) from my name to something more generic like "(c) The empymod developers".

I hope you found empymod useful (despite the bug ;-) ).

@ruboerner
Copy link
Author

ruboerner commented Sep 16, 2019

Thanks Dieter,

Kudos for the empymod package!

Here's the reference:

@incollection{ward1988electromagnetic,
title={Electromagnetic theory for geophysical applications},
author={Ward, Stanley H and Hohmann, Gerald W},
booktitle={Electromagnetic Methods in Applied Geophysics: Voume 1, Theory},
pages={130--311},
year={1988},
publisher={Society of Exploration Geophysicists}
}

...have a nice holiday!

@prisae prisae added the enhancement New feature or request label Sep 17, 2019
@prisae
Copy link
Member

prisae commented Sep 17, 2019

OK. I thought about it again, and talked it through with Evert Slob, who was one of the co-others of the paper on which the code is based (Hunziker et al., 2015, Geophysics).

So currently it returns the H-field, the field due to a magnetic dipole. Your PR would turn that into a B-field for a coil, which turns your PR in a feature request rather than a bug fix. So it would have to be implemented optionally, not exclusively. And also, if we implement it for source coils we should implement it for receiver coils too.

I'll have a think about it. Maybe an additional input parameter for dipole and bipole. Or a new function coil in addition to dipole and bipole.

Inputs/ideas/opinions welcome!

@prisae
Copy link
Member

prisae commented Sep 18, 2019

One possibility is to have for msrc/mrec in addition to False/True a third state, 'loop'. That would only work for bipole though, not for dipole, but I think that is fine. bipole is the more flexible function that can also do everything which dipole can...

Do you mind if I work directly on your PR, @ruboerner ?

@ruboerner
Copy link
Author

One possibility is to have for msrc/mrec in addition to False/True a third state, 'loop'. That would only work for bipole though, not for dipole, but I think that is fine. bipole is the more flexible function that can also do everything which dipole can...

I think it might be better to introduce a new function for magnetic loops as "bipole" suggests that electric bipoles are used. This might just be a stripped-down version of bipole without e sources?

Do you mind if I work directly on your PR, @ruboerner ?

I'm fine with that.

@prisae
Copy link
Member

prisae commented Sep 18, 2019

Sounds good. You think just loop-loop, or both, loop-loop and loop-dipole? As far as I know, in reality the magnetic source is always a loop, whereas the receiver can be both.

As I mentioned, I'll be off from today for two weeks, but will have a look at this afterwards. Is it OK if I bother you for some testing/feedback once I have something? I personally have not much experience with magnetic sources, so it would be great and highly appreciated to have your input!

@ruboerner
Copy link
Author

Sounds good. You think just loop-loop, or both, loop-loop and loop-dipole? As far as I know, in reality the magnetic source is always a loop, whereas the receiver can be both.

Yes, most land-based TEM systems use loops as sources and coils or small loops as receivers, which is exactly what you suggest.

As I mentioned, I'll be off from today for two weeks, but will have a look at this afterwards. Is it OK if I bother you for some testing/feedback once I have something? I personally have not much experience with magnetic sources, so it would be great and highly appreciated to have your input!

Yes, don't worry, it's absolutely ok. I'm glad to help.

Have a nice time off!

@prisae
Copy link
Member

prisae commented Oct 4, 2019

I hope to draft it early next week. I though of using bipole as a starting point, but with the following simplifications:

  • Magnetic loop sources, with azimuth and dip; unit length plus strength.
  • Magnetic loop and dipole receivers, with azimuth and dip; unit length.
  • Only time (or also frequency)?

Does that make sense?

Any clever idea for the function name? Simply loop comes to my mind, but there might be a better alternative.

@prisae
Copy link
Member

prisae commented Oct 10, 2019

It is necessary for frequency and time domain modelling, so I moved it to fem. Have a look at the new example here:
https://github.com/empymod/empymod-examples/blob/master/5b_TEM.ipynb
where I reproduced the results by Ward and Hohmann, 1988, Figures 4.2-4.5.

Now, given that, I actually think it is a bug in empymod.kernel. \zeta = s\mu = i\omega\mu; there must be a factor \zeta missing somewhere for magnetic sources...

I'll have to dig into that in more detail, so don't expect it to resolve anytime soon. I don't want to include a workaround in model that fixes a bug in kernel.

@coveralls
Copy link

Coverage Status

Coverage decreased (-1.6%) to 98.38% when pulling 03d769f on ruboerner:master into 7f65e3a on empymod:master.

@prisae
Copy link
Member

prisae commented Oct 10, 2019

Note to self to not forget: it should not be mu_0, but the mu of the layer in which the source resides, and then differently for the different wavenumber-kernels depending if affected by vertical or horizontal mu, mu_v or mu_h (hence use mu=mu_0*mu_{r;s}^h or mu=mu_0*mu_{r;s}^v). Of course, if the source is in the air that all simplifies to mu_0 again. But the current implementation only holds for that special case, make it more general.

@prisae
Copy link
Member

prisae commented Oct 10, 2019

I am turning in circles. I take back what I said before. Again, it is the difference between a magnetic dipole and a loop source. So not a bug. Just confusing for someone never actually involved with magnetic sources. I am still confused with the units though... I will discuss this through and come back with a solution.

@prisae
Copy link
Member

prisae commented Oct 11, 2019

@ruboerner , do you know of any analytical solutions for magnetic source with an electric receiver? What leaves me a bit uneasy with implementing a fix for if msrc is that this also affects magnetic-source to electric-receiver cases, and I am not sure if they are affected in the same way...

@prisae
Copy link
Member

prisae commented Oct 11, 2019

Comparison with simpegEM1D confirms the problem...

@prisae prisae added bug Something isn't working and removed bug Something isn't working labels Oct 11, 2019
@prisae
Copy link
Member

prisae commented Oct 14, 2019

Extensive discussion, amongst others with the authors of the original article and their code EMmod, confirm that everything is fine with the current implementation. All sources and receivers are assumed to be dipoles.

This changes for loops, and the solution therefore is really to have a loop-function. If the source is a loop, it needs the factor j\omega\mu; if the receiver is a loop, it needs another j\omega\mu.

@prisae
Copy link
Member

prisae commented Oct 15, 2019

Hi @ruboerner - This took more effort than I anticipated, but it is in. There is a new version empymod v1.10.0, which has a new function model.loop. It takes the same arguments as model.bipole, except that

  • mrec can be [True, False, 'loop']`.

Furthermore, the following parameters are removed:

  • msrc=True: fixed, cannot be changed;
  • srcpts=1: fixed, cannot be changed.

This means that it is a loop source, measured by

  • an electric or magnetic, arbitrary rotated, finite length bipole, or
  • a loop

In the end I worked on a new branch, as everything changed a bit (see #48). I will therefore close this PR. I mentioned your help in the Credits-file.

I would appreciate if you could test the new version and let me know if it works for you!

Thanks.

@prisae prisae closed this Oct 15, 2019
@prisae
Copy link
Member

prisae commented Oct 19, 2019

Here a graphical summary of it, with explanations:
https://nbviewer.jupyter.org/github/empymod/empymod-examples/blob/master/7b_Dipoles_and_Loops.ipynb

index

@ruboerner
Copy link
Author

Hi @prisae , sorry for the late response. Big kudos for your effort you invested in implementing magnetic sources. This is indeed a huge improvement!

@prisae
Copy link
Member

prisae commented Oct 22, 2019

Thanks @ruboerner . Did you test it, does it work work for you as expected?

There is obviously much more that could be done in empymod for TEM-style things. Like allowing for more complicated waveforms, windowing as often used in TEM's, etc. But this is far off my current topic... But I'd be happy to include more things or assist in implementing them, if there is interest.

@prisae
Copy link
Member

prisae commented Nov 6, 2019

Instead of using empymod.loop, we can also actually model an electric loop.

I added examples here:
https://github.com/empymod/empymod-examples/blob/master/7b_Dipoles_and_Loops.ipynb
modelling a loop with either four el. point sources, or four electric finite length dipole sources.

@prisae
Copy link
Member

prisae commented Nov 22, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants