diff options
author | Erik Schnetter <schnetter@aei.mpg.de> | 2005-04-25 16:10:00 +0000 |
---|---|---|
committer | Erik Schnetter <schnetter@aei.mpg.de> | 2005-04-25 16:10:00 +0000 |
commit | c3697a07c1256db7185c24750a4d3ca0506436d4 (patch) | |
tree | 207d09d80c0a369522f3ab83677d46fd8f0fa86d /CarpetDev/CarpetIOF5 | |
parent | 384d2acbe1f33481841c38823853fbd22976903c (diff) |
CarpetIOF5: Start an I/O thorn that uses the F5 file format
darcs-hash:20050425161012-891bb-e7d03751330723d007d3dc97b0d56addc3ccda48.gz
Diffstat (limited to 'CarpetDev/CarpetIOF5')
27 files changed, 1952 insertions, 0 deletions
diff --git a/CarpetDev/CarpetIOF5/README b/CarpetDev/CarpetIOF5/README new file mode 100644 index 000000000..db04ce1ad --- /dev/null +++ b/CarpetDev/CarpetIOF5/README @@ -0,0 +1,8 @@ +Cactus Code Thorn CarpetIOF5 +Thorn Author(s) : Erik Schnetter <schnetter@aei.mpg.de> +Thorn Maintainer(s) : Erik Schnetter <schnetter@aei.mpg.de> +-------------------------------------------------------------------------- + +Purpose of the thorn: + +Input and output data using the HDF5 based F5 file format. diff --git a/CarpetDev/CarpetIOF5/configuration.ccl b/CarpetDev/CarpetIOF5/configuration.ccl new file mode 100644 index 000000000..b098a4df2 --- /dev/null +++ b/CarpetDev/CarpetIOF5/configuration.ccl @@ -0,0 +1,3 @@ +# Configuration definitions for thorn CarpetIOF5 + +REQUIRES CarpetLib HDF5 IOUtil diff --git a/CarpetDev/CarpetIOF5/doc/documentation.tex b/CarpetDev/CarpetIOF5/doc/documentation.tex new file mode 100644 index 000000000..9d8b3d19e --- /dev/null +++ b/CarpetDev/CarpetIOF5/doc/documentation.tex @@ -0,0 +1,144 @@ +% *======================================================================* +% Cactus Thorn template for ThornGuide documentation +% Author: Ian Kelley +% Date: Sun Jun 02, 2002 +% $Header: /cactusdevcvs/Cactus/doc/ThornGuide/template.tex,v 1.12 2004/01/07 20:12:39 rideout Exp $ +% +% 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: /cactusdevcvs/Cactus/doc/ThornGuide/template.tex,v 1.12 2004/01/07 20:12:39 rideout Exp $ + +\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{Erik Schnetter \textless schnetter@aei.mpg.de\textgreater} + +% The title of the document (not necessarily the name of the Thorn) +\title{} + +% the date your document was last changed, if your document is in CVS, +% please use: +% \date{$ $Date: 2004/01/07 20:12:39 $ $} +\date{April 24 2005} + +\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/CarpetIOF5/interface.ccl b/CarpetDev/CarpetIOF5/interface.ccl new file mode 100644 index 000000000..a5cfb62ea --- /dev/null +++ b/CarpetDev/CarpetIOF5/interface.ccl @@ -0,0 +1,23 @@ +# Interface definition for thorn CarpetIOF5 + +IMPLEMENTS: IOF5 + +USES INCLUDE: bbox.hh defs.hh vect.hh + + + +CCTK_INT next_output_iteration TYPE=scalar +CCTK_REAL next_output_time TYPE=scalar +CCTK_INT this_iteration TYPE=scalar + + + +CCTK_INT FUNCTION Coord_GroupSystem \ + (CCTK_POINTER_TO_CONST IN cctkGH, \ + CCTK_STRING IN groupname) +REQUIRES FUNCTION Coord_GroupSystem + +# Check whether existing output files should be truncated or not +CCTK_INT FUNCTION IO_TruncateOutputFiles \ + (CCTK_POINTER_TO_CONST IN cctkGH) +REQUIRES FUNCTION IO_TruncateOutputFiles diff --git a/CarpetDev/CarpetIOF5/param.ccl b/CarpetDev/CarpetIOF5/param.ccl new file mode 100644 index 000000000..726a09b0d --- /dev/null +++ b/CarpetDev/CarpetIOF5/param.ccl @@ -0,0 +1,17 @@ +# Parameter definitions for thorn CarpetIOF5 + +STRING out_dir "Output directory, overrides 'IO::out_dir'" STEERABLE = ALWAYS +{ + "^$" :: "Empty: use IO::out_dir" + ".+" :: "Not empty: directory name" +} "" + +STRING out_extension "File extension for CarpetIOF5 output" STEERABLE = ALWAYS +{ + ".*" :: "File extension (including a leading dot, if desired)" +} ".f5" + +STRING out_vars "Variables and groups which should be output in the F5 file format" STEERABLE = ALWAYS +{ + .* :: "List of group or variable names" +} "" diff --git a/CarpetDev/CarpetIOF5/schedule.ccl b/CarpetDev/CarpetIOF5/schedule.ccl new file mode 100644 index 000000000..0d936d041 --- /dev/null +++ b/CarpetDev/CarpetIOF5/schedule.ccl @@ -0,0 +1 @@ +# Schedule definitions for thorn CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/coordinate_system.cc b/CarpetDev/CarpetIOF5/src/coordinate_system.cc new file mode 100644 index 000000000..c0371f0ca --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/coordinate_system.cc @@ -0,0 +1,132 @@ +#include <sstream> + +#include <hdf5.h> + +#include "cctk.h" + +#include "coordinate_system.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + coordinate_system_t:: + coordinate_system_t (topology_t & topology) + : m_topology (topology) + { + } + + + + coordinate_system_t:: + ~ coordinate_system_t () + { + } + + + + hid_t coordinate_system_t:: + get_hdf5_coordinate_system () + const + { + return m_hdf5_coordinate_system; + } + + + + bool coordinate_system_t:: + invariant () + const + { + return true; + } + + + + Cartesian_coordinate_system_t:: + Cartesian_coordinate_system_t (topology_t & topology, + vect<CCTK_REAL, dim> const & level_origin, + vect<CCTK_REAL, dim> const & level_delta) + : coordinate_system_t (topology), + m_level_origin (level_origin), + m_level_delta (level_delta) + { + assert (all (m_level_delta > 0)); + + init(); + + assert (invariant()); + } + + + + Cartesian_coordinate_system_t:: + Cartesian_coordinate_system_t (topology_t & topology, + vect<CCTK_REAL, dim> const & coarse_origin, + vect<CCTK_REAL, dim> const & coarse_delta, + vect<int, dim> const & level_offset, + vect<int, dim> const & level_offset_denominator) + : coordinate_system_t (topology) + { + assert (all (coarse_delta > 0)); + assert (all (level_offset_denominator > 0)); + + mesh_refinement_topology_t * mesh_refinement_topology + = dynamic_cast<mesh_refinement_topology_t *> (& topology); + assert (mesh_refinement_topology != 0); + mesh_refinement_topology + ->calculate_level_origin_delta (coarse_origin, coarse_delta, + level_offset, level_offset_denominator, + m_level_origin, m_level_delta); + + init(); + + assert (invariant()); + } + + + + Cartesian_coordinate_system_t:: + ~ Cartesian_coordinate_system_t () + { + herr_t const herr = H5Gclose (m_hdf5_coordinate_system); + assert (! herr); + } + + + + void Cartesian_coordinate_system_t:: + init () + { + assert (all (m_level_delta > 0)); + + ostringstream buf; + buf << "Cartesian 3D, x0=" << m_level_origin << ", dx=" << m_level_delta; + char const * const name = buf.str().c_str(); + + m_hdf5_coordinate_system + = open_or_create_group (m_topology.get_hdf5_topology(), name); + assert (m_hdf5_coordinate_system >= 0); + + write_or_check_attribute + (m_hdf5_coordinate_system, "origin", m_level_origin); + write_or_check_attribute + (m_hdf5_coordinate_system, "delta", m_level_delta); + } + + + + bool Cartesian_coordinate_system_t:: + invariant () + const + { + return (coordinate_system_t::invariant() + and all (m_level_delta > 0)); + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/coordinate_system.hh b/CarpetDev/CarpetIOF5/src/coordinate_system.hh new file mode 100644 index 000000000..c0362119e --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/coordinate_system.hh @@ -0,0 +1,83 @@ +#ifndef COORDINATE_SYSTEM_HH +#define COORDINATE_SYSTEM_HH + +#include <hdf5.h> + +#include "cctk.h" + +#include "defs.hh" +#include "vect.hh" + +#include "topology.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + class coordinate_system_t { + + protected: + + topology_t & m_topology; + + hid_t m_hdf5_coordinate_system; + + coordinate_system_t (topology_t & topology); + + public: + + virtual + ~ coordinate_system_t (); + + hid_t + get_hdf5_coordinate_system () + const; + + virtual bool + invariant () + const; + + }; + + + + class Cartesian_coordinate_system_t : public coordinate_system_t { + + vect<CCTK_REAL, dim> m_level_origin; + vect<CCTK_REAL, dim> m_level_delta; + + public: + + Cartesian_coordinate_system_t (topology_t & topology, + vect<CCTK_REAL, dim> const & level_origin, + vect<CCTK_REAL, dim> const & level_delta); + + Cartesian_coordinate_system_t (topology_t & topology, + vect<CCTK_REAL, dim> const & coarse_origin, + vect<CCTK_REAL, dim> const & coarse_delta, + vect<int, dim> const & level_offset, + vect<int, dim> const & level_offset_denominator); + + private: + + void + init (); + + public: + + virtual + ~ Cartesian_coordinate_system_t (); + + virtual bool + invariant () + const; + + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef COORDINATE_SYSTEM_HH diff --git a/CarpetDev/CarpetIOF5/src/data_region.cc b/CarpetDev/CarpetIOF5/src/data_region.cc new file mode 100644 index 000000000..77fe28485 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/data_region.cc @@ -0,0 +1,124 @@ +#include <cassert> +#include <cstdlib> +#include <sstream> + +#include "cctk.h" + +#include "data_region.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + using std::ostringstream; + + + + data_region_t:: + data_region_t (tensor_component_t & tensor_component, + bbox<int, dim> const & region) + : m_tensor_component (tensor_component), + m_region (region) + { + assert (! region.empty()); + + ostringstream buf; + buf << "Region " << m_region; + char const * const name = buf.str().c_str(); + assert (name != 0); + + int const vartype = CCTK_VarTypeI (m_tensor_component.get_variable()); + assert (vartype >= 0); + hid_t const datatype = hdf5_datatype_from_cactus (vartype); + assert (datatype >= 0); + + m_properties = H5Pcreate (H5P_DATASET_CREATE); + assert (m_properties >= 0); + + vect<hsize_t, dim> const dims + = (region.shape() / region.stride()).reverse(); + m_dataspace = H5Screate_simple (dim, & dims [0], & dims [0]); + assert (m_dataspace >= 0); + + m_dataset + = H5Dcreate (m_dataspace, name, datatype, m_dataspace, m_properties); + assert (m_dataset >= 0); + + write_or_check_attribute + (m_dataset, "iorigin", region.lower() / region.stride()); + + assert (invariant()); + } + + + + data_region_t:: + ~ data_region_t () + { + herr_t herr; + + herr = H5Dclose (m_dataset); + assert (! herr); + + herr = H5Sclose (m_dataspace); + assert (! herr); + + herr = H5Pclose (m_properties); + assert (! herr); + } + + + + template<typename T> + void data_region_t:: + write (T const * const data) + const + { + T dummy; + hid_t const memory_datatype = hdf5_datatype (dummy); + assert (memory_datatype >= 0); + + vect<hsize_t, dim> const dims + = (m_region.shape() / m_region.stride()).reverse(); + hid_t const memory_dataspace + = H5Screate_simple (dim, & dims [0], & dims [0]); + assert (memory_dataspace >= 0); + + hid_t const transfer_properties = H5Pcreate (H5P_DATASET_XFER); + assert (transfer_properties >= 0); + + herr_t herr; + herr + = H5Dwrite (m_dataset, memory_datatype, memory_dataspace, + m_dataspace, transfer_properties, data); + assert (! herr); + + herr = H5Pclose (transfer_properties); + assert (! herr); + + herr = H5Sclose (memory_dataspace); + assert (! herr); + } + + template void data_region_t::write (CCTK_INT const * const data) const; + template void data_region_t::write (CCTK_REAL const * const data) const; + template void data_region_t::write (CCTK_COMPLEX const * const data) const; + + + + bool data_region_t:: + invariant () + const + { + return (! m_region.empty() + and m_properties >= 0 + and m_dataset >= 0 + and m_dataspace >= 0); + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/data_region.hh b/CarpetDev/CarpetIOF5/src/data_region.hh new file mode 100644 index 000000000..f7c1713cc --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/data_region.hh @@ -0,0 +1,50 @@ +#ifndef DATA_REGION_HH +#define DATA_REGION_HH + +#include <hdf5.h> + +#include "bbox.hh" +#include "defs.hh" + +#include "tensor_component.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + class data_region_t { + + tensor_component_t & m_tensor_component; + + bbox<int, dim> const m_region; + + hid_t m_properties; + hid_t m_dataset; + hid_t m_dataspace; + + public: + + data_region_t (tensor_component_t & tensor_component, + bbox<int, dim> const & region); + + virtual + ~ data_region_t (); + + template<typename T> + void + write (T const * data) + const; + + virtual bool + invariant () + const; + + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef DATA_REGION_HH diff --git a/CarpetDev/CarpetIOF5/src/extending.cc b/CarpetDev/CarpetIOF5/src/extending.cc new file mode 100644 index 000000000..129a96847 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/extending.cc @@ -0,0 +1,50 @@ +#include <cassert> + +#include "cctk.h" + +#include "extending.hh" + + + +namespace CarpetIOF5 { + + char const * const extending:: + extension_name = "CarpetIOF5"; + + void extending:: + create (cGH * cctkGH) + { + assert (cctkGH); + int const handle = CCTK_RegisterGHExtension (extension_name); + assert (handle >= 0); + int const ierr = CCTK_RegisterGHExtensionSetupGH (handle, setup); + assert (! ierr); + } + + void * extending:: + setup (tFleshConfig * const config, + int const convlevel, + cGH * const cctkGH) + { + assert (config); + assert (cctkGH); + return new extension_t; + } + + extending:: + extending (cGH const * cctkGH) + { + assert (cctkGH); + void * const ext = CCTK_GHExtension (cctkGH, extension_name); + assert (ext != 0); + m_extension = static_cast<extension_t *> (ext); + } + + set<char const *> extending:: + get_did_truncate() + const + { + return m_extension->did_truncate; + } + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/extending.hh b/CarpetDev/CarpetIOF5/src/extending.hh new file mode 100644 index 000000000..5d25aaabd --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/extending.hh @@ -0,0 +1,50 @@ +#ifndef EXTENDING_HH +#define EXTENDING_HH + +#include <set> + +#include "cctk.h" + + + +namespace CarpetIOF5 { + + using std::set; + + + + class extending { + + static char const * const extension_name; + + struct extension_t { + set<char const *> did_truncate; + }; + + extension_t * m_extension; + + public: + + static void + create (cGH * cctkGH); + + private: + + static void * + setup (tFleshConfig * config, + int convlevel, + cGH * cctkGH); + + public: + + extending (cGH const * cctkGH); + + set<char const *> + get_did_truncate () + const; + + }; + +} // namespace CarpetIOF5 + +#endif // #ifndef EXDENDING_HH diff --git a/CarpetDev/CarpetIOF5/src/file.cc b/CarpetDev/CarpetIOF5/src/file.cc new file mode 100644 index 000000000..987592383 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/file.cc @@ -0,0 +1,81 @@ +#include <cassert> + +#include <hdf5.h> + +#include "cctk.h" + +#include "file.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + file_t:: + file_t (cGH const * const cctkGH, + char const * const filename) + : m_cctkGH (cctkGH), + m_filename (filename) + { + assert (cctkGH); + assert (filename); + + extending extension (cctkGH); + + bool const should_truncate = IO_TruncateOutputFiles (cctkGH); + + bool const did_truncate + = (extension.get_did_truncate().find (filename) + != extension.get_did_truncate().end()); + + htri_t is_hdf5 = H5Fis_hdf5 (filename); + assert (is_hdf5 >= 0); + bool const file_exists = is_hdf5 > 0; + + if ((should_truncate and ! did_truncate) or ! file_exists) + { + m_hdf5_file + = H5Fcreate (filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + extension.get_did_truncate().insert (filename); + } + else + { + m_hdf5_file = H5Fopen (filename, H5F_ACC_RDWR, H5P_DEFAULT); + } + + assert (invariant()); + } + + + + file_t:: + ~ file_t() + { + herr_t const herr = H5Fclose (m_hdf5_file); + assert (! herr); + } + + + + hid_t file_t:: + get_hdf5_file() + const + { + return m_hdf5_file; + } + + + + bool file_t:: + invariant() + const + { + return (m_cctkGH != 0 + and m_filename != 0 + and m_hdf5_file >= 0); + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/file.hh b/CarpetDev/CarpetIOF5/src/file.hh new file mode 100644 index 000000000..73c3b8508 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/file.hh @@ -0,0 +1,45 @@ +#ifndef FILE_HH +#define FILE_HH + +#include <hdf5.h> + +#include "cctk.h" + +#include "extending.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + class file_t { + + cGH const * const m_cctkGH; + + char const * const m_filename; + + hid_t m_hdf5_file; + + public: + + file_t (cGH const * cctkGH, + char const * filename); + + virtual + ~ file_t (); + + hid_t + get_hdf5_file () + const; + + virtual bool + invariant () + const; + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef FILE_HH diff --git a/CarpetDev/CarpetIOF5/src/make.code.defn b/CarpetDev/CarpetIOF5/src/make.code.defn new file mode 100644 index 000000000..bed641c27 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/make.code.defn @@ -0,0 +1,15 @@ +# Main make.code.defn file for thorn CarpetIOF5 + +# Source files in this directory +SRCS = coordinate_system.cc \ + data_region.cc \ + extending.cc file.cc \ + physical_quantity.cc \ + simulation.cc \ + tensor_component.cc \ + timestep.cc \ + topology.cc \ + utils.cc + +# Subdirectories containing source files +SUBDIRS = diff --git a/CarpetDev/CarpetIOF5/src/physical_quantity.cc b/CarpetDev/CarpetIOF5/src/physical_quantity.cc new file mode 100644 index 000000000..0d6640442 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/physical_quantity.cc @@ -0,0 +1,67 @@ +#include <cassert> +#include <cstdlib> + +#include "cctk.h" + +#include "physical_quantity.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + physical_quantity_t:: + physical_quantity_t (coordinate_system_t & coordinate_system, + int const group) + : m_coordinate_system (coordinate_system), + m_group (group) + { + assert (group >= 0 and group < CCTK_NumGroups()); + + char * const name = CCTK_GroupName (group); + assert (name != 0); + + m_hdf5_physical_quantity + = open_or_create_group (m_coordinate_system + .get_hdf5_coordinate_system(), + name); + assert (m_hdf5_physical_quantity >= 0); + + free (name); + + assert (invariant()); + } + + + + physical_quantity_t:: + ~ physical_quantity_t () + { + herr_t const herr = H5Gclose (m_hdf5_physical_quantity); + assert (! herr); + } + + + + hid_t physical_quantity_t:: + get_hdf5_physical_quantity () + const + { + return m_hdf5_physical_quantity; + } + + + + bool physical_quantity_t:: + invariant () + const + { + return (m_group >= 0 and m_group < CCTK_NumGroups() + and m_hdf5_physical_quantity >= 0); + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/physical_quantity.hh b/CarpetDev/CarpetIOF5/src/physical_quantity.hh new file mode 100644 index 000000000..9367c8dd0 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/physical_quantity.hh @@ -0,0 +1,44 @@ +#ifndef PHYSICAL_QUANTITY_HH +#define PHYSICAL_QUANTITY_HH + +#include <hdf5.h> + +#include "coordinate_system.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + class physical_quantity_t { + + coordinate_system_t & m_coordinate_system; + + int const m_group; + + hid_t m_hdf5_physical_quantity; + + public: + + physical_quantity_t (coordinate_system_t & coordinate_system, + int group); + + virtual + ~ physical_quantity_t (); + + hid_t + get_hdf5_physical_quantity () + const; + + virtual bool + invariant () + const; + + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef PHYSICAL_QUANTITY_HH diff --git a/CarpetDev/CarpetIOF5/src/simulation.cc b/CarpetDev/CarpetIOF5/src/simulation.cc new file mode 100644 index 000000000..7db365ddd --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/simulation.cc @@ -0,0 +1,68 @@ +#include <cassert> +#include <string> +#include <sstream> + +#include <hdf5.h> + +#include "cctk.h" + +#include "simulation.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + using std::ostringstream; + + + + simulation_t:: + simulation_t (timestep_t & timestep, + char const * const name) + : m_timestep (timestep) + { + ostringstream buf; + buf << name; + m_name = buf.str(); + + m_hdf5_simulation + = open_or_create_group (m_timestep.get_hdf5_timestep(), + m_name.c_str()); + assert (m_hdf5_simulation >= 0); + + assert (invariant()); + } + + + + simulation_t:: + ~ simulation_t() + { + herr_t const herr = H5Gclose (m_hdf5_simulation); + assert (! herr); + } + + + + hid_t simulation_t:: + get_hdf5_simulation() + const + { + return m_hdf5_simulation; + } + + + + bool simulation_t:: + invariant() + const + { + return m_hdf5_simulation >= 0; + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/simulation.hh b/CarpetDev/CarpetIOF5/src/simulation.hh new file mode 100644 index 000000000..33be7c2cf --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/simulation.hh @@ -0,0 +1,50 @@ +#ifndef SIMULATION_HH +#define SIMULATION_HH + +#include <set> +#include <string> + +#include <hdf5.h> + +#include "cctk.h" + +#include "timestep.hh" + + + +namespace CarpetIOF5 { + + using std::string; + + namespace F5 { + + class simulation_t { + + timestep_t & m_timestep; + + string m_name; + + hid_t m_hdf5_simulation; + + public: + + simulation_t (timestep_t & timestep, + char const * name); + + virtual + ~ simulation_t (); + + hid_t + get_hdf5_simulation () + const; + + virtual bool + invariant () + const; + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef SIMULATION_HH diff --git a/CarpetDev/CarpetIOF5/src/tensor_component.cc b/CarpetDev/CarpetIOF5/src/tensor_component.cc new file mode 100644 index 000000000..37d013e18 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/tensor_component.cc @@ -0,0 +1,76 @@ +#include <cassert> +#include <cstdlib> + +#include "cctk.h" + +#include "tensor_component.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + tensor_component_t:: + tensor_component_t (physical_quantity_t & physical_quantity, + int const variable) + : m_physical_quantity (physical_quantity), + m_variable (variable) + { + assert (variable >= 0 and variable < CCTK_NumVars()); + + char * const name = CCTK_FullName (variable); + assert (name != 0); + + m_hdf5_tensor_component + = open_or_create_group (m_physical_quantity + .get_hdf5_physical_quantity(), + name); + assert (m_hdf5_tensor_component >= 0); + + free (name); + + assert (invariant()); + } + + + + tensor_component_t:: + ~ tensor_component_t () + { + herr_t const herr = H5Gclose (m_hdf5_tensor_component); + assert (! herr); + } + + + + hid_t tensor_component_t:: + get_variable () + const + { + return m_variable; + } + + + + hid_t tensor_component_t:: + get_hdf5_tensor_component () + const + { + return m_hdf5_tensor_component; + } + + + + bool tensor_component_t:: + invariant () + const + { + return (m_variable >= 0 and m_variable < CCTK_NumVars() + and m_hdf5_tensor_component >= 0); + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/tensor_component.hh b/CarpetDev/CarpetIOF5/src/tensor_component.hh new file mode 100644 index 000000000..39a8ecf23 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/tensor_component.hh @@ -0,0 +1,48 @@ +#ifndef TENSOR_COMPONENT_HH +#define TENSOR_COMPONENT_HH + +#include <hdf5.h> + +#include "physical_quantity.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + class tensor_component_t { + + physical_quantity_t & m_physical_quantity; + + int const m_variable; + + hid_t m_hdf5_tensor_component; + + public: + + tensor_component_t (physical_quantity_t & physical_quantity, + int variable); + + virtual + ~ tensor_component_t (); + + hid_t + get_variable () + const; + + hid_t + get_hdf5_tensor_component () + const; + + virtual bool + invariant () + const; + + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef TENSOR_COMPONENT_HH diff --git a/CarpetDev/CarpetIOF5/src/timestep.cc b/CarpetDev/CarpetIOF5/src/timestep.cc new file mode 100644 index 000000000..ffed82efc --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/timestep.cc @@ -0,0 +1,85 @@ +#include <cassert> +#include <iomanip> +#include <limits> +#include <string> +#include <sstream> + +#include <hdf5.h> + +#include "cctk.h" + +#include "timestep.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + using std::numeric_limits; + using std::setprecision; + using std::ostringstream; + + + + timestep_t:: + timestep_t (file_t & file, + CCTK_REAL const time, + char const * const name) + : m_file (file), + m_time (time) + { + // Construct a group name from the simulation time + ostringstream buf; + if (name != 0) + { + // Use the name argument if it is present + buf << name; + } + else + { + // Create a string from the time without losing information + int const precision = numeric_limits<CCTK_REAL>::digits10 + 2; + buf << setprecision (precision) << "T=" << time; + } + m_name = buf.str(); + + m_hdf5_timestep + = open_or_create_group (m_file.get_hdf5_file(), m_name.c_str()); + assert (m_hdf5_timestep >= 0); + write_or_check_attribute (m_hdf5_timestep, "time", time); + + assert (invariant()); + } + + + + timestep_t:: + ~ timestep_t() + { + herr_t const herr = H5Gclose (m_hdf5_timestep); + assert (! herr); + } + + + + hid_t timestep_t:: + get_hdf5_timestep() + const + { + return m_hdf5_timestep; + } + + + + bool timestep_t:: + invariant() + const + { + return m_hdf5_timestep >= 0; + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/timestep.hh b/CarpetDev/CarpetIOF5/src/timestep.hh new file mode 100644 index 000000000..f02db1916 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/timestep.hh @@ -0,0 +1,52 @@ +#ifndef TIMESTEP_HH +#define TIMESTEP_HH + +#include <string> + +#include <hdf5.h> + +#include "cctk.h" + +#include "file.hh" + + + +namespace CarpetIOF5 { + + using std::string; + + namespace F5 { + + class timestep_t { + + file_t & m_file; + + CCTK_REAL const m_time; + + string m_name; + + hid_t m_hdf5_timestep; + + public: + + timestep_t (file_t & file, + CCTK_REAL time, + char const * name = 0); + + virtual + ~ timestep_t (); + + hid_t + get_hdf5_timestep () + const; + + virtual bool + invariant () + const; + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef TIMESTEP_HH diff --git a/CarpetDev/CarpetIOF5/src/topology.cc b/CarpetDev/CarpetIOF5/src/topology.cc new file mode 100644 index 000000000..20c8c8db7 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/topology.cc @@ -0,0 +1,156 @@ +#include <cassert> +#include <sstream> + +#include <hdf5.h> + +#include "cctk.h" + +#include "topology.hh" +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + topology_t:: + topology_t (simulation_t & simulation) + : m_simulation (simulation) + { + } + + + + topology_t:: + ~ topology_t () + { + } + + + + hid_t topology_t:: + get_hdf5_topology() + const + { + return m_hdf5_topology; + } + + + + bool topology_t:: + invariant() + const + { + return m_hdf5_topology >= 0; + } + + + + unigrid_topology_t:: + unigrid_topology_t (simulation_t & simulation) + : topology_t (simulation) + { + char const * const name = "Vertices"; + m_hdf5_topology + = open_or_create_group (m_simulation.get_hdf5_simulation(), name); + assert (m_hdf5_topology >= 0); + + assert (invariant()); + } + + + + unigrid_topology_t:: + ~ unigrid_topology_t () + { + herr_t const herr = H5Gclose (m_hdf5_topology); + assert (! herr); + } + + + + bool unigrid_topology_t:: + invariant() + const + { + return topology_t::invariant(); + } + + + + mesh_refinement_topology_t:: + mesh_refinement_topology_t (simulation_t & simulation, + int const refinement_level, + int const max_refinement_levels, + int const level_refinement_factor, + int const max_refinement_factor) + : topology_t (simulation), + m_refinement_level (refinement_level), + m_max_refinement_levels (max_refinement_levels), + m_level_refinement_factor (level_refinement_factor), + m_max_refinement_factor (max_refinement_factor) + { + assert (refinement_level >= 0); + assert (refinement_level < max_refinement_levels); + assert (level_refinement_factor > 0); + assert (level_refinement_factor <= max_refinement_factor); + + ostringstream buf; + buf << "Vertices level " << refinement_level; + char const * const name = buf.str().c_str(); + + m_hdf5_topology + = open_or_create_group (m_simulation.get_hdf5_simulation(), name); + assert (m_hdf5_topology >= 0); + + assert (invariant()); + } + + + + void mesh_refinement_topology_t:: + calculate_level_origin_delta (vect<CCTK_REAL, dim> const & coarse_origin, + vect<CCTK_REAL, dim> const & coarse_delta, + vect<int, dim> const & level_offset, + vect<int, dim> const & level_offset_denominator, + vect<CCTK_REAL, dim> & level_origin, + vect<CCTK_REAL, dim> & level_delta) + const + { + assert (all (coarse_delta > 0)); + assert (all (level_offset_denominator > 0)); + + CCTK_REAL const one = 1; + level_delta = coarse_delta / m_level_refinement_factor; + level_origin + = (coarse_origin + + (level_offset * one / level_offset_denominator + / m_max_refinement_factor)); + } + + + + mesh_refinement_topology_t:: + ~ mesh_refinement_topology_t () + { + herr_t const herr = H5Gclose (m_hdf5_topology); + assert (! herr); + } + + + + bool mesh_refinement_topology_t:: + invariant() + const + { + return (topology_t::invariant() + and m_refinement_level >= 0 + and m_refinement_level < m_max_refinement_levels + and m_level_refinement_factor > 0 + and m_level_refinement_factor <= m_max_refinement_factor); + } + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/topology.hh b/CarpetDev/CarpetIOF5/src/topology.hh new file mode 100644 index 000000000..13e879e89 --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/topology.hh @@ -0,0 +1,100 @@ +#ifndef TOPOLOGY_HH +#define TOPOLOGY_HH + +#include <hdf5.h> + +#include "cctk.h" + +#include "defs.hh" +#include "vect.hh" + +#include "simulation.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + class topology_t { + + protected: + + simulation_t & m_simulation; + + hid_t m_hdf5_topology; + + topology_t (simulation_t & simulation); + + public: + + virtual + ~ topology_t (); + + public: + + hid_t + get_hdf5_topology () + const; + + virtual bool + invariant () + const; + }; + + + + class unigrid_topology_t : public topology_t { + + public: + + // Create unigrid topology + unigrid_topology_t (simulation_t & simulation); + + virtual + ~ unigrid_topology_t (); + + virtual bool + invariant () + const; + }; + + + + class mesh_refinement_topology_t : public topology_t { + + int const m_refinement_level; + int const m_max_refinement_levels; + int const m_level_refinement_factor; + int const m_max_refinement_factor; + + public: + + mesh_refinement_topology_t (simulation_t & simulation, + int refinement_level, + int max_refinement_levels, + int level_refinement_factor, + int max_refinement_factor); + + void + calculate_level_origin_delta (vect<CCTK_REAL, dim> const & coarse_origin, + vect<CCTK_REAL, dim> const & coarse_delta, + vect<int, dim> const & level_offset, + vect<int, dim> const & level_offset_denominator, + vect<CCTK_REAL, dim> & level_origin, + vect<CCTK_REAL, dim> & level_delta) + const; + + virtual + ~ mesh_refinement_topology_t (); + + virtual bool + invariant () + const; + }; + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef TOPOLOGY_HH diff --git a/CarpetDev/CarpetIOF5/src/utils.cc b/CarpetDev/CarpetIOF5/src/utils.cc new file mode 100644 index 000000000..6bd4c4b0e --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/utils.cc @@ -0,0 +1,303 @@ +#include <cassert> +#include <complex> +#include <vector> + +#include <hdf5.h> + +#include "cctk.h" + +#include "defs.hh" + +#include "utils.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + using std::complex; + using std::vector; + + + + hid_t + hdf5_datatype (signed char const & dummy) + { + return H5T_NATIVE_SCHAR; + } + + hid_t + hdf5_datatype (short const & dummy) + { + return H5T_NATIVE_SHORT; + } + + hid_t + hdf5_datatype (int const & dummy) + { + return H5T_NATIVE_INT; + } + + hid_t + hdf5_datatype (long const & dummy) + { + return H5T_NATIVE_LONG; + } + + hid_t + hdf5_datatype (long long const & dummy) + { + return H5T_NATIVE_LLONG; + } + + hid_t + hdf5_datatype (float const & dummy) + { + return H5T_NATIVE_FLOAT; + } + + hid_t + hdf5_datatype (double const & dummy) + { + return H5T_NATIVE_DOUBLE; + } + + hid_t + hdf5_datatype (long double const & dummy) + { + return H5T_NATIVE_LDOUBLE; + } + + hid_t + hdf5_datatype (CCTK_COMPLEX8 const & dummy) + { + CCTK_REAL4 real; + return hdf5_complex_datatype (dummy, real); + } + + hid_t + hdf5_datatype (CCTK_COMPLEX16 const & dummy) + { + CCTK_REAL8 real; + return hdf5_complex_datatype (dummy, real); + } + + hid_t + hdf5_datatype (CCTK_COMPLEX32 const & dummy) + { + CCTK_REAL16 real; + return hdf5_complex_datatype (dummy, real); + } + + template<typename T, typename R> + hid_t + hdf5_complex_datatype (T const & dummy, R const & real) + { + static bool initialised = false; + static hid_t hdf_complex; + + if (! initialised) + { + initialised = true; + + hsize_t const dim = 2; + int const perm = 0; + + hdf_complex = H5Tarray_create (hdf5_datatype (real), 1, & dim, & perm); + assert (hdf_complex >= 0); + } + + return hdf_complex; + } + + + + hid_t + hdf5_datatype_from_cactus (int const cactus_type) + { + switch (cactus_type) { + case CCTK_VARIABLE_VOID : return H5I_INVALID_HID; + case CCTK_VARIABLE_BYTE : { CCTK_BYTE const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_INT : { CCTK_INT const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_INT1 : { CCTK_INT1 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_INT2 : { CCTK_INT2 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_INT4 : { CCTK_INT4 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_INT8 : { CCTK_INT8 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_REAL : { CCTK_REAL const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_REAL4 : { CCTK_REAL4 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_REAL8 : { CCTK_REAL8 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_REAL16 : { CCTK_REAL16 const dummy = 0; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_COMPLEX : { CCTK_COMPLEX dummy ; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_COMPLEX8 : { CCTK_COMPLEX8 dummy ; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_COMPLEX16: { CCTK_COMPLEX16 dummy ; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_COMPLEX32: { CCTK_COMPLEX32 dummy ; return hdf5_datatype (dummy); } + case CCTK_VARIABLE_CHAR : return H5I_INVALID_HID; + case CCTK_VARIABLE_STRING : return H5I_INVALID_HID; + case CCTK_VARIABLE_POINTER : return H5I_INVALID_HID; + case CCTK_VARIABLE_FPOINTER : return H5I_INVALID_HID; + } + return H5I_INVALID_HID; + } + + + + hid_t + open_or_create_group (hid_t const where, + char const * const name) + { + assert (where >= 0); + assert (name != 0); + + bool group_exists; + H5E_BEGIN_TRY { + H5G_stat_t statbuf; + herr_t const herr + = H5Gget_objinfo (where, name, true, & statbuf); + group_exists = herr == 0; + } H5E_END_TRY; + + hid_t group; + if (group_exists) + { + group = H5Gopen (where, name); + } + else + { + group = H5Gcreate (where, name, 0); + } + + return group; + } + + + + template<typename T> + void + write_or_check_attribute (hid_t const where, + char const * const name, + T const * const values, + int const num_values) + { + assert (where >= 0); + assert (name != 0); + assert (num_values >= 0); + assert (num_values == 0 or values != 0); + + T dummy; + hid_t const datatype = hdf5_datatype (dummy); + + hid_t attribute; + H5E_BEGIN_TRY { + attribute = H5Aopen_name (where, name); + } H5E_END_TRY; + + if (attribute < 0) + { + // The attribute does not yet exist; create it + hsize_t const dim = num_values; + hid_t const dataspace = H5Screate_simple (1, & dim, & dim); + assert (dataspace >= 0); + attribute = H5Acreate (where, name, datatype, dataspace, H5P_DEFAULT); + assert (attribute >= 0); + herr_t herr; + herr = H5Awrite (attribute, datatype, values); + assert (! herr); + herr = H5Aclose (attribute); + assert (! herr); + herr = H5Sclose (dataspace); + assert (! herr); + } + else + { + // The attribute already exists; read and check it + hid_t const dataspace = H5Aget_space (attribute); + htri_t const is_simple = H5Sis_simple (dataspace); + assert (is_simple >= 0); + assert (is_simple > 0); + int const ndims = H5Sget_simple_extent_ndims (dataspace); + assert (ndims == 1); + hsize_t dim; + herr_t herr; + herr = H5Sget_simple_extent_dims (dataspace, & dim, 0); + assert (dim == num_values); + vector<T> buf (dim); + herr = H5Aread (attribute, datatype, & buf.front()); + assert (! herr); + herr = H5Sclose (dataspace); + assert (! herr); + herr = H5Aclose (attribute); + assert (! herr); + for (int n = 0; n < num_values; ++ n) + { + assert (values [n] == buf [n]); + } + } + } + + template + void + write_or_check_attribute (hid_t const where, + char const * const name, + int const * const values, + int const num_values); + template + void + write_or_check_attribute (hid_t const where, + char const * const name, + CCTK_REAL const * const values, + int const num_values); + + + + template<typename T> + void + write_or_check_attribute (hid_t const where, + char const * const name, + T const & value) + { + assert (where >= 0); + assert (name != 0); + + write_or_check_attribute (where, name, & value, 1); + } + + template + void + write_or_check_attribute (hid_t const where, + char const * const name, + int const & value); + template + void + write_or_check_attribute (hid_t const where, + char const * const name, + CCTK_REAL const & value); + + + + template<typename T, int D> + void + write_or_check_attribute (hid_t where, + char const * name, + vect<T,D> const & value) + { + assert (where >= 0); + assert (name != 0); + + write_or_check_attribute (where, name, & value [0], D); + } + + template + void + write_or_check_attribute (hid_t where, + char const * name, + vect<int, dim> const & value); + template + void + write_or_check_attribute (hid_t where, + char const * name, + vect<CCTK_REAL, dim> const & value); + + } // namespace F5 + +} // namespace CarpetIOF5 diff --git a/CarpetDev/CarpetIOF5/src/utils.hh b/CarpetDev/CarpetIOF5/src/utils.hh new file mode 100644 index 000000000..28b6e044f --- /dev/null +++ b/CarpetDev/CarpetIOF5/src/utils.hh @@ -0,0 +1,77 @@ +#ifndef utils_HH +#define utils_HH + +#include <hdf5.h> + +#include "cctk.h" + +#include "vect.hh" + + + +namespace CarpetIOF5 { + + namespace F5 { + + hid_t + hdf5_datatype (signed char const & dummy); + hid_t + hdf5_datatype (short const & dummy); + hid_t + hdf5_datatype (int const & dummy); + hid_t + hdf5_datatype (long const & dummy); + hid_t + hdf5_datatype (long long const & dummy); + hid_t + hdf5_datatype (float const & dummy); + hid_t + hdf5_datatype (double const & dummy); + hid_t + hdf5_datatype (long double const & dummy); + hid_t + hdf5_datatype (CCTK_COMPLEX8 const & dummy); + hid_t + hdf5_datatype (CCTK_COMPLEX16 const & dummy); + hid_t + hdf5_datatype (CCTK_COMPLEX32 const & dummy); + + template<typename T, typename R> + hid_t + hdf5_complex_datatype (T const & dummy, R const & real); + + hid_t + hdf5_datatype_from_cactus (int cactus_type); + + + + hid_t + open_or_create_group (hid_t where, + char const * name); + + + + template<typename T> + void + write_or_check_attribute (hid_t where, + char const * name, + T const * values, + int num_values); + + template<typename T> + void + write_or_check_attribute (hid_t where, + char const * name, + T const & value); + + template<typename T, int D> + void + write_or_check_attribute (hid_t where, + char const * name, + vect<T,D> const & value); + + } // namespace F5 + +} // namespace CarpetIOF5 + +#endif // #ifndef UTILS_HH |