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

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 45 additions & 35 deletions simpeg/electromagnetics/static/resistivity/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,18 @@ class Dipole(BaseSrc):
----------
receiver_list : list of simpeg.electromagnetics.static.resistivity.receivers.BaseRx
A list of DC/IP receivers
location_a : (n_source, dim) numpy.array_like
A electrode locations; remember to set 'location_b' keyword argument to define N electrode locations.
location_b : (n_source, dim) numpy.array_like
B electrode locations; remember to set 'location_a' keyword argument to define M electrode locations.
location : list or tuple of length 2 of numpy.array_like
A and B electrode locations. In this case, do not set the 'location_a' and 'location_b'
keyword arguments. And we supply a list or tuple of the form [location_a, location_b].
location_a : (dim) array_like
A electrode locations; remember to set ``location_b`` keyword argument
to define B electrode location.
location_b : (dim) array_like
B electrode locations; remember to set ``location_a`` keyword argument
to define A electrode location.
location : tuple of array_like, optional
A and B electrode locations. If ``location_a`` and ``location_b`` are
provided, don't pass values to this argument. Otherwise, provide
a tuple of the form ``(location_a, location_b)``.
current : float, optional
Current amplitude in :math:`A` that goes through each electrode.
"""

def __init__(
Expand All @@ -154,41 +159,46 @@ def __init__(
location_a=None,
location_b=None,
location=None,
**kwargs,
Copy link
Member

Choose a reason for hiding this comment

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

🎉

current=1.0,
):
if "current" in kwargs.keys():
value = kwargs.pop("current")
current = [value, -value]
else:
current = [1.0, -1.0]

# if location_a set, then use location_a, location_b
if location_a is not None:
if location_b is None:
raise ValueError(
"For a dipole source both location_a and location_b " "must be set"
if location is None and location_a is None and location_b is None:
raise TypeError(
"Found 'location', 'location_a' and 'location_b' as None. "
"Please specify 'location', or 'location_a' and 'location_b' "
"when defining a dipole source."
)
if location is not None and (location_a is not None or location_b is not None):
raise TypeError(
"Found 'location_a' and/or 'location_b' as not None values. "
"When passing a not None value for 'location', 'location_a' and "
"'location_b' should be set to None."
)
if location is None:
if location_a is None:
raise TypeError(
"Invalid 'location_a' set to None. When 'location' is None, "
"both 'location_a' and 'location_b' should be set to "
"a value different than None."
)

if location is not None:
raise ValueError(
"Cannot set both location and location_a, location_b. "
"Please provide either location=(location_a, location_b) "
"or both location_a=location_a, location_b=location_b"
if location_b is None:
raise TypeError(
"Invalid 'location_b' set to None. When 'location' is None, "
"both 'location_a' and 'location_b' should be set to "
"a value different than None."
)

location = [location_a, location_b]

elif location is not None:
if len(location) != 2:
raise ValueError(
"location must be a list or tuple of length 2: "
"[location_a, location_b]. The input location has "
f"length {len(location)}"
)
if len(location) != 2:
raise ValueError(
"location must be a list or tuple of length 2: "
"[location_a, location_b]. The input location has "
f"length {len(location)}"
)

# instantiate
super().__init__(
receiver_list=receiver_list, location=location, current=current, **kwargs
receiver_list=receiver_list,
location=location,
current=[current, -current],
)

def __repr__(self):
Expand Down
152 changes: 152 additions & 0 deletions tests/em/static/test_dc_sources_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"""
Test interface for some DC sources.
"""

import pytest
import numpy as np
from simpeg.electromagnetics.static import resistivity as dc


class TestDipoleLocations:
r"""
Test the location, location_a and location_b arguments for the Dipole

Considering that `location`, `location_a`, `location_b` can be None or not
None, then we have 8 different possible combinations.


.. code::

| location | location_a | location_b | Result |
|----------|------------|------------|--------|
| None | None | None | Error |
| None | None | not None | Error |
| None | not None | None | Error |
| None | not None | not None | Run |
| not None | None | None | Run |
| not None | None | not None | Error |
| not None | not None | None | Error |
| not None | not None | not None | Error |
"""

@pytest.fixture
def receiver(self):
"""Sample DC dipole receiver."""
receiver = dc.receivers.Dipole(
locations_m=np.array([[-100, 0]]),
locations_n=np.array([[100, 0]]),
data_type="volt",
)
return receiver

def test_all_nones(self, receiver):
"""
Test error being raised when passing all location as None
"""
msg = "Found 'location', 'location_a' and 'location_b' as None. "
with pytest.raises(TypeError, match=msg):
dc.sources.Dipole(
receiver_list=[receiver],
location_a=None,
location_b=None,
location=None,
)

@pytest.mark.parametrize("electrode", ("a", "b", "both"))
def test_not_nones(self, receiver, electrode):
"""
Test error after location as not None, and location_a and/or location_b
as not None
"""
msg = (
"Found 'location_a' and/or 'location_b' as not None values. "
"When passing a not None value for 'location', 'location_a' and "
"'location_b' should be set to None."
)
electrode_a = np.array([-1.0, 0.0])
electrode_b = np.array([1.0, 0.0])
if electrode == "a":
kwargs = dict(location_a=electrode_a, location_b=None)
elif electrode == "b":
kwargs = dict(location_a=None, location_b=electrode_b)
else:
kwargs = dict(location_a=electrode_a, location_b=electrode_b)
with pytest.raises(TypeError, match=msg):
dc.sources.Dipole(
receiver_list=[receiver],
location=[electrode_a, electrode_b],
**kwargs,
)

@pytest.mark.parametrize("none_electrode", ("a", "b"))
def test_single_location_as_none(self, receiver, none_electrode):
"""
Test error after location is None and one of location_a or location_b
is also None.
"""
msg = (
f"Invalid 'location_{none_electrode}' set to None. "
"When 'location' is None, both 'location_a' and 'location_b' "
"should be set to a value different than None."
)
electrode_a = np.array([-1.0, 0.0])
electrode_b = np.array([1.0, 0.0])
if none_electrode == "a":
kwargs = dict(location_a=None, location_b=electrode_b)
else:
kwargs = dict(location_a=electrode_a, location_b=None)
with pytest.raises(TypeError, match=msg):
dc.sources.Dipole(
receiver_list=[receiver],
location=None,
**kwargs,
)

def test_location_none(self, receiver):
"""
Test if object is correctly initialized with location set to None
"""
electrode_a = np.array([-1.0, 0.0])
electrode_b = np.array([1.0, 0.0])
source = dc.sources.Dipole(
receiver_list=[receiver],
location_a=electrode_a,
location_b=electrode_b,
location=None,
)
assert isinstance(source.location, np.ndarray)
assert len(source.location) == 2
np.testing.assert_allclose(source.location, [electrode_a, electrode_b])

def test_location_not_none(self, receiver):
"""
Test if object is correctly initialized with location is set
"""
electrode_a = np.array([-1.0, 0.0])
electrode_b = np.array([1.0, 0.0])
source = dc.sources.Dipole(
receiver_list=[receiver],
location=[electrode_a, electrode_b],
)
assert isinstance(source.location, np.ndarray)
assert len(source.location) == 2
np.testing.assert_allclose(source.location, [electrode_a, electrode_b])

@pytest.mark.parametrize("length", (0, 1, 3))
def test_location_invalid_num_elements(self, length, receiver):
"""
Test error after passing location with invalid number of elements
"""
if length == 0:
location = ()
elif length == 1:
location = (np.array([1.0, 0.0]),)
else:
location = (
np.array([1.0, 0.0]),
np.array([1.0, 0.0]),
np.array([1.0, 0.0]),
)
msg = "location must be a list or tuple of length 2"
with pytest.raises(ValueError, match=msg):
dc.sources.Dipole(receiver_list=[receiver], location=location)