From 4afda80c0ed50b919bca31c00bc0fb5221cc523c Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Fri, 10 Sep 2010 13:38:17 -0500 Subject: CarpetIONirvana: Move from Carpet to CarpetDev arrangement --- CarpetDev/CarpetIONirvana/README | 9 + CarpetDev/CarpetIONirvana/configuration.ccl | 5 + CarpetDev/CarpetIONirvana/doc/documentation.tex | 144 ++++++ CarpetDev/CarpetIONirvana/interface.ccl | 88 ++++ CarpetDev/CarpetIONirvana/param.ccl | 70 +++ CarpetDev/CarpetIONirvana/schedule.ccl | 16 + CarpetDev/CarpetIONirvana/src/CarpetIONirvana.cc | 586 +++++++++++++++++++++++ CarpetDev/CarpetIONirvana/src/CarpetIONirvana.hh | 139 ++++++ CarpetDev/CarpetIONirvana/src/Output.cc | 360 ++++++++++++++ CarpetDev/CarpetIONirvana/src/make.code.defn | 9 + 10 files changed, 1426 insertions(+) create mode 100644 CarpetDev/CarpetIONirvana/README create mode 100644 CarpetDev/CarpetIONirvana/configuration.ccl create mode 100644 CarpetDev/CarpetIONirvana/doc/documentation.tex create mode 100644 CarpetDev/CarpetIONirvana/interface.ccl create mode 100644 CarpetDev/CarpetIONirvana/param.ccl create mode 100644 CarpetDev/CarpetIONirvana/schedule.ccl create mode 100644 CarpetDev/CarpetIONirvana/src/CarpetIONirvana.cc create mode 100644 CarpetDev/CarpetIONirvana/src/CarpetIONirvana.hh create mode 100644 CarpetDev/CarpetIONirvana/src/Output.cc create mode 100644 CarpetDev/CarpetIONirvana/src/make.code.defn (limited to 'CarpetDev') 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 +Maintainer(s): Christian Reisswig +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; virequests[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 vindexrequests[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 "{ out_every = }" 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 > > > 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 > > 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 + +#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 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 + 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 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& dirs); + + static void OutputDirection (const cGH* cctkGH, + int vindex, + string alias, + string basefilename, + const vect& dirs, + bool is_new_file, + bool truncate_file); + + + static ivect GetOutputOffset (const cGH* cctkGH, int m, + const vect& 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 +#include +#include +#include + +#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 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(md, buffer); + File.WriteField(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 shape(dim, 0); + vector 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 cctk_nghostzones(size); + CCTK_GroupnghostzonesVI (cctkGH, size, &cctk_nghostzones[0], + request->vindex); + + attribute acycle("cycle", cctkGH->cctk_iteration); + attribute areflevel("reflevel", refinementlevel); + attribute atimelevel("timelevel", request->timelevel); + attribute amap("map", Carpet::map); + attribute afilenum("filenum", filenum); + attribute atime("time", cctkGH->cctk_time); + attribute > alsh("lsh", shape); + attribute > aghosts("ghosts", cctk_nghostzones); + attribute > aiorigin("iorigin", iorigin); + attribute acomp("comp", Carpet::component); + attribute avarname("varname", name); + attribute avargroupname("vargroupname", groupname); + attribute avargrouptype; + attribute ameshname; + attribute acoordinates; + attribute > aorigin; + attribute > 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("meshname", "Curvilinear"); + acoordinates = attribute("coordinates", "grid::coordinates"); // the group-name of the coordinates + } + else + { + ameshname = attribute("meshname", "Carpet-AMR"); + acoordinates = attribute("coordinates", "none"); // we don't need external coordinates to represent mesh + } + } + else + { + ameshname = attribute("meshname", "Carpet-AMR"); + acoordinates = attribute("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; dcctk_levfac[d]; + } + } else { + for (int d=0; d origin(dim, 0); + vector delta(dim, 0); + for (int d=0; dcctk_levoff[d] / cctkGH->cctk_levoffdenom[d] + pos[d]); + delta[d] = coord_delta[d]; + } + + aorigin = attribute >("origin", origin); + adelta = attribute >("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("vargrouptype", "scalar"); + } else if (CCTK_EQUALS (tensortypealias, "4scalar")) { + /* 4-scalar */ + avargrouptype = attribute("vargrouptype", "4scalar"); + } else if (CCTK_EQUALS (tensortypealias, "u") + || CCTK_EQUALS (tensortypealias, "d")) { + /* vector */ + avargrouptype = attribute("vargrouptype", "vector"); + assert (numvars == dim); + } else if (CCTK_EQUALS (tensortypealias, "4u") + || CCTK_EQUALS (tensortypealias, "4d")) { + /* 4-vector */ + avargrouptype = attribute("vargrouptype", "4scalar"); + assert (numvars == dim+1); + } else if (CCTK_EQUALS (tensortypealias, "du")) { + /* tensor */ + avargrouptype = attribute("vargrouptype", "tensor"); + assert (numvars == dim*dim); + } else if (CCTK_EQUALS (tensortypealias, "uu_sym") + || CCTK_EQUALS (tensortypealias, "dd_sym")) { + /* symmetric tensor */ + avargrouptype = attribute("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("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("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("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 -- cgit v1.2.3