Skip to content

Commit

Permalink
More granular options parsing for Environment
Browse files Browse the repository at this point in the history
Partially addresses libqueso#569

Following the lead from GPMSAOptions, refactor EnvOptionsValues to
allow construction from defaults vs. passed options object, with
optional override from parsed user input file.  Finer grained
construct, set_defaults(), parse(), further allow a client to
intersperse setting options via C++ as well since member variables are
public.

This commit changes a couple historical behaviors:

 * If there was an inbound EnvOptionsValues object, the input file
   never got parsed.

 * An Environment could have a NULL m_optionsObj; now we construct one
   with default values.  This could lead to subsequent code cleanup.

Retains optional boost::program_options parser for now.
  • Loading branch information
briadam committed Oct 12, 2017
1 parent 902e670 commit ccd8e90
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 186 deletions.
25 changes: 17 additions & 8 deletions src/core/inc/Environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,19 @@ class BaseEnvironment {
//! @name Constructor/Destructor methods
//@{
//! Default constructor.
BaseEnvironment(const char* passedOptionsInputFileName, EnvOptionsValues* alternativeOptionsValues);
/*!
* initialOptionsValues can be overridden by those in
* passedOptionsInputFileName
*/
BaseEnvironment(const char* passedOptionsInputFileName, EnvOptionsValues* initialOptionsValues);

//! Alternate constructor.
/*!
* initialOptionsValues can be overridden by those in
* passedOptionsInputFileName
*/
BaseEnvironment(const std::string & passedOptionsInputFileName,
EnvOptionsValues* alternativeOptionsValues);
EnvOptionsValues* initialOptionsValues);

//! Destructor
/*! It deallocates memory and does other cleanup for the class object and its class members when
Expand Down Expand Up @@ -456,7 +465,7 @@ class EmptyEnvironment : public BaseEnvironment {
//! @name Constructor/Destructor methods
//@{
//! Default constructor. Does nothing.
/*! It initialized BaseEnvironment with no input file and a NULL pointer for the alternativeOptionsValues.*/
/*! It initializes BaseEnvironment with no input file and default options */
EmptyEnvironment();

//! Destructor
Expand Down Expand Up @@ -486,24 +495,24 @@ class FullEnvironment : public BaseEnvironment {
* path for output files.
*/
#ifdef QUESO_HAS_MPI
FullEnvironment(RawType_MPI_Comm inputComm, const char* passedOptionsInputFileName, const char* prefix, EnvOptionsValues* alternativeOptionsValues);
FullEnvironment(RawType_MPI_Comm inputComm, const char* passedOptionsInputFileName, const char* prefix, EnvOptionsValues* initialOptionsValues);

FullEnvironment(RawType_MPI_Comm inputComm,
const std::string& passedOptionsInputFileName,
const std::string& prefix,
EnvOptionsValues* alternativeOptionsValues);
EnvOptionsValues* initialOptionsValues);
#endif

//! Serial constructor.
/*!
* No communicator is passed. Output path handling is exactly as in the
* parallel ctor.
*/
FullEnvironment(const char* passedOptionsInputFileName, const char* prefix, EnvOptionsValues* alternativeOptionsValues);
FullEnvironment(const char* passedOptionsInputFileName, const char* prefix, EnvOptionsValues* initialOptionsValues);

FullEnvironment(const std::string& passedOptionsInputFileName,
const std::string& prefix,
EnvOptionsValues* alternativeOptionsValues);
EnvOptionsValues* initialOptionsValues);

//! Destructor
~FullEnvironment();
Expand All @@ -526,7 +535,7 @@ class FullEnvironment : public BaseEnvironment {
void construct(const char *prefix);

//! Checks the options input file and reads the options.
void readOptionsInputFile();
void readOptionsInputFile(const char* prefix);
//void queso_terminate_handler();

};
Expand Down
9 changes: 9 additions & 0 deletions src/core/inc/EnvironmentOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ class EnvOptionsValues
//! Copy constructor
EnvOptionsValues(const EnvOptionsValues& src);

//! Set parameter option names to begin with prefix
void set_prefix(const char* prefix);

//! Set default values for parameter options
void set_defaults();

