aboutsummaryrefslogtreecommitdiff
path: root/CarpetDev/CarpetIOF5/src/output.cc
diff options
context:
space:
mode:
Diffstat (limited to 'CarpetDev/CarpetIOF5/src/output.cc')
-rw-r--r--CarpetDev/CarpetIOF5/src/output.cc470
1 files changed, 277 insertions, 193 deletions
diff --git a/CarpetDev/CarpetIOF5/src/output.cc b/CarpetDev/CarpetIOF5/src/output.cc
index d376bbfcf..8a5ab5e53 100644
--- a/CarpetDev/CarpetIOF5/src/output.cc
+++ b/CarpetDev/CarpetIOF5/src/output.cc
@@ -41,10 +41,11 @@ namespace CarpetIOF5 {
class output_iterator_t {
// Can't be cGH const, since the mode loops change change its
// entries
- cGH* const cctkGH;
+ cGH *const cctkGH;
vector<bool> const output_var; // whether to output this variable
- bool const output_everything;
+ bool const output_past_timelevels;
+ bool const output_metadata;
bool const is_multipatch;
int group_type; // CCTK_GF or CCTK_ARRAY
@@ -64,7 +65,7 @@ namespace CarpetIOF5 {
rvect origin, delta;
rvect lower, upper;
- map_indices_t (cGH const* const cctkGH, int const gindex)
+ map_indices_t(cGH const *const cctkGH, int const gindex)
{
DECLARE_CCTK_ARGUMENTS;
@@ -79,8 +80,8 @@ namespace CarpetIOF5 {
} else {
// grid array
cGroupDynamicData dyndata;
- int const ierr = CCTK_GroupDynamicData (cctkGH, gindex, &dyndata);
- assert (not ierr);
+ int const ierr = CCTK_GroupDynamicData(cctkGH, gindex, &dyndata);
+ assert(not ierr);
// HDF5 and F5 can't handle dim=0
dim = max(dyndata.dim, 1);
for (int d=0; d<dyndata.dim; ++d) {
@@ -103,11 +104,11 @@ namespace CarpetIOF5 {
struct component_indices_t: map_indices_t {
// elements >=dim remain undefined
- ivect lbnd, lsh, lghosts, ughosts;
+ ivect lbnd, lssh, lghosts, ughosts;
ivect imin, imax, ioff, ilen;
rvect clower, cupper;
- component_indices_t (cGH const* const cctkGH, int const gindex)
+ component_indices_t(cGH const *const cctkGH, int const gindex)
: map_indices_t(cctkGH, gindex)
{
DECLARE_CCTK_ARGUMENTS;
@@ -117,32 +118,37 @@ namespace CarpetIOF5 {
// grid function
for (int d=0; d<(::dim); ++d) {
lbnd[d] = cctk_lbnd[d];
- lsh[d] = cctk_lsh[d];
+ lssh[d] = CCTK_LSSH(0,d);
lghosts[d] = cctk_bbox[2*d ] ? 0 : cctk_nghostzones[d];
ughosts[d] = cctk_bbox[2*d+1] ? 0 : cctk_nghostzones[d];
}
} else {
// grid array
cGroupDynamicData dyndata;
- int const ierr = CCTK_GroupDynamicData (cctkGH, gindex, &dyndata);
- assert (not ierr);
+ int const ierr = CCTK_GroupDynamicData(cctkGH, gindex, &dyndata);
+ assert(not ierr);
for (int d=0; d<dyndata.dim; ++d) {
lbnd[d] = dyndata.lbnd[d];
- lsh[d] = dyndata.lsh[d];
+#ifdef CCTK_GROUPDYNAMICDATA_HAS_LSSH
+ lssh[d] = dyndata.lssh[CCTK_LSSH_IDX(0,d)];
+#else
+ lssh[d] = dyndata.lsh[d];
+#endif
lghosts[d] = dyndata.bbox[2*d ] ? 0 : dyndata.nghostzones[d];
ughosts[d] = dyndata.bbox[2*d+1] ? 0 : dyndata.nghostzones[d];
}
for (int d=dyndata.dim; d<(::dim); ++d) {
lbnd[d] = 0;
- lsh[d] = 1;
+ lssh[d] = 1;
lghosts[d] = 0;
ughosts[d] = 0;
}
}
for (int d=0; d<(::dim); ++d) {
imin[d] = 0;
- imax[d] = lsh[d];
+ imax[d] = lssh[d];
if (not output_ghost_points) {
+#warning "TODO: Don't output ghosts on refinement boundaries; only output ghosts for inter-process boundaries"
int const overlap = min(ughosts[d], minimum_component_overlap);
imin[d] += lghosts[d];
imax[d] -= ughosts[d] - overlap;
@@ -160,18 +166,20 @@ namespace CarpetIOF5 {
public:
- output_iterator_t (cGH* const cctkGH_,
- vector<bool> const& output_var_,
- bool const output_everything_)
+ output_iterator_t(cGH *const cctkGH_,
+ vector<bool> const& output_var_,
+ bool const output_past_timelevels_,
+ bool const output_metadata_)
: cctkGH(cctkGH_),
output_var(output_var_),
- output_everything(output_everything_),
+ output_past_timelevels(output_past_timelevels_),
+ output_metadata(output_metadata_),
is_multipatch
(CCTK_IsFunctionAliased("MultiPatch_GetSystemSpecification"))
{
}
- void iterate (hid_t const file)
+ void iterate(hid_t const file)
{
// Iterate over the variables in groups, first all grid
// functions, then all non-GF groups
@@ -182,28 +190,28 @@ namespace CarpetIOF5 {
if (output_var.at(vindex)) {
int const gindex = CCTK_GroupIndexFromVarI(vindex);
if (CCTK_GroupTypeI(gindex) == CCTK_GF) {
- vindices.push_back (vindex);
+ vindices.push_back(vindex);
}
}
}
if (not vindices.empty()) {
- output_simulation (file);
+ output_simulation(file);
}
group_type = CCTK_ARRAY;
for (group_index=0; group_index<CCTK_NumGroups(); ++group_index) {
if (CCTK_GroupTypeI(group_index) != CCTK_GF) {
vindices.clear();
- int const first_vindex = CCTK_FirstVarIndexI (group_index);
- int const num_vars = CCTK_NumVarsInGroupI (group_index);
+ int const first_vindex = CCTK_FirstVarIndexI(group_index);
+ int const num_vars = CCTK_NumVarsInGroupI(group_index);
for (int vindex=first_vindex; vindex<first_vindex+num_vars; ++vindex)
{
if (output_var.at(vindex)) {
- vindices.push_back (vindex);
+ vindices.push_back(vindex);
}
}
if (not vindices.empty()) {
- output_simulation (file);
+ output_simulation(file);
}
}
}
@@ -213,39 +221,41 @@ namespace CarpetIOF5 {
private:
- void output_simulation (hid_t const file)
+ void output_simulation(hid_t const file)
{
DECLARE_CCTK_PARAMETERS;
indent_t indent;
- bool error_flag = false;
gridname = generate_gridname(cctkGH);
cout << indent << "simulation=" << gridname << "\n";
- assert (is_global_mode());
+ assert(is_global_mode());
chartname = generate_chartname(cctkGH);
+ cout << indent << "chartname=" << chartname << "\n";
int const max_rl = group_type == CCTK_GF ? reflevels : 1;
for (int rl=0; rl<max_rl; ++rl) {
// Continue only if this level exists at this iteration
- assert (maxtimereflevelfact % timereffacts.AT(rl) == 0);
+ assert(maxtimereflevelfact % timereffacts.AT(rl) == 0);
int const do_every =
group_type == CCTK_GF ? maxtimereflevelfact / timereffacts.AT(rl) : 1;
if (cctkGH->cctk_iteration % do_every == 0) {
+#warning "TODO: don't switch modes"
ENTER_LEVEL_MODE(cctkGH, rl) {
DECLARE_CCTK_ARGUMENTS;
- assert (timelevel == 0);
+ assert(timelevel == 0);
int const max_tl =
- output_everything or output_all_timelevels ?
+ output_past_timelevels or output_all_timelevels ?
(group_type == CCTK_GF ?
timelevels :
CCTK_NumTimeLevelsI(group_index)) :
1;
for (timelevel=0; timelevel<max_tl; ++timelevel) {
- cctkGH->cctk_time = tt->get_time (mglevel, reflevel, timelevel);
+ cctkGH->cctk_time = tt->get_time(mglevel, reflevel, timelevel);
+#if 0
// Choose (arbitrarily) the root level as default
// topology, for readers which don't understand AMR
if (reflevel == 0) {
@@ -253,43 +263,24 @@ namespace CarpetIOF5 {
F5Path *const globalpath = F5Rcreate_vertex_refinement3D
(file, cctk_time, gridname.c_str(), &v2h(reffact)[0],
chartname.c_str());
- assert (globalpath);
- FAILWARN (F5Rlink_default_vertex_topology (globalpath,
- &v2h(reffact)[0]));
+ assert(globalpath);
+#warning "TODO: Probably must not call this for cell-centred AMR; this probably makes the call to F5Rcreate_coordinate_topology below fail"
+ FAILWARN(F5Rlink_default_vertex_topology(globalpath,
+ &v2h(reffact)[0]));
// Define iteration
- FAILWARN (F5Rset_timestep (globalpath, cctk_iteration));
-
- // Attach Cactus/Carpet metadata
- if (timelevel == 0) {
- // hid_t const metadata_group = globalpath->Grid_hid;
- ostringstream pathname;
- pathname << FIBER_CONTENT_GRIDS << "/" << gridname;
- hid_t group;
- group = H5Gopen (globalpath->ContentsGroup_hid,
- pathname.str().c_str(),
- H5P_DEFAULT);
- if (group < 0) {
- group = H5Gcreate (globalpath->ContentsGroup_hid,
- pathname.str().c_str(),
- H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
- }
- assert (group >= 0);
- write_metadata (cctkGH, group);
- herr_t const herr = H5Gclose (group);
- assert (not herr);
- }
+ FAILWARN(F5Rset_timestep(globalpath, cctk_iteration));
// Close topology
- F5close (globalpath);
-
- } // if reflevel==0
+ F5close(globalpath);
+ }
+#endif
- output_reflevel (file);
+ output_reflevel(file);
} // for timelevel
timelevel = 0;
- cctkGH->cctk_time = tt->get_time (mglevel, reflevel, timelevel);
+ cctkGH->cctk_time = tt->get_time(mglevel, reflevel, timelevel);
} LEAVE_LEVEL_MODE;
} // if do_every
@@ -299,12 +290,13 @@ namespace CarpetIOF5 {
- void output_reflevel (hid_t const file)
+ void output_reflevel(hid_t const file)
{
DECLARE_CCTK_ARGUMENTS;
indent_t indent;
+ bool error_flag = false;
- assert (is_level_mode());
+ assert(is_level_mode());
ivect const reffact = spacereffacts.AT(reflevel);
topologyname = generate_topologyname(cctkGH, group_index, reffact);
@@ -314,26 +306,100 @@ namespace CarpetIOF5 {
// Define grid hierarchy
map_indices_t const mi(cctkGH, group_index);
- int const indexdepth = vhh.at(0)->refcent == vertex_centered ? 0 : 1;
- F5Path *const path =
- F5Rcreate_coordinate_topology (file, &cctk_time,
- gridname.c_str(), chartname.c_str(),
- topologyname.c_str(),
- indexdepth,
- mi.dim, mi.dim, &v2h(reffact)[0]);
- assert (path);
-
- BEGIN_LOCAL_MAP_LOOP (cctkGH, CCTK_GF) {
- output_map (path);
+ F5Path *path = NULL;
+ F5Path *coordpath = NULL;
+ bool close_coordpath = true;
+ if (group_type == CCTK_GF) {
+ int const indexdepth = vhh.at(0)->refcent == vertex_centered ? 0 : 1;
+ if (indexdepth == 0) {
+ path =
+ F5Rcreate_coordinate_topology(file, &cctk_time,
+ gridname.c_str(), chartname.c_str(),
+ topologyname.c_str(),
+ 0,
+ mi.dim, mi.dim, &v2h(reffact)[0]);
+ } else {
+ char vertextopologyname[1000];
+ TopologyName(vertextopologyname, sizeof vertextopologyname,
+ &v2h(reffact)[0], 0, dim);
+ coordpath =
+ F5Rcreate_coordinate_topology(file, &cctk_time,
+ gridname.c_str(), chartname.c_str(),
+ vertextopologyname,
+ 0,
+ mi.dim, mi.dim, &v2h(reffact)[0]);
+ path =
+ F5Rcreate_coordinate_topology(file, &cctk_time,
+ gridname.c_str(),
+ /*chartname.c_str(),*/
+ vertextopologyname,
+ topologyname.c_str(),
+ indexdepth,
+ mi.dim, mi.dim, &v2h(reffact)[0]);
+#warning "TODO: how should these two topologies be linked?"
+ // assert(mi.dim == 3);
+ // assert(all(reffact == 1));
+ // path =
+ // F5Rcreate_hexaedrons_as_vertices_topology(file, &cctk_time,
+ // gridname.c_str());
+ }
+ } else {
+ path =
+ F5Rcreate_coordinate_topology(file, &cctk_time,
+ gridname.c_str(), chartname.c_str(),
+ topologyname.c_str(),
+ 0,
+ mi.dim, mi.dim, &v2h(reffact)[0]);
+ }
+ if (!coordpath) {
+ coordpath = path;
+ close_coordpath = false;
+ }
+ assert(coordpath);
+ assert(path);
+
+#warning "TODO: Attach the number of I/O processes to the topology. WB sent email with suggestions."
+
+ // Define default topology (once per grid)
+ if (group_type == CCTK_GF and reflevel == 0 and timelevel == 0) {
+ FAILWARN(F5Rlink_default_vertex_topology(path, &v2h(reffact)[0]));
+
+ // Define iteration
+ FAILWARN(F5Rset_timestep(path, cctk_iteration));
+ }
+
+ // Attach Cactus/Carpet metadata (only once per output)
+ if (output_metadata) {
+ if (group_type == CCTK_GF and reflevel == 0 and timelevel == 0) {
+ // hid_t const metadata_group = path->Grid_hid;
+ ostringstream pathname;
+ pathname << FIBER_CONTENT_GRIDS << "/" << gridname;
+ hid_t group;
+ group = H5Gopen(path->ContentsGroup_hid, pathname.str().c_str(),
+ H5P_DEFAULT);
+ if (group < 0) {
+ group = H5Gcreate(path->ContentsGroup_hid, pathname.str().c_str(),
+ H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ }
+ assert(group >= 0);
+ write_metadata(cctkGH, group);
+ herr_t const herr = H5Gclose(group);
+ assert(not herr);
+ }
+ }
+
+ BEGIN_LOCAL_MAP_LOOP(cctkGH, group_type) {
+ output_map(path);
} END_LOCAL_MAP_LOOP;
- // Close topology
- F5close (path);
+ // Close topologies
+ if (close_coordpath) F5close(coordpath);
+ F5close(path);
}
- void output_map (F5Path *const path)
+ void output_map(F5Path *const path)
{
DECLARE_CCTK_ARGUMENTS;
indent_t indent;
@@ -341,9 +407,9 @@ namespace CarpetIOF5 {
cout << indent << "map=" << Carpet::map << "\n";
- assert (is_singlemap_mode());
+ assert(is_singlemap_mode());
- if (not is_multipatch) {
+ if (group_type != CCTK_GF or not is_multipatch) {
// Define level geometry
map_indices_t const mi(cctkGH, group_index);
F5_vec3_double_t const vlower = v2d(mi.lower);
@@ -355,42 +421,42 @@ namespace CarpetIOF5 {
charts.at(3) = F5B_standard_cartesian_chart3D();
}
if (not charts.at(mi.dim)) {
- assert (mi.dim != 0);
- char const* coordnames[] = {"x", "y", "z"};
+ assert(mi.dim != 0);
+ char const *coordnames[] = {"x", "y", "z"};
ostringstream chartnamebuf;
chartnamebuf << "Cartesian " << mi.dim << "D";
charts.at(mi.dim) =
F5B_new_global_float_chart(coordnames,
mi.dim, chartnamebuf.str().c_str(),
F5_FORTRAN_ORDER);
- assert (charts.at(mi.dim));
+ assert(charts.at(mi.dim));
}
// hid_t const type = charts.at(mi.dim)->DoublePrecision.Point_hid_t;
hid_t const type = path->myChart->DoublePrecision.Point_hid_t;
- assert (type);
- FAILWARN (F5Fwrite_linear (path, FIBER_HDF5_POSITIONS_STRING,
- mi.dim, &v2h(mi.gsh)[0],
- type,
- &vlower, &vdelta));
+ assert(type);
+ FAILWARN(F5Fwrite_linear(path, FIBER_HDF5_POSITIONS_STRING,
+ mi.dim, &v2h(mi.gsh)[0],
+ type,
+ &vlower, &vdelta));
#warning "TODO: path and chart don't match"
- FAILWARN (F5Fset_range (path, &vlower, &vupper));
+ FAILWARN(F5Fset_range(path, &vlower, &vupper));
}
- BEGIN_LOCAL_COMPONENT_LOOP (cctkGH, CCTK_GF) {
- output_component (path);
+ BEGIN_LOCAL_COMPONENT_LOOP(cctkGH, group_type) {
+ output_component(path);
} END_LOCAL_COMPONENT_LOOP;
}
- void output_component (F5Path *const path)
+ void output_component(F5Path *const path)
{
DECLARE_CCTK_ARGUMENTS;
DECLARE_CCTK_PARAMETERS;
indent_t indent;
bool error_flag = false;
- assert (is_local_mode());
+ assert(is_local_mode());
fragmentname = generate_fragmentname(cctkGH, Carpet::map, component);
cout << indent
@@ -406,16 +472,16 @@ namespace CarpetIOF5 {
// box was already defined above, but it provides the
// individual components' bounding boxes.)
component_indices_t const ci(cctkGH, group_index);
- FAILWARN (F5Fwrite_linear_fraction (path, FIBER_HDF5_POSITIONS_STRING,
- ci.dim,
- &v2h(ci.gsh)[0], &v2h(ci.ilen)[0],
- F5T_COORD3_DOUBLE,
- &ci.clower, &ci.delta,
- &v2h(ci.ioff)[0],
- fragmentname.c_str()));
+ FAILWARN(F5Fwrite_linear_fraction(path, FIBER_HDF5_POSITIONS_STRING,
+ ci.dim,
+ &v2h(ci.gsh)[0], &v2h(ci.ilen)[0],
+ F5T_COORD3_DOUBLE,
+ &ci.clower, &ci.delta,
+ &v2h(ci.ioff)[0],
+ fragmentname.c_str()));
} else {
// Output coordinates
- output_variable (path, CCTK_VarIndex("grid::x"), true);
+ output_variable(path, CCTK_VarIndex("grid::x"), true);
}
}
@@ -423,14 +489,14 @@ namespace CarpetIOF5 {
for (vector<int>::const_iterator
vi = vindices.begin(); vi != vindices.end(); ++vi)
{
- output_variable (path, *vi);
+ output_variable(path, *vi);
}
}
- void output_variable (F5Path *const path, int const var,
- bool const write_positions = false)
+ void output_variable(F5Path *const path, int const var,
+ bool const write_positions = false)
{
DECLARE_CCTK_ARGUMENTS;
DECLARE_CCTK_PARAMETERS;
@@ -439,7 +505,7 @@ namespace CarpetIOF5 {
int ierr;
- assert (var >= 0);
+ assert(var >= 0);
if (write_positions) {
cout << indent << "positions\n";
} else {
@@ -447,18 +513,21 @@ namespace CarpetIOF5 {
char *const groupname = CCTK_GroupNameFromVarI(var);
cout << indent
<< "variable=" << fullname << " (group=" << groupname << ")\n";
- free (groupname);
- free (fullname);
+ free(groupname);
+ free(fullname);
}
int const group = CCTK_GroupIndexFromVarI(var);
int const v0 = CCTK_FirstVarIndexI(group);
+ // Don't output groups without storage
+ if (not CCTK_QueryGroupStorageI(cctkGH, group)) return;
+
cGroup groupdata;
- ierr = CCTK_GroupData (group, &groupdata);
- assert (not ierr);
+ ierr = CCTK_GroupData(group, &groupdata);
+ assert(not ierr);
- assert ((groupdata.grouptype == CCTK_GF) == (group_type == CCTK_GF));
+ assert((groupdata.grouptype == CCTK_GF) == (group_type == CCTK_GF));
// Output distrib=constant variables only on process 0
switch (groupdata.disttype) {
@@ -469,19 +538,20 @@ namespace CarpetIOF5 {
// do nothing
break;
default:
- assert (0);
+ assert(0);
}
- assert (groupdata.stagtype == 0);
+ assert(groupdata.stagtype == 0);
#warning "TODO: Do not output symmetry zones (unless requested by the user)"
#warning "TODO: Do not output buffer zones (is that easily possible?)"
- int const will_cover_complete_domain = not is_multipatch and reflevel==0;
+ int const will_cover_complete_domain =
+ (group_type != CCTK_GF or not is_multipatch) and reflevel==0;
cGroupDynamicData dyndata;
- ierr = CCTK_GroupDynamicData (cctkGH, group, &dyndata);
- assert (not ierr);
+ ierr = CCTK_GroupDynamicData(cctkGH, group, &dyndata);
+ assert(not ierr);
// Only output active timelevels
if (timelevel >= dyndata.activetimelevels) return;
@@ -490,8 +560,8 @@ namespace CarpetIOF5 {
tensortype_t tensortype = tt_error;
- int const coordinates_group = CCTK_GroupIndex ("grid::coordinates");
- assert (coordinates_group >= 0);
+ int const coordinates_group = CCTK_GroupIndex("grid::coordinates");
+ assert(coordinates_group >= 0);
if (group == coordinates_group) {
@@ -501,7 +571,7 @@ namespace CarpetIOF5 {
} else if (var == v0+dim) {
tensortype = tt_scalar;
} else {
- assert (0);
+ assert(0);
}
} else {
@@ -541,14 +611,14 @@ namespace CarpetIOF5 {
case tt_scalar: {
// Scalar field
- assert (not write_positions);
+ assert(not write_positions);
switch (groupdata.vartype) {
case CCTK_VARIABLE_INT: type = H5T_NATIVE_INT; break;
case CCTK_VARIABLE_REAL: type = H5T_NATIVE_DOUBLE; break;
default: assert(0);
}
num_comps = 1;
- name = generate_fieldname (cctkGH, var, tensortype);
+ name = generate_fieldname(cctkGH, var, tensortype);
break;
}
@@ -564,17 +634,17 @@ namespace CarpetIOF5 {
name =
write_positions ?
FIBER_HDF5_POSITIONS_STRING :
- generate_fieldname (cctkGH, var, tensortype);
+ generate_fieldname(cctkGH, var, tensortype);
if (write_positions) {
htri_t const exists =
- H5Lexists (path->Representation_hid, name.c_str(), H5P_DEFAULT);
- assert (exists >= 0);
+ H5Lexists(path->Representation_hid, name.c_str(), H5P_DEFAULT);
+ assert(exists >= 0);
if (exists) {
string const fragmentpath = name + "/" + fragmentname;
htri_t const exists2 =
- H5Lexists (path->Representation_hid, fragmentpath.c_str(),
- H5P_DEFAULT);
- assert (exists2 >= 0);
+ H5Lexists(path->Representation_hid, fragmentpath.c_str(),
+ H5P_DEFAULT);
+ assert(exists2 >= 0);
if (exists2) {
// Write positions only once
indent_t indent2;
@@ -588,43 +658,46 @@ namespace CarpetIOF5 {
case tt_symtensor: {
// Symmetric tensor field
- assert (not write_positions);
+ assert(not write_positions);
switch (groupdata.vartype) {
case CCTK_VARIABLE_REAL: type = F5T_METRIC33_DOUBLE; break;
default: assert(0);
}
num_comps = dim*(dim+1)/2;
- name = generate_fieldname (cctkGH, var, tensortype);
+ name = generate_fieldname(cctkGH, var, tensortype);
break;
}
case tt_tensor: {
// Non-symmetric tensor field
- assert (not write_positions);
+ assert(not write_positions);
switch (groupdata.vartype) {
case CCTK_VARIABLE_REAL: type = F5T_BIVEC3_DOUBLE; break;
default: assert(0);
}
num_comps = dim*dim;
- name = generate_fieldname (cctkGH, var, tensortype);
+ name = generate_fieldname(cctkGH, var, tensortype);
break;
}
default:
- assert (0);
+ assert(0);
}
cout << indent << "fieldname=" << name << "\n";
// Write data
- assert (type >= 0);
- assert (num_comps > 0);
- assert (name.size() > 0);
+ assert(type >= 0);
+ assert(num_comps > 0);
+ assert(name.size() > 0);
+
+ // Ensure that the data types match
+ int const vartype = CCTK_VarTypeI(var);
+ assert(num_comps * CCTK_VarTypeSize(vartype) == (int)H5Tget_size(type));
component_indices_t const ci(cctkGH, group_index);
- void const* data[num_comps];
- int const vartype = CCTK_VarTypeI(var);
+ void const *data[num_comps];
switch (vartype) {
case CCTK_VARIABLE_INT: {
@@ -637,8 +710,8 @@ namespace CarpetIOF5 {
for (int j=0; j<ci.ilen[1]; ++j) {
for (int i=0; i<ci.ilen[0]; ++i) {
int const isrc =
- (ci.imin[0]+i + ci.lsh[0] *
- (ci.imin[1]+j + ci.lsh[1] *
+ (ci.imin[0]+i + ci.lssh[0] *
+ (ci.imin[1]+j + ci.lssh[1] *
(ci.imin[2]+k)));
int const idst = i + ci.ilen[0] * (j + ci.ilen[1] * k);
rdata[idst] = varptr[isrc];
@@ -660,8 +733,8 @@ namespace CarpetIOF5 {
for (int j=0; j<ci.ilen[1]; ++j) {
for (int i=0; i<ci.ilen[0]; ++i) {
int const isrc =
- (ci.imin[0]+i + ci.lsh[0] *
- (ci.imin[1]+j + ci.lsh[1] *
+ (ci.imin[0]+i + ci.lssh[0] *
+ (ci.imin[1]+j + ci.lssh[1] *
(ci.imin[2]+k)));
int const idst = i + ci.ilen[0] * (j + ci.ilen[1] * k);
rdata[idst] = varptr[isrc];
@@ -678,17 +751,17 @@ namespace CarpetIOF5 {
}
// Dataset properties
- hid_t const prop = H5Pcreate (H5P_DATASET_CREATE);
- assert (prop >= 0);
+ hid_t const prop = H5Pcreate(H5P_DATASET_CREATE);
+ assert(prop >= 0);
// Enable compression if requested
if (compression_level >= 0) {
- FAILWARN (H5Pset_chunk (prop, ci.dim, &v2h(ci.ilen).reverse()[0]));
- FAILWARN (H5Pset_deflate (prop, compression_level));
+ FAILWARN(H5Pset_chunk(prop, ci.dim, &v2h(ci.ilen).reverse()[0]));
+ FAILWARN(H5Pset_deflate(prop, compression_level));
}
// Enable checksums if requested
if (use_checksums) {
- FAILWARN (H5Pset_chunk (prop, ci.dim, &v2h(ci.ilen).reverse()[0]));
- FAILWARN (H5Pset_fletcher32 (prop));
+ FAILWARN(H5Pset_chunk(prop, ci.dim, &v2h(ci.ilen).reverse()[0]));
+ FAILWARN(H5Pset_fletcher32(prop));
}
if (num_comps == 1 and not separate_single_component_tensors) {
@@ -697,27 +770,39 @@ namespace CarpetIOF5 {
// instead)
// TODO: Extent F5 API to allow writing non-fragmented datasets
FAILWARN
- (F5Fwrite_fraction (path, name.c_str(),
+ (F5Fwrite_fraction(path, name.c_str(),
+ ci.dim,
+ is_multipatch ? NULL : &v2h(ci.gsh)[0],
+ &v2h(ci.ilen)[0],
+ type, type, data[0],
+ &v2h(ci.ioff)[0],
+ &v2h(ci.lghosts)[0], &v2h(ci.ughosts)[0],
+ fragmentname.c_str(), prop));
+ } else {
+ int const full_coverage =
+ will_cover_complete_domain and not fragment_contiguous_components;
+ // F5ls does not seem to support what F5 generates in this
+ // case. It seems that F5 does not generate a separated object
+ // (it does not generate a group for all datasets), but
+ // declares that it does create one (it calls it
+ // FragmentedSeparatedCompound). F5ls then gets confused
+ // because it cannot open this group.
+ if (not full_coverage and num_comps == 1) {
+ CCTK_WARN(CCTK_WARN_ALERT,
+ "Outputting scalars in a fragmented, separated way. "
+ "This does not seem to be supported by F5ls "
+ "(or is implemented wrong in the F5 library).");
+ }
+ FAILWARN
+ (F5FSwrite_fraction(path, name.c_str(),
ci.dim,
is_multipatch ? NULL : &v2h(ci.gsh)[0],
&v2h(ci.ilen)[0],
- type, type, data[0],
+ type, type, data,
&v2h(ci.ioff)[0],
&v2h(ci.lghosts)[0], &v2h(ci.ughosts)[0],
- fragmentname.c_str(), prop));
- } else {
- int const full_coverage =
- will_cover_complete_domain and not fragment_contiguous_components;
- FAILWARN
- (F5FSwrite_fraction (path, name.c_str(),
- ci.dim,
- is_multipatch ? NULL : &v2h(ci.gsh)[0],
- &v2h(ci.ilen)[0],
- type, type, data,
- &v2h(ci.ioff)[0],
- &v2h(ci.lghosts)[0], &v2h(ci.ughosts)[0],
- fragmentname.c_str(), prop,
- full_coverage));
+ fragmentname.c_str(), prop,
+ full_coverage));
}
for (int d=0; d<num_comps; ++d) {
@@ -729,7 +814,7 @@ namespace CarpetIOF5 {
data[d] = NULL;
}
- FAILWARN (H5Pclose (prop));
+ FAILWARN(H5Pclose(prop));
}
@@ -737,50 +822,47 @@ namespace CarpetIOF5 {
- void write_metadata (cGH const* const cctkGH, hid_t const file)
+ void write_metadata(cGH const *const cctkGH, hid_t const file)
{
DECLARE_CCTK_PARAMETERS;
- assert (cctkGH);
- assert (file >= 0);
+ assert(cctkGH);
+ assert(file >= 0);
herr_t herr;
- CCTK_INFO ("Writing simulation metadata...");
- // NOTE: We could write the metadata into only one of the process
- // files (to save space), or write it into a separate metadata
- // file
+ CCTK_INFO("Writing simulation metadata...");
// Create metadata only once
- // TODO: update metadata at some point
- htri_t const exists = H5Lexists (file, metadata_group, H5P_DEFAULT);
- assert (exists >= 0);
+ // TODO: instead, overwrite the metadata
+ htri_t const exists = H5Lexists(file, metadata_group, H5P_DEFAULT);
+ assert(exists >= 0);
if (exists) return;
// Create a group to hold all metadata
hid_t const group =
- H5Gcreate (file, metadata_group, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
- assert (group >= 0);
+ H5Gcreate(file, metadata_group, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ assert(group >= 0);
// General information
- WriteAttribute (group, "Cactus version", CCTK_FullVersion());
+ WriteAttribute(group, "Cactus version", CCTK_FullVersion());
// Unique identifiers
- if (CCTK_IsFunctionAliased ("UniqueConfigID")) {
+ if (CCTK_IsFunctionAliased("UniqueConfigID")) {
WriteAttribute
(group, "config id", (char const*) UniqueConfigID(cctkGH));
}
- if (CCTK_IsFunctionAliased ("UniqueBuildID")) {
+ if (CCTK_IsFunctionAliased("UniqueBuildID")) {
WriteAttribute
(group, "build id", (char const*) UniqueBuildID(cctkGH));
}
- if (CCTK_IsFunctionAliased ("UniqueSimulationID")) {
+ if (CCTK_IsFunctionAliased("UniqueSimulationID")) {
WriteAttribute
(group, "simulation id", (char const*) UniqueSimulationID(cctkGH));
}
- if (CCTK_IsFunctionAliased ("UniqueRunID")) {
+ if (CCTK_IsFunctionAliased("UniqueRunID")) {
WriteAttribute
(group, "run id", (char const*) UniqueRunID(cctkGH));
}
@@ -791,35 +873,37 @@ namespace CarpetIOF5 {
// Number of I/O processes (i.e. the number of output files)
int const nprocs = CCTK_nProcs(cctkGH);
int const nioprocs = nprocs;
- WriteAttribute (group, "nioprocs", nioprocs);
+ WriteAttribute(group, "nioprocs", nioprocs);
#endif
// Write parameters into a separate dataset (they may be too large
// for an attribute)
int const get_all = 1;
- char *const parameters = IOUtil_GetAllParameters (cctkGH, get_all);
- assert (parameters);
- WriteLargeAttribute (group, all_parameters, parameters);
- free (parameters);
+ char *const parameters = IOUtil_GetAllParameters(cctkGH, get_all);
+ assert(parameters);
+ WriteLargeAttribute(group, all_parameters, parameters);
+ free(parameters);
// Grid structure
- string const gs = serialise_grid_structure (cctkGH);
- WriteLargeAttribute (group, grid_structure, gs.c_str());
+ string const gs = serialise_grid_structure(cctkGH);
+ WriteLargeAttribute(group, grid_structure, gs.c_str());
- herr = H5Gclose (group);
- assert (not herr);
+ herr = H5Gclose(group);
+ assert(not herr);
}
- void output (cGH const* const cctkGH,
- hid_t const file,
- vector<bool> const& output_var,
- bool const output_everything)
+ void output(cGH const *const cctkGH,
+ hid_t const file,
+ vector<bool> const& output_var,
+ bool const output_past_timelevels,
+ bool const output_metadata)
{
output_iterator_t
- iterator(const_cast<cGH*>(cctkGH), output_var, output_everything);
- iterator.iterate (file);
+ iterator(const_cast<cGH*>(cctkGH), output_var,
+ output_past_timelevels, output_metadata);
+ iterator.iterate(file);
}
} // end namespace CarpetIOF5