diff options
Diffstat (limited to 'CarpetDev/CarpetIOF5/src/input.cc')
-rw-r--r-- | CarpetDev/CarpetIOF5/src/input.cc | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/CarpetDev/CarpetIOF5/src/input.cc b/CarpetDev/CarpetIOF5/src/input.cc new file mode 100644 index 000000000..ecf7dda5c --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/input.cc @@ -0,0 +1,563 @@ +#include <cctk.h> +#include <cctk_Arguments.h> +#include <cctk_Parameters.h> + +#include <cassert> +#include <cstdlib> +#include <cstring> +#include <iomanip> +#include <iostream> +#include <limits> +#include <sstream> +#include <string> + +#include <hdf5.h> +#include <F5/F5F.h> +#include <F5/F5R.h> +#include <F5/F5iterate.h> +#include <F5/F5uniform.h> + +#include <bbox.hh> +#include <vect.hh> + +#include <carpet.hh> + +#include "iof5.hh" + + + +namespace CarpetIOF5 { + + using namespace std; + using namespace Carpet; + + + + // Use a class for reading data, so that we have an easy way to pass + // variables between the various iterators + class input_iterator_t { + cGH *cctkGH; + + double time; + char const *gridname; + char const *topologyname; + int index_depth; // 0=vertex, 1=cell + int topological_dimension; + char const *fieldname; + char const *fragmentname; + + // string chartname; + + public: + input_iterator_t (cGH *const cctkGH_) + : cctkGH(cctkGH_), + time(nan), + gridname(NULL), + topologyname(NULL), index_depth(-1), topological_dimension(-1), + fieldname(NULL), + fragmentname(NULL) + { + } + + + + private: + + void read_timeslice (F5Path *const path) + { + indent_t indent; + cout << indent << "time=" << time << "\n"; + +#if 0 + // TODO: Loop over all charts that exist for the grid, or at + // least remember how many maps there are. (This is also + // written as part of the grid structure.) + // F5iterate_grid_atlas? + for (int m=0; m<maps; ++m) { + indent_t indent; + chartname = generate_chartname(cctkGH, m); + cout << indent << "chart=\"" << chartname << "\"\n"; + F5iterate_grids + (path, NULL, grid_iterator, this, NULL, chartname.c_str()); + } +#endif + + F5iterate_grids (path, NULL, grid_iterator, this, NULL, NULL); + + // Synchronise + BEGIN_REFLEVEL_LOOP(cctkGH) { +#if 0 + int groups[] = { + CCTK_GroupIndex("GRID::COORDINATES") + }; + int const ngroups = sizeof groups / sizeof *groups; + for (int i=0; i<ngroups; ++i) { + assert (groups[i]>=0); + } + iret = CCTK_SyncGroupsI (cctkGH, ngroups, groups); + assert (iret >= 0); +#endif +#warning "TODO: don't modify boundaries" + BEGIN_LOCAL_MAP_LOOP(cctkGH, CCTK_GF) { + BEGIN_LOCAL_COMPONENT_LOOP(cctkGH, CCTK_GF) { + DECLARE_CCTK_ARGUMENTS; + CCTK_LOOP3_BOUNDARIES(boundaries, cctkGH, + i,j,k, 1,1,1, + cctk_lsh[0]-1,cctk_lsh[1]-1,cctk_lsh[2]-1) + { + int const ind3d = CCTK_GFINDEX3D(cctkGH, i,j,k); + x[ind3d] = 0.0; + y[ind3d] = 0.0; + z[ind3d] = 0.0; + r[ind3d] = 0.0; + } CCTK_ENDLOOP3_BOUNDARIES(boundaries); + } END_LOCAL_COMPONENT_LOOP; + } END_LOCAL_MAP_LOOP; + } END_REFLEVEL_LOOP; + } + + void read_grid (F5Path *const path) + { + indent_t indent; + cout << indent << "grid=\"" << gridname << "\"\n"; + // F5iterate_vertex_fields (path, NULL, field_iterator, this, NULL, NULL); + F5iterate_topologies (path, NULL, topology_iterator, this); + } + + void read_topology (F5Path *const path) + { + indent_t indent; + + herr_t herr; + + cout << indent << "topology=\"" << topologyname << "\"" + << " (" << (index_depth==0 ? "vertex" : "cell") << ")\n"; + + // Ignore topologies that are only an alias for another topology + H5G_stat_t stat; + herr = H5Gget_objinfo (path->Grid_hid, topologyname, false, &stat); + assert (not herr); + if (stat.type == H5G_LINK) { + char linkval[100000]; + herr = H5Gget_linkval + (path->Grid_hid, topologyname, sizeof linkval, linkval); + assert (not herr); + indent_t indent; + cout << indent << "alias for topology \"" << linkval << "\"\n" + << indent << "ignoring this topology\n"; + return; + } + + // F5iterate_topology_fields + // (path, NULL, field_iterator, this, chartname.c_str(), NULL); + F5iterate_topology_fields (path, NULL, field_iterator, this, NULL, NULL); + } + + void read_field (F5Path *const path) + { + indent_t indent; + cout << indent << "field=\"" << fieldname << "\"\n"; + + if (strcmp(fieldname, "GRID::COORDINATES")!=0 and + strcmp(fieldname, "GRID::r")!=0) + { + indent_t indent; + cout << indent << "ignoring this field\n"; + return; + } + + F5iterate_field_fragments (path, NULL, fragment_iterator, this); + } + + void read_fragment (F5Path *const path) + { + indent_t indent; + + int iret; + void *pret; + + cout << indent << "fragment=\"" << fragmentname << "\"\n"; + + + + // Determine refinement level from the topology + // (Could also use topology name instead) + hsize_t hreffact[FIBER_MAX_RANK]; + iret = F5LAget_dimensions(path->Topology_hid, + FIBER_HDF5_REFINEMENT_INFO, hreffact); + assert (iret == dim); + hsize_t hreffact2[FIBER_MAX_RANK]; + pret = F5Tpermute_dimensions(path, dim, hreffact2, hreffact); + assert (pret); + ivect const reffact = h2v(hreffact2); + int rl; + for (rl=0; rl<reflevels; ++rl) { + if (all(reffact == Carpet::spacereffacts.AT(rl))) break; + } + assert (rl<reflevels); + + // Determine map from fragment name + // TODO: store map number as attribute? + int const m = interpret_fragmentname (cctkGH, fragmentname); + + { + indent_t indent; + cout << indent << "reading refinement level " << rl << "\n"; + cout << indent << "reading map " << m << "\n"; + } + + ENTER_LEVEL_MODE(cctkGH, rl) { + ENTER_SINGLEMAP_MODE(cctkGH, m, CCTK_GF) { + + if (strcmp(fieldname, "GRID::r") == 0) { + + read_variable (path, fragmentname, CCTK_VarIndex("grid::r")); + + } else if (strcmp(fieldname, "GRID::COORDINATES") == 0) { + + read_variable (path, "Dx", CCTK_VarIndex("grid::x")); + read_variable (path, "Dy", CCTK_VarIndex("grid::y")); + read_variable (path, "Dz", CCTK_VarIndex("grid::z")); + + } else { + // do nothing + } + + } LEAVE_SINGLEMAP_MODE; + } LEAVE_LEVEL_MODE; + } + + void read_variable (F5Path *const path, char const *const name, + int const var) + { + indent_t indent; + + herr_t herr; + int ierr; + int iret; + void *pret; + + assert (path); + assert (name); + assert (var >= 0); + + cout << indent << "dataset=\"" << name << "\"\n"; + + assert (var >= 0); + { + char *const fullname = CCTK_FullName(var); + cout << indent << "variable=" << fullname << "\n"; + free (fullname); + } + + + + // Determine fragment properties + H5O_info_t info; + herr = + H5Oget_info_by_name (path->Field_hid, fragmentname, &info, H5P_DEFAULT); + assert (not herr); + bool const fragment_is_group = info.type == H5O_TYPE_GROUP; + hid_t field; + if (fragment_is_group) { + field = H5Gopen (path->Field_hid, fragmentname, H5P_DEFAULT); + assert (field >= 0); + } else { + field = path->Field_hid; + } + + hid_t const fragment = H5Dopen(field, name, H5P_DEFAULT); + assert (fragment); + + // Check index depth + int index_depth_; + iret = F5Tget_index_depth(path, &index_depth_); + assert (iret); + assert (index_depth_ == index_depth); + + // Read the fragment offset. This is stored with the dataset + // group. + hsize_t hoff[FIBER_MAX_RANK]; + iret = F5LAget_dimensions(fragment_is_group ? field : fragment, + FIBER_FRAGMENT_OFFSET_ATTRIBUTE, hoff); + assert (iret == dim); + hsize_t hoff2[FIBER_MAX_RANK]; + pret = F5Tpermute_dimensions(path, dim, hoff2, hoff); + assert (pret); + ivect const foff = h2v(hoff2); + assert (all(foff>=0)); + +#if 0 + // Read the fragment size. This is stored with the field -- why + // is this different from the offset? + hsize_t hlen[FIBER_MAX_RANK]; + iret = + F5LAget_dimensions(path->Field_hid, + FIBER_FIELD_DATASPACE_DIMENSIONS_ATTRIBUTE, hlen); + assert (iret == dim); + hsize_t hlen2[FIBER_MAX_RANK]; + pret = F5Tpermute_dimensions(path, dim, hlen2, hlen); + assert (pret); + ivect const flen = h2v(hlen2); + assert (all(flen>=0)); +#endif + hid_t const space = H5Dget_space(fragment); + assert (space>=0); + iret = H5Sget_simple_extent_ndims(space); + assert (iret == dim); + hsize_t hlen[dim]; + iret = H5Sget_simple_extent_dims(space, hlen, NULL); + hsize_t hlen2[dim]; + pret = F5Tpermute_dimensions(path, dim, hlen2, hlen); + assert (pret); + ivect const flen = h2v(hlen2); + assert (all(flen>=0)); + herr = H5Sclose (space); + assert (not herr); + + ibbox const fbox (foff, foff+flen-1, 1); + { + indent_t indent; + cout << indent << "dataset bbox is " << foff << ":" << foff+flen << "\n"; + } + + + + // Examine Cactus variable + int const group = CCTK_GroupIndexFromVarI(var); + cGroup groupdata; + ierr = CCTK_GroupData(group, &groupdata); + assert (not ierr); + + // TODO + assert (groupdata.grouptype == CCTK_GF); + assert (groupdata.vartype == CCTK_VARIABLE_REAL); + assert (groupdata.disttype == CCTK_DISTRIB_DEFAULT); + assert (groupdata.stagtype == 0); + assert (groupdata.dim == dim); + + // TODO: This is too expensive; only traverse Carpet's data + // structures instead. (This should be implemented via a + // gh::locate_positions, which will turn require support from + // the internal tree data structure.) + BEGIN_COMPONENT_LOOP(cctkGH, CCTK_GF) { + DECLARE_CCTK_ARGUMENTS; + + ivect lbnd, lsh, lghosts, ughosts; + ivect imin, imax, ioff, ilen; + for (int d=0; d<dim; ++d) { + lbnd[d] = cctk_lbnd[d]; + lsh[d] = cctk_lsh[d]; + // F5 counts the total overlap, which is the sum of the + // ghost zones on this and the adjacent component + lghosts[d] = cctk_bbox[2*d ] ? 0 : 2*cctk_nghostzones[d]; + ughosts[d] = cctk_bbox[2*d+1] ? 0 : 2*cctk_nghostzones[d]; + imin[d] = 0; + imax[d] = lsh[d]; + // Do not read in ghost zones + imin[d] += lghosts[d] / 2; + imax[d] -= ughosts[d] / 2; + ioff[d] = lbnd[d] + imin[d]; + ilen[d] = imax[d] - imin[d]; + } + ibbox const lbox (lbnd, lbnd+lsh-1, 1); + ibbox const ibox (ioff, ioff+ilen-1, 1); + ibbox const ovlp = ibox & fbox; + + if (ovlp.empty()) { + indent_t indent; + cout << indent << "dataset does not intersect component " << component << "; skipping component\n"; + continue; + } + + indent_t indent; + cout << indent << "dataset intersects component " << component << "\n" + << indent << "reading bbox " << ovlp.lower() << ":" << ovlp.upper() << " of " << ibox.lower() << ":" << ibox.upper() << "\n"; + + int const proc = vhh.AT(Carpet::map)->processor(reflevel, component); +#warning "TODO: send dataset to destination process" + assert (proc == dist::rank()); + + int const timelevel = 0; + void *const data = CCTK_VarDataPtrI(cctkGH, timelevel, var); + assert (data); + + + + hvect const hzero(0); + hvect mlsh; + pret = F5Tpermute_dimensions + (path, dim, &mlsh[0], &v2h(lbox.shape())[0]); + assert (pret); + hid_t const memspace = H5Screate_simple(dim, &mlsh[0], NULL); + assert (memspace >= 0); + hvect mmin; + pret = F5Tpermute_dimensions + (path, dim, &mmin[0], &v2h(ovlp.lower()-lbox.lower())[0]); + assert (pret); + hvect mlen; + pret = F5Tpermute_dimensions + (path, dim, &mlen[0], &v2h(ovlp.shape())[0]); + assert (pret); + assert (all(mmin >= hzero)); + assert (all(mmin+mlen <= mlsh)); + herr = H5Sselect_hyperslab + (memspace, H5S_SELECT_SET, &mmin[0], NULL, &mlen[0], NULL); + assert (not herr); + // cout << "mlsh=" << mlsh << " mmin=" << mmin << " mlen=" << mlen << "\n"; + + hvect flsh; + pret = F5Tpermute_dimensions + (path, dim, &flsh[0], &v2h(fbox.shape())[0]); + assert (pret); + hid_t const filespace = H5Screate_simple(dim, &flsh[0], NULL); + assert (filespace >= 0); + hvect fmin; + pret = F5Tpermute_dimensions + (path, dim, &fmin[0], &v2h(ovlp.lower()-fbox.lower())[0]); + assert (pret); + hvect const flen = mlen; + assert (all(fmin >= hzero)); + assert (all(fmin+flen <= flsh)); + herr = H5Sselect_hyperslab + (filespace, H5S_SELECT_SET, &fmin[0], NULL, &flen[0], NULL); + // cout << "flsh=" << flsh << " fmin=" << fmin << " flen=" << flen << "\n"; + + herr = H5Dread (fragment, H5T_NATIVE_DOUBLE, memspace, filespace, + H5P_DEFAULT, data); + assert (not herr); + + herr = H5Sclose(memspace); + assert (not herr); + herr = H5Sclose(filespace); + assert (not herr); + + } END_COMPONENT_LOOP; + + + + herr = H5Dclose(fragment); + assert (not herr); + + if (fragment_is_group) { + herr = H5Gclose(field); + assert (not herr); + } + } + + + + public: + + void iterate (hid_t const object) + { + F5iterate_timeslices (object, NULL, timeslice_iterator, this); + } + + static + herr_t timeslice_iterator (F5Path *const path, double const time, + void *const userdata) + { + input_iterator_t* const iterator = (input_iterator_t*)userdata; + iterator->time = time; + iterator->read_timeslice (path); + return 0; + } + + static + herr_t grid_iterator (F5Path *const path, char const *const gridname, + void *const userdata) + { + input_iterator_t* const iterator = (input_iterator_t*)userdata; + iterator->gridname = gridname; + iterator->read_grid (path); + return 0; + } + + static + herr_t topology_iterator (F5Path *const path, + char const *const topologyname, + int const index_depth, + int const topological_dimension, + void *const userdata) + { + input_iterator_t* const iterator = (input_iterator_t*)userdata; + iterator->topologyname = topologyname; + iterator->index_depth = index_depth; + iterator->topological_dimension = topological_dimension; + iterator->read_topology (path); + return 0; + } + + static + herr_t field_iterator (F5Path *const path, char const *const fieldname, + void *const userdata) + { + input_iterator_t* const iterator = (input_iterator_t*)userdata; + iterator->fieldname = fieldname; + iterator->read_field (path); + return 0; + } + + static + herr_t fragment_iterator (F5Path *const path, + char const *const fragmentname, + void *const userdata) + { + input_iterator_t* const iterator = (input_iterator_t*)userdata; + iterator->fragmentname = fragmentname; + iterator->read_fragment (path); + return 0; + } + + }; // class input_iterator_t + + + + extern "C" + void F5_Input (CCTK_ARGUMENTS) + { + DECLARE_CCTK_ARGUMENTS; + DECLARE_CCTK_PARAMETERS; + + herr_t herr; + + + + assert (is_global_mode()); + CCTK_VInfo (CCTK_THORNSTRING, "F5_Input: iteration=%d", cctk_iteration); + + + + // Open file + string const basename = + generate_basename (cctkGH, CCTK_VarIndex("grid::r")); + int const myproc = CCTK_MyProc(cctkGH); + int const nprocs = CCTK_nProcs(cctkGH); + for (int proc=myproc; ; proc+=nprocs) { + string const name = + create_filename (cctkGH, basename, proc, false); + + bool file_exists; + H5E_BEGIN_TRY { + file_exists = H5Fis_hdf5(name.c_str()) > 0; + } H5E_END_TRY; + if (not file_exists) break; + + indent_t indent; + cout << indent << "process=" << proc << "\n"; + + hid_t const file = H5Fopen (name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); + assert (file >= 0); + + // Iterate over all time slices + input_iterator_t iterator(cctkGH); + iterator.iterate (file); + + // Close file + herr = H5Fclose (file); + assert (not herr); + } + } + +} // end namespace CarpetIOF5 |