//! Given prefix, read the input file for parameters named "prefix"+*
void parse(const BaseEnvironment* env, const char* prefix);

//! Destructor
virtual ~EnvOptionsValues();
//@}
Expand Down
103 changes: 50 additions & 53 deletions src/core/src/Environment.C
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ FilePtrSetStruct::~FilePtrSetStruct()
// Default constructor --------------------------------
BaseEnvironment::BaseEnvironment(
const char* passedOptionsInputFileName,
EnvOptionsValues* alternativeOptionsValues)
EnvOptionsValues* initialOptionsValues)
:
m_fullEnvIsReady (false),
m_worldRank (-1),
Expand Down Expand Up @@ -182,14 +182,19 @@ BaseEnvironment::BaseEnvironment(
// If the user passed in an options object pointer, we really shouldn't let
// ScopedPtr delete their object, so we make a copy. That way, the dtor
// will kill this local copy and leave the user's object in tact.
if (alternativeOptionsValues != NULL) {
m_optionsObj.reset(new EnvOptionsValues(*alternativeOptionsValues));
if (initialOptionsValues != NULL) {
m_optionsObj.reset(new EnvOptionsValues(*initialOptionsValues));
}
else {
// BMA 20170925: Changed this to default construct the options when none
// are passed in, so downstream checks for != NULL may behave differently
m_optionsObj.reset(new EnvOptionsValues());
}
}

BaseEnvironment::BaseEnvironment(
const std::string& passedOptionsInputFileName,
EnvOptionsValues* alternativeOptionsValues)
EnvOptionsValues* initialOptionsValues)
:
m_fullEnvIsReady (false),
m_worldRank (-1),
Expand Down Expand Up @@ -219,8 +224,13 @@ BaseEnvironment::BaseEnvironment(
// If the user passed in an options object pointer, we really shouldn't let
// ScopedPtr delete their object, so we make a copy. That way, the dtor
// will kill this local copy and leave the user's object in tact.
if (alternativeOptionsValues != NULL) {
m_optionsObj.reset(new EnvOptionsValues(*alternativeOptionsValues));
if (initialOptionsValues != NULL) {
m_optionsObj.reset(new EnvOptionsValues(*initialOptionsValues));
}
else {
// BMA 20170925: Changed this to default construct the options when none
// are passed in, so downstream checks for != NULL may behave differently
m_optionsObj.reset(new EnvOptionsValues());
}
}

Expand Down Expand Up @@ -1200,9 +1210,9 @@ FullEnvironment::FullEnvironment(
RawType_MPI_Comm inputComm,
const char* passedOptionsInputFileName,
const char* prefix,
EnvOptionsValues* alternativeOptionsValues)
EnvOptionsValues* initialOptionsValues)
:
BaseEnvironment(passedOptionsInputFileName,alternativeOptionsValues)
BaseEnvironment(passedOptionsInputFileName,initialOptionsValues)
{
this->construct(inputComm, prefix);
}
Expand All @@ -1211,9 +1221,9 @@ FullEnvironment::FullEnvironment(
RawType_MPI_Comm inputComm,
const std::string& passedOptionsInputFileName,
const std::string& prefix,
EnvOptionsValues* alternativeOptionsValues)
EnvOptionsValues* initialOptionsValues)
:
BaseEnvironment(passedOptionsInputFileName,alternativeOptionsValues)
BaseEnvironment(passedOptionsInputFileName,initialOptionsValues)
{
this->construct(inputComm, prefix.c_str());
}
Expand Down Expand Up @@ -1247,26 +1257,9 @@ FullEnvironment::construct (RawType_MPI_Comm inputComm,
std::cout << "In FullEnv, finished dealing with MPI initially" << std::endl;
#endif

//////////////////////////////////////////////////
// Read options
//////////////////////////////////////////////////
// If NULL, we create one
if (m_optionsObj == NULL) {
// If there's an input file, we grab the options from there. Otherwise the
// defaults are used
if (m_optionsInputFileName != "") {
#ifndef QUESO_DISABLE_BOOST_PROGRAM_OPTIONS
m_allOptionsMap.reset(new boost::program_options::variables_map());
m_allOptionsDesc.reset(new boost::program_options::options_description("Allowed options"));
#endif // QUESO_DISABLE_BOOST_PROGRAM_OPTIONS

readOptionsInputFile();

m_input->parse_input_file(m_optionsInputFileName);
}

m_optionsObj.reset(new EnvOptionsValues(this, prefix));
}
if (!m_optionsInputFileName.empty())
readOptionsInputFile(prefix);

// If help option was supplied, print info
if (m_optionsObj->m_help != "") {
Expand Down Expand Up @@ -1491,26 +1484,27 @@ FullEnvironment::construct (RawType_MPI_Comm inputComm,
FullEnvironment::FullEnvironment(
const char* passedOptionsInputFileName,
const char* prefix,
EnvOptionsValues* alternativeOptionsValues)
EnvOptionsValues* initialOptionsValues)
:
BaseEnvironment(passedOptionsInputFileName,alternativeOptionsValues)
BaseEnvironment(passedOptionsInputFileName,initialOptionsValues)
{
this->construct(prefix);
}

FullEnvironment::FullEnvironment(
const std::string& passedOptionsInputFileName,
const std::string& prefix,
EnvOptionsValues* alternativeOptionsValues)
EnvOptionsValues* initialOptionsValues)
:
BaseEnvironment(passedOptionsInputFileName,alternativeOptionsValues)
BaseEnvironment(passedOptionsInputFileName,initialOptionsValues)
{
this->construct(prefix.c_str());
}

void
FullEnvironment::construct (const char *prefix)
{

#ifdef QUESO_MEMORY_DEBUGGING
std::cout << "Entering FullEnv" << std::endl;
#endif
Expand All @@ -1532,26 +1526,9 @@ FullEnvironment::construct (const char *prefix)
std::cout << "In FullEnv, finished dealing with MPI initially" << std::endl;
#endif

//////////////////////////////////////////////////
// Read options
//////////////////////////////////////////////////
// If NULL, we create one
if (m_optionsObj == NULL) {
// If there's an input file, we grab the options from there. Otherwise the
// defaults are used
if (m_optionsInputFileName != "") {
#ifndef QUESO_DISABLE_BOOST_PROGRAM_OPTIONS
m_allOptionsMap.reset(new boost::program_options::variables_map());
m_allOptionsDesc.reset(new boost::program_options::options_description("Allowed options"));
#endif // QUESO_DISABLE_BOOST_PROGRAM_OPTIONS

readOptionsInputFile();

m_input->parse_input_file(m_optionsInputFileName);
}

m_optionsObj.reset(new EnvOptionsValues(this, prefix));
}
if (!m_optionsInputFileName.empty())
readOptionsInputFile(prefix);

// If help option was supplied, print info
if (m_optionsObj->m_help != "") {
Expand Down Expand Up @@ -1782,9 +1759,17 @@ void queso_terminate_handler()


//-------------------------------------------------------
// Previous behavior:
// * IF alternative options passed in, use them exclusively
// * ELSE IF input file, parse and set options from it
// * ELSE use default options
// New behavior:
// * START with default options or passed alternative options
// * IF input file, any parsed options override stored values
void
FullEnvironment::readOptionsInputFile()
FullEnvironment::readOptionsInputFile(const char* prefix)
{
// Check file for readability for both Boost and GetPot cases
std::ifstream* ifs = new std::ifstream(m_optionsInputFileName.c_str());
if (ifs->is_open()) {
//ifs->close();
Expand All @@ -1804,6 +1789,18 @@ FullEnvironment::readOptionsInputFile()
queso_error();
}

// prepare BPO data structures
#ifndef QUESO_DISABLE_BOOST_PROGRAM_OPTIONS
m_allOptionsMap.reset(new boost::program_options::variables_map());
m_allOptionsDesc.reset(new boost::program_options::options_description("Allowed options"));
#endif // QUESO_DISABLE_BOOST_PROGRAM_OPTIONS

// perform the GetPot parse
m_input->parse_input_file(m_optionsInputFileName);

// allow input file options to override current options class values
m_optionsObj->parse(this, prefix);

return;
}

Expand Down
Loading

0 comments on commit ccd8e90

Please sign in to comment.