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()
- (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.