simpeg / discretize

Discretization tools for finite volume and inverse problems.

Home Page:http://discretize.simpeg.xyz/

Repository from Github https://github.comsimpeg/discretizeRepository from Github https://github.comsimpeg/discretize

Plot values at their locations, not interpolate to cell centers

prisae opened this issue · comments

Currently plot_slice, plot_3d_slicer, and potentially other plotting routines average edge- and face-defined values to cell centres. This has at least two implications:

  • the plotted result is less precise, as the values are linearly interpolated (we don't plot the actually computed numbers);
  • the memory requirement for the required interpolation can be limiting if you have millions of cells.

It should not be difficult to change, I think. We could even have a flag to keep the current way or choose the new way. Instead of interpolation we would have to choose the corresponding locations.

What I am not sure is if there are other reasons, which I have not thought of, which would prevent us from making this change?

(Carrying it over from Slack.)

Example:

Code for figure
import emg3d
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm

# Simple grid
hh = 50*np.arange(1, 16)**1.05
hx = np.r_[hh[::-1], hh]
grid = emg3d.TensorMesh([hx, hx, hx], 'CCC')

# Simple model
model = emg3d.Model(grid, property_x=1.0)
model.property_x[:, :8, :] = 10.0
model.property_x[:, -8:, :] = 0.5

# Solve
efield = emg3d.solve_source(model, (0, 0, 0, 0, 0), frequency=10)

# Average Ex field to cell centers (for status quo plot)
ex = grid.average_edge_x_to_cell * efield.fx.ravel('F')
ex = ex.reshape(grid.shape_cells, order='F')

# Figure
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex=True, sharey=True)
fig.suptitle("Showing as an example |Re(Ex)|")

# Flat, cell centers, status quo
ax1.set_title('(a) CC, "flat", status quo')
ax1.pcolormesh(
    grid.nodes_x,
    grid.nodes_y,
    abs(ex[:, :, 16].real.T),
    shading='flat',
    norm=LogNorm(),
)

# Gouraud, edges
ax2.set_title('(b) At locs, "gouraud"')
ax2.pcolormesh(
    grid.cell_centers_x,
    grid.nodes_y,
    abs(efield.fx[:, :, 16].real.T),
    shading='gouraud',
    norm=LogNorm(),
)

# Flat, edges
ax3.set_title('(c) At locs, "flat"')
ax3.pcolormesh(
    grid.nodes_x,
    np.r_[grid.cell_centers_y[0]-grid.h[1][0]/2, grid.cell_centers_y, grid.cell_centers_y[-1]+grid.h[1][-1]/2],
    abs(efield.fx[:, :, 16].real.T),
    shading='flat',
    norm=LogNorm(),
)

# Nearest, edges
ax4.set_title('(d) At locs, "nearest"')
ax4.pcolormesh(
    grid.cell_centers_x,
    grid.nodes_y,
    abs(efield.fx[:, :, 16].real.T),
    shading='nearest',
    norm=LogNorm(),
)

fig.tight_layout()

pcolormesh

  • (a) has the limitations mention in the issue (interpolated not actual values; resulting memory limitation).
  • (b) has the same limitations as (a).
  • (c) would be good, IMHO; needs taking care to define the nodes.
  • (d) would be easiest to do; I am not yet sure if the underlying assumption of cell widths is OK in our case with stretched grids.