This is a basic question about what options are available for defining the scope of some parameters. I'd particularly like to have a sense of the tradeoffs in speed, memory, code clarity, ease of implementation, and code safety. My programming experience is clearly modest, and I have little formal training. I suspect one or two options will be obvious 'right' answers.
I have a simulation encapsulated in its own class called Simulation
. Some of the parameters used in the simulation are read in from a set of files when the Simulation is initialized, and these parameters are currently stored in a few two-dimensional arrays. These arrays, demPMFs
and serotypePars
, are currently both private members of Simulation
:
// Simulation.h
class Simulation
{
Simulation( int simID );
~Simulation();
public:
// ...[code snipped]...
private:
double demPMFs[ NUM_SOCIODEM_FILES ][ INIT_NUM_AGE_CATS ];
double serotypePars[ NUM_EPID_FILES ][ INIT_NUM_STYPES ];
// ...[code snipped]...
};
The simulations mostly involve modifying instances of class Host
. Member functions of class Host
frequently need access to parameter values stored in serotypePars
. Previously, I had all the data now in serotypePars
stored as const
numerics interpreted at compile time, but now that these parameters are read from a file, things are a little more complicated (for me, anyway).
What is the fastest and safest way for me to grant all members of class Host
'read-only' access to serotypePars
? Fastest deserves priority: There are no other classes in my program, so global
is a (crude) potential solution; all simulations will run from identical parameter sets. I'm reluctant to pass the array to individual functions that act on Host
members, since there are probably a dozen and some are quite nested. (For example, I have intermediate wrapper structs that cannot take two-dimensional arrays as arguments, and I'm unsure what syntactical work-arounds there might be. I would like to stick with arrays for speed purposes, and my non-uniform prng generators all expect arrays.)
I would greatly appreciate knowing what would require the least modification of the existing code while not introducing huge dangers.
Thanks for any insight you can offer.
A related challenge I have is not knowing exactly how to access Simulation members from the Host class, unless these members are passed to the Host function. Here's basically what happens:
// main.cpp
int main() {
for ( int s = 1; s < NUM_SIMS+1; s++ ) {
Simulation thisSim(s);
thisSim.runDemSim();
thisSim.runEpidSim();
// ... code snipped ...
}
}
Function Simulation::runDemSim()
and Simulation::runEpidSim()
create, modify, and destroy many instances of class Host
. Pointers to these instances are stored in a Boost MultiIndex container, which is where the intermediate wrapper functions come in. One of the many modifications involves ultimately calling Host::calcRecovery
, which needs access to serotypePars
:
// Host.cpp
// ... code snipped ...
double Host::calcRecovery( int s, double currentTime, double infectionTime, boost::mt19937& rng ) {
// ...code snipped...
effectiveMean = serotypePars[ MEAN_DURATION_INDEX ][ s ] * currentInfections * pastInfections;
double rt = rgamma( effectiveMean, serotypePars[ VAR_DURATION_INDEX ][ s ], rng );
}
(Apologies if TMI.) Simply declaring serotypePars
public in the Simulation
class definition resulted in a "serotypePars was not declared in this scope" error in Host.cpp.
Solution summary
GMan's suggestion that I package all the simulation parameters in a private class, e.g., SimulationPars
, seems like the most elegant and extensible route. An instance of SimulationPars
could belong in every Simulation
, and a pointer to SimulationPars
can be passed to the constructor of every Host
within a given Simulation
. Thanks to everyone for the thoughtful discussions.