aboutsummaryrefslogtreecommitdiff
path: root/Carpet
diff options
context:
space:
mode:
authorChristian Reisswig <reisswig@tapir.caltech.edu>2010-08-27 23:04:52 -0700
committerBarry Wardell <barry.wardell@gmail.com>2011-12-14 18:21:15 +0000
commit2205c4de243d010b29f651a4ecd51c32e7b161bb (patch)
tree5fdc7d9bbfdf6ef220cdcddaa01cd38580dadf03 /Carpet
parent15e8a3f30f3dfdb70ecda83c4813383a39475b89 (diff)
New Nirvana file format.
Datasets are properly output. Current Issues: Assumes double output for now (can be more generic, however). If files exist, attributes, datasets are not overwritten and writer crashes. These are minor problems and they can be fixed easily. I just wanted to have a first 'working' copy comitted.
Diffstat (limited to 'Carpet')
-rw-r--r--Carpet/CarpetIONirvana/README9
-rw-r--r--Carpet/CarpetIONirvana/configuration.ccl5
-rw-r--r--Carpet/CarpetIONirvana/doc/documentation.tex144
-rw-r--r--Carpet/CarpetIONirvana/interface.ccl88
-rw-r--r--Carpet/CarpetIONirvana/param.ccl70
-rw-r--r--Carpet/CarpetIONirvana/schedule.ccl16
-rw-r--r--Carpet/CarpetIONirvana/src/CarpetIONirvana.cc586
-rw-r--r--Carpet/CarpetIONirvana/src/CarpetIONirvana.hh139
-rw-r--r--Carpet/CarpetIONirvana/src/Output.cc351
-rw-r--r--Carpet/CarpetIONirvana/src/make.code.defn9
10 files changed, 1417 insertions, 0 deletions
diff --git a/Carpet/CarpetIONirvana/README b/Carpet/CarpetIONirvana/README
new file mode 100644
index 000000000..3df3e34b4
--- /dev/null
+++ b/Carpet/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/Carpet/CarpetIONirvana/configuration.ccl b/Carpet/CarpetIONirvana/configuration.ccl
new file mode 100644
index 000000000..ef2b9dc15
--- /dev/null
+++ b/Carpet/CarpetIONirvana/configuration.ccl
@@ -0,0 +1,5 @@
+# Configuration definitions for thorn CarpetIONirvana
+
+REQUIRES Carpet CarpetLib IOUtil #Nirvana
+
+REQUIRES THORNS: Carpet CarpetLib IOUtil
diff --git a/Carpet/CarpetIONirvana/doc/documentation.tex b/Carpet/CarpetIONirvana/doc/documentation.tex
new file mode 100644
index 000000000..174f3b185
--- /dev/null
+++ b/Carpet/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/Carpet/CarpetIONirvana/interface.ccl b/Carpet/CarpetIONirvana/interface.ccl
new file mode 100644
index 000000000..400f6d003
--- /dev/null
+++ b/Carpet/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/Carpet/CarpetIONirvana/param.ccl b/Carpet/CarpetIONirvana/param.ccl
new file mode 100644
index 000000000..88529f70e
--- /dev/null
+++ b/Carpet/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/Carpet/CarpetIONirvana/schedule.ccl b/Carpet/CarpetIONirvana/schedule.ccl
new file mode 100644
index 000000000..5154cb400
--- /dev/null
+++ b/Carpet/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/Carpet/CarpetIONirvana/src/CarpetIONirvana.cc b/Carpet/CarpetIONirvana/src/CarpetIONirvana.cc
new file mode 100644
index 000000000..47dbe7344
--- /dev/null
+++ b/Carpet/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/Carpet/CarpetIONirvana/src/CarpetIONirvana.hh b/Carpet/CarpetIONirvana/src/CarpetIONirvana.hh
new file mode 100644
index 000000000..e13385dad
--- /dev/null
+++ b/Carpet/CarpetIONirvana/src/CarpetIONirvana.hh
@@ -0,0 +1,139 @@
+#ifndef CARPETIOHDF5_HH
+#define CARPETIOHDF5_HH
+
+#include "/home/reisswig/Cactus/arrangements/ExternalLibraries/Nirvana/CarpetN5.hh"
+#include "/home/reisswig/Cactus/arrangements/ExternalLibraries/Nirvana/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/Carpet/CarpetIONirvana/src/Output.cc b/Carpet/CarpetIONirvana/src/Output.cc
new file mode 100644
index 000000000..fce780e29
--- /dev/null
+++ b/Carpet/CarpetIONirvana/src/Output.cc
@@ -0,0 +1,351 @@
+#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;
+ CarpetN5 File(filename, dist::size(), false);
+
+ 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];
+ }
+
+ 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> > 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", "Multiblock");
+ 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 << 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/Carpet/CarpetIONirvana/src/make.code.defn b/Carpet/CarpetIONirvana/src/make.code.defn
new file mode 100644
index 000000000..c87402a98
--- /dev/null
+++ b/Carpet/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