aboutsummaryrefslogtreecommitdiff
path: root/Carpet/CarpetIOScalar/src/ioscalar.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Carpet/CarpetIOScalar/src/ioscalar.cc')
-rw-r--r--Carpet/CarpetIOScalar/src/ioscalar.cc487
1 files changed, 487 insertions, 0 deletions
diff --git a/Carpet/CarpetIOScalar/src/ioscalar.cc b/Carpet/CarpetIOScalar/src/ioscalar.cc
new file mode 100644
index 000000000..83b450bb5
--- /dev/null
+++ b/Carpet/CarpetIOScalar/src/ioscalar.cc
@@ -0,0 +1,487 @@
+#include <cassert>
+#include <cstdlib>
+#include <fstream>
+#include <iomanip>
+#include <list>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+
+#include "CactusBase/IOUtil/src/ioGH.h"
+
+#include "carpet.hh"
+
+
+
+extern "C" {
+ static const char* rcsid = "$Header: /home/eschnett/C/carpet/Carpet/Carpet/CarpetIOScalar/src/ioscalar.cc,v 1.6 2004/08/05 10:28:25 schnetter Exp $";
+ CCTK_FILEVERSION(Carpet_CarpetIOScalar_ioscalar_cc);
+}
+
+
+
+// That's a hack
+namespace Carpet {
+ void UnsupportedVarType (const int vindex);
+}
+
+
+
+namespace CarpetIOScalar {
+
+ using namespace std;
+ using namespace Carpet;
+
+
+
+ // Definition of local types
+ struct info {
+ string reduction;
+ int handle;
+ };
+
+
+
+ // Registered functions
+ void* SetupGH (tFleshConfig* fc, int convLevel, cGH* cctkGH);
+ int OutputGH (const cGH* cctkGH);
+ int OutputVarAs (const cGH* cctkGH, const char* varname, const char* alias);
+ int TimeToOutput (const cGH* cctkGH, int vindex);
+ int TriggerOutput (const cGH* cctkGH, int vindex);
+
+ // Internal functions
+ void SetFlag (int index, const char* optstring, void* arg);
+
+
+
+ // Definition of static members
+ int GHExtension;
+ int IOMethod;
+ vector<bool> do_truncate;
+ vector<int> last_output;
+
+
+
+ // Special output routines for complex numbers
+
+#ifdef CCTK_REAL4
+ ostream& operator<< (ostream& os, const CCTK_COMPLEX8& val)
+ {
+ return os << CCTK_Cmplx8Real(val) << " " << CCTK_Cmplx8Imag(val);
+ }
+#endif
+
+#ifdef CCTK_REAL8
+ ostream& operator<< (ostream& os, const CCTK_COMPLEX16& val)
+ {
+ return os << CCTK_Cmplx16Real(val) << " " << CCTK_Cmplx16Imag(val);
+ }
+#endif
+
+#ifdef CCTK_REAL16
+ ostream& operator<< (ostream& os, const CCTK_COMPLEX32& val)
+ {
+ return os << CCTK_Cmplx32Real(val) << " " << CCTK_Cmplx32Imag(val);
+ }
+#endif
+
+
+
+ extern "C" void
+ CarpetIOScalarStartup ()
+ {
+ CCTK_RegisterBanner ("AMR scalar I/O provided by CarpetIOScalar");
+
+ GHExtension = CCTK_RegisterGHExtension("CarpetIOScalar");
+ CCTK_RegisterGHExtensionSetupGH (GHExtension, SetupGH);
+
+ IOMethod = CCTK_RegisterIOMethod ("CarpetIOScalar");
+ CCTK_RegisterIOMethodOutputGH (IOMethod, OutputGH);
+ CCTK_RegisterIOMethodOutputVarAs (IOMethod, OutputVarAs);
+ CCTK_RegisterIOMethodTimeToOutput (IOMethod, TimeToOutput);
+ CCTK_RegisterIOMethodTriggerOutput (IOMethod, TriggerOutput);
+ }
+
+
+
+ extern "C" void
+ CarpetIOScalarInit (CCTK_ARGUMENTS)
+ {
+ DECLARE_CCTK_ARGUMENTS;
+
+ *this_iteration = 0;
+ *last_output_iteration = 0;
+ *last_output_time = cctkGH->cctk_time;
+ }
+
+
+
+ void*
+ SetupGH (tFleshConfig* const fc, int const convLevel, cGH* const cctkGH)
+ {
+ DECLARE_CCTK_PARAMETERS;
+ const void *dummy;
+
+ dummy = &fc;
+ dummy = &convLevel;
+ dummy = &cctkGH;
+ dummy = &dummy;
+
+ // Truncate all files if this is not a restart
+ do_truncate.resize (CCTK_NumVars(), true);
+
+ // No iterations have yet been output
+ last_output.resize (CCTK_NumVars(), -1);
+
+ // We register only once, ergo we get only one handle. We store
+ // that statically, so there is no need to pass anything to
+ // Cactus.
+ return NULL;
+ }
+
+
+
+ int
+ OutputGH (const cGH * const cctkGH)
+ {
+ for (int vindex=0; vindex<CCTK_NumVars(); ++vindex) {
+ if (TimeToOutput(cctkGH, vindex)) {
+ TriggerOutput(cctkGH, vindex);
+ }
+ }
+ return 0;
+ }
+
+
+
+ int
+ OutputVarAs (const cGH * const cctkGH,
+ const char* const varname, const char* const alias)
+ {
+ DECLARE_CCTK_ARGUMENTS;
+ DECLARE_CCTK_PARAMETERS;
+
+ assert (is_level_mode());
+
+ const int n = CCTK_VarIndex(varname);
+ if (n<0) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Variable \"%s\" does not exist", varname);
+ return -1;
+ }
+ assert (n>=0 && n<CCTK_NumVars());
+ const int group = CCTK_GroupIndexFromVarI (n);
+ assert (group>=0 && group<(int)Carpet::arrdata.size());
+ const int n0 = CCTK_FirstVarIndexI(group);
+ assert (n0>=0 && n0<CCTK_NumVars());
+ const int var = n - n0;
+ assert (var>=0 && var<CCTK_NumVarsInGroupI(group));
+ const int num_tl = CCTK_NumTimeLevelsFromVarI(n);
+ assert (num_tl>=1);
+
+ // Check for storage
+ if (! CCTK_QueryGroupStorageI(cctkGH, group)) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Cannot output variable \"%s\" because it has no storage",
+ varname);
+ return 0;
+ }
+
+ assert (do_global_mode);
+
+ const int vartype = CCTK_VarTypeI(n);
+ assert (vartype >= 0);
+
+ // Get grid hierarchy extentsion from IOUtil
+ const ioGH * const iogh = (const ioGH *)CCTK_GHExtension (cctkGH, "IO");
+ assert (iogh);
+
+ // Create the output directory
+ const char* myoutdir = outScalar_dir;
+ if (CCTK_EQUALS(myoutdir, "")) {
+ myoutdir = out_dir;
+ }
+ if (CCTK_MyProc(cctkGH)==0) {
+ CCTK_CreateDirectory (0755, myoutdir);
+ }
+
+ // Find the set of desired reductions
+ list<info> reductions;
+ string const redlist (outScalar_reductions);
+ string::const_iterator p = redlist.begin();
+ while (p!=redlist.end()) {
+ while (p!=redlist.end() && isspace(*p)) ++p;
+ if (p==redlist.end()) break;
+ string::const_iterator const start = p;
+ while (p!=redlist.end() && !isspace(*p)) ++p;
+ string::const_iterator const end = p;
+ string const reduction (start, end);
+ int const handle = CCTK_ReductionHandle (reduction.c_str());
+ if (handle < 0) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Reduction operator \"%s\" does not exist (maybe there is no reduction thorn active?)",
+ reduction.c_str());
+ } else {
+ info i;
+ i.reduction = reduction;
+ i.handle = handle;
+ reductions.push_back (i);
+ }
+ }
+
+ // Output in global mode
+ BEGIN_GLOBAL_MODE(cctkGH) {
+
+ for (list<info>::const_iterator ireduction = reductions.begin();
+ ireduction != reductions.end();
+ ++ireduction)
+ {
+ string const reduction = ireduction->reduction;
+
+ ofstream file;
+ if (CCTK_MyProc(cctkGH)==0) {
+
+ // Invent a file name
+ ostringstream filenamebuf;
+ filenamebuf << myoutdir << "/" << alias << "." << reduction
+ << ".asc";
+ // we need a persistent temporary here
+ string filenamestr = filenamebuf.str();
+ const char* const filename = filenamestr.c_str();
+
+ // If this is the first time, then write a nice header
+ if (do_truncate.at(n) && ! iogh->recovered) {
+ file.open (filename, ios::out | ios::trunc);
+ file << "# " << varname << " (" << alias << ")" << endl;
+ file << "# iteration time data" << endl;
+ } else {
+ file.open (filename, ios::out | ios::app);
+ }
+ if (! file.good()) {
+ CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Could not open output file \"%s\" for variable \"%s\"",
+ filename, varname);
+ }
+
+ assert (file.is_open());
+
+ file << setprecision(15);
+ assert (file.good());
+
+ } // if on the root processor
+
+ int const handle = ireduction->handle;
+
+ union {
+#define TYPECASE(N,T) T var_##T;
+#include "Carpet/Carpet/src/typecase"
+#undef TYPECASE
+ } result;
+
+ int const ierr
+ = CCTK_Reduce (cctkGH, 0, handle, 1, vartype, &result, 1, n);
+ assert (! ierr);
+
+ if (CCTK_MyProc(cctkGH)==0) {
+
+ file << cctk_iteration << " " << cctk_time << " ";
+
+ switch (vartype) {
+#define TYPECASE(N,T) \
+ case N: \
+ file << result.var_##T; \
+ break;
+#include "Carpet/Carpet/src/typecase"
+#undef TYPECASE
+ default:
+ UnsupportedVarType (n);
+ }
+
+ file << endl;
+ assert (file.good());
+ }
+
+ if (CCTK_MyProc(cctkGH)==0) {
+ file.close();
+ assert (file.good());
+ }
+
+ assert (! file.is_open());
+
+ } // for reductions
+
+ } END_GLOBAL_MODE;
+
+ // Don't truncate again
+ do_truncate.at(n) = false;
+
+ return 0;
+ }
+
+
+
+ int
+ TimeToOutput (const cGH * const cctkGH, int const vindex)
+ {
+ DECLARE_CCTK_ARGUMENTS;
+ DECLARE_CCTK_PARAMETERS;
+
+ assert (vindex>=0 && vindex<CCTK_NumVars());
+
+
+
+ if (! do_global_mode) return 0;
+
+
+
+ // check whether to output at this iteration
+ bool output_this_iteration;
+
+ const char* myoutcriterion = outScalar_criterion;
+ if (CCTK_EQUALS(myoutcriterion, "default")) {
+ myoutcriterion = out_criterion;
+ }
+
+ if (CCTK_EQUALS (myoutcriterion, "never")) {
+
+ // Never output
+ output_this_iteration = false;
+
+ } else if (CCTK_EQUALS (myoutcriterion, "iteration")) {
+
+ int myoutevery = outScalar_every;
+ if (myoutevery == -2) {
+ myoutevery = out_every;
+ }
+ if (myoutevery <= 0) {
+ // output is disabled
+ output_this_iteration = false;
+ } else if (cctk_iteration == *this_iteration) {
+ // we already decided to output this iteration
+ output_this_iteration = true;
+ } else if (cctk_iteration >= *last_output_iteration + myoutevery) {
+ // it is time for the next output
+ output_this_iteration = true;
+ *last_output_iteration = cctk_iteration;
+ *this_iteration = cctk_iteration;
+ } else {
+ // we want no output at this iteration
+ output_this_iteration = false;
+ }
+
+ } else if (CCTK_EQUALS (myoutcriterion, "time")) {
+
+ CCTK_REAL myoutdt = outScalar_dt;
+ if (myoutdt == -2) {
+ myoutdt = out_dt;
+ }
+ if (myoutdt < 0) {
+ // output is disabled
+ output_this_iteration = false;
+ } else if (myoutdt == 0) {
+ // output all iterations
+ output_this_iteration = true;
+ } else if (cctk_iteration == *this_iteration) {
+ // we already decided to output this iteration
+ output_this_iteration = true;
+ } else if (cctk_time / cctk_delta_time
+ >= (*last_output_time + myoutdt) / cctk_delta_time - 1.0e-12) {
+ // it is time for the next output
+ output_this_iteration = true;
+ *last_output_time = cctk_time;
+ *this_iteration = cctk_iteration;
+ } else {
+ // we want no output at this iteration
+ output_this_iteration = false;
+ }
+
+ } else {
+
+ assert (0);
+
+ } // select output criterion
+
+ if (! output_this_iteration) return 0;
+
+
+
+ // check which variables to output
+ static vector<bool> output_variables;
+ static int output_variables_iteration = -1;
+
+ if (cctk_iteration > output_variables_iteration) {
+ output_variables.resize (CCTK_NumVars());
+
+ const char* const varlist = outScalar_vars;
+ if (CCTK_TraverseString (varlist, SetFlag, &output_variables,
+ CCTK_GROUP_OR_VAR) < 0)
+ {
+ CCTK_WARN (output_variables_iteration < 0 && strict_io_parameter_check ?
+ 0 : 1,
+ "error while parsing parameter 'IOScalar::outScalar_vars'");
+ }
+
+ output_variables_iteration = cctk_iteration;
+ }
+
+ if (! output_variables.at(vindex)) return 0;
+
+
+
+ if (last_output.at(vindex) == cctk_iteration) {
+ // Has already been output during this iteration
+ char* const varname = CCTK_FullName(vindex);
+ CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Skipping output for variable \"%s\", because this variable "
+ "has already been output during the current iteration -- "
+ "probably via a trigger during the analysis stage",
+ varname);
+ free (varname);
+ return 0;
+ }
+
+ assert (last_output.at(vindex) < cctk_iteration);
+
+ // Should be output during this iteration
+ return 1;
+ }
+
+
+
+ int
+ TriggerOutput (const cGH * const cctkGH, int const vindex)
+ {
+ DECLARE_CCTK_ARGUMENTS;
+
+ assert (vindex>=0 && vindex<CCTK_NumVars());
+
+ char* const varname = CCTK_FullName(vindex);
+ const int retval = OutputVarAs (cctkGH, varname, CCTK_VarName(vindex));
+ free (varname);
+
+ last_output.at(vindex) = cctk_iteration;
+
+ return retval;
+ }
+
+
+
+ void
+ SetFlag (int const index, const char * const optstring, void * const arg)
+ {
+ const void *dummy;
+
+ dummy = &optstring;
+ dummy = &dummy;
+
+ vector<bool>& flags = *(vector<bool>*)arg;
+ flags.at(index) = true;
+ }
+
+
+
+} // namespace CarpetIOScalar