Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6180f97
tesseroid docstrings; fix mistakes, add examples, and clarify
mdtanker Nov 28, 2025
2f98d34
docstring typos
mdtanker Nov 28, 2025
b40f6bc
rename _forward.tesseroid.py to _forward.tesseroid_gravity.py to matc…
mdtanker Mar 27, 2026
40a78f3
add tesseroid thickness plot to gallery example
mdtanker Mar 27, 2026
89060b1
add tesseroid edges to plots and more description of radii in user guide
mdtanker Mar 27, 2026
a6622ee
fix docstring of prism_layer.gravity()
mdtanker Mar 27, 2026
5c655b5
fix typos in tesseroid_layer.py docstrings
mdtanker Mar 27, 2026
2a24f51
use explicit tesseroid boundary names in get_tesseroid to match get_p…
mdtanker Mar 27, 2026
a4f463b
add _discard_thin_tesseroids function
mdtanker Mar 27, 2026
14ef67e
add test for discarding thin tesseroids
mdtanker Mar 27, 2026
ee31a8a
add tests for tesseroid layer gravity progressbar
mdtanker Mar 27, 2026
b448375
fix miss-spelled test name
mdtanker Mar 27, 2026
fb47337
change expected values for doctest for tesseroid layer
mdtanker Mar 27, 2026
72121b8
Merge branch 'main' into tesseroids
mdtanker Mar 27, 2026
448ccfb
remove whitespace
mdtanker Mar 27, 2026
2bdaead
Update harmonica/_forward/tesseroid_layer.py
mdtanker Mar 27, 2026
e7639b9
Update doc/user_guide/forward_modelling/tesseroid.rst
mdtanker Mar 27, 2026
38dfae8
Update doc/user_guide/forward_modelling/tesseroid.rst
mdtanker Mar 27, 2026
39cb6c5
Update harmonica/_forward/tesseroid_layer.py
mdtanker Mar 27, 2026
dac7977
Update harmonica/_forward/tesseroid_layer.py
mdtanker Mar 27, 2026
ce7c208
Merge branch 'main' into tesseroids
mdtanker Mar 27, 2026
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
32 changes: 29 additions & 3 deletions doc/gallery_src/forward/tesseroid_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,20 @@
ellipsoid = bl.WGS84

longitude, latitude = np.meshgrid(topo.longitude, topo.latitude)

# Compute radius of WGS84 ellipsoid at each lat/lon coordinates
reference = ellipsoid.geocentric_radius(latitude)

# Compute surface topography with respect to the center of the Earth
surface = topo + reference

# tesseroids above sea level have density of 2670 kg/m³ and tesseroids located below sea
# level have density of -1630 kg/m³
density = xr.where(topo > 0, 2670.0, 1040.0 - 2670.0)

# Create a layer of tesseroids representing the topography
# These have tops and bottoms defined by Earth's topography with respect to the center
# of the Earth.
tesseroids = hm.tesseroid_layer(
coordinates=(topo.longitude, topo.latitude),
surface=surface,
Expand All @@ -53,16 +63,32 @@
extra_coords_names="radius",
)

# Plot gravity field
fig = pygmt.Figure()

# Plot tesseroid thickness
fig.grdimage(
tesseroids.top - tesseroids.bottom,
projection="M15c",
nan_transparent=True,
cmap="viridis",
frame="+tTesseroid thickness",
)
fig.basemap(frame=True)
fig.colorbar(frame="af+lthickness (m)")
fig.coast(shorelines="0.5p,black", borders=["1/0.5p,black"])

fig.shift_origin(xshift="17c")

# Plot gravity field
maxabs = vd.maxabs(gravity.g_z)
pygmt.makecpt(cmap="polar", series=(-maxabs, maxabs))
pygmt.makecpt(cmap="balance+h0", series=(-maxabs, maxabs))
fig.grdimage(
gravity.g_z,
projection="M15c",
nan_transparent=True,
frame="+tForward gravity",
)
fig.basemap(frame=True)
fig.colorbar(frame='af+l"Gravity [mGal]"', position="JCR")
fig.colorbar(frame="af+lGravity (mGal)")
fig.coast(shorelines="0.5p,black", borders=["1/0.5p,black"])
fig.show()
45 changes: 43 additions & 2 deletions doc/user_guide/forward_modelling/tesseroid.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ boundaries in the following order: *west*, *east*, *south*, *north*, *bottom*,
*top*, where the former four are its longitudinal and latitudinal boundaries in
decimal degrees and the latter two are the two radii given in meters.

These two radii represent the top and bottom surfaces of the tesseroid, and should be
given as distances from the center of the Earth. Note this is different from the
vertical boundaries used for **prisms** in Cartesian coordinates, which are given as
heights above or below some reference level (e.g., mean sea level or a reference ellipsoid).

