diff --git a/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5/main.cc b/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5/main.cc index e745dacf..1e3c7c94 100644 --- a/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5/main.cc +++ b/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5/main.cc @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) { bool output(false); if (argc != 2) throw std::invalid_argument("Expected ./main seed!\n"); int seed(atoi(argv[1])); + int reportItersPeriod(50); double nxRanks(2); double nyRanks(2); @@ -45,8 +46,19 @@ int main(int argc, char *argv[]) { ParallelEnv env(&argc, &argv, nxRanks, nyRanks, nzRanks); - Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, - cfl, Ng, gamma, sigma, cp, mu1, mu2, frameSkip); + const int nOptionalSimArgs = 1; + std::vector optionalSimArgs = {seed}; + std::vector optionalSimArgNames = {"seed"}; + + // Create an arg object that will contain all parameters needed by the simulation, that will be stored on the Data object. + // The DataArgs constructor takes those parameters that are required rather than optional. + // The chained setter functions can be used to set any of the optional parameters. They can be used in any order and default + // values will be used for any parameters that are not set + DataArgs dataArgs = DataArgs(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime) + .sCfl(cfl).sNg(Ng).sGamma(gamma).sCp(cp).sMu1(mu1).sMu2(mu2).sFrameSkip(frameSkip).sSigma(sigma) + .sReportItersPeriod(reportItersPeriod).sOptionalSimArgs(optionalSimArgs, optionalSimArgNames, nOptionalSimArgs); + + Data data = Data(dataArgs, &env); // Choose particulars of simulation SRMHD model(&data); diff --git a/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/data_t0.checkpoint.hdf5 b/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/data_t0.checkpoint.hdf5 index b0b53345..cd38c7d3 100644 Binary files a/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/data_t0.checkpoint.hdf5 and b/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/data_t0.checkpoint.hdf5 differ diff --git a/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/main.cc b/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/main.cc index 9b1ac9f2..d6c9db0c 100644 --- a/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/main.cc +++ b/Examples/KelvinHelmholtz/SingleFluidIdealRandomMPIHDF5CheckpointRestart/main.cc @@ -28,7 +28,8 @@ int main(int argc, char *argv[]) { double ymax(1.0); double zmin(0.0); double zmax(1.0); - double endTime(3.0); + //double endTime(3.0); + double endTime(0.01); double cfl(0.6); double gamma(4.0/3.0); double sigma(10); @@ -43,16 +44,16 @@ int main(int argc, char *argv[]) { ParallelEnv env(&argc, &argv, 2, 2, 1); - //const char* filename = "data_t3.checkpoint.hdf5"; const char* filename = "data_t0.checkpoint.hdf5"; - //Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, - //cfl, Ng, gamma, sigma, cp, mu1, mu2, frameSkip, reportItersPeriod); + // Create an arg object that will contain all parameters needed by the simulation, that will be stored on the Data object. + // ParallelCheckpointArgs sets those parameters that can be read from the restart file, while the chained setter functions + // that follow can be used to set the additional variables that are not stored in the restart file, as well as override + // any other variables (should only need to overwrite endTime when starting from a restart file) + ParallelCheckpointArgs checkpointArgs = ParallelCheckpointArgs(filename, &env).sEndTime(endTime) + .sMu1(mu1).sMu2(mu2).sFrameSkip(frameSkip).sReportItersPeriod(reportItersPeriod); - ParallelCheckpointArgs checkpointArgs(filename, &env); - checkpointArgs.endTime=endTime; - - Data data(checkpointArgs, &env, mu1, mu2, frameSkip, reportItersPeriod); + Data data = Data(checkpointArgs, &env); // Choose particulars of simulation SRMHD model(&data); @@ -67,11 +68,11 @@ int main(int argc, char *argv[]) { printf("Seed: %d\n", seed); - KHRandomInstabilitySingleFluid init(&data, 1, seed); - //ParallelCheckpointRestart init(&data, filename, &env); - + //KHRandomInstabilitySingleFluid init(&data, 1, seed); + ParallelCheckpointRestart init(&data, filename, &env); + RKSplit timeInt(&data, &model, &bcs, &fluxMethod); - + ParallelSaveDataHDF5 save(&data, &env, "data_parallel", ParallelSaveDataHDF5::OUTPUT_ALL); // Now objects have been created, set up the simulation diff --git a/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5/main.cc b/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5/main.cc index 08bb68d2..4e435129 100644 --- a/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5/main.cc +++ b/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5/main.cc @@ -10,6 +10,8 @@ #include "serialSaveDataHDF5.h" #include "weno.h" #include +#include +#include using namespace std; @@ -27,7 +29,7 @@ int main(int argc, char *argv[]) { double zmin(0.0); double zmax(1.0); //double endTime(3.0); - double endTime(0.0); + double endTime(0.01); double cfl(0.6); double gamma(4.0/3.0); double sigma(10); @@ -42,8 +44,24 @@ int main(int argc, char *argv[]) { SerialEnv env(&argc, &argv, 1, 1, 1); - Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, - cfl, Ng, gamma, sigma, cp, mu1, mu2, frameSkip, reportItersPeriod); + const int nOptionalSimArgs = 1; + std::vector optionalSimArgs = {seed}; + std::vector optionalSimArgNames = {"seed"}; + + // Create an arg object that will contain all parameters needed by the simulation, that will be stored on the Data object. + // The DataArgs constructor takes those parameters that are required rather than optional. + // The chained setter functions can be used to set any of the optional parameters. They can be used in any order and default + // values will be used for any parameters that are not set + DataArgs dataArgs = DataArgs(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime) + .sCfl(cfl).sNg(Ng).sGamma(gamma).sCp(cp).sMu1(mu1).sMu2(mu2).sFrameSkip(frameSkip).sSigma(sigma) + .sReportItersPeriod(reportItersPeriod).sOptionalSimArgs(optionalSimArgs, optionalSimArgNames, nOptionalSimArgs); + + Data data = Data(dataArgs, &env); + + // The following is an example of creating the Data object without using named parameters -- in this case vars must be specified + // in order and all optional parameters before the last optional parameter of interest must be listed + //Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, + //cfl, Ng, gamma, sigma, cp, mu1, mu2, frameSkip, reportItersPeriod); // Choose particulars of simulation SRMHD model(&data); diff --git a/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/data_t0.checkpoint.hdf5 b/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/data_t0.checkpoint.hdf5 index b0b53345..cd38c7d3 100644 Binary files a/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/data_t0.checkpoint.hdf5 and b/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/data_t0.checkpoint.hdf5 differ diff --git a/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/main.cc b/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/main.cc index eb2b236c..0eee90ee 100644 --- a/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/main.cc +++ b/Examples/KelvinHelmholtz/SingleFluidIdealRandomSerialHDF5CheckpointRestart/main.cc @@ -11,7 +11,8 @@ #include "serialEnv.h" #include "serialSaveDataHDF5.h" #include "weno.h" -#include +#include +#include using namespace std; @@ -28,7 +29,8 @@ int main(int argc, char *argv[]) { double ymax(1.0); double zmin(0.0); double zmax(1.0); - double endTime(3.0); + //double endTime(3.0); + double endTime(0.01); double cfl(0.6); double gamma(4.0/3.0); double sigma(10); @@ -43,16 +45,21 @@ int main(int argc, char *argv[]) { SerialEnv env(&argc, &argv, 1, 1, 1); - //const char* filename = "data_t3.checkpoint.hdf5"; const char* filename = "data_t0.checkpoint.hdf5"; - //Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, - // cfl, Ng, gamma, sigma, cp, mu1, mu2, frameSkip, reportItersPeriod); - - SerialCheckpointArgs checkpointArgs(filename, &env); - checkpointArgs.endTime=endTime; - - Data data(checkpointArgs, &env, mu1, mu2, frameSkip, reportItersPeriod); + const int nOptionalSimArgs = 1; + std::vector optionalSimArgs = {seed}; + std::vector optionalSimArgNames = {"seed"}; + + // Create an arg object that will contain all parameters needed by the simulation, that will be stored on the Data object. + // SerialCheckpointArgs sets those parameters that can be read from the restart file, while the chained setter functions + // that follow can be used to set the additional variables that are not stored in the restart file, as well as override + // any other variables (should only need to overwrite endTime when starting from a restart file) + SerialCheckpointArgs checkpointArgs = SerialCheckpointArgs(filename, &env).sEndTime(endTime) + .sMu1(mu1).sMu2(mu2).sFrameSkip(frameSkip).sReportItersPeriod(reportItersPeriod); + //.sOptionalSimArgs(optionalSimArgs, optionalSimArgNames, nOptionalSimArgs); + + Data data = Data(checkpointArgs, &env); // Choose particulars of simulation SRMHD model(&data); diff --git a/Project/CPU/Include/checkpointArgs.h b/Project/CPU/Include/checkpointArgs.h deleted file mode 100644 index 68a48018..00000000 --- a/Project/CPU/Include/checkpointArgs.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CHECKPOINTARGS_H -#define CHECKPOINTARGS_H - -#include -#include -#include "platformEnv.h" - - -//! Object containing parameters required to populate Data from a restart file -/*! - @par - Parameters are read into CheckpointArgs from a checkpoint restart file. These are then used - to initialise Data. This is the best way to make sure that simulation parameters are consistent with - the restart file being used for initialisation. - -*/ -class CheckpointArgs -{ - public: - -int - //@{ - nx, ny, nz; //!< Number of physical cells in specified direction - //@} - double - //@{ - xmin, xmax, - ymin, ymax, //!< Positional limits of domain in specified direction - zmin, zmax, - //@} - endTime, //!< End time of simulation - cfl; //!< Courant factor - int Ng; //!< Number of ghost cells - double - gamma, //!< Adiabatic index - sigma; //!< Resistivity - int - //@{ - Ncons, Nprims, Naux; //!< Number of specified variables - //@} - double - cp; //!< Constant divergence cleaning term - double - gam; //!< Exponent in the functional conductivity - double - t, //!< Current time - dt; //!< Width of current timestep - int - //@{ - Nx, Ny, Nz; //!< Total number of compute cells in domain in the specified direction - //@} - - - //! Constructor - /*! - @par - reads parameters from a checkpoint restart file into this object for use in Data constructor - */ - CheckpointArgs() {}; - -}; - -#endif diff --git a/Project/CPU/Include/dataArgs.h b/Project/CPU/Include/dataArgs.h new file mode 100644 index 00000000..0f75ec5e --- /dev/null +++ b/Project/CPU/Include/dataArgs.h @@ -0,0 +1,165 @@ +#ifndef DATAARGS_H +#define DATAARGS_H + +#include +#include +#include "platformEnv.h" + + +//! Object containing parameters required to populate Data, including from a restart file +/*! + @par + Parameters can be read into DataArgs from a checkpoint restart file. These are then used + to initialise Data. This is the best way to make sure that simulation parameters are consistent with + the restart file being used for initialisation. + + Note that the defaults here should be the same as the defaults set in the Data constructor in simData.h + that does not use named parameters. + +*/ +class DataArgsBase +{ + public: + + // The following Args are written to a checkpoint restart file and can therefore be initialised from file + // if one is provided. They can also be manually set by the user. + // ------------------------------------------------------------------------- + + int + //@{ + nx, ny, nz; //!< Number of physical cells in specified direction + //@} + double + //@{ + xmin, xmax, + ymin, ymax, //!< Positional limits of domain in specified direction + zmin, zmax, + //@} + frameSkip=10, //!< Number of timesteps per file output + endTime, //!< End time of simulation + cfl=0.5; //!< Courant factor + int Ng=4; //!< Number of ghost cells + double + gamma=5.0/3.0, //!< Adiabatic index + sigma=1e3; //!< Resistivity + int + //@{ + Ncons, Nprims, Naux; //!< Number of specified variables + //@} + double + cp=0.1; //!< Constant divergence cleaning term + double + t=0, //!< Current time + dt; //!< Width of current timestep + int + //@{ + Nx, Ny, Nz; //!< Total number of compute cells in domain in the specified direction + //@} + + // The following Args are never written to a restart file and therefore must always be manually set by the user + // in all cases. + // ------------------------------------------------------------------------- + double mu1=-1.0e4, mu2=1.0e4; //!< Charge mass ratio of specified fluid species, q/m (for two fluid model) + int + reportItersPeriod=1; //!< Period with which time step data is reported to screen during program execution + bool + functionalSigma=false; //!< Are we using a functional (vs homogeneous) conductivity? + double + gam=12; //!< Exponent in the functional conductivity + + std::vector + optionalSimArgs; //!< Array of optional arguments that depend on the simulation being run + std::vector + optionalSimArgNames; //!< Names of optionalSimArgs array elements + int + nOptionalSimArgs=0; //!< Number of elements to include in optionalSimArgs array + + //! Constructor + DataArgsBase() { + }; + +}; + +//! Object containing parameters required to populate Data manually (as opposed to from a restart file) +/*! + @par + Required parameters must be set in the constructor. + Setters are created for each optional parameter to allow creation of the object using chained + named parameters, according to the strategy described in (https://isocpp.org/wiki/faq/ctors#named-parameter-idiom). +*/ +class DataArgs : public DataArgsBase +{ + public: + + //! Constructor + /*! + @par + Set required parameters to be used by the Data object. + */ + DataArgs(int nx, int ny, int nz, + double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax, + double endTime) { + this->nx = nx; this->ny = ny; this->nz = nz; + this->xmin = xmin; this->ymin = ymin; this->zmin = zmin; + this->xmax = xmax; this->ymax = ymax; this->zmax = zmax; + this->endTime = endTime; + }; + + DataArgs& sCfl(double cfl) { + this->cfl = cfl; return *this; + } + + DataArgs& sNg(double Ng) { + this->Ng = Ng; return *this; + } + + DataArgs& sGamma(double gamma) { + this->gamma = gamma; return *this; + } + + DataArgs& sSigma(double sigma) { + this->sigma = sigma; return *this; + } + + DataArgs& sCp(double cp) { + this->cp = cp; return *this; + } + + DataArgs& sMu1(double mu1) { + this->mu1 = mu1; return *this; + } + + DataArgs& sMu2(double mu2) { + this->mu2 = mu2; return *this; + } + + DataArgs& sReportItersPeriod(int reportItersPeriod) { + this->reportItersPeriod = reportItersPeriod; return *this; + } + + DataArgs& sfunctionalSigma(bool functionalSigma) { + this->functionalSigma = functionalSigma; return *this; + } + + DataArgs& sGam(double gam) { + this->gam = gam; return *this; + } + + DataArgs& sFrameSkip(double frameSkip) { + this->frameSkip = frameSkip; return *this; + } + + // input arrays are copied to memory on this object. The input arrays are unchanged and their memory remains allocated + // if optionalSimArgs and optionalSimArgNames have already been defined on this object, they are overwritten + DataArgs& sOptionalSimArgs(std::vector optionalSimArgs, std::vector optionalSimArgNames, int nOptionalSimArgs) { + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; + return *this; + } + +}; + +#endif diff --git a/Project/CPU/Include/parallelCheckpointArgs.h b/Project/CPU/Include/parallelCheckpointArgs.h index 588b1bba..600c4a15 100644 --- a/Project/CPU/Include/parallelCheckpointArgs.h +++ b/Project/CPU/Include/parallelCheckpointArgs.h @@ -4,6 +4,7 @@ #include #include #include "parallelEnv.h" +#include "dataArgs.h" //! Object containing parameters required to populate Data from a restart file in parallel /*! @@ -13,7 +14,7 @@ the restart file being used for initialisation. */ -class ParallelCheckpointArgs : public CheckpointArgs +class ParallelCheckpointArgs : public DataArgsBase { public: @@ -28,6 +29,100 @@ class ParallelCheckpointArgs : public CheckpointArgs const char* name, ParallelEnv *env); + ParallelCheckpointArgs& sNx(int nx) { + this->nx = nx; return *this; + } + + ParallelCheckpointArgs& sNy(int ny) { + this->ny = ny; return *this; + } + + ParallelCheckpointArgs& sNz(int nz) { + this->nz = nz; return *this; + } + + ParallelCheckpointArgs& sXmin(double xmin) { + this->xmin = xmin; return *this; + } + + ParallelCheckpointArgs& sYmin(double ymin) { + this->ymin = ymin; return *this; + } + + ParallelCheckpointArgs& sZmin(double zmin) { + this->zmin = zmin; return *this; + } + + ParallelCheckpointArgs& sXmax(double xmax) { + this->xmax = xmax; return *this; + } + + ParallelCheckpointArgs& sYmax(double ymax) { + this->ymax = ymax; return *this; + } + + ParallelCheckpointArgs& sZmax(double zmax) { + this->zmax = zmax; return *this; + } + + ParallelCheckpointArgs& sEndTime(double endTime) { + this->endTime = endTime; return *this; + } + + ParallelCheckpointArgs& sCfl(double cfl) { + this->cfl = cfl; return *this; + } + + ParallelCheckpointArgs& sNg(double Ng) { + this->Ng = Ng; return *this; + } + + ParallelCheckpointArgs& sGamma(double gamma) { + this->gamma = gamma; return *this; + } + + ParallelCheckpointArgs& sSigma(double sigma) { + this->sigma = sigma; return *this; + } + + ParallelCheckpointArgs& sCp(double cp) { + this->cp = cp; return *this; + } + + ParallelCheckpointArgs& sMu1(double mu1) { + this->mu1 = mu1; return *this; + } + + ParallelCheckpointArgs& sMu2(double mu2) { + this->mu2 = mu2; return *this; + } + + ParallelCheckpointArgs& sReportItersPeriod(int reportItersPeriod) { + this->reportItersPeriod = reportItersPeriod; return *this; + } + + ParallelCheckpointArgs& sfunctionalSigma(bool functionalSigma) { + this->functionalSigma = functionalSigma; return *this; + } + + ParallelCheckpointArgs& sGam(double gam) { + this->gam = gam; return *this; + } + + ParallelCheckpointArgs& sFrameSkip(double frameSkip) { + this->frameSkip = frameSkip; return *this; + } + + // input arrays are copied to memory on this object. The input arrays are unchanged and their memory remains allocated + // if optionalSimArgs and optionalSimArgNames are already set on this object, they are overwritten + ParallelCheckpointArgs& sOptionalSimArgs(std::vector optionalSimArgs, std::vector optionalSimArgNames, int nOptionalSimArgs) { + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; + return *this; + } + + }; #endif diff --git a/Project/CPU/Include/serialCheckpointArgs.h b/Project/CPU/Include/serialCheckpointArgs.h index 42d4e06d..07ea818c 100644 --- a/Project/CPU/Include/serialCheckpointArgs.h +++ b/Project/CPU/Include/serialCheckpointArgs.h @@ -4,6 +4,7 @@ #include #include #include "platformEnv.h" +#include "dataArgs.h" //! Object containing parameters required to populate Data from a restart file in serial /*! @@ -13,7 +14,7 @@ the restart file being used for initialisation. */ -class SerialCheckpointArgs : public CheckpointArgs +class SerialCheckpointArgs : public DataArgsBase { public: @@ -28,6 +29,100 @@ class SerialCheckpointArgs : public CheckpointArgs const char* name, PlatformEnv *env); + SerialCheckpointArgs& sNx(int nx) { + this->nx = nx; return *this; + } + + SerialCheckpointArgs& sNy(int ny) { + this->ny = ny; return *this; + } + + SerialCheckpointArgs& sNz(int nz) { + this->nz = nz; return *this; + } + + SerialCheckpointArgs& sXmin(double xmin) { + this->xmin = xmin; return *this; + } + + SerialCheckpointArgs& sYmin(double ymin) { + this->ymin = ymin; return *this; + } + + SerialCheckpointArgs& sZmin(double zmin) { + this->zmin = zmin; return *this; + } + + SerialCheckpointArgs& sXmax(double xmax) { + this->xmax = xmax; return *this; + } + + SerialCheckpointArgs& sYmax(double ymax) { + this->ymax = ymax; return *this; + } + + SerialCheckpointArgs& sZmax(double zmax) { + this->zmax = zmax; return *this; + } + + SerialCheckpointArgs& sEndTime(double endTime) { + this->endTime = endTime; return *this; + } + + SerialCheckpointArgs& sCfl(double cfl) { + this->cfl = cfl; return *this; + } + + SerialCheckpointArgs& sNg(double Ng) { + this->Ng = Ng; return *this; + } + + SerialCheckpointArgs& sGamma(double gamma) { + this->gamma = gamma; return *this; + } + + SerialCheckpointArgs& sSigma(double sigma) { + this->sigma = sigma; return *this; + } + + SerialCheckpointArgs& sCp(double cp) { + this->cp = cp; return *this; + } + + SerialCheckpointArgs& sMu1(double mu1) { + this->mu1 = mu1; return *this; + } + + SerialCheckpointArgs& sMu2(double mu2) { + this->mu2 = mu2; return *this; + } + + SerialCheckpointArgs& sReportItersPeriod(int reportItersPeriod) { + this->reportItersPeriod = reportItersPeriod; return *this; + } + + SerialCheckpointArgs& sfunctionalSigma(bool functionalSigma) { + this->functionalSigma = functionalSigma; return *this; + } + + SerialCheckpointArgs& sGam(double gam) { + this->gam = gam; return *this; + } + + SerialCheckpointArgs& sFrameSkip(double frameSkip) { + this->frameSkip = frameSkip; return *this; + } + + // input arrays are copied to memory on this object. The input arrays are unchanged and their memory remains allocated + // if optionalSimArgs and optionalSimArgNames are already set on this object, they are overwritten + SerialCheckpointArgs& sOptionalSimArgs(std::vector optionalSimArgs, std::vector optionalSimArgNames, int nOptionalSimArgs) { + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; + return *this; + } }; #endif + + diff --git a/Project/CPU/Include/simData.h b/Project/CPU/Include/simData.h index 9b074c56..7add0aa5 100644 --- a/Project/CPU/Include/simData.h +++ b/Project/CPU/Include/simData.h @@ -4,7 +4,7 @@ #include #include #include "platformEnv.h" -#include "checkpointArgs.h" +#include "dataArgs.h" // Macro for getting array index #define ID(variable, idx, jdx, kdx) ((variable)*(d->Nx)*(d->Ny)*(d->Nz) + (idx)*(d->Ny)*(d->Nz) + (jdx)*(d->Nz) + (kdx)) @@ -120,6 +120,12 @@ class Data is, js, ks, ie, je, ke; //!< Cell IDs for interior grid points //@} + std::vector + optionalSimArgs; //!< Array of optional arguments that depend on the simulation being run + std::vector + optionalSimArgNames; //!< Names of optionalSimArgs array elements + int + nOptionalSimArgs=0; //!< Number of elements to include in optionalSimArgs array //! Element ID function @@ -166,10 +172,10 @@ class Data This is separated from the constructor to avoid duplicated code between the two available constructors for Data. */ - void initData(PlatformEnv *env); + void initData(PlatformEnv *env, int nOptionalSimArgs=0, std::vector optionalSimArgs=std::vector(), std::vector optionalSimArgNames=std::vector()); - //! Constructor + //! Constructor -- all vars specified by comma separated list /*! @par Allocates the memory required for the state arrays and sets the simulation @@ -218,14 +224,11 @@ class Data constants to the given values. Does not set initial state, thats done by the initialFunc object. @param args simulation arguments such as cfl, sigma etc, as read from checkpoint restart file - @param mu1 charge mass ratio of species 1 - @param mu2 charge mass ratio of species 2 @param env environment object containing platform details eg MPI ranks - @param frameskip number of timesteps per file output - @param reportItersPeriod period with which time step data is reported to screen during program execution */ - Data(CheckpointArgs args, PlatformEnv *env, double mu1=-1.0e4, double mu2=1.0e4, - int frameskip=10, int reportItersPeriod=1, int functionalSigma=false, double gam=12); + Data(DataArgsBase args, PlatformEnv *env); + + ~Data() {}; }; diff --git a/Project/CPU/Src/checkpointArgs.cc b/Project/CPU/Src/dataArgs.cc similarity index 97% rename from Project/CPU/Src/checkpointArgs.cc rename to Project/CPU/Src/dataArgs.cc index c6d2cffb..8644e544 100644 --- a/Project/CPU/Src/checkpointArgs.cc +++ b/Project/CPU/Src/dataArgs.cc @@ -8,7 +8,7 @@ #include -CheckpointArgs::CheckpointArgs(const char* name, PlatformEnv *env) +DataArgs::DataArgs(const char* name, PlatformEnv *env) { herr_t error=0, tmpError=-1; hid_t file = H5Fopen(name, H5F_ACC_RDONLY, H5P_DEFAULT); diff --git a/Project/CPU/Src/parallelCheckpointArgs.cc b/Project/CPU/Src/parallelCheckpointArgs.cc index 20b6d485..b2bcb44a 100644 --- a/Project/CPU/Src/parallelCheckpointArgs.cc +++ b/Project/CPU/Src/parallelCheckpointArgs.cc @@ -7,8 +7,7 @@ #include "hdf5_hl.h" #include - -ParallelCheckpointArgs::ParallelCheckpointArgs(const char* name, ParallelEnv *env) : CheckpointArgs() +ParallelCheckpointArgs::ParallelCheckpointArgs(const char* name, ParallelEnv *env) : DataArgsBase() { herr_t error=0, tmpError=-1; @@ -30,6 +29,33 @@ ParallelCheckpointArgs::ParallelCheckpointArgs(const char* name, ParallelEnv *en if (tmpError < 0) error = tmpError; if (error<0) throw std::runtime_error("Checkpoint restart file is missing some global attributes"); + // Read optional file attributes + hid_t optionalGroup = H5Gopen(file, "Optional", H5P_DEFAULT); + if (optionalGroup >= 0){ + // if the hdf5 file we're using has an optional sim args group. This may not be the case if the + // file is in an older style + tmpError = H5LTget_attribute_int(optionalGroup, ".", "nOptionalSimArgs", &(this->nOptionalSimArgs)); + + hid_t attr; + double optionalArg; + char *argName = (char*) malloc(256*sizeof(char)); + // There should be no way for these arrays to have been written to, but clearing them just in case + this->optionalSimArgs.clear(); + this->optionalSimArgNames.clear(); + for (int i(0); inOptionalSimArgs; i++){ + // read all the optional arguments, skipping the first attribute in this group, which is nOptionalSimArgs + // and has already been read + attr = H5Aopen_by_idx(optionalGroup, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i+1, H5P_DEFAULT, H5P_DEFAULT); + tmpError = H5Aread(attr, H5T_NATIVE_DOUBLE, &optionalArg); + tmpError = H5Aget_name(attr, 256, argName); + (this->optionalSimArgs).push_back(optionalArg); + (this->optionalSimArgNames).push_back(argName); + H5Aclose(attr); + } + free(argName); + } + H5Gclose(optionalGroup); + // Remaining required attributes are stored in the Domain group hid_t group = H5Gopen(file, "Domain", H5P_DEFAULT); tmpError = H5LTget_attribute_int(group, ".", "nx", &(nx)); diff --git a/Project/CPU/Src/parallelInitFuncFromCheckpoint.cc b/Project/CPU/Src/parallelInitFuncFromCheckpoint.cc index 263a8100..8769820b 100644 --- a/Project/CPU/Src/parallelInitFuncFromCheckpoint.cc +++ b/Project/CPU/Src/parallelInitFuncFromCheckpoint.cc @@ -80,13 +80,17 @@ void ParallelCheckpointRestart::readDataSetDouble(const hid_t *group, const char } } } + + H5Pclose(dataset_access_property_list); + H5Sclose(dataspace_total); + H5Sclose(dataspace_local); + H5Dclose(dataset); } ParallelCheckpointRestart::ParallelCheckpointRestart(Data * data, const char *name, ParallelEnv *env) : InitialFunc(data) { // Syntax Data * d(data); - herr_t error=0; hid_t file_access_property_list = H5Pcreate(H5P_FILE_ACCESS); @@ -103,16 +107,17 @@ ParallelCheckpointRestart::ParallelCheckpointRestart(Data * data, const char *na error = H5LTget_attribute_int(groupCons, ".", "Ncons", &(NconsFile)); if (error<0 || NconsFile < d->Ncons) throw std::runtime_error("Too few conserved vars recorded in checkpoint restart file for this model"); - hid_t groupPrims = H5Gopen(file, "Primitive", H5P_DEFAULT); - error = H5LTget_attribute_int(groupPrims, ".", "Nprims", &(NprimsFile)); - if (error<0 || NconsFile < d->Nprims) throw std::runtime_error("Too few primitive vars recorded in checkpoint restart file for this model"); - // Read all cons vars for(int var(0); var < d->Ncons; var++) { readDataSetDouble(&groupCons, d->consLabels[var].c_str(), &var, d->cons, env); } H5Gclose(groupCons); + hid_t groupPrims = H5Gopen(file, "Primitive", H5P_DEFAULT); + error = H5LTget_attribute_int(groupPrims, ".", "Nprims", &(NprimsFile)); + if (error<0 || NconsFile < d->Nprims) throw std::runtime_error("Too few primitive vars recorded in checkpoint restart file for this model"); + + // Read all prims vars for(int var(0); var < d->Nprims; var++) { readDataSetDouble(&groupPrims, d->primsLabels[var].c_str(), &var, d->prims, env); @@ -120,4 +125,5 @@ ParallelCheckpointRestart::ParallelCheckpointRestart(Data * data, const char *na H5Gclose(groupPrims); H5Fclose(file); + H5Pclose(file_access_property_list); } diff --git a/Project/CPU/Src/parallelSaveDataHDF5.cc b/Project/CPU/Src/parallelSaveDataHDF5.cc index 712465d4..845db7bd 100644 --- a/Project/CPU/Src/parallelSaveDataHDF5.cc +++ b/Project/CPU/Src/parallelSaveDataHDF5.cc @@ -289,6 +289,16 @@ void ParallelSaveDataHDF5::saveConsts() H5LTset_attribute_double(this->file, ".", "sigma", &d->sigma, 1); H5LTset_attribute_double(this->file, ".", "cp", &d->cp, 1); H5LTset_attribute_double(this->file, ".", "t", &d->t, 1); + + // For each one of the optional simulation arguments, write it to disk + hid_t group = H5Gcreate(this->file, "Optional", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5LTset_attribute_int(group, ".", "nOptionalSimArgs", &d->nOptionalSimArgs, 1); + for(int i(0); i < d->nOptionalSimArgs; i++) { + string name = d->optionalSimArgNames[i]; + double arg = d->optionalSimArgs[i]; + H5LTset_attribute_double(group, ".", name.c_str(), &arg, 1); + } + H5Gclose(group); } diff --git a/Project/CPU/Src/serialCheckpointArgs.cc b/Project/CPU/Src/serialCheckpointArgs.cc index 6a222f32..9e66848f 100644 --- a/Project/CPU/Src/serialCheckpointArgs.cc +++ b/Project/CPU/Src/serialCheckpointArgs.cc @@ -7,8 +7,7 @@ #include "hdf5_hl.h" #include - -SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : CheckpointArgs() +SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : DataArgsBase() { herr_t error=0, tmpError=-1; hid_t file = H5Fopen(name, H5F_ACC_RDONLY, H5P_DEFAULT); @@ -28,6 +27,32 @@ SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : if (tmpError < 0) error = tmpError; if (error<0) throw std::runtime_error("Checkpoint restart file is missing some global attributes"); + // Read optional file attributes + hid_t optionalGroup = H5Gopen(file, "Optional", H5P_DEFAULT); + if (optionalGroup >= 0){ + // if the hdf5 file we're using has an optional sim args group. This may not be the case if the + // file is in an older style + tmpError = H5LTget_attribute_int(optionalGroup, ".", "nOptionalSimArgs", &(this->nOptionalSimArgs)); + + hid_t attr; + double optionalArg; + char *argName = (char*) malloc(256*sizeof(char)); + // There should be no way for these arrays to have been written to, but clearing them just in case + this->optionalSimArgs.clear(); + this->optionalSimArgNames.clear(); + for (int i(0); ioptionalSimArgs).push_back(optionalArg); + (this->optionalSimArgNames).push_back(argName); + } + free(argName); + H5Gclose(optionalGroup); + } + // Remaining required attributes are stored in the Domain group hid_t group = H5Gopen(file, "Domain", H5P_DEFAULT); tmpError = H5LTget_attribute_int(group, ".", "nx", &(nx)); @@ -65,3 +90,4 @@ SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : } + diff --git a/Project/CPU/Src/serialSaveDataHDF5.cc b/Project/CPU/Src/serialSaveDataHDF5.cc index 7b5463d4..d358d6d1 100644 --- a/Project/CPU/Src/serialSaveDataHDF5.cc +++ b/Project/CPU/Src/serialSaveDataHDF5.cc @@ -247,6 +247,16 @@ void SerialSaveDataHDF5::saveConsts() H5LTset_attribute_double(this->file, ".", "sigma", &d->sigma, 1); H5LTset_attribute_double(this->file, ".", "cp", &d->cp, 1); H5LTset_attribute_double(this->file, ".", "t", &d->t, 1); + + // For each one of the optional simulation arguments, write it to disk + hid_t group = H5Gcreate(this->file, "Optional", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5LTset_attribute_int(group, ".", "nOptionalSimArgs", &d->nOptionalSimArgs, 1); + for(int i(0); i < d->nOptionalSimArgs; i++) { + string name = d->optionalSimArgNames[i]; + double arg = d->optionalSimArgs[i]; + H5LTset_attribute_double(group, ".", name.c_str(), &arg, 1); + } + H5Gclose(group); } diff --git a/Project/CPU/Src/simData.cc b/Project/CPU/Src/simData.cc index 44a97db3..f2c90fd4 100644 --- a/Project/CPU/Src/simData.cc +++ b/Project/CPU/Src/simData.cc @@ -2,9 +2,12 @@ #include "platformEnv.h" #include #include +#include #define IDn(variable, idx, jdx, kdx) ((variable)*(this->Nx)*(this->Ny)*(this->Nz) + (idx)*(this->Ny)*(this->Nz) + (jdx)*(this->Nz) + (kdx)) +using namespace std; + Data::Data(int nx, int ny, int nz, double xmin, double xmax, double ymin, double ymax, @@ -35,8 +38,7 @@ Data::Data(int nx, int ny, int nz, initData(env); } -Data::Data(CheckpointArgs args, PlatformEnv *env, double mu1, double mu2, - int frameSkip, int reportItersPeriod, int functionalSigma, double gam) +Data::Data(DataArgsBase args, PlatformEnv *env) : nx(args.nx), ny(args.ny), nz(args.nz), xmin(args.xmin), xmax(args.xmax), @@ -47,16 +49,16 @@ Data::Data(CheckpointArgs args, PlatformEnv *env, double mu1, double mu2, memSet(0), bcsSet(0), Ncons(0), Nprims(0), Naux(0), cp(args.cp), - mu1(mu1), mu2(mu2), - frameSkip(frameSkip), - reportItersPeriod(reportItersPeriod), - functionalSigma(functionalSigma), gam(gam), - t(args.t) + mu1(args.mu1), mu2(args.mu2), + frameSkip(args.frameSkip), + reportItersPeriod(args.reportItersPeriod), + functionalSigma(args.functionalSigma), gam(args.gam), + t(args.t) { - initData(env); + initData(env, args.nOptionalSimArgs, args.optionalSimArgs, args.optionalSimArgNames); } -void Data::initData(PlatformEnv *env){ +void Data::initData(PlatformEnv *env, int nOptionalSimArgs, std::vector optionalSimArgs, std::vector optionalSimArgNames){ // TODO -- handle nx not dividing perfectly into nxRanks // Set Nx to be nx per MPI process + ghost cells @@ -102,6 +104,11 @@ void Data::initData(PlatformEnv *env){ if (this->mu1 > 0.0 or this->mu2 < 0.0) { throw std::invalid_argument("Species 1 must have negative charge, mu1 < 0, and species 2 must have positive charge, mu2 > 0.\n"); } + + // Allocate and initialise optional simulation parameters if we have been passed any + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; } double Data::sigmaFunc(double * cons, double * prims, double * aux, int i, int j, int k) @@ -118,3 +125,4 @@ double Data::sigmaFunc(double * cons, double * prims, double * aux, int i, int j return sigma * pow(cons[IDn(0, i, j, k)], gam); } } + diff --git a/Project/GPU/Include/parallelCheckpointArgs.h b/Project/GPU/Include/parallelCheckpointArgs.h index d2a2f09e..d99399e4 100644 --- a/Project/GPU/Include/parallelCheckpointArgs.h +++ b/Project/GPU/Include/parallelCheckpointArgs.h @@ -4,6 +4,7 @@ #include #include #include "parallelEnv.h" +#include "dataArgs.h" //! Wrapper around Data object for populating Data from a checkpoint restart file @@ -15,7 +16,7 @@ known to lower objects---good practice.
*/ -class ParallelCheckpointArgs : public CheckpointArgs +class ParallelCheckpointArgs : public DataArgsBase { public: @@ -32,6 +33,101 @@ class ParallelCheckpointArgs : public CheckpointArgs const char* name, ParallelEnv *env); + + ParallelCheckpointArgs& sNx(int nx) { + this->nx = nx; return *this; + } + + ParallelCheckpointArgs& sNy(int ny) { + this->ny = ny; return *this; + } + + ParallelCheckpointArgs& sNz(int nz) { + this->nz = nz; return *this; + } + + ParallelCheckpointArgs& sXmin(double xmin) { + this->xmin = xmin; return *this; + } + + ParallelCheckpointArgs& sYmin(double ymin) { + this->ymin = ymin; return *this; + } + + ParallelCheckpointArgs& sZmin(double zmin) { + this->zmin = zmin; return *this; + } + + ParallelCheckpointArgs& sXmax(double xmax) { + this->xmax = xmax; return *this; + } + + ParallelCheckpointArgs& sYmax(double ymax) { + this->ymax = ymax; return *this; + } + + ParallelCheckpointArgs& sZmax(double zmax) { + this->zmax = zmax; return *this; + } + + ParallelCheckpointArgs& sEndTime(double endTime) { + this->endTime = endTime; return *this; + } + + ParallelCheckpointArgs& sCfl(double cfl) { + this->cfl = cfl; return *this; + } + + ParallelCheckpointArgs& sNg(double Ng) { + this->Ng = Ng; return *this; + } + + ParallelCheckpointArgs& sGamma(double gamma) { + this->gamma = gamma; return *this; + } + + ParallelCheckpointArgs& sSigma(double sigma) { + this->sigma = sigma; return *this; + } + + ParallelCheckpointArgs& sCp(double cp) { + this->cp = cp; return *this; + } + + ParallelCheckpointArgs& sMu1(double mu1) { + this->mu1 = mu1; return *this; + } + + ParallelCheckpointArgs& sMu2(double mu2) { + this->mu2 = mu2; return *this; + } + + ParallelCheckpointArgs& sReportItersPeriod(int reportItersPeriod) { + this->reportItersPeriod = reportItersPeriod; return *this; + } + + ParallelCheckpointArgs& sfunctionalSigma(bool functionalSigma) { + this->functionalSigma = functionalSigma; return *this; + } + + ParallelCheckpointArgs& sGam(double gam) { + this->gam = gam; return *this; + } + + ParallelCheckpointArgs& sFrameSkip(double frameSkip) { + this->frameSkip = frameSkip; return *this; + } + + // input arrays are copied to memory on this object. The input arrays are unchanged and their memory remains allocated + // if optionalSimArgs and optionalSimArgNames are already set on this object, they are overwritten + ParallelCheckpointArgs& sOptionalSimArgs(std::vector optionalSimArgs, std::vector optionalSimArgNames, int nOptionalSimArgs) { + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; + return *this; + } + + }; #endif diff --git a/Project/GPU/Include/serialCheckpointArgs.h b/Project/GPU/Include/serialCheckpointArgs.h index 8b072fbd..bc3bf35b 100644 --- a/Project/GPU/Include/serialCheckpointArgs.h +++ b/Project/GPU/Include/serialCheckpointArgs.h @@ -4,6 +4,7 @@ #include #include #include "platformEnv.h" +#include "dataArgs.h" //! Wrapper around Data object for populating Data from a checkpoint restart file @@ -15,7 +16,7 @@ known to lower objects---good practice.
*/ -class SerialCheckpointArgs : public CheckpointArgs +class SerialCheckpointArgs : public DataArgsBase { public: @@ -32,6 +33,98 @@ class SerialCheckpointArgs : public CheckpointArgs const char* name, PlatformEnv *env); + SerialCheckpointArgs& sNx(int nx) { + this->nx = nx; return *this; + } + + SerialCheckpointArgs& sNy(int ny) { + this->ny = ny; return *this; + } + + SerialCheckpointArgs& sNz(int nz) { + this->nz = nz; return *this; + } + + SerialCheckpointArgs& sXmin(double xmin) { + this->xmin = xmin; return *this; + } + + SerialCheckpointArgs& sYmin(double ymin) { + this->ymin = ymin; return *this; + } + + SerialCheckpointArgs& sZmin(double zmin) { + this->zmin = zmin; return *this; + } + + SerialCheckpointArgs& sXmax(double xmax) { + this->xmax = xmax; return *this; + } + + SerialCheckpointArgs& sYmax(double ymax) { + this->ymax = ymax; return *this; + } + + SerialCheckpointArgs& sZmax(double zmax) { + this->zmax = zmax; return *this; + } + + SerialCheckpointArgs& sEndTime(double endTime) { + this->endTime = endTime; return *this; + } + + SerialCheckpointArgs& sCfl(double cfl) { + this->cfl = cfl; return *this; + } + + SerialCheckpointArgs& sNg(double Ng) { + this->Ng = Ng; return *this; + } + + SerialCheckpointArgs& sGamma(double gamma) { + this->gamma = gamma; return *this; + } + + SerialCheckpointArgs& sSigma(double sigma) { + this->sigma = sigma; return *this; + } + + SerialCheckpointArgs& sCp(double cp) { + this->cp = cp; return *this; + } + + SerialCheckpointArgs& sMu1(double mu1) { + this->mu1 = mu1; return *this; + } + + SerialCheckpointArgs& sMu2(double mu2) { + this->mu2 = mu2; return *this; + } + + SerialCheckpointArgs& sReportItersPeriod(int reportItersPeriod) { + this->reportItersPeriod = reportItersPeriod; return *this; + } + + SerialCheckpointArgs& sfunctionalSigma(bool functionalSigma) { + this->functionalSigma = functionalSigma; return *this; + } + + SerialCheckpointArgs& sGam(double gam) { + this->gam = gam; return *this; + } + + SerialCheckpointArgs& sFrameSkip(double frameSkip) { + this->frameSkip = frameSkip; return *this; + } + + // input arrays are copied to memory on this object. The input arrays are unchanged and their memory remains allocated + // if optionalSimArgs and optionalSimArgNames are already set on this object, they are overwritten + SerialCheckpointArgs& sOptionalSimArgs(std::vector optionalSimArgs, std::vector optionalSimArgNames, int nOptionalSimArgs) { + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; + return *this; + } }; #endif diff --git a/Project/GPU/Include/simData.h b/Project/GPU/Include/simData.h index 24665c62..d60ed404 100644 --- a/Project/GPU/Include/simData.h +++ b/Project/GPU/Include/simData.h @@ -4,7 +4,7 @@ #include #include #include "platformEnv.h" -#include "checkpointArgs.h" +#include "dataArgs.h" /*! @@ -125,8 +125,15 @@ class Data dims, //!< Number of dimensions of simulation //@{ is, js, ks, - ie, je, ke, //!< Cell IDs for interior grid points + ie, je, ke; //!< Cell IDs for interior grid points //@} + std::vector + optionalSimArgs; //!< Array of optional arguments that depend on the simulation being run + std::vector + optionalSimArgNames; //!< Names of optionalSimArgs array elements + int + nOptionalSimArgs=0; //!< Number of elements to include in optionalSimArgs array + int GPUcount; //!< Number of NVIDIA devices detected cudaDeviceProp prop; //!< Properties of NVIDIA device (assuming all are same) @@ -158,10 +165,10 @@ class Data This is separated from the constructor to avoid duplicated code between the two available constructors for Data. */ - void initData(PlatformEnv *env); + void initData(PlatformEnv *env, int nOptionalSimArgs=0, std::vector optionalSimArgs=std::vector(), std::vector optionalSimArgNames=std::vector()); - //! Constructor + //! Constructor -- all vars specified by comma separated list /*! @par Allocates the memory required for the state arrays and sets the simulation @@ -206,8 +213,9 @@ class Data @param mu1 charge mass ratio of species 1 @param mu2 charge mass ratio of species 2 */ - Data(CheckpointArgs args, PlatformEnv *env, double mu1=-1.0e4, double mu2=1.0e4, - int frameskip=10); + Data(DataArgsBase args, PlatformEnv *env); + + ~Data() {}; }; diff --git a/Project/GPU/Src/checkpointArgs.cu b/Project/GPU/Src/dataArgs.cu similarity index 97% rename from Project/GPU/Src/checkpointArgs.cu rename to Project/GPU/Src/dataArgs.cu index c6d2cffb..8644e544 100644 --- a/Project/GPU/Src/checkpointArgs.cu +++ b/Project/GPU/Src/dataArgs.cu @@ -8,7 +8,7 @@ #include -CheckpointArgs::CheckpointArgs(const char* name, PlatformEnv *env) +DataArgs::DataArgs(const char* name, PlatformEnv *env) { herr_t error=0, tmpError=-1; hid_t file = H5Fopen(name, H5F_ACC_RDONLY, H5P_DEFAULT); diff --git a/Project/GPU/Src/main.cu b/Project/GPU/Src/main.cu index 60e4f941..f3ecf9c8 100644 --- a/Project/GPU/Src/main.cu +++ b/Project/GPU/Src/main.cu @@ -3,7 +3,7 @@ #include "parallelCheckpointArgs.h" #include "simulation.h" #include "initFunc.h" -#include "initFuncFromCheckpoint.h" +#include "parallelInitFuncFromCheckpoint.h" #include "srmhd.h" #include "srrmhd.h" #include "boundaryConds.h" @@ -62,13 +62,38 @@ int main(int argc, char *argv[]) { const char* filename = "data_t0.checkpoint.hdf5"; - ParallelCheckpointArgs checkpointArgs(filename, &env); - checkpointArgs.endTime=endTime; - - Data data(checkpointArgs, &env); - - //Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, - //cfl, Ng, gamma, sigma); + //ParallelCheckpointArgs checkpointArgs(filename, &env); + //checkpointArgs.endTime=endTime; + + // Create an arg object that will contain all parameters needed by the simulation, that will be stored on the Data object. + // ParallelCheckpointArgs sets those parameters that can be read from the restart file, while the chained setter functions + // that follow can be used to set the additional variables that are not stored in the restart file, as well as override + // any other variables (should only need to overwrite endTime when starting from a restart file) +/* + ParallelCheckpointArgs checkpointArgs = ParallelCheckpointArgs(filename, &env).sEndTime(endTime); + + Data data = Data(checkpointArgs, &env); +*/ + + const int nOptionalSimArgs = 1; + std::vector optionalSimArgs = {100}; + std::vector optionalSimArgNames = {"seed"}; + + // Create an arg object that will contain all parameters needed by the simulation, that will be stored on the Data object. + // The DataArgs constructor takes those parameters that are required rather than optional. + // The chained setter functions can be used to set any of the optional parameters. They can be used in any order and default + // values will be used for any parameters that are not set + DataArgs dataArgs = DataArgs(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime) + .sCfl(cfl).sNg(Ng).sGamma(gamma).sSigma(sigma) + .sOptionalSimArgs(optionalSimArgs, optionalSimArgNames, nOptionalSimArgs); + + Data data = Data(dataArgs, &env); + + // Create a data object using the old interface + /* + Data data(nx, ny, nz, xmin, xmax, ymin, ymax, zmin, zmax, endTime, &env, + cfl, Ng, gamma, sigma); + */ // Choose particulars of simulation SRMHD model(&data); @@ -79,7 +104,8 @@ int main(int argc, char *argv[]) { Simulation sim(&data, &env); - KHInstabilitySingleFluid init(&data, 1); + //KHInstabilitySingleFluid init(&data, 1); + ParallelCheckpointRestart init(&data, filename, &env); RK2 timeInt(&data, &model, &bcs, &fluxMethod); diff --git a/Project/GPU/Src/parallelCheckpointArgs.cu b/Project/GPU/Src/parallelCheckpointArgs.cu index 20b6d485..7a1902bd 100644 --- a/Project/GPU/Src/parallelCheckpointArgs.cu +++ b/Project/GPU/Src/parallelCheckpointArgs.cu @@ -8,7 +8,7 @@ #include -ParallelCheckpointArgs::ParallelCheckpointArgs(const char* name, ParallelEnv *env) : CheckpointArgs() +ParallelCheckpointArgs::ParallelCheckpointArgs(const char* name, ParallelEnv *env) : DataArgsBase() { herr_t error=0, tmpError=-1; @@ -30,6 +30,33 @@ ParallelCheckpointArgs::ParallelCheckpointArgs(const char* name, ParallelEnv *en if (tmpError < 0) error = tmpError; if (error<0) throw std::runtime_error("Checkpoint restart file is missing some global attributes"); + // Read optional file attributes + hid_t optionalGroup = H5Gopen(file, "Optional", H5P_DEFAULT); + if (optionalGroup >= 0){ + // if the hdf5 file we're using has an optional sim args group. This may not be the case if the + // file is in an older style + tmpError = H5LTget_attribute_int(optionalGroup, ".", "nOptionalSimArgs", &(this->nOptionalSimArgs)); + + hid_t attr; + double optionalArg; + char *argName = (char*) malloc(256*sizeof(char)); + // There should be no way for these arrays to have been written to, but clearing them just in case + this->optionalSimArgs.clear(); + this->optionalSimArgNames.clear(); + for (int i(0); inOptionalSimArgs; i++){ + // read all the optional arguments, skipping the first attribute in this group, which is nOptionalSimArgs + // and has already been read + attr = H5Aopen_by_idx(optionalGroup, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, i+1, H5P_DEFAULT, H5P_DEFAULT); + tmpError = H5Aread(attr, H5T_NATIVE_DOUBLE, &optionalArg); + tmpError = H5Aget_name(attr, 256, argName); + (this->optionalSimArgs).push_back(optionalArg); + (this->optionalSimArgNames).push_back(argName); + H5Aclose(attr); + } + free(argName); + } + H5Gclose(optionalGroup); + // Remaining required attributes are stored in the Domain group hid_t group = H5Gopen(file, "Domain", H5P_DEFAULT); tmpError = H5LTget_attribute_int(group, ".", "nx", &(nx)); diff --git a/Project/GPU/Src/parallelInitFuncFromCheckpoint.cu b/Project/GPU/Src/parallelInitFuncFromCheckpoint.cu index f9533624..15a3d4aa 100644 --- a/Project/GPU/Src/parallelInitFuncFromCheckpoint.cu +++ b/Project/GPU/Src/parallelInitFuncFromCheckpoint.cu @@ -93,6 +93,11 @@ void ParallelCheckpointRestart::readDataSetDouble(const hid_t *group, const char } } } + + H5Pclose(dataset_access_property_list); + H5Sclose(dataspace_total); + H5Sclose(dataspace_local); + H5Dclose(dataset); } ParallelCheckpointRestart::ParallelCheckpointRestart(Data * data, const char *name, ParallelEnv *env) : InitialFunc(data) @@ -116,16 +121,17 @@ ParallelCheckpointRestart::ParallelCheckpointRestart(Data * data, const char *na error = H5LTget_attribute_int(groupCons, ".", "Ncons", &(NconsFile)); if (error<0 || NconsFile < d->Ncons) throw std::runtime_error("Too few conserved vars recorded in checkpoint restart file for this model"); - hid_t groupPrims = H5Gopen(file, "Primitive", H5P_DEFAULT); - error = H5LTget_attribute_int(groupPrims, ".", "Nprims", &(NprimsFile)); - if (error<0 || NconsFile < d->Nprims) throw std::runtime_error("Too few primitive vars recorded in checkpoint restart file for this model"); - // Read all cons vars for(int var(0); var < d->Ncons; var++) { readDataSetDouble(&groupCons, d->consLabels[var].c_str(), &var, d->cons, env); } H5Gclose(groupCons); + hid_t groupPrims = H5Gopen(file, "Primitive", H5P_DEFAULT); + error = H5LTget_attribute_int(groupPrims, ".", "Nprims", &(NprimsFile)); + if (error<0 || NconsFile < d->Nprims) throw std::runtime_error("Too few primitive vars recorded in checkpoint restart file for this model"); + + // Read all prims vars for(int var(0); var < d->Nprims; var++) { readDataSetDouble(&groupPrims, d->primsLabels[var].c_str(), &var, d->prims, env); @@ -133,4 +139,5 @@ ParallelCheckpointRestart::ParallelCheckpointRestart(Data * data, const char *na H5Gclose(groupPrims); H5Fclose(file); + H5Pclose(file_access_property_list); } diff --git a/Project/GPU/Src/parallelSaveDataHDF5.cu b/Project/GPU/Src/parallelSaveDataHDF5.cu index c045e432..ffd7dbda 100644 --- a/Project/GPU/Src/parallelSaveDataHDF5.cu +++ b/Project/GPU/Src/parallelSaveDataHDF5.cu @@ -290,6 +290,16 @@ void ParallelSaveDataHDF5::saveConsts() H5LTset_attribute_double(this->file, ".", "sigma", &d->sigma, 1); H5LTset_attribute_double(this->file, ".", "cp", &d->cp, 1); H5LTset_attribute_double(this->file, ".", "t", &d->t, 1); + + // For each one of the optional simulation arguments, write it to disk + hid_t group = H5Gcreate(this->file, "Optional", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5LTset_attribute_int(group, ".", "nOptionalSimArgs", &d->nOptionalSimArgs, 1); + for(int i(0); i < d->nOptionalSimArgs; i++) { + string name = d->optionalSimArgNames[i]; + double arg = d->optionalSimArgs[i]; + H5LTset_attribute_double(group, ".", name.c_str(), &arg, 1); + } + H5Gclose(group); } diff --git a/Project/GPU/Src/serialCheckpointArgs.cu b/Project/GPU/Src/serialCheckpointArgs.cu index c69ffd93..9c18b288 100644 --- a/Project/GPU/Src/serialCheckpointArgs.cu +++ b/Project/GPU/Src/serialCheckpointArgs.cu @@ -8,7 +8,7 @@ #include -SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : CheckpointArgs +SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : DataArgsBase() { herr_t error=0, tmpError=-1; hid_t file = H5Fopen(name, H5F_ACC_RDONLY, H5P_DEFAULT); @@ -28,6 +28,32 @@ SerialCheckpointArgs::SerialCheckpointArgs(const char* name, PlatformEnv *env) : if (tmpError < 0) error = tmpError; if (error<0) throw std::runtime_error("Checkpoint restart file is missing some global attributes"); + // Read optional file attributes + hid_t optionalGroup = H5Gopen(file, "Optional", H5P_DEFAULT); + if (optionalGroup >= 0){ + // if the hdf5 file we're using has an optional sim args group. This may not be the case if the + // file is in an older style + tmpError = H5LTget_attribute_int(optionalGroup, ".", "nOptionalSimArgs", &(this->nOptionalSimArgs)); + + hid_t attr; + double optionalArg; + char *argName = (char*) malloc(256*sizeof(char)); + // There should be no way for these arrays to have been written to, but clearing them just in case + this->optionalSimArgs.clear(); + this->optionalSimArgNames.clear(); + for (int i(0); ioptionalSimArgs).push_back(optionalArg); + (this->optionalSimArgNames).push_back(argName); + } + free(argName); + H5Gclose(optionalGroup); + } + // Remaining required attributes are stored in the Domain group hid_t group = H5Gopen(file, "Domain", H5P_DEFAULT); tmpError = H5LTget_attribute_int(group, ".", "nx", &(nx)); diff --git a/Project/GPU/Src/serialSaveDataHDF5.cu b/Project/GPU/Src/serialSaveDataHDF5.cu index 45853d50..4c0b4051 100644 --- a/Project/GPU/Src/serialSaveDataHDF5.cu +++ b/Project/GPU/Src/serialSaveDataHDF5.cu @@ -248,6 +248,16 @@ void SerialSaveDataHDF5::saveConsts() H5LTset_attribute_double(this->file, ".", "sigma", &d->sigma, 1); H5LTset_attribute_double(this->file, ".", "cp", &d->cp, 1); H5LTset_attribute_double(this->file, ".", "t", &d->t, 1); + + // For each one of the optional simulation arguments, write it to disk + hid_t group = H5Gcreate(this->file, "Optional", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + H5LTset_attribute_int(group, ".", "nOptionalSimArgs", &d->nOptionalSimArgs, 1); + for(int i(0); i < d->nOptionalSimArgs; i++) { + string name = d->optionalSimArgNames[i]; + double arg = d->optionalSimArgs[i]; + H5LTset_attribute_double(group, ".", name.c_str(), &arg, 1); + } + H5Gclose(group); } diff --git a/Project/GPU/Src/simData.cu b/Project/GPU/Src/simData.cu index 58bfc73f..9e9109e0 100644 --- a/Project/GPU/Src/simData.cu +++ b/Project/GPU/Src/simData.cu @@ -3,6 +3,9 @@ #include "cudaErrorCheck.h" #include #include +#include + +using namespace std; Data::Data(int nx, int ny, int nz, double xmin, double xmax, @@ -30,8 +33,7 @@ Data::Data(int nx, int ny, int nz, initData(env); } -Data::Data(CheckpointArgs args, PlatformEnv *env, double mu1, double mu2, - int frameSkip) +Data::Data(DataArgsBase args, PlatformEnv *env) : nx(args.nx), ny(args.ny), nz(args.nz), xmin(args.xmin), xmax(args.xmax), @@ -42,14 +44,14 @@ Data::Data(CheckpointArgs args, PlatformEnv *env, double mu1, double mu2, memSet(0), bcsSet(0), Ncons(0), Nprims(0), Naux(0), cp(args.cp), - mu1(mu1), mu2(mu2), - frameSkip(frameSkip), + mu1(args.mu1), mu2(args.mu2), + frameSkip(args.frameSkip), t(args.t) { - initData(env); + initData(env, args.nOptionalSimArgs, args.optionalSimArgs, args.optionalSimArgNames); } -void Data::initData(PlatformEnv *env){ +void Data::initData(PlatformEnv *env, int nOptionalSimArgs, std::vector optionalSimArgs, std::vector optionalSimArgNames){ // TODO -- handle nx not dividing perfectly into nxRanks // Set Nx to be nx per MPI process + ghost cells @@ -102,6 +104,11 @@ void Data::initData(PlatformEnv *env){ throw std::invalid_argument("Species 1 must have negative charge, mu1 < 0, and species 2 must have positive charge, mu2 > 0.\n"); } + // Allocate and initialise optional simulation parameters if we have been passed any + this->nOptionalSimArgs = nOptionalSimArgs; + this->optionalSimArgs = optionalSimArgs; + this->optionalSimArgNames = optionalSimArgNames; + // Determine the specs of the GPU(s) and thus set details in simData cudaGetDeviceCount(&GPUcount); cudaGetDeviceProperties(&prop, 0); diff --git a/Project/GPU/data_t0.checkpoint.hdf5 b/Project/GPU/data_t0.checkpoint.hdf5 index c3c39aeb..cd38c7d3 100644 Binary files a/Project/GPU/data_t0.checkpoint.hdf5 and b/Project/GPU/data_t0.checkpoint.hdf5 differ