Skip to content

Commit

Permalink
Infile examples (#731)
Browse files Browse the repository at this point in the history
Added quick-plot capability and a documentation page.
  • Loading branch information
mkstoyanov authored Aug 16, 2024
1 parent 7b5b659 commit 56b80df
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 6 deletions.
1 change: 1 addition & 0 deletions doxygen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ doxygen_add_docs(asgard_doxygen
README.md
doxygen/installation.md
doxygen/basic_usage.md
doxygen/plotting.md
src/asgard.hpp
src/asgard_discretization.hpp
src/asgard_program_options.hpp
Expand Down
3 changes: 2 additions & 1 deletion doxygen/basic_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,6 @@ in several ways:
...
cmake -DCMAKE_INSTALL_PREFIX=<path-to-venv> ....
```
See the [Quick Plotting Documentation.](plotting.md)

The installed examples contain Python and MATLAB demonstration scripts.
The installed examples contain detailed Python and MATLAB demonstration scripts.
39 changes: 39 additions & 0 deletions doxygen/plotting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Quick Plotting

ASGarD does not have an objective to provide plotting capabilities but rather
the capability to interpret the sparse grid storage formats and to generate
plotting data for actual plotting tools.
After enabling both Python and HighFive (see the installation instruction),
the asgard python module can be used as an executable:

Get the version, i.e., plot nothing and show only the library build information:
```
python3 -m asgard
```

Quick plot command of the first two dimensions of a stored solution, extra
dimensions will be set to the middle of their min-max ranges:
```
python3 -m asgard outfile.h5
```
The quick plot command will use matplotlib and make a basic image (or 1D curve).
The installed examples show how to obtain the raw data and enable fine grained
control over the plotting format or even use a matplotlib alternatives.

If matplotlib plot can also be written to an image file, e.g., if the data files
are stored on a remote machine that has matplotlib but no display connection:
```
python3 -m asgard outfile.h5 outfile.png
```
Here, `outfile.png` is any supported matplotlib format.

If matplotlib is missing or we want to skip plotting, we can print only the
file high-level meta data to the console:
```
python3 -m asgard -s outfile.h5
```
The `-s` switch can be replaced with either `-stats` or `-summary`.




24 changes: 24 additions & 0 deletions infiles/continuity2dsg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# this is just a simple input example
-title : Continuity 2D
-subtitle : sparse grid level 8, quadratic basis

# df / dt + \div_x f = S
# source chosen to manufacture an exact solution
-pde : continuity_2

# disctretization in space
# level 8 sparse grid and quadratic basis
# the grid has 11520 degrees-of-freedom
-grid : sparse
-start-levels : 8
-degree : 2

# explicit time-step, 100 steps
-step-method : expl
-dt : 1.E-4
-num-steps : 100

# final RMSE error
# absolute: 4.55829e-09
# relative: 3.51175e-05
# (tested on a random laptop)
83 changes: 81 additions & 2 deletions python/asgard.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import sys

from ctypes import c_char_p, c_int, c_int64, c_double, c_float, c_void_p, POINTER, CDLL, create_string_buffer, RTLD_GLOBAL
import numpy as np

import h5py # required for now, maybe add lighter module later

_matplotlib_found_ = True
try:
import matplotlib.pyplot as asgplot
except:
_matplotlib_found_ = False

from asgard_config import __version__, __author__, __pyasgard_libasgard_path__

libasgard = CDLL(__pyasgard_libasgard_path__, mode = RTLD_GLOBAL)
Expand All @@ -16,6 +23,8 @@

libasgard.asgard_pydelete_reconstruct_solution.argtypes = [c_void_p, ]

libasgard.asgard_print_version_help.argtypes = []

libasgard.asgard_reconstruct_solution_setbounds.argtypes = [c_void_p, POINTER(c_double), POINTER(c_double)]
libasgard.asgard_reconstruct_solution.argtypes = [c_void_p, POINTER(c_double), c_int, POINTER(c_double)]
libasgard.asgard_reconstruct_cell_centers.argtypes = [c_void_p, POINTER(c_double)]
Expand Down Expand Up @@ -52,15 +61,17 @@ def __init__(self, filename, verbose = False):
self.num_dimensions = fdata['ndims'][()]
self.degree = fdata['degree'][()]

self.state = fdata['soln'][()]
self.state = fdata['state'][()]
self.cells = fdata['elements'][()]
self.time = fdata['time'][()]

self.num_cells = int(len(self.cells) / (2 * self.num_dimensions))

self.dimension_names = [None for i in range(self.num_dimensions)]
self.dimension_min = np.zeros((self.num_dimensions,))
self.dimension_max = np.zeros((self.num_dimensions,))
for i in range(self.num_dimensions):
self.dimension_names[i] = fdata['dim{0}_name'.format(i)][()].decode("utf-8")
self.dimension_min[i] = fdata['dim{0}_min'.format(i)][()]
self.dimension_max[i] = fdata['dim{0}_max'.format(i)][()]

Expand All @@ -70,7 +81,7 @@ def __init__(self, filename, verbose = False):

if self.verbose:
if self.state.dtype == np.float64:
print('using double precisoin data (double) - 64-bit')
print('using double precision data (double) - 64-bit')
else:
print('using single precision data (float) - 32-bit')
print('dimensions: {0}'.format(self.num_dimensions))
Expand Down Expand Up @@ -202,6 +213,16 @@ def plot_data2d(self, dims, num_points = 32):
return self.evaluate(pgrid).reshape(XX.shape), XX, YY

def evaluate(self, points):
'''
points must be a 2d numpy array with shape (num_x, num_dimensions)
where the num_x is the number of points for the evaluate command
each row must describe a point inside the domain, but no checking will
be performed
returns a vector with the size num_x holding the corresponding values
of the field
'''
assert len(points.shape) == 2, 'points must be a 2d numpy array with num-columns equal to self.num_dimensions'
assert points.shape[1] == self.num_dimensions, 'points.shape[1] (%d) must be equal to self.num_dimensions (%d)' % (points.shape[1], self.num_dimensions)

Expand All @@ -213,6 +234,13 @@ def evaluate(self, points):
return presult

def cell_centers(self):
'''
returns the geometric centers of the sparse grid cells
do not attempt to plot at these points as they are set right on the
the discontinuities of the basis functions and the evaluate()
algorithm may be unstable due to rounding error
'''
presult = np.empty((self.num_cells, self.num_dimensions), np.float64)

libasgard.asgard_reconstruct_cell_centers(self.recsol,
Expand All @@ -229,3 +257,54 @@ def __str__(self):
s += " degree: %d\n" % self.degree
s += " time: %f" % self.time
return s

if __name__ == "__main__":
if len(sys.argv) < 2:
libasgard.asgard_print_version_help()
elif sys.argv[1] in ("-s", "-stat", "-stats", "-summary"):
if len(sys.argv) < 3:
print("stats summary option requires a filename")
else:
shot = pde_snapshot(sys.argv[2])
print("\n", shot, "\n")
elif not _matplotlib_found_:
print("could not 'import matplotlib'")
print("to print only stats summary use")
print(" python3 -m asgard -s %s" % sys.argv[2])
libasgard.asgard_print_version_help()
else:
shot = pde_snapshot(sys.argv[1])
print("\n", shot, "\n")

asgplot.title(shot.title, fontsize = 'large')

if shot.num_dimensions == 1:
z, x = shot.plot_data1d((()), num_points = 256)
asgplot.plot(x, z)
asgplot.xlabel(shot.dimension_names[0], fontsize = 'large')
else:
plist = [(), ()]
for i in range(2, shot.num_dimensions):
plit.append(0.49 * (shot.dimension_max[i] + shot.dimension_min[i]))

z, x, y = shot.plot_data2d(plist, num_points = 256)

xmin = shot.dimension_min[0]
ymin = shot.dimension_min[1]
xmax = shot.dimension_max[0]
ymax = shot.dimension_max[1]

p = asgplot.imshow(z, cmap='jet', extent=[xmin, xmax, ymin, ymax])

asgplot.colorbar(p, orientation='vertical')

asgplot.gca().set_anchor('C')

asgplot.xlabel(shot.dimension_names[0], fontsize='large')
asgplot.ylabel(shot.dimension_names[1], fontsize='large')

if len(sys.argv) > 2:
asgplot.savefig(sys.argv[2])
else:
asgplot.show()

6 changes: 4 additions & 2 deletions src/asgard_io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ void write_output(PDE<P> const &pde, std::vector<moment<P>> const &moments,
dims[dim].domain_min);
H5Easy::dump(file, "dim" + std::to_string(dim) + "_max",
dims[dim].domain_max);
H5Easy::dump(file, "dim" + std::to_string(dim) + "_name",
dims[dim].name);
}

auto &elements = hash_table.get_active_table();
Expand All @@ -212,7 +214,7 @@ void write_output(PDE<P> const &pde, std::vector<moment<P>> const &moments,
.write_raw(elements.data());

file.createDataSet<P>(
"soln", HighFive::DataSpace({static_cast<size_t>(vec.size())}), plist)
"state", HighFive::DataSpace({static_cast<size_t>(vec.size())}), plist)
.write_raw(vec.data());

// save E field
Expand Down Expand Up @@ -430,7 +432,7 @@ restart_data<P> read_output(PDE<P> &pde, elements::table const &hash_table,
H5Easy::load<std::vector<int64_t>>(file, std::string("elements"));

fk::vector<P> solution =
fk::vector<P>(H5Easy::load<std::vector<P>>(file, std::string("soln")));
fk::vector<P>(H5Easy::load<std::vector<P>>(file, std::string("state")));

// load E field
pde.E_field = std::move(
Expand Down
5 changes: 5 additions & 0 deletions src/asgard_reconstruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,9 @@ void asgard_reconstruct_cell_centers(void const *pntr, double x[])
->cell_centers(x);
}

void asgard_print_version_help()
{
asgard::prog_opts::print_version_help();
}

} // extern "C"
6 changes: 5 additions & 1 deletion src/asgard_reconstruct.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ void asgard_reconstruct_solution(void const*, double const[], int, double[]);
* \brief C binding for reconstruct_solution::cell_centers()
*/
void asgard_reconstruct_cell_centers(void const *pntr, double x[]);

/*!
* \ingroup asgard_postprocess
* \brief C binding to print the library stats
*/
void asgard_print_version_help();
} // extern "C"
#endif

0 comments on commit 56b80df

Please sign in to comment.