aboutsummaryrefslogtreecommitdiff
path: root/CarpetDev
diff options
context:
space:
mode:
authorErik Schnetter <schnetter@cct.lsu.edu>2010-09-10 13:38:17 -0500
committerBarry Wardell <barry.wardell@gmail.com>2011-12-14 18:25:20 +0000
commit4afda80c0ed50b919bca31c00bc0fb5221cc523c (patch)
treef2496912042a213bb50dd6d0e316844979ce63e7 /CarpetDev
parent79dada933702bb122e25edef4bd281ba997d77ed (diff)
CarpetIONirvana: Move from Carpet to CarpetDev arrangement
Diffstat (limited to 'CarpetDev')
-rw-r--r--CarpetDev/CarpetIONirvana/README9
-rw-r--r--CarpetDev/CarpetIONirvana/configuration.ccl5
-rw-r--r--CarpetDev/CarpetIONirvana/doc/documentation.tex144
-rw-r--r--CarpetDev/CarpetIONirvana/interface.ccl88
-rw-r--r--CarpetDev/CarpetIONirvana/param.ccl70
-rw-r--r--CarpetDev/CarpetIONirvana/schedule.ccl16
-rw-r--r--CarpetDev/CarpetIONirvana/src/CarpetIONirvana.cc586
-rw-r--r--CarpetDev/CarpetIONirvana/src/CarpetIONirvana.hh139
-rw-r--r--CarpetDev/CarpetIONirvana/src/Output.cc360
-rw-r--r--CarpetDev/CarpetIONirvana/src/make.code.defn9
10 files changed, 1426 insertions, 0 deletions
diff --git a/CarpetDev/CarpetIONirvana/README b/CarpetDev/CarpetIONirvana/README
new file mode 100644
index 000000000..3df3e34b4
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/README
@@ -0,0 +1,9 @@
+Cactus Code Thorn CarpetIONirvana
+Author(s) : Christian Reisswig <reisswig@tapir.caltech.edu>
+Maintainer(s): Christian Reisswig <reisswig@tapir.caltech.edu>
+Licence : lGPL
+--------------------------------------------------------------------------
+
+1. Purpose
+
+not documented
diff --git a/CarpetDev/CarpetIONirvana/configuration.ccl b/CarpetDev/CarpetIONirvana/configuration.ccl
new file mode 100644
index 000000000..6b41cf9d7
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/configuration.ccl
@@ -0,0 +1,5 @@
+# Configuration definitions for thorn CarpetIONirvana
+
+REQUIRES Carpet CarpetLib IOUtil HDF5 Nirvana
+
+REQUIRES THORNS: Carpet CarpetLib IOUtil
diff --git a/CarpetDev/CarpetIONirvana/doc/documentation.tex b/CarpetDev/CarpetIONirvana/doc/documentation.tex
new file mode 100644
index 000000000..174f3b185
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/doc/documentation.tex
@@ -0,0 +1,144 @@
+% *======================================================================*
+% Cactus Thorn template for ThornGuide documentation
+% Author: Ian Kelley
+% Date: Sun Jun 02, 2002
+% $Header$
+%
+% Thorn documentation in the latex file doc/documentation.tex
+% will be included in ThornGuides built with the Cactus make system.
+% The scripts employed by the make system automatically include
+% pages about variables, parameters and scheduling parsed from the
+% relevant thorn CCL files.
+%
+% This template contains guidelines which help to assure that your
+% documentation will be correctly added to ThornGuides. More
+% information is available in the Cactus UsersGuide.
+%
+% Guidelines:
+% - Do not change anything before the line
+% % START CACTUS THORNGUIDE",
+% except for filling in the title, author, date, etc. fields.
+% - Each of these fields should only be on ONE line.
+% - Author names should be separated with a \\ or a comma.
+% - You can define your own macros, but they must appear after
+% the START CACTUS THORNGUIDE line, and must not redefine standard
+% latex commands.
+% - To avoid name clashes with other thorns, 'labels', 'citations',
+% 'references', and 'image' names should conform to the following
+% convention:
+% ARRANGEMENT_THORN_LABEL
+% For example, an image wave.eps in the arrangement CactusWave and
+% thorn WaveToyC should be renamed to CactusWave_WaveToyC_wave.eps
+% - Graphics should only be included using the graphicx package.
+% More specifically, with the "\includegraphics" command. Do
+% not specify any graphic file extensions in your .tex file. This
+% will allow us to create a PDF version of the ThornGuide
+% via pdflatex.
+% - References should be included with the latex "\bibitem" command.
+% - Use \begin{abstract}...\end{abstract} instead of \abstract{...}
+% - Do not use \appendix, instead include any appendices you need as
+% standard sections.
+% - For the benefit of our Perl scripts, and for future extensions,
+% please use simple latex.
+%
+% *======================================================================*
+%
+% Example of including a graphic image:
+% \begin{figure}[ht]
+% \begin{center}
+% \includegraphics[width=6cm]{MyArrangement_MyThorn_MyFigure}
+% \end{center}
+% \caption{Illustration of this and that}
+% \label{MyArrangement_MyThorn_MyLabel}
+% \end{figure}
+%
+% Example of using a label:
+% \label{MyArrangement_MyThorn_MyLabel}
+%
+% Example of a citation:
+% \cite{MyArrangement_MyThorn_Author99}
+%
+% Example of including a reference
+% \bibitem{MyArrangement_MyThorn_Author99}
+% {J. Author, {\em The Title of the Book, Journal, or periodical}, 1 (1999),
+% 1--16. {\tt http://www.nowhere.com/}}
+%
+% *======================================================================*
+
+% If you are using CVS use this line to give version information
+% $Header$
+
+\documentclass{article}
+
+% Use the Cactus ThornGuide style file
+% (Automatically used from Cactus distribution, if you have a
+% thorn without the Cactus Flesh download this from the Cactus
+% homepage at www.cactuscode.org)
+\usepackage{../../../../doc/latex/cactus}
+
+\begin{document}
+
+% The author of the documentation
+\author{Christian Reisswig \textless reisswig@tapir.caltech.edu\textgreater}
+
+% The title of the document (not necessarily the name of the Thorn)
+\title{CarpetIONirvana}
+
+% the date your document was last changed, if your document is in CVS,
+% please use:
+% \date{$ $Date: 2004-01-07 12:12:39 -0800 (Wed, 07 Jan 2004) $ $}
+\date{August 26 2010}
+
+\maketitle
+
+% Do not delete next line
+% START CACTUS THORNGUIDE
+
+% Add all definitions used in this documentation here
+% \def\mydef etc
+
+% Add an abstract for this thorn's documentation
+\begin{abstract}
+
+\end{abstract}
+
+% The following sections are suggestive only.
+% Remove them or add your own.
+
+\section{Introduction}
+
+\section{Physical System}
+
+\section{Numerical Implementation}
+
+\section{Using This Thorn}
+
+\subsection{Obtaining This Thorn}
+
+\subsection{Basic Usage}
+
+\subsection{Special Behaviour}
+
+\subsection{Interaction With Other Thorns}
+
+\subsection{Examples}
+
+\subsection{Support and Feedback}
+
+\section{History}
+
+\subsection{Thorn Source Code}
+
+\subsection{Thorn Documentation}
+
+\subsection{Acknowledgements}
+
+
+\begin{thebibliography}{9}
+
+\end{thebibliography}
+
+% Do not delete next line
+% END CACTUS THORNGUIDE
+
+\end{document}
diff --git a/CarpetDev/CarpetIONirvana/interface.ccl b/CarpetDev/CarpetIONirvana/interface.ccl
new file mode 100644
index 000000000..400f6d003
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/interface.ccl
@@ -0,0 +1,88 @@
+# Interface definition for thorn CarpetIONirvana
+
+IMPLEMENTS: IONirvana
+
+includes header: CarpetIONirvana.hh in CarpetIONirvana.hh
+
+uses include header: carpet.hh
+uses include header: CarpetTimers.hh
+
+uses include header: defs.hh
+
+uses include header: bbox.hh
+uses include header: vect.hh
+
+uses include header: data.hh
+uses include header: gdata.hh
+
+uses include header: ggf.hh
+uses include header: gh.hh
+
+uses include header: typecase.hh
+uses include header: typeprops.hh
+
+
+
+CCTK_INT next_output_iteration TYPE=scalar
+CCTK_REAL next_output_time TYPE=scalar
+CCTK_INT this_iteration TYPE=scalar
+
+CCTK_INT last_output_iteration_slice[3] TYPE=scalar
+CCTK_REAL last_output_time_slice[3] TYPE=scalar
+CCTK_INT this_iteration_slice[3] TYPE=scalar
+
+
+CCTK_INT FUNCTION Coord_GroupSystem \
+ (CCTK_POINTER_TO_CONST IN GH, \
+ CCTK_STRING IN groupname)
+USES FUNCTION Coord_GroupSystem
+
+# Specify whether a map uses a Cartesian or a curvilinear coordinate system
+CCTK_INT FUNCTION \
+ MultiPatch_MapIsCartesian \
+ (CCTK_INT IN map)
+USES FUNCTION MultiPatch_MapIsCartesian
+
+
+# Determine which boundaries are symmetry boundaries
+CCTK_INT FUNCTION \
+ SymmetryTableHandleForGrid (CCTK_POINTER_TO_CONST IN cctkGH)
+REQUIRES FUNCTION SymmetryTableHandleForGrid
+
+CCTK_INT FUNCTION \
+ SymmetryTableHandleForGI (CCTK_POINTER_TO_CONST IN cctkGH, \
+ CCTK_INT IN group_index)
+REQUIRES FUNCTION SymmetryTableHandleForGI
+
+
+# Check whether existing output files should be truncated or not
+CCTK_INT FUNCTION IO_TruncateOutputFiles \
+ (CCTK_POINTER_TO_CONST IN GH)
+
+REQUIRES FUNCTION IO_TruncateOutputFiles
+
+
+
+# Return a pointer to an unmodifiable C string
+# which contains a unique ID for this configuration
+CCTK_POINTER_TO_CONST \
+FUNCTION UniqueConfigID (CCTK_POINTER_TO_CONST IN cctkGH)
+USES FUNCTION UniqueConfigID
+
+# Return a pointer to an unmodifiable C string
+# which contains a unique ID for this build
+CCTK_POINTER_TO_CONST \
+FUNCTION UniqueBuildID (CCTK_POINTER_TO_CONST IN cctkGH)
+USES FUNCTION UniqueBuildID
+
+# Return a pointer to an unmodifiable C string
+# which contains a unique ID for this simulation
+CCTK_POINTER_TO_CONST \
+FUNCTION UniqueSimulationID (CCTK_POINTER_TO_CONST IN cctkGH)
+USES FUNCTION UniqueSimulationID
+
+# Return a pointer to an unmodifiable C string
+# which contains a unique ID for this run
+CCTK_POINTER_TO_CONST \
+FUNCTION UniqueRunID (CCTK_POINTER_TO_CONST IN cctkGH)
+USES FUNCTION UniqueRunID
diff --git a/CarpetDev/CarpetIONirvana/param.ccl b/CarpetDev/CarpetIONirvana/param.ccl
new file mode 100644
index 000000000..88529f70e
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/param.ccl
@@ -0,0 +1,70 @@
+# Parameter definitions for thorn CarpetIONirvana
+
+
+
+shares: IO
+
+USES STRING out_dir AS io_out_dir
+USES KEYWORD out_criterion AS io_out_criterion
+USES INT out_every AS io_out_every
+USES REAL out_dt AS io_out_dt
+USES BOOLEAN strict_io_parameter_check
+USES KEYWORD verbose
+USES BOOLEAN out_single_precision
+USES BOOLEAN abort_on_io_errors
+
+
+
+shares: Cactus
+
+USES REAL cctk_initial_time
+
+
+
+private:
+
+STRING out_dir "Name of CarpetIONirvana output directory, overrides 'IO::out_dir'" STEERABLE = ALWAYS
+{
+ "^$" :: "Empty: use IO::out_dir"
+ ".+" :: "Not empty: directory name"
+} ""
+
+STRING out_vars "Variables to output in CarpetIONirvana file format" STEERABLE = ALWAYS
+{
+ "" :: "List of group or variable names"
+} ""
+
+
+STRING out_extension "File extension to use for CarpetIONirvana output" STEERABLE = ALWAYS
+{
+ "" :: "File extension (including a leading dot, if desired)"
+} ".h5"
+
+KEYWORD out_criterion "Criterion to select CarpetIONirvana output intervals, overrides out_every" STEERABLE = ALWAYS
+{
+ "default" :: "Use 'IO::out_criterion'"
+ "never" :: "Never output"
+ "iteration" :: "Output every so many iterations"
+ "divisor" :: "Output if (iteration % out_every) == 0."
+ "time" :: "Output every that much coordinate time"
+} "default"
+
+INT out_every "How often to do CarpetIONirvana output, overrides out_every" STEERABLE = ALWAYS
+{
+ 1:* :: "Output every so many time steps"
+ -1:0 :: "No output"
+ -2 :: "Use 'IO::out_every'"
+} -2
+
+REAL out_dt "How often to do CarpetIONirvana output, overrides 'IO::out_dt'" STEERABLE = ALWAYS
+{
+ (0:* :: "In intervals of that much coordinate time"
+ 0 :: "As often as possible"
+ -1 :: "Disable output"
+ -2 :: "Default to 'IO::out_dt'"
+} -2
+
+
+
+
+
diff --git a/CarpetDev/CarpetIONirvana/schedule.ccl b/CarpetDev/CarpetIONirvana/schedule.ccl
new file mode 100644
index 000000000..5154cb400
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/schedule.ccl
@@ -0,0 +1,16 @@
+# Schedule definitions for thorn CarpetIONirvana
+
+storage: next_output_iteration next_output_time this_iteration
+storage: last_output_iteration_slice last_output_time_slice this_iteration_slice
+
+schedule CarpetIONirvana_Startup at STARTUP after IOUtil_Startup
+{
+ LANG: C
+} "Startup routine"
+
+schedule CarpetIONirvana_Init at BASEGRID
+{
+ LANG: C
+ OPTIONS: global
+} "Initialisation routine"
+
diff --git a/CarpetDev/CarpetIONirvana/src/CarpetIONirvana.cc b/CarpetDev/CarpetIONirvana/src/CarpetIONirvana.cc
new file mode 100644
index 000000000..47dbe7344
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/src/CarpetIONirvana.cc
@@ -0,0 +1,586 @@
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <iomanip>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "util_Table.h"
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+#include "cctk_Version.h"
+
+#include "CactusBase/IOUtil/src/ioGH.h"
+#include "CactusBase/IOUtil/src/ioutil_CheckpointRecovery.h"
+
+#include "CarpetTimers.hh"
+
+#include "CarpetIONirvana.hh"
+
+#include "defs.hh"
+#include "gh.hh"
+
+
+
+namespace CarpetIONirvana
+{
+
+using namespace std;
+using namespace Carpet;
+using namespace Nirvana;
+
+
+// Variable definitions
+
+// when was the last checkpoint written ?
+static int last_checkpoint_iteration = -1;
+static CCTK_REAL last_checkpoint_walltime;
+
+
+// registered GH extension setup routine
+static void* SetupGH (tFleshConfig* const fleshconfig,
+ const int convLevel, cGH* const cctkGH);
+
+// callbacks for CarpetIOHDF5's I/O method
+static int OutputGH (const cGH* const cctkGH);
+static int OutputVarAs (const cGH* const cctkGH, const char* const varname,
+ const char* const alias);
+static int TimeToOutput (const cGH* const cctkGH, const int vindex);
+static int TriggerOutput (const cGH* const cctkGH, const int vindex);
+
+// general checkpoint routine
+static void Checkpoint (const cGH* const cctkGH, int called_from);
+
+// callback for I/O parameter parsing routine
+static void GetVarIndex (int vindex, const char* optstring, void* arg);
+
+static void CheckSteerableParameters (const cGH *const cctkGH,
+ CarpetIONirvanaGH *myGH);
+
+
+//////////////////////////////////////////////////////////////////////////////
+// public routines
+//////////////////////////////////////////////////////////////////////////////
+
+int CarpetIONirvana_Startup (void)
+{
+ CCTK_RegisterBanner ("Carpet Data Nirvana I/O");
+
+ const int GHExtension = CCTK_RegisterGHExtension (CCTK_THORNSTRING);
+ CCTK_RegisterGHExtensionSetupGH (GHExtension, SetupGH);
+
+ /*IONirvana<0>::Startup();
+ IONirvana<1>::Startup();
+ IONirvana<2>::Startup();*/
+
+ return (0);
+}
+
+
+// Called at basegrid during regular startup
+void CarpetIONirvana_Init (CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS;
+
+ *this_iteration = -1;
+ *next_output_iteration = 0;
+ *next_output_time = cctk_time;
+
+ for (int d=0; d<3; ++d) {
+ this_iteration_slice[d] = 0;
+ last_output_iteration_slice[d] = 0;
+ last_output_time_slice[d] = cctk_time;
+ }
+}
+
+
+
+
+hid_t CCTKtoHDF5_Datatype (const cGH* const cctkGH,
+ int cctk_type, bool single_precision)
+{
+ hid_t retval;
+
+ const CarpetIONirvanaGH *myGH =
+ (CarpetIONirvanaGH *) CCTK_GHExtension (cctkGH, CCTK_THORNSTRING);
+
+ /*switch (cctk_type) {
+
+ case CCTK_VARIABLE_CHAR: retval = HDF5_CHAR; break;
+
+ case CCTK_VARIABLE_INT: retval = HDF5_INT; break;
+#ifdef CCTK_INT1
+ case CCTK_VARIABLE_INT1: retval = H5T_NATIVE_CHAR; break;
+#endif
+#ifdef CCTK_INT2
+ case CCTK_VARIABLE_INT2: retval = H5T_NATIVE_SHORT; break;
+#endif
+#ifdef CCTK_INT4
+ case CCTK_VARIABLE_INT4: retval = H5T_NATIVE_INT; break;
+#endif
+#ifdef CCTK_INT8
+ case CCTK_VARIABLE_INT8: retval = H5T_NATIVE_LLONG; break;
+#endif
+
+ case CCTK_VARIABLE_REAL: retval = HDF5_REAL;
+#ifdef CCTK_REAL4
+ if (single_precision) {
+ retval = H5T_NATIVE_FLOAT;
+ }
+#endif
+ break;
+
+ case CCTK_VARIABLE_COMPLEX: retval = myGH->HDF5_COMPLEX;
+#ifdef CCTK_REAL4
+ if (single_precision) {
+ retval = myGH->HDF5_COMPLEX8;
+ }
+#endif
+ break;
+
+#ifdef CCTK_REAL4
+ case CCTK_VARIABLE_REAL4: retval = H5T_NATIVE_FLOAT; break;
+ case CCTK_VARIABLE_COMPLEX8: retval = myGH->HDF5_COMPLEX8; break;
+#endif
+#ifdef CCTK_REAL8
+ case CCTK_VARIABLE_REAL8: retval = H5T_NATIVE_DOUBLE; break;
+ case CCTK_VARIABLE_COMPLEX16: retval = myGH->HDF5_COMPLEX16; break;
+#endif
+#ifdef CCTK_REAL16
+ case CCTK_VARIABLE_REAL16: retval = H5T_NATIVE_LDOUBLE; break;
+ case CCTK_VARIABLE_COMPLEX32: retval = myGH->HDF5_COMPLEX32; break;
+#endif
+
+ default: CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Unsupported CCTK variable datatype %d", cctk_type);
+ retval = -1;
+ }*/
+
+ return (retval);
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// private routines
+//////////////////////////////////////////////////////////////////////////////
+static void* SetupGH (tFleshConfig* const fleshconfig,
+ const int convLevel, cGH* const cctkGH)
+{
+ DECLARE_CCTK_PARAMETERS;
+
+ int error_count = 0;
+
+ // register CarpetIONirvana's routines as a new I/O method
+ const int IOMethod = CCTK_RegisterIOMethod ("IONirvana");
+ CCTK_RegisterIOMethodOutputGH (IOMethod, OutputGH);
+ CCTK_RegisterIOMethodOutputVarAs (IOMethod, OutputVarAs);
+ CCTK_RegisterIOMethodTimeToOutput (IOMethod, TimeToOutput);
+ CCTK_RegisterIOMethodTriggerOutput (IOMethod, TriggerOutput);
+
+ if (not CCTK_Equals (verbose, "none")) {
+ CCTK_INFO ("I/O Method 'Nirvana': Sending data to Nirvana ");
+ }
+
+ const int numvars = CCTK_NumVars ();
+
+ // allocate a new GH extension structure
+ CarpetIONirvanaGH* myGH = new CarpetIONirvanaGH;
+
+ myGH->requests.resize(numvars);
+ myGH->out_vars = strdup ("");
+ myGH->out_every_default = out_every - 1;
+
+ // initial I/O parameter check
+ myGH->out_dir = 0;
+ myGH->stop_on_parse_errors = strict_io_parameter_check;
+ CheckSteerableParameters (cctkGH, myGH);
+ myGH->stop_on_parse_errors = 0;
+
+
+ return (myGH);
+}
+
+
+static void CheckSteerableParameters (const cGH *const cctkGH,
+ CarpetIONirvanaGH *myGH)
+{
+ DECLARE_CCTK_PARAMETERS;
+
+ // re-parse the 'IOHDF5::out_dir' parameter if it has changed
+ const char *my_out_dir = *out_dir ? out_dir : io_out_dir;
+ char *the_out_dir;
+ if (strcmp (my_out_dir, ".")) {
+ int i = strlen (my_out_dir);
+ if (not strstr (my_out_dir, "%u")) {
+ the_out_dir = (char*) malloc (i + 2);
+ strcpy (the_out_dir, my_out_dir);
+ the_out_dir[i] = '/';
+ the_out_dir[i+1] = 0;
+ } else {
+ // TODO: ensure that there is exactly one "%u" and no other "%"
+ // substrings, except possibly "%%".
+ the_out_dir = (char*) malloc (i + 20);
+ snprintf (the_out_dir, i+19, my_out_dir, dist::rank());
+ strcat (the_out_dir, "/");
+ }
+ } else {
+ the_out_dir = strdup ("");
+ }
+
+ if (not myGH->out_dir or strcmp (the_out_dir, myGH->out_dir)) {
+ free (myGH->out_dir);
+ myGH->out_dir = the_out_dir;
+
+ // create the output directory
+ int result = IOUtil_CreateDirectory (cctkGH, myGH->out_dir,
+ true,
+ dist::rank());
+ if (result < 0) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Problem creating HDF5 output directory '%s'", myGH->out_dir);
+ } else if (result > 0 and CCTK_Equals (verbose, "full")) {
+ CCTK_VInfo (CCTK_THORNSTRING,
+ "HDF5 output directory '%s' already exists", myGH->out_dir);
+ }
+ } else {
+ free (the_out_dir);
+ }
+
+ // re-parse the 'IONirvana::out_vars' parameter if it has changed
+ if (strcmp (out_vars, myGH->out_vars)) {
+#ifdef IOUTIL_PARSER_HAS_OUT_DT
+ IOUtil_ParseVarsForOutput (cctkGH, CCTK_THORNSTRING, "IONirvana::out_vars",
+ myGH->stop_on_parse_errors, out_vars,
+ -1, -1.0, &myGH->requests[0]);
+#else
+ IOUtil_ParseVarsForOutput (cctkGH, CCTK_THORNSTRING, "IONirvana::out_vars",
+ myGH->stop_on_parse_errors, out_vars,
+ -1, &myGH->requests[0]);
+#endif
+
+ // notify the user about the new setting
+ if (not CCTK_Equals (verbose, "none")) {
+ int count = 0;
+ ostringstream msg;
+ msg << "Periodic scalar output requested for:";
+ for (int vi=0; vi<CCTK_NumVars(); ++vi) {
+ if (myGH->requests[vi]) {
+ ++count;
+ char* const fullname = CCTK_FullName(vi);
+ msg << eol << " " << fullname;
+ free (fullname);
+ }
+ }
+ if (count > 0) {
+ CCTK_INFO (msg.str().c_str());
+ }
+ }
+
+ // save the last setting of 'IOHDF5::out_vars' parameter
+ free (myGH->out_vars);
+ myGH->out_vars = strdup (out_vars);
+ }
+}
+
+
+static int OutputGH (const cGH* const cctkGH)
+{
+ static Carpet::Timer timer ("CarpetIONirvana::OutputGH");
+ timer.start();
+ for (int vindex = CCTK_NumVars () - 1; vindex >= 0; vindex--) {
+ if (TimeToOutput (cctkGH, vindex)) {
+ TriggerOutput (cctkGH, vindex);
+ }
+ }
+ timer.stop();
+
+ return (0);
+}
+
+
+static int TimeToOutput (const cGH* const cctkGH, const int vindex)
+{
+ DECLARE_CCTK_ARGUMENTS;
+ DECLARE_CCTK_PARAMETERS;
+
+ const int numvars = CCTK_NumVars();
+ assert (vindex>=0 and vindex<numvars);
+
+ if (CCTK_GroupTypeFromVarI (vindex) != CCTK_GF and not do_global_mode) {
+ return 0;
+ }
+
+ CarpetIONirvanaGH *myGH =
+ (CarpetIONirvanaGH *) CCTK_GHExtension (cctkGH, CCTK_THORNSTRING);
+ CheckSteerableParameters (cctkGH, myGH);
+
+ // check if output for this variable was requested
+ if (not myGH->requests[vindex]) {
+ return (0);
+ }
+
+ // check whether this refinement level should be output
+ if (not (myGH->requests[vindex]->refinement_levels & (1 << reflevel))) {
+ return (0);
+ }
+
+ // check if output for this variable was requested individually
+ // by a "<varname>{ out_every = <number> }" option string
+ // this will overwrite the output criterion setting
+ const char *myoutcriterion = CCTK_EQUALS (out_criterion, "default") ?
+ io_out_criterion : out_criterion;
+ if (myGH->requests[vindex]->out_every >= 0) {
+ myoutcriterion = "divisor";
+ }
+
+ if (CCTK_EQUALS (myoutcriterion, "never")) {
+ return (0);
+ }
+
+ // check whether to output at this iteration
+ bool output_this_iteration = false;
+
+ if (CCTK_EQUALS (myoutcriterion, "iteration")) {
+ int myoutevery = out_every == -2 ? io_out_every : out_every;
+ if (myoutevery > 0) {
+ if (*this_iteration == cctk_iteration) {
+ // we already decided to output this iteration
+ output_this_iteration = true;
+ } else if (cctk_iteration >= *next_output_iteration) {
+ // it is time for the next output
+ output_this_iteration = true;
+ *this_iteration = cctk_iteration;
+ *next_output_iteration = cctk_iteration + myoutevery;
+ }
+ }
+ } else if (CCTK_EQUALS (myoutcriterion, "divisor")) {
+ int myoutevery = out_every == -2 ? io_out_every : out_every;
+ if (myGH->requests[vindex]->out_every >= 0) {
+ myoutevery = myGH->requests[vindex]->out_every;
+ }
+ if (myoutevery > 0 and (cctk_iteration % myoutevery) == 0) {
+ // we already decided to output this iteration
+ output_this_iteration = true;
+ }
+ } else if (CCTK_EQUALS (myoutcriterion, "time")) {
+ CCTK_REAL myoutdt = out_dt == -2 ? io_out_dt : out_dt;
+ if (myoutdt == 0 or *this_iteration == cctk_iteration) {
+ output_this_iteration = true;
+ } else if (myoutdt > 0) {
+ int do_output =
+ (cctk_time / cctk_delta_time >=
+ *next_output_time / cctk_delta_time - 1.0e-12);
+ MPI_Bcast (&do_output, 1, MPI_INT, 0, dist::comm());
+ if (do_output) {
+ // it is time for the next output
+ output_this_iteration = true;
+ *this_iteration = cctk_iteration;
+ *next_output_time = cctk_time + myoutdt;
+ }
+ }
+ }
+
+ return output_this_iteration ? 1 : 0;
+}
+
+
+static int TriggerOutput (const cGH* const cctkGH, const int vindex)
+{
+ DECLARE_CCTK_PARAMETERS;
+ int retval;
+
+ char* const fullname = CCTK_FullName(vindex);
+
+ const int gindex = CCTK_GroupIndexFromVarI(vindex);
+ char* const groupname = CCTK_GroupName(gindex);
+ for (char* p=groupname; *p; ++p) *p=tolower(*p);
+ retval = OutputVarAs (cctkGH, fullname, groupname);
+ free (groupname);
+
+ free (fullname);
+
+ return (retval);
+}
+
+
+static void GetVarIndex (int vindex, const char* optstring, void* arg)
+{
+ if (optstring) {
+ char *fullname = CCTK_FullName (vindex);
+ CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Option string '%s' will be ignored for Nirvana output of "
+ "variable '%s'", optstring, fullname);
+ free (fullname);
+ }
+
+ *((int *) arg) = vindex;
+}
+
+
+static int OutputVarAs (const cGH* const cctkGH, const char* const fullname,
+ const char* const alias)
+{
+ DECLARE_CCTK_ARGUMENTS;
+ DECLARE_CCTK_PARAMETERS;
+
+ int error_count = 0;
+ int vindex = -1;
+
+ if (CCTK_TraverseString (fullname, GetVarIndex, &vindex, CCTK_VAR) < 0) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "error while parsing variable name '%s' (alias name '%s')",
+ fullname, alias);
+ return (-1);
+ }
+
+ if (vindex < 0) {
+ return (-1);
+ }
+
+ const int group = CCTK_GroupIndexFromVarI (vindex);
+ assert (group >= 0);
+ cGroup groupdata;
+ CCTK_GroupData (group, &groupdata);
+ if (groupdata.grouptype == CCTK_SCALAR or groupdata.grouptype == CCTK_ARRAY) {
+ assert (do_global_mode);
+ }
+
+ // get the default I/O request for this variable
+ const CarpetIONirvanaGH *myGH =
+ (CarpetIONirvanaGH *) CCTK_GHExtension (cctkGH, CCTK_THORNSTRING);
+ ioRequest* request = myGH->requests[vindex];
+ if (not request) {
+#ifdef IOUTIL_PARSER_HAS_OUT_DT
+ request = IOUtil_DefaultIORequest (cctkGH, vindex, 1, -1.0);
+#else
+ request = IOUtil_DefaultIORequest (cctkGH, vindex, 1);
+#endif
+ }
+
+ // Get grid hierarchy extentsion from IOUtil
+ const ioGH * const iogh = (const ioGH *) CCTK_GHExtension (cctkGH, "IO");
+ assert (iogh);
+
+
+ // Invent a base file name
+ int ioproc = 0, nfiles = 1;
+ string filename;
+ filename.append (myGH->out_dir);
+ //filename.append (alias);
+ filename.append("cactus-simulation-output");
+ if (not (groupdata.disttype == CCTK_DISTRIB_CONSTANT or
+ dist::size() == 1)) {
+ ioproc = dist::rank();
+ nfiles = dist::size();
+ }
+
+ // check if the file has been created already
+ typedef std::map<string, vector<vector<vector<int> > > > filelist;
+ static filelist created_files;
+ filelist::iterator thisfile = created_files.find (filename);
+ bool is_new_file = thisfile == created_files.end();
+ if (is_new_file) {
+ int const numvars = CCTK_NumVars ();
+ vector<vector<vector<int> > > last_outputs; // [ml][rl][var]
+ last_outputs.resize (mglevels);
+ for (int ml = 0; ml < mglevels; ++ml) {
+ last_outputs[ml].resize (maxreflevels);
+ for (int rl = 0; rl < maxreflevels; ++rl) {
+ last_outputs[ml][rl].resize (numvars, cctk_iteration - 1);
+ }
+ }
+ thisfile = created_files.insert (thisfile,
+ filelist::value_type (filename,
+ last_outputs));
+ assert (thisfile != created_files.end());
+ }
+
+ const int firstvar = CCTK_FirstVarIndexI(group);
+ const int numvars = CCTK_NumVarsInGroupI(group);
+
+ // check if this variable has been output already during this iteration
+ int& last_output = thisfile->second.at(mglevel).at(reflevel).at(vindex);
+ if (last_output == cctk_iteration) {
+ // Has already been output during this iteration
+ if (vindex == firstvar + numvars - 1) {
+ char* 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 < cctk_iteration);
+ last_output = cctk_iteration;
+
+ // Check for storage
+ if (not CCTK_QueryGroupStorageI (cctkGH, group)) {
+ CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Cannot output variable '%s' because it has no storage",
+ fullname);
+ return (0);
+ }
+
+ // Open the output file if this is a designated I/O processor
+ CCTK_REAL io_files = 0;
+ CCTK_REAL io_bytes = 0;
+ BeginTimingIO (cctkGH);
+
+ if (CCTK_Equals (verbose, "full")) {
+ CCTK_VInfo (CCTK_THORNSTRING,
+ "Writing variable '%s' on mglevel %d reflevel %d",
+ fullname, mglevel, reflevel);
+ }
+ for (int var = firstvar; var < firstvar + numvars; var++) {
+ ioRequest* r = myGH->requests[var];
+ if (not r) {
+#ifdef IOUTIL_PARSER_HAS_OUT_DT
+ r = IOUtil_DefaultIORequest (cctkGH, var, 1, -1.0);
+#else
+ r = IOUtil_DefaultIORequest (cctkGH, var, 1);
+#endif
+ }
+ if (groupdata.disttype == CCTK_DISTRIB_CONSTANT) {
+ error_count += WriteVar(cctkGH, filename, ioproc, io_bytes, r);
+ }
+ else
+ error_count += WriteVar(cctkGH, filename, ioproc, io_bytes, r);
+
+ if (r != myGH->requests[var]) IOUtil_FreeIORequest (&r);
+
+ // mark this variable to have been output at this iteration
+ thisfile->second.at(mglevel).at(reflevel).at(var) = cctk_iteration;
+ }
+
+ // free I/O request structure
+ if (request != myGH->requests[vindex]) {
+ IOUtil_FreeIORequest (&request);
+ }
+
+ // Close the file
+
+ EndTimingIO (cctkGH, io_files, io_bytes, true);
+
+ if (error_count > 0 and abort_on_io_errors) {
+ CCTK_WARN (0, "Aborting simulation due to previous I/O errors");
+ }
+
+ return (0);
+}
+
+
+
+
+
+
+} // namespace CarpetIONirvana
diff --git a/CarpetDev/CarpetIONirvana/src/CarpetIONirvana.hh b/CarpetDev/CarpetIONirvana/src/CarpetIONirvana.hh
new file mode 100644
index 000000000..399b37e38
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/src/CarpetIONirvana.hh
@@ -0,0 +1,139 @@
+#ifndef CARPETIONIRVANA_HH
+#define CARPETIONIRVANA_HH
+
+#include "CarpetN5.hh"
+#include "metadata.hh"
+
+#include <vector>
+
+#include "cctk_Arguments.h"
+#include "CactusBase/IOUtil/src/ioutil_Utils.h"
+#include "carpet.hh"
+
+
+
+
+// CarpetIONirvana GH extension structure
+typedef struct
+{
+ // default number of times to output
+ int out_every_default;
+
+ // list of variables to output
+ char *out_vars;
+
+ // stop on I/O parameter parsing errors ?
+ int stop_on_parse_errors;
+
+ // I/O request description list (for all variables)
+ vector<ioRequest*> requests;
+
+ // directory in which to output
+ char *out_dir;
+
+ // ring buffer for list of successfully created cp files
+ int checkpoint_keep;
+ int cp_filename_index;
+ char **cp_filename_list;
+
+ // list of recovery files to remove
+ int recovery_num_filenames;
+ char **recovery_filename_list;
+
+ // iteration number of the last checkpoint
+ int last_checkpoint_iteration;
+
+ // hdf5 datatype for complex variables; to be set at run time
+ hid_t HDF5_COMPLEX, HDF5_COMPLEX8, HDF5_COMPLEX16, HDF5_COMPLEX32;
+
+} CarpetIONirvanaGH;
+
+
+namespace CarpetIONirvana
+{
+
+ // worker routines to write a single variable
+ int WriteVar (const cGH* const cctkGH,
+ const string& filename,
+ const int filenum,
+ CCTK_REAL & io_bytes,
+ const ioRequest* const request);
+
+ // returns an HDF5 datatype corresponding to the given CCTK datatype
+ hid_t CCTKtoHDF5_Datatype (const cGH* const cctkGH,
+ int cctk_type,
+ bool single_precision);
+
+
+ // Everything is a class template, so that it can easily be
+ // instantiated for all output dimensions
+
+/* template<int outdim>
+ struct IONirvana {
+
+ // name of the output directory
+ static char* my_out_slice_dir;
+
+ // list of variables to output
+ static char* my_out_slice_vars;
+
+ // I/O request description list (for all variables)
+ static vector<ioRequest*> slice_requests;
+
+
+
+ // Scheduled functions
+ static int Startup();
+
+ // Registered functions
+ static void* SetupGH (tFleshConfig* fc, int convLevel, cGH* cctkGH);
+
+ static int OutputGH (const cGH* cctkGH);
+ static int OutputVarAs (const cGH* cctkGH,
+ const char* varname, const char* alias);
+ static int TimeToOutput (const cGH* cctkGH, int vindex);
+ static int TriggerOutput (const cGH* cctkGH, int vindex);
+
+ // Other functions
+ static void CheckSteerableParameters (const cGH* cctkGH);
+
+ static bool DidOutput (const cGH* cctkGH,
+ int vindex,
+ string basefilename,
+ bool& is_new_file, bool& truncate_file);
+
+ static bool DirectionIsRequested (const vect<int,outdim>& dirs);
+
+ static void OutputDirection (const cGH* cctkGH,
+ int vindex,
+ string alias,
+ string basefilename,
+ const vect<int,outdim>& dirs,
+ bool is_new_file,
+ bool truncate_file);
+
+
+ static ivect GetOutputOffset (const cGH* cctkGH, int m,
+ const vect<int,outdim>& dirs);
+
+ };*/ // struct IONirvana
+
+ // scheduled routines (must be declared as C according to schedule.ccl)
+ extern "C" {
+
+ int CarpetIONirvana_RecoverParameters (void);
+ int CarpetIONirvana_SetNumRefinementLevels (void);
+ int CarpetIONirvana_Startup (void);
+ void CarpetIONirvana_Init (CCTK_ARGUMENTS);
+ void CarpetIONirvana_InitCheckpointingIntervals (CCTK_ARGUMENTS);
+ void CarpetIONirvana_RecoverGridStructure (CCTK_ARGUMENTS);
+ void CarpetIONirvana_CloseFiles (CCTK_ARGUMENTS);
+ void CarpetIONirvana_InitialDataCheckpoint (CCTK_ARGUMENTS);
+ void CarpetIONirvana_EvolutionCheckpoint (CCTK_ARGUMENTS);
+ void CarpetIONirvana_TerminationCheckpoint (CCTK_ARGUMENTS);
+
+ } // extern "C"
+
+} // namespace CarpetIONirvana
+
+#endif // !defined(CarpetIONirvana_HH)
diff --git a/CarpetDev/CarpetIONirvana/src/Output.cc b/CarpetDev/CarpetIONirvana/src/Output.cc
new file mode 100644
index 000000000..fdcd5b3c5
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/src/Output.cc
@@ -0,0 +1,360 @@
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+#include "util_Table.h"
+
+#include "operators.hh"
+#include "typeprops.hh"
+#include "CarpetIONirvana.hh"
+#include "CactusBase/IOUtil/src/ioGH.h"
+
+
+namespace CarpetIONirvana
+{
+
+using namespace std;
+using namespace Carpet;
+using namespace Nirvana;
+
+
+static int GetMetaData (const cGH *const cctkGH, const char *name,
+ const char *groupname, int filenum,
+ int vdim, int refinementlevel,
+ const ioRequest* request,
+ const ibbox& bbox, metadata& md);
+
+
+
+int WriteVar (const cGH* const cctkGH,
+ const string& filename,
+ const int filenum,
+ CCTK_REAL & io_bytes,
+ const ioRequest* const request)
+{
+ DECLARE_CCTK_PARAMETERS;
+
+ int error_count = 0;
+ char *fullname = CCTK_FullName(request->vindex);
+ const int gindex = CCTK_GroupIndexFromVarI (request->vindex);
+ assert (gindex >= 0 and gindex < (int) Carpet::arrdata.size ());
+ char *groupname = CCTK_GroupName(gindex);
+ const int var = request->vindex - CCTK_FirstVarIndexI (gindex);
+ assert (var >= 0 and var < CCTK_NumVars ());
+ cGroup group;
+ CCTK_GroupData (gindex, &group);
+
+
+ // Scalars and arrays have only one refinement level 0,
+ // regardless of what the current refinement level is.
+ // Output for them must be called in global mode.
+ int refinementlevel = reflevel;
+ if (group.grouptype == CCTK_SCALAR or group.grouptype == CCTK_ARRAY) {
+ assert (do_global_mode);
+ refinementlevel = 0;
+ }
+
+ // HDF5 doesn't like 0-dimensional arrays
+ if (group.grouptype == CCTK_SCALAR) group.dim = 1;
+
+ // Traverse all maps
+ BEGIN_LOCAL_MAP_LOOP (cctkGH, group.grouptype) {
+ BEGIN_LOCAL_COMPONENT_LOOP (cctkGH, group.grouptype) {
+
+ // const ggf* ff = arrdata.at(gindex).at(Carpet::map).data.at(var);
+ // const ibbox& bbox = (*ff) (request->timelevel, refinementlevel,
+ // group.disttype == CCTK_DISTRIB_CONSTANT ?
+ // 0 : component, mglevel)->extent();
+ const dh* dd = arrdata.at(gindex).at(Carpet::map).dd;
+ const ibbox& bbox =
+ dd->light_boxes.AT(mglevel).AT(refinementlevel)
+ .AT(group.disttype == CCTK_DISTRIB_CONSTANT ? 0 : component).exterior;
+
+ // Don't create zero-sized components
+ if (bbox.empty()) continue;
+
+ // As per Cactus convention, DISTRIB=CONSTANT arrays
+ // (including grid scalars) are assumed to be the same on
+ // all processors and are therefore stored only by processor 0.
+ void* data = cctkGH->data[request->vindex][request->timelevel];
+ const void* mydata = data;
+ if (group.disttype == CCTK_DISTRIB_CONSTANT) {
+
+ MPI_Datatype datatype;
+ switch (specific_cactus_type(group.vartype)) {
+#define TYPECASE(N,T) \
+ case N: { T dummy; datatype = dist::mpi_datatype(dummy); } break;
+#include "typecase.hh"
+#undef TYPECASE
+ default: assert (0 and "invalid datatype");
+ }
+
+ const size_t size = bbox.size() * CCTK_VarTypeSize (group.vartype);
+ if (dist::rank() > 0) {
+ data = malloc (size);
+ }
+ MPI_Bcast (data, bbox.size(), datatype, 0, MPI_COMM_WORLD);
+
+ if (memcmp (mydata, data, size)) {
+ CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "values for DISTRIB=CONSTANT grid variable '%s' "
+ "(timelevel %d) differ between processors 0 and %d; "
+ "only the array from processor 0 will be stored",
+ fullname, request->timelevel, component);
+ }
+ }
+
+ vector<double> buffer(bbox.size());
+ for (int i=0; i < bbox.size(); ++i)
+ buffer[i] = ((double* )data)[i];
+
+ // the metadata describing the mesh
+ metadata md;
+
+ error_count += GetMetaData (cctkGH, fullname, groupname, filenum,
+ group.dim, refinementlevel,
+ request, bbox, md);
+
+ //cout << fullname << " " << cctkGH->cctk_iteration << endl;
+ string past_checkpoint = "";
+ const bool write_only = true; // this prevents the file-format to scan existing files
+ CarpetN5 File(filename, write_only, dist::size(), false, past_checkpoint);
+
+ File.WriteMesh(md);
+ File.WriteMesh(md, filenum);
+ File.WriteField<double>(md, buffer);
+ File.WriteField<double>(md, buffer, filenum);
+
+
+ if (data != mydata) free (data);
+
+ } END_LOCAL_COMPONENT_LOOP;
+ } END_LOCAL_MAP_LOOP;
+
+ free (fullname);
+ free (groupname);
+
+
+
+ // return the number of errors that occured during this output
+ return error_count;
+}
+
+
+// add attributes to an HDF5 dataset
+static int GetMetaData (const cGH *const cctkGH, const char *name,
+ const char *groupname, int filenum,
+ int vdim, int refinementlevel,
+ const ioRequest* request,
+ const ibbox& bbox, metadata& md)
+{
+ assert (vdim>=0 and vdim<=dim);
+ int error_count = 0;
+
+ // Get the shape of the dataset
+ vector<int> shape(dim, 0);
+ vector<int> iorigin(dim, 0);
+ for (int d = 0; d < vdim; ++d) {
+ iorigin[d] = (bbox.lower() / bbox.stride())[d];
+ shape[d] = (bbox.shape() / bbox.stride())[d];
+ }
+
+ int size = 3;
+ vector<int> cctk_nghostzones(size);
+ CCTK_GroupnghostzonesVI (cctkGH, size, &cctk_nghostzones[0],
+ request->vindex);
+
+ attribute<int> acycle("cycle", cctkGH->cctk_iteration);
+ attribute<int> areflevel("reflevel", refinementlevel);
+ attribute<int> atimelevel("timelevel", request->timelevel);
+ attribute<int> amap("map", Carpet::map);
+ attribute<int> afilenum("filenum", filenum);
+ attribute<double> atime("time", cctkGH->cctk_time);
+ attribute<vector<int> > alsh("lsh", shape);
+ attribute<vector<int> > aghosts("ghosts", cctk_nghostzones);
+ attribute<vector<int> > aiorigin("iorigin", iorigin);
+ attribute<int> acomp("comp", Carpet::component);
+ attribute<string> avarname("varname", name);
+ attribute<string> avargroupname("vargroupname", groupname);
+ attribute<string> avargrouptype;
+ attribute<string> ameshname;
+ attribute<string> acoordinates;
+ attribute<vector<double> > aorigin;
+ attribute<vector<double> > adelta;
+
+ // Specify whether the coordinate system is Cartesian or not
+ if (CCTK_IsFunctionAliased ("MultiPatch_MapIsCartesian")) {
+ int const map_is_cartesian = MultiPatch_MapIsCartesian (Carpet::map);
+ if (!map_is_cartesian)
+ {
+ ameshname = attribute<string>("meshname", "Curvilinear");
+ acoordinates = attribute<string>("coordinates", "grid::coordinates"); // the group-name of the coordinates
+ }
+ else
+ {
+ ameshname = attribute<string>("meshname", "Carpet-AMR");
+ acoordinates = attribute<string>("coordinates", "none"); // we don't need external coordinates to represent mesh
+ }
+ }
+ else
+ {
+ ameshname = attribute<string>("meshname", "Carpet-AMR");
+ acoordinates = attribute<string>("coordinates", "none"); // we don't need external coordinates to represent mesh
+ }
+
+ // write bbox attributes if we have coordinate system info
+ CCTK_REAL origin[dim], delta[dim];
+ int coord_system_handle = -1;
+ if (CCTK_IsFunctionAliased ("Coord_GroupSystem"))
+ {
+ char *groupname = CCTK_GroupNameFromVarI (request->vindex);
+ coord_system_handle = Coord_GroupSystem (cctkGH, groupname);
+ free (groupname);
+ }
+
+ CCTK_INT coord_handles[dim];
+ if (coord_system_handle >= 0 and
+ Util_TableGetIntArray (coord_system_handle, vdim,
+ coord_handles, "COORDINATES") >= 0) {
+#if 0 // dh::dbases
+ const ibbox& baseext =
+ vdd.at(Carpet::map)->bases.at(mglevel).at(reflevel).exterior;
+#endif
+ const ibbox& baseext =
+ vhh.at(Carpet::map)->baseextents.at(mglevel).at(reflevel);
+
+ const ivect pos = (bbox.lower() - baseext.lower()) / bbox.stride();
+
+ rvect global_lower;
+ rvect coord_delta;
+ const int m = Carpet::map;
+ if (CCTK_GroupTypeFromVarI (request->vindex) == CCTK_GF) {
+ rvect const cctk_origin_space =
+ origin_space.at(m).at(mglevel);
+ rvect const cctk_delta_space =
+ delta_space.at(m) * rvect (mglevelfact);
+ for (int d=0; d<dim; ++d) {
+ // lower boundary of Carpet's integer indexing
+ global_lower[d] = cctk_origin_space[d];
+ // grid spacing of Carpet's integer indexing
+ coord_delta[d] =
+ cctk_delta_space[d] / cctkGH->cctk_levfac[d];
+ }
+ } else {
+ for (int d=0; d<dim; ++d) {
+ global_lower[d] = 0.0;
+ coord_delta[d] = 1.0;
+ }
+ }
+
+ vector<fp> origin(dim, 0);
+ vector<fp> delta(dim, 0);
+ for (int d=0; d<dim; ++d) {
+ origin[d] = global_lower[d] + coord_delta[d] * (cctkGH->cctk_levoff[d] / cctkGH->cctk_levoffdenom[d] + pos[d]);
+ delta[d] = coord_delta[d];
+ }
+
+ aorigin = attribute<vector<fp> >("origin", origin);
+ adelta = attribute<vector<fp> >("delta", delta);
+ }
+
+ // find out tensor type
+ char tensortypealias[100];
+ int table;
+ const int gindex = CCTK_GroupIndexFromVarI (request->vindex);
+ const int numvars = CCTK_NumVarsInGroupI(gindex);
+ assert (numvars>0);
+ table = CCTK_GroupTagsTableI(gindex);
+ assert (table>=0);
+
+ int ierr = Util_TableGetString
+ (table, sizeof tensortypealias, tensortypealias, "tensortypealias");
+ if (ierr == UTIL_ERROR_TABLE_NO_SUCH_KEY) {
+ /* assume a scalar */
+ strcpy (tensortypealias, "scalar");
+ } else if (ierr<0) {
+ char * groupname = CCTK_GroupName(gindex);
+ assert (groupname);
+ CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Error in tensor type alias declaration for group \"%s\"",
+ groupname);
+ free (groupname);
+ }
+
+ if (CCTK_EQUALS (tensortypealias, "scalar")) {
+ /* scalar */
+ avargrouptype = attribute<string>("vargrouptype", "scalar");
+ } else if (CCTK_EQUALS (tensortypealias, "4scalar")) {
+ /* 4-scalar */
+ avargrouptype = attribute<string>("vargrouptype", "4scalar");
+ } else if (CCTK_EQUALS (tensortypealias, "u")
+ || CCTK_EQUALS (tensortypealias, "d")) {
+ /* vector */
+ avargrouptype = attribute<string>("vargrouptype", "vector");
+ assert (numvars == dim);
+ } else if (CCTK_EQUALS (tensortypealias, "4u")
+ || CCTK_EQUALS (tensortypealias, "4d")) {
+ /* 4-vector */
+ avargrouptype = attribute<string>("vargrouptype", "4scalar");
+ assert (numvars == dim+1);
+ } else if (CCTK_EQUALS (tensortypealias, "du")) {
+ /* tensor */
+ avargrouptype = attribute<string>("vargrouptype", "tensor");
+ assert (numvars == dim*dim);
+ } else if (CCTK_EQUALS (tensortypealias, "uu_sym")
+ || CCTK_EQUALS (tensortypealias, "dd_sym")) {
+ /* symmetric tensor */
+ avargrouptype = attribute<string>("vargrouptype", "symmetric-tensor");
+ assert (numvars == dim*(dim+1)/2);
+ } else if (CCTK_EQUALS (tensortypealias, "ddd_sym")) {
+ /* 3rd rank tensor, symmetric in last 2 indices */
+ avargrouptype = attribute<string>("vargrouptype", "rank3-tensor-symmetric");
+ assert (numvars == dim*dim*(dim+1)/2);
+ } else if (CCTK_EQUALS (tensortypealias, "4uu_sym")
+ || CCTK_EQUALS (tensortypealias, "4dd_sym")) {
+ /* symmetric 4-tensor */
+ avargrouptype = attribute<string>("vargrouptype", "4tensor-symmetric");
+ assert (numvars == (dim+1)*(dim+2)/2);
+ } else if (CCTK_EQUALS (tensortypealias, "weylscalars_real")) {
+ /* Weyl scalars, stored as 10 real numbers */
+ avargrouptype = attribute<string>("vargrouptype", "scalar");
+ assert (numvars == 10);
+ } else {
+ char * groupname = CCTK_GroupName(gindex);
+ assert (groupname);
+ CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Illegal tensor type alias for group \"%s\"",
+ groupname);
+ free (groupname);
+ }
+
+ // Append attributes to metadata
+ md << afilenum; // the filenumber that contains the data
+ md << ameshname; // the name of the mesh
+ md << acycle; // the current cycle/iteration
+ md << atime; // the time corresponding to cycle
+ md << amap; // the map
+ md << areflevel; // the refinement level
+ md << atimelevel; // the time level
+ md << acomp; // the grid component
+ md << alsh; // the number of points of the local piece of grid data
+ md << aiorigin; // the integer origin of the grid
+ md << aorigin; // the origin in coordinate space
+ md << adelta; // the delta spacing
+ md << acoordinates; // the name of the coordinate group
+ md << aghosts; // number of ghostzones
+
+ md << avarname; // the name of the variable
+ md << avargroupname; // the name of the variable's group
+ md << avargrouptype; // tensor type
+
+ // return the number of errors that occured during this output
+ return error_count;
+}
+
+
+} // namespace CarpetIONirvana
diff --git a/CarpetDev/CarpetIONirvana/src/make.code.defn b/CarpetDev/CarpetIONirvana/src/make.code.defn
new file mode 100644
index 000000000..c87402a98
--- /dev/null
+++ b/CarpetDev/CarpetIONirvana/src/make.code.defn
@@ -0,0 +1,9 @@
+# Main make.code.defn file for thorn CarpetIONirvana
+
+# Source files in this directory
+SRCS = CarpetIONirvana.cc Output.cc
+
+# Extend CXXFLAGS if HDF5 library was built with LFS support
+ifneq ($(strip $(HDF5_LFS_FLAGS)),)
+ CXXFLAGS += $(HDF5_LFS_FLAGS)
+endif