Skip to content

Commit

Permalink
Add a test for normalizing warning
Browse files Browse the repository at this point in the history
  • Loading branch information
prisae committed Jan 6, 2025
1 parent 6e81641 commit 0006a55
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 19 deletions.
43 changes: 24 additions & 19 deletions emg3d/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ def _point_vector_magnetic(grid, coordinates, frequency):
return vfield


def _dipole_vector(grid, points, decimals=9):
def _dipole_vector(grid, points, decimals=9, nodes=None):
"""Get n-segment dipole source by distributing them to the relevant cells.
Expand All @@ -814,6 +814,26 @@ def _dipole_vector(grid, points, decimals=9):
"""

# Round nodes and source coordinates (to avoid floating point issues etc).
# Recursion: only necessary in first go.
if nodes:
nodes_x, nodes_y, nodes_z = nodes
else:
nodes_x = np.round(grid.nodes_x, decimals)
nodes_y = np.round(grid.nodes_y, decimals)
nodes_z = np.round(grid.nodes_z, decimals)
pts = np.round(np.asarray(points, dtype=float), decimals)

# Ensure source is within nodes.
outside = (
min(pts[:, 0]) < nodes_x[0] or max(pts[:, 0]) > nodes_x[-1] or
min(pts[:, 1]) < nodes_y[0] or max(pts[:, 1]) > nodes_y[-1] or
min(pts[:, 2]) < nodes_z[0] or max(pts[:, 2]) > nodes_z[-1]
)
if outside:
raise ValueError(f"Provided source outside grid: {pts}.")
points = pts

vfield = Field(grid, dtype=float)

# Recursively loop through segments.
Expand All @@ -822,26 +842,12 @@ def _dipole_vector(grid, points, decimals=9):
# Add each segments' vector field to total vector field.
for p0, p1 in zip(points[:-1, :], points[1:, :]):
vfield.field += _dipole_vector(
grid, points=np.r_[[p0, p1]], decimals=decimals
grid, points=np.r_[[p0, p1]], decimals=decimals,
nodes=(nodes_x, nodes_y, nodes_z)
).field

return vfield

# Round nodes and source coordinates (to avoid floating point issues etc).
nodes_x = np.round(grid.nodes_x, decimals)
nodes_y = np.round(grid.nodes_y, decimals)
nodes_z = np.round(grid.nodes_z, decimals)
points = np.round(np.asarray(points, dtype=float), decimals)

# Ensure source is within nodes.
outside = (
min(points[:, 0]) < nodes_x[0] or max(points[:, 0]) > nodes_x[-1] or
min(points[:, 1]) < nodes_y[0] or max(points[:, 1]) > nodes_y[-1] or
min(points[:, 2]) < nodes_z[0] or max(points[:, 2]) > nodes_z[-1]
)
if outside:
raise ValueError(f"Provided source outside grid: {points}.")

# Dipole lengths in x-, y-, and z-directions, and overall.
dxdydz = points[1, :] - points[0, :]
length = np.linalg.norm(dxdydz)
Expand Down Expand Up @@ -919,8 +925,7 @@ def min_max_ind(vector, i):
for field in [vfield.fx, vfield.fy, vfield.fz]:
sum_s = abs(field.sum())
# Normalize and warn; SHOULD NEVER HAPPEN
# (if it happens add it to the tests and remove the pragma-flag!
if abs(sum_s-1) > 1e-6: # pragma: no cover
if abs(sum_s-1) > 1e-6:
msg = f"emg3d: Normalizing Source: {sum_s:.10f}."
warnings.warn(msg, UserWarning)
field /= sum_s
Expand Down
9 changes: 9 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,15 @@ def test_warnings(self):
with pytest.raises(ValueError, match='Provided finite dipole'):
fields._dipole_vector(grid, source)

# Create a BaseMesh and modify the widths, so _dipole_vector will
# have to normalize.
h = np.ones(4)
grid = emg3d.meshes.BaseMesh([h, h, h], (0, 0, 0))
grid.h = [grid.h[0], grid.h[1]*.3, grid.h[2]]
source = np.array([[0, 1, 2], [3, 3, 2]])
with pytest.warns(UserWarning, match='Normalizing Source'):
fields._dipole_vector(grid, source)


@pytest.mark.parametrize("njit", [True, False])
def test_edge_curl_factor(njit):
Expand Down

0 comments on commit 0006a55

Please sign in to comment.