Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8c62b2f

Browse files
authored
allow complex mu for forward time-domain em1d (simpeg#1739)
#### Summary Support complex permeability in forward 1D time-domain em simulations. #### PR Checklist * [x] If this is a work in progress PR, set as a Draft PR * [x] Linted my code according to the [style guides](https://docs.simpeg.xyz/latest/content/getting_started/contributing/code-style.html). * [x] Added [tests](https://docs.simpeg.xyz/latest/content/getting_started/contributing/testing.html) to verify changes to the code. * [x] Added necessary documentation to any new functions/classes following the expect [style](https://docs.simpeg.xyz/latest/content/getting_started/contributing/documentation.html). * [x] Marked as ready for review (if this is was a draft PR), and converted to a Pull Request * [x] Tagged ``@simpeg/simpeg-developers`` when ready for review. #### What does this implement/fix? removes cast to `real` #### Additional information `geoana` supports complex permeability in the kernel, so the cast to real is unnecessary.
1 parent 9a8c46e commit 8c62b2f

6 files changed

Lines changed: 105 additions & 5 deletions

File tree

.ci/environment_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ dependencies:
77
- pymatsolver>=0.3
88
- matplotlib-base
99
- discretize>=0.12
10-
- geoana>=0.7
10+
- geoana>=0.8.1
1111
- libdlf
1212
- typing_extensions
1313

environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
- pymatsolver>=0.3
1010
- matplotlib-base
1111
- discretize>=0.12
12-
- geoana>=0.7
12+
- geoana>=0.8.1
1313
- libdlf
1414
- typing_extensions
1515

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ dependencies = [
2020
"pymatsolver>=0.3",
2121
"matplotlib",
2222
"discretize>=0.12",
23-
"geoana>=0.7",
23+
"geoana>=0.8.1",
2424
"libdlf",
2525
"typing_extensions; python_version<'3.13'",
2626
]

simpeg/electromagnetics/time_domain/simulation_1d.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,7 @@ def fields(self, m):
243243
sig = self.compute_complex_sigma(frequencies)
244244
mu = self.compute_complex_mu(frequencies)
245245

246-
# TODO geoana currently only support real mu input.
247-
rTE = rTE_forward(frequencies, unique_lambs, sig, mu.real, self.thicknesses)
246+
rTE = rTE_forward(frequencies, unique_lambs, sig, mu, self.thicknesses)
248247
rTE = rTE[:, inv_lambs]
249248
v = ((C0s * rTE) @ self._fhtfilt.j0 + (C1s * rTE) @ self._fhtfilt.j1) @ W.T
250249

tests/em/em1d/test_EM1D_FD_fwd.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,5 +606,42 @@ def test_rx_loc_shapes(rx_class, n_locs1, n_locs2, orientation, component):
606606
np.testing.assert_allclose(J, J[0], rtol=1e-12)
607607

608608

609+
@pytest.mark.parametrize("prop", ["conductivity", "permeability"])
610+
def test_real_vs_complex(prop):
611+
"""just makes sure that it respect a complex conductivity, in that it is different
612+
from the real value.
613+
"""
614+
offsets = np.linspace(5, 20, 10)
615+
rx1_locs = np.pad(offsets[:, None], ((0, 0), (0, 2)), constant_values=0)
616+
rx_list = [
617+
fdem.receivers.PointMagneticField(rx1_locs, orientation="x", component="real"),
618+
fdem.receivers.PointMagneticField(rx1_locs, orientation="x", component="imag"),
619+
]
620+
621+
src = fdem.sources.MagDipole(rx_list, frequency=0.1)
622+
srv = fdem.Survey(src)
623+
624+
sim = fdem.Simulation1DLayered(survey=srv, sigma=[1.0])
625+
if prop == "conductivity":
626+
sim.eta = 0.5
627+
else:
628+
sim.dchi = 1.0
629+
630+
d_c = sim.dpred(None)
631+
632+
# create another simulation that is just the real part of sigma and mu
633+
sim_real = fdem.Simulation1DLayered(survey=srv, sigma=[1.0])
634+
635+
# hijack these to just return the real values from the complex valued simulation
636+
# that way we are sure the two simulations have the same real parts of mu and sigma
637+
# but different imaginary portions
638+
sim_real.compute_complex_sigma = lambda f: sim.compute_complex_sigma(f).real
639+
sim_real.compute_complex_mu = lambda f: sim.compute_complex_mu(f).real
640+
641+
d_r = sim_real.dpred(None)
642+
643+
assert np.all(d_r != d_c)
644+
645+
609646
if __name__ == "__main__":
610647
unittest.main()

tests/em/em1d/test_EM1D_TD_general_fwd.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import unittest
2+
import pytest
23
from simpeg import maps
34
import simpeg.electromagnetics.time_domain as tdem
45
from simpeg.electromagnetics.utils import convolve_with_waveform
@@ -285,5 +286,68 @@ def test_backwards_compatible_filter_key():
285286
assert sim.time_filter == "key_81_2009"
286287

287288

289+
@pytest.mark.parametrize("prop", ["conductivity", "permeability"])
290+
def test_real_vs_complex(prop):
291+
"""just makes sure that it respect a complex conductivity, in that it is different
292+
from the real value.
293+
"""
294+
source_location = np.array([0.0, 0.0, 100.0 + 1e-5])
295+
receiver_locations = np.array([[0.0, 0.0, 100.0 + 1e-5]])
296+
receiver_orientation = "z" # "x", "y" or "z"
297+
times = np.logspace(-5, -2, 31)
298+
radius = 20.0
299+
300+
# Waveform
301+
waveform = tdem.sources.TriangularWaveform(
302+
start_time=-0.01, peak_time=-0.005, off_time=0.0
303+
)
304+
305+
# Receiver list
306+
307+
# Define receivers at each location.
308+
b_receiver = tdem.receivers.PointMagneticFluxDensity(
309+
receiver_locations, times, receiver_orientation
310+
)
311+
dbzdt_receiver = tdem.receivers.PointMagneticFluxTimeDerivative(
312+
receiver_locations, times, receiver_orientation
313+
)
314+
receivers_list = [
315+
b_receiver,
316+
dbzdt_receiver,
317+
] # Make a list containing all receivers even if just one
318+
319+
# Must define the transmitter properties and associated receivers
320+
source_list = [
321+
tdem.sources.CircularLoop(
322+
receivers_list,
323+
location=source_location,
324+
waveform=waveform,
325+
radius=radius,
326+
)
327+
]
328+
329+
survey = tdem.Survey(source_list)
330+
331+
sim = tdem.Simulation1DLayered(survey=survey, sigma=[1.0])
332+
if prop == "conductivity":
333+
sim.eta = 0.5
334+
else:
335+
sim.dchi = 1.0
336+
337+
d_c = sim.dpred(None)
338+
339+
sim_real = tdem.Simulation1DLayered(survey=survey, sigma=[1.0])
340+
341+
# hijack these to just return the real values from the complex valued simulation
342+
# that way we are sure the two simulations have the same real parts of mu and sigma
343+
# but different imaginary portions
344+
sim_real.compute_complex_sigma = lambda f: sim.compute_complex_sigma(f).real
345+
sim_real.compute_complex_mu = lambda f: sim.compute_complex_mu(f).real
346+
347+
d_r = sim_real.dpred(None)
348+
349+
assert np.all(d_r != d_c)
350+
351+
288352
if __name__ == "__main__":
289353
unittest.main()

0 commit comments

Comments
 (0)