.. note::

The :func:`harmonica.tesseroid_gravity` numerically computed the
Expand All @@ -45,7 +50,7 @@ decimal degrees and the latter two are the two radii given in meters.


Lets define a single tesseroid and compute the gravitational potential
it generates on a regular grid of computation points located at 10 km above
it generates on a regular grid of computation points located at 10 km above
its *top* boundary.

Get the WGS84 reference ellipsoid from :mod:`boule` so we can obtain its mean
Expand Down Expand Up @@ -127,6 +132,15 @@ And finally plot the computed gravitational field

fig.colorbar(cmap=True, frame=["a200f50", "x+lmGal"])
fig.coast(shorelines="1p,black")

# Plot edges of tesseroid
fig.plot(
x=[tesseroid[0], tesseroid[1], tesseroid[1], tesseroid[0], tesseroid[0]],
y=[tesseroid[2], tesseroid[2], tesseroid[3], tesseroid[3], tesseroid[2]],
pen="1p,red",
label="Tesseroid boundary",
)
fig.legend()

fig.show()

Expand Down Expand Up @@ -182,6 +196,20 @@ And plot the results:
fig.colorbar(cmap=True, frame=["a1000f500", "x+lmGal"])
fig.coast(shorelines="1p,black")

# Plot edges of tesseroids
for i, tesseroid in enumerate(tesseroids):
if i == 0:
label="Tesseroid boundaries"
else:
label=None
fig.plot(
x=[tesseroid[0], tesseroid[1], tesseroid[1], tesseroid[0], tesseroid[0]],
y=[tesseroid[2], tesseroid[2], tesseroid[3], tesseroid[3], tesseroid[2]],
pen="1p,red",
label=label,
)
fig.legend()

fig.show()


Expand Down Expand Up @@ -264,10 +292,23 @@ Finally, lets plot it:
frame=["a", f"+t{title}"],
cmap="viridis",
)

fig.colorbar(cmap=True, frame=["a200f100", "x+lmGal"])
fig.coast(shorelines="1p,black")

# Plot edges of tesseroids
for i, tesseroid in enumerate(tesseroids):
if i == 0:
label="Tesseroid boundaries"
else:
label=None
fig.plot(
x=[tesseroid[0], tesseroid[1], tesseroid[1], tesseroid[0], tesseroid[0]],
y=[tesseroid[2], tesseroid[2], tesseroid[3], tesseroid[3], tesseroid[2]],
pen="1p,red",
label=label,
)
fig.legend()

fig.show()

----
Expand Down
2 changes: 1 addition & 1 deletion harmonica/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from ._forward.prism_gravity import prism_gravity
from ._forward.prism_layer import DatasetAccessorPrismLayer, prism_layer
from ._forward.prism_magnetic import prism_magnetic
from ._forward.tesseroid import tesseroid_gravity
from ._forward.tesseroid_gravity import tesseroid_gravity
from ._forward.tesseroid_layer import DatasetAccessorTesseroidLayer, tesseroid_layer
from ._gravity_corrections import bouguer_correction
from ._io.icgem_gdf import load_icgem_gdf
Expand Down
2 changes: 1 addition & 1 deletion harmonica/_forward/_tesseroid_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def gauss_legendre_quadrature(
glq_nodes : list
Unscaled location of GLQ nodes for each direction.
glq_weights : list
GLQ weigths for each node for each direction.
GLQ weights for each node for each direction.
kernel : func
Kernel function for the gravitational field of point masses.

Expand Down
4 changes: 2 additions & 2 deletions harmonica/_forward/_tesseroid_variable_density.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def gauss_legendre_quadrature_variable_density(
glq_nodes : list
Unscaled location of GLQ nodes for each direction.
glq_weights : list
GLQ weigths for each node for each direction.
GLQ weights for each node for each direction.
kernel : func
Kernel function for the gravitational field of point masses.

Expand Down Expand Up @@ -136,7 +136,7 @@ def density_based_discretization(tesseroids, density):
Returns
-------
discretized_tesseroids : 2d-array
Array containing the coordinates of radially discretized tesseriods.
Array containing the coordinates of radially discretized tesseroids.
Each row of the array will have the boundaries for each new tesseroid.
"""
discretized_tesseroids = []
Expand Down
2 changes: 1 addition & 1 deletion harmonica/_forward/prism_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ def gravity(
The density of the prisms will be assigned from the ``data_var`` chosen
through the ``density_name`` argument.
Ignores the prisms which ``top`` or ``bottom`` boundaries are
``np.nan``s.
``np.nan``'s.
Prisms thinner than a given threshold can be optionally ignored through
the ``thickness_threshold`` argument.
All ``kwargs`` will be passed to :func:`harmonica.prism_gravity`.
Expand Down
Loading
Loading