示例#1
0
void directory_model::open_item(QModelIndex index)
{
    if (index.model() != this)
        return;

    QString text = index.data().toString();
    if (text == "..")
        go_up();

    list<file_info>::iterator file_it = _files.begin();
    advance(file_it, index.row());

    if (file_it->directory)
    {
        if (file_it->link)  // directory link
        {
            string name, to;
            if (_sys->parse_link(file_it->name, name, to))
            {
                fs::path p = _path / name;
                _path_history[p] = *file_it;  // save before change
                change_directory(p, true);
            }
        }
        else // directory
            change_directory(_path / text.toStdString());
    }
}
示例#2
0
void directory_model::remove_item(QItemSelectionModel * selection)
{
    if (selection->model() != this)
        return;

    QModelIndexList indexes = selection->selection().indexes();

    vector<list<file_info>::const_iterator> remove_iter_list;
    remove_iter_list.reserve(indexes.size());

    // first, remove from fs
    for (QModelIndex & index : selection->selection().indexes())
    {
        int row = index.row();

        list<file_info>::const_iterator file_it = _files.begin();
        advance(file_it, row);
        remove_iter_list.push_back(file_it);

        _sys->rm(_path / file_it->name);
    }

    beginResetModel();
    for (auto it : remove_iter_list)
        _files.erase(it);
    endResetModel();
}
示例#3
0
auto remove_evens_and_double_odds(list<int>& data)
{
    for(auto cur = data.begin(); cur != data.end();)
        if (*cur & 0x1)
            cur = data.insert(cur, *cur), advance(cur, 2);
        else
            cur = data.erase(cur);
}
示例#4
0
int main()
{
    forward_list<int> vi = {0,1,2,3,4,5,6,7,8,9};
    auto iter = vi.begin(), prev = vi.before_begin();
    while (iter != vi.end()) {
        if (*iter % 2) {
            iter = vi.insert_after(prev, *iter);
            advance(iter, 2);
            advance(prev, 2);
        } else
            iter = vi.erase_after(prev);
    }

    for (auto i : vi)
        cout << i << " ";

    return 0;
}
示例#5
0
int main() {
	auto insert_point = data.begin();
	advance(insert_point, 2);
	istringstream iss("10 20 30");
	copy(istream_iterator<int>(iss), istream_iterator<int>(),
	     inserter(data, insert_point));
	copy(data.begin(), data.end(),
	     ostream_iterator<int>(cout, " "));
	cout << endl;
}
示例#6
0
QVariant directory_model::data(QModelIndex const & index, int role) const
{
    switch (role)
    {
    case Qt::EditRole:
    case Qt::DisplayRole:
    {
        if (index.column() == 0 && index.row() < _files.size())
        {
            list<file_info>::const_iterator it = _files.begin();
            advance(it, index.row());
            return QString::fromUtf8(it->name.c_str());
        }
        break;
    }

    case Qt::DecorationRole:
    {
        if (index.column() == 0 && index.row() < _files.size())
        {
            QVariant result;

            list<file_info>::const_iterator it = _files.begin();
            advance(it, index.row());
            if (it->directory)
                result.setValue(get_icon("folder"));
            else if (it->executable)
                result.setValue(get_icon("application-x-executable"));
            else
                result.setValue(get_icon("document-new"));

            return result;
        }
        break;
    }
    }  // switch

    return QVariant{};
}
示例#7
0
void IFPWidget::displayFrame(int fnum)
{
	IFPAnimation* anim = anims[ui.animList->currentRow()];

	IFPAnimation::ObjectIterator it = anim->getObjectBegin();
	advance(it, ui.objList->currentRow());
	IFPObject* obj = *it;

	IFPObject::FrameIterator fit = obj->getFrameBegin();
	advance(fit, fnum);
	IFPRotFrame* frame = *fit;

	Quaternion rot = frame->getRotation();
	ui.frameRotLabel->setText(tr("%1, %2, %3, %4").arg(rot.getX()).arg(rot.getY()).arg(rot.getZ())
			.arg(rot.getW()));

	ui.frameTimeLabel->setText(QString("%1").arg(frame->getTime()));

	if (obj->getFrameType() == IFPObject::RotTransFrame) {
		IFPRotTransFrame* rtframe = (IFPRotTransFrame*) frame;
		Vector3 trans = rtframe->getTranslation();

		ui.frameTransLabel->setText(tr("%1, %2, %3").arg(trans.getX()).arg(trans.getY()).arg(trans.getZ()));
		ui.frameScaleLabel->setText(tr("-"));
	} else if (obj->getFrameType() == IFPObject::RotTransScaleFrame) {
		IFPRotTransScaleFrame* rtsframe = (IFPRotTransScaleFrame*) frame;
		Vector3 trans = rtsframe->getTranslation();
		Vector3 scale = rtsframe->getScale();

		ui.frameTransLabel->setText(tr("%1, %2, %3").arg(trans.getX()).arg(trans.getY()).arg(trans.getZ()));
		ui.frameScaleLabel->setText(tr("%1, %2, %3").arg(scale.getX()).arg(scale.getY()).arg(scale.getZ()));
	} else {
		ui.frameTransLabel->setText(tr("-"));
		ui.frameScaleLabel->setText(tr("-"));
	}
}
示例#8
0
bool directory_model::setData(QModelIndex const & index, QVariant const & value, int role)
{
    if (role != Qt::EditRole || index.column() != 0 || index.row() >= _files.size())
        return false;

    string newname = value.toString().toStdString();

    list<file_info>::iterator file_it = _files.begin();
    advance(file_it, index.row());

    if (newname == file_it->name)
        return false;

    rename(file_it->name, newname);
    file_it->name = newname;

    emit dataChanged(index, index);

    return true;
}
示例#9
0
void IFPWidget::currentObjectChanged(int row)
{
	if (row == -1) {
		ui.frameTypeLabel->setText(tr("-"));
		ui.boneIDLabel->setText(tr("-"));
		return;
	}

	IFPAnimation* anim = anims[ui.animList->currentRow()];
	IFPAnimation::ObjectIterator it = anim->getObjectBegin();
	advance(it, row);
	IFPObject* obj = *it;

	switch (obj->getFrameType()) {
	case IFPObject::RotFrame:
		ui.frameTypeLabel->setText(tr("Rotation Frames (Child Frames)"));
		break;
	case IFPObject::RotTransFrame:
		ui.frameTypeLabel->setText(tr("Rotation/Translation Frames (Root Frames)"));
		break;
	case IFPObject::RotTransScaleFrame:
		ui.frameTypeLabel->setText(tr("Rotation/Translation/Scale Frames"));
		break;
	case IFPObject::Unknown2Frame:
		ui.frameTypeLabel->setText(tr("Unknown (FrameType = 2)"));
		break;
	}

	ui.boneIDLabel->setText(QString("%1").arg(obj->getBoneID()));

	printf("Object has %d frames\n", obj->getFrameCount());
	ui.frameNumSpinner->setRange(0, obj->getFrameCount()-1);
	ui.frameNumSlider->setRange(0, obj->getFrameCount()-1);
	ui.frameNumSpinner->setValue(0);
	ui.frameNumSlider->setValue(0);
	displayFrame(0);
}
示例#10
0
void Objects::Slideshow::render( double timestamp )
{
  using Graphics::spriteGroup;
  using Graphics::sprites;
  using std::advance;

  // Can't do the initialisation of self_lastUpdate anywhere else
  if ( self_lastUpdate == 0 )
    self_lastUpdate = timestamp;

  // Iterate slides
  if ( self_timeout > 0 and timestamp - self_lastUpdate > self_timeout)
  {
    self_lastUpdate = timestamp;
    self_slidePos++;

    if ( self_slidePos == Graphics::sprites[ self_spriteGroup ] . size() )
      self_slidePos = 0;
  }

  spriteGroup::iterator drawIter = sprites[ self_spriteGroup ].begin();
  advance( drawIter, self_slidePos );
  

  // If there's a sprite at our iterator. (If the group is empty then 
  // begin() is also end() and so not a sprite)
  if ( drawIter != sprites[ self_spriteGroup ] . end() )
  {
    if ( self_coordType == Objects::NORM )
      drawIter -> second -> draw(self_x, self_y, self_w, self_h);

    if ( self_coordType == Objects::NON_NORM )
      drawIter -> second -> draw( (int)self_x, (int)self_y, 
                                         (int)self_w, (int)self_h);
  }
}
示例#11
0
void STLRepository::read( const shared_ptr< Query > query, const function< void ( const shared_ptr< Query > ) >& callback )
{
    Resources values;
    Resources resources;
    const auto keys = query->get_keys( );
    
    unique_lock< mutex> lock( m_resources_lock );
    
    if ( not keys.empty( ) )
    {
        for ( const auto& key : keys )
        {
            auto resource = find_if( m_resources.begin( ), m_resources.end( ), [ &key ]( const Resource & resource )
            {
                if ( resource.count( "key" ) == 0 )
                {
                    return false;
                }
                
                return String::lowercase( key ) == String::lowercase( String::to_string( resource.lower_bound( "key" )->second ) );
            } );
            
            if ( resource == m_resources.end( ) )
            {
                query->set_error_code( 40004 );
                return callback( query );
            }
            
            resources.push_back( *resource );
        }
    }
    else
    {
        resources = m_resources;
    }
    
    lock.unlock( );
    
    filter( resources, query->get_inclusive_filters( ), query->get_exclusive_filters( ) ); //just pass query
    
    const auto& index = query->get_index( );
    const auto& limit = query->get_limit( );
    
    if ( index < resources.size( ) and limit not_eq 0 )
    {
        auto start = resources.begin( );
        advance( start, index );
        
        while ( start not_eq resources.end( ) and limit not_eq values.size( ) )
        {
            values.push_back( *start );
            start++;
        }
    }
    
    include( query->get_include( ), values );
    
    auto results = fields( values, query );
    
    query->set_resultset( results );
    callback( query );
}
示例#12
0
void Objects::Gridshow::render( double timestamp )
{
  // Can't set it to current time for first time anywhere else.
  if ( self_lastUpdate == 0 )
    self_lastUpdate = timestamp;

  // This loops the slides. 
  if ( self_timeout > 0 and timestamp - self_lastUpdate > self_timeout)
  {
    self_slidePos += self_numCells;
    size_t groupSize = Graphics::sprites[self_spriteGroup].size();
    if ( self_slidePos  >= groupSize )
      self_slidePos = 0;
    
    self_lastUpdate = timestamp;
  }

  using Graphics::Sprite;
  using Graphics::sprites;
  using Graphics::spriteGroup;
  using std::advance;

  //Drawing loop - start at the current sprite
  spriteGroup::iterator drawIter = sprites[self_spriteGroup].begin();
  advance( drawIter, self_slidePos );
 
  int gridX = 0;
  int gridY = 0;

  //We draw "self_numCells" sprites
  for (int i = 0; i < self_numCells; i++)
  {
    // If the iterator no longer gives us a real sprite, then break
    if ( drawIter == Graphics::sprites[self_spriteGroup] . end() )
      break;

    Sprite* cellSprite = drawIter -> second;

    // No need for error message, as you should already know that it's NULL
    // by previous errors
    if ( cellSprite == NULL )
      continue;
    
    if ( self_coordType == Objects::NON_NORM )
    {
      int cellX = self_x + gridX * self_w;
      int cellY = self_y + gridY * self_h;

      cellSprite -> draw( cellX, cellY, (int)self_w, (int) self_h );
    }
    if ( self_coordType == Objects::NORM )
    {
      double cellX = self_x + gridX * self_w;
      double cellY = self_y + gridY * self_h;

      cellSprite -> draw( cellX, cellY, self_w, self_h );
    }

    //Do appropriate moving of drawing position
    gridX++;
    if (gridX >= self_cellsWide)
    {
      gridX = 0;
      gridY++;
    }

    // Move to next sprite
    drawIter++;
  }

}
示例#13
0
file_info & directory_model::get_file(int row)
{
    auto it = _files.begin();
    advance(it, row);
    return *it;
}
示例#14
0
//! Execute random walk simulator application mode.
void executeRandomWalkSimulator( 
    const std::string databasePath, 
    const tudat::input_output::parsed_data_vector_utilities::ParsedDataVectorPtr parsedData )
{
    ///////////////////////////////////////////////////////////////////////////

    // Declare using-statements.

    using std::advance;
    using std::cerr;
    using std::cout;
    using std::endl;
    using std::max_element;
    using std::min_element;
    using std::numeric_limits;
    using std::ofstream;
    using std::ostringstream;
    using std::setprecision;
    using std::string;

    using boost::iequals;
    using namespace boost::filesystem; 
    using boost::make_shared;   

    using namespace assist::astrodynamics;
    using namespace assist::basics;
    using namespace assist::mathematics;

    using namespace tudat::basic_astrodynamics::orbital_element_conversions;
    using namespace tudat::basic_mathematics::mathematical_constants;
    using namespace tudat::input_output;
    using namespace tudat::input_output::dictionary;
    using namespace tudat::statistics;

    using namespace stomi::astrodynamics;
    using namespace stomi::database;
    using namespace stomi::input_output;

    ///////////////////////////////////////////////////////////////////////////

    // Extract input parameters.

    // Get dictionary.
    const DictionaryPointer dictionary = getRandomWalkSimulatorDictionary( );

    // Print database path to console.
    cout << "Database                                                  " 
         << databasePath << endl;

    // Extract required parameters. 
    const string randomWalkRunName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ), 
                findEntry( dictionary, "RANDOMWALKRUN" ) );
    cout << "Random walk run                                           "  
         << randomWalkRunName << endl;  

    // Extract optional parameters. 
    const int numberOfThreads = extractParameterValue< int >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "NUMBEROFTHREADS" ), 1 );
    cout << "Number of threads                                         " 
         << numberOfThreads << endl;  

    const string outputMode = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "OUTPUTMODE" ), "DATABASE" );
    cout << "Output mode                                               "
         << outputMode << endl;          

    const string fileOutputDirectory = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "FILEOUTPUTDIRECTORY" ), "" ) + "/";
    cout << "File output directory                                     "
         << fileOutputDirectory << endl;

    const string randomWalkSimulations = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKSIMULATIONS" ), "ALL" );
    cout << "Random walk simulations                                   "
         << randomWalkSimulations << endl;         

    const string randomWalkRunTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKRUNTABLENAME" ), "random_walk_run" );
    cout << "Random walk run table                                     " 
         << randomWalkRunTableName << endl;

    const string randomWalkInputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKINPUTTABLENAME" ), "random_walk_input" );
    cout << "Random walk input table                                   " 
         << randomWalkInputTableName << endl;         

    const string randomWalkPerturberTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKPERTURBERTABLENAME" ),
                "random_walk_perturbers" );
    cout << "Random walk perturber table                               "
         << randomWalkPerturberTableName << endl;

    const string randomWalkOutputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKOUTPUTTABLENAME" ), "random_walk_output" );
    cout << "Random walk output table                                  "
              << randomWalkOutputTableName << endl; 

    const string testParticleCaseTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "TESTPARTICLECASETABLENAME" ), "test_particle_case" );
    cout << "Test particle case table                                  "
         << testParticleCaseTableName << endl;                

    const string testParticleKickTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "TESTPARTICLEKICKTABLENAME" ), "test_particle_kicks" );
    cout << "Test particle kick table                                  "
         << testParticleKickTableName << endl;          

    // Retrieve and store random walk run data from database.
    RandomWalkRunPointer randomWalkRun;

    // Random walk run data is extracted in local scope from the database, with overwritten
    // parameters extracted from the input file, to ensure that none of these parameters are used
    // globally elsewhere in this file.
    {
        const RandomWalkRunPointer retrievedRandomWalkRun = getRandomWalkRun( 
            databasePath, randomWalkRunName, randomWalkRunTableName ); 

        const double perturberRingNumberDensity = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "PERTURBERRINGNUMBERDENSITY" ),
                    retrievedRandomWalkRun->perturberRingNumberDensity );    
        cout << "Perturber ring number density                             " 
             << perturberRingNumberDensity << " perturbers per R_Hill" << endl;

        const double perturberRingMass = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "PERTURBERRINGMASS" ),
                    retrievedRandomWalkRun->perturberRingMass );    
        cout << "Perturber ring mass                                       "
             << perturberRingMass << " M_PerturbedBody" << endl;              

        const double observationPeriod = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "OBSERVATIONPERIOD" ),
                    retrievedRandomWalkRun->observationPeriod, &convertJulianYearsToSeconds );
        cout << "Observation period                                        "
             << convertSecondsToJulianYears( observationPeriod ) << " yrs" << endl; 

        const unsigned int numberOfEpochWindows = extractParameterValue< unsigned int >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "NUMBEROFEPOCHWINDOWS" ),
                    retrievedRandomWalkRun->numberOfEpochWindows );    
        cout << "Number of epoch windows                                   "
             << numberOfEpochWindows << endl;                                                 

        const double epochWindowSize = extractParameterValue< double >(
                    parsedData->begin( ), parsedData->end( ),
                    findEntry( dictionary, "EPOCHWINDOWSIZE" ),
                    retrievedRandomWalkRun->epochWindowSize, &convertJulianDaysToSeconds  );
        cout << "Epoch window size                                         "
             << convertSecondsToJulianDays( epochWindowSize ) << " days" << endl;     

        // Store random walk run data with possible overwritten data.
        randomWalkRun = make_shared< RandomWalkRun >( 
            retrievedRandomWalkRun->randomWalkRunId, randomWalkRunName, 
            retrievedRandomWalkRun->testParticleCaseId, perturberRingNumberDensity,
            perturberRingMass, observationPeriod, numberOfEpochWindows, epochWindowSize );
    }

    // Check that all required parameters have been set.
    checkRequiredParameters( dictionary );

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Fetch test particle case and random walk input data from database.

    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Database operations" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Generate output message.
    cout << "Fetching test particle case data from database ..." << endl;      

    // Retrieve and store test particle case data.
    const TestParticleCasePointer testParticleCaseData = getTestParticleCase( 
        databasePath, randomWalkRun->testParticleCaseId, testParticleCaseTableName ); 

    // Generate output message to indicate that test particle case data was fetched successfully.
    cout << "Test particle case data fetched successfully from database!" << endl;   

    // Generate output message.
    cout << "Fetching random walk input data from database ..." << endl;   

    // Check if all incomplete random walk simulations are to be executed and fetch the random
    // walk input table, else only fetch the requested random walk simulation IDs.
    RandomWalkInputTable randomWalkInputTable;

    if ( iequals( randomWalkSimulations, "ALL" )  )
    {
        cout << "Fetching all incomplete random walk Monte Carlo runs ..." << endl;    

        // Get entire random walk input table from database.
        randomWalkInputTable = getCompleteRandomWalkInputTable(
                    databasePath, randomWalkRun->randomWalkRunId, 
                    randomWalkInputTableName, randomWalkPerturberTableName );
    }

    else
    {
        cout << "Fetching all requested random walk Monte Carlo runs ..." << endl;    

        // Get selected random walk input table from database.
        randomWalkInputTable = getSelectedRandomWalkInputTable(
                    databasePath, randomWalkRun->randomWalkRunId, randomWalkSimulations, 
                    randomWalkInputTableName, randomWalkPerturberTableName );
    }

    // Generate output message to indicate that the input table was fetched successfully.
    cout << "Random walk input data (" << randomWalkInputTable.size( )
         << " rows) fetched successfully from database!" << endl;    

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Compute derived parameters.

    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Derived parameters" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Compute epoch window spacing [s].
    const double epochWindowSpacing 
        = randomWalkRun->observationPeriod / ( randomWalkRun->numberOfEpochWindows - 1 );
    cout << "Epoch window spacing                                      " 
         << convertSecondsToJulianDays( epochWindowSpacing ) << " days" << endl;

    // Compute mass of perturbed body [kg].
    const double perturbedBodyMass = computeMassOfSphere(
                testParticleCaseData->perturbedBodyRadius, 
                testParticleCaseData->perturbedBodyBulkDensity );
    cout << "Perturbed body mass                                       " 
         << perturbedBodyMass << " kg" << endl;

    // Compute perturbed body's gravitational parameter [m^3 s^-2].
    const double perturbedBodyGravitationalParameter
            = computeGravitationalParameter( perturbedBodyMass );
    cout << "Perturbed body gravitational parameter                    " 
         << perturbedBodyGravitationalParameter << " m^3 s^-2" << endl;
         
    // Compute perturber population using density and semi-major axis distribution limits.
    // Note, in the floor() function, adding 0.5 is a workaround for the fact that there is no
    // round() function in C++03 (it is available in C++11).
    ConvertHillRadiiToMeters convertHillRadiiToMeters( 
        testParticleCaseData->centralBodyGravitationalParameter, 
        perturbedBodyGravitationalParameter, 
        testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0( semiMajorAxisIndex ) );
    const double perturberRingNumberDensityInMeters 
        = randomWalkRun->perturberRingNumberDensity / convertHillRadiiToMeters( 1.0 );
    const unsigned int perturberPopulation = std::floor( 
        2.0 * testParticleCaseData->semiMajorAxisDistributionLimit 
        * perturberRingNumberDensityInMeters + 0.5 );
    cout << "Perturber population                                      " 
         << perturberPopulation << endl;

    // Compute perturber mass ratio.
    // Note, for the random walk simulations, the mass ratio is equal for all perturbers.
    const double perturberMassRatio = randomWalkRun->perturberRingMass / perturberPopulation;
    cout << "Perturber mass ratio                                      "
         << perturberMassRatio << endl;

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Execute Monte Carlo simulation.
    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Simulation loop" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Execute simulation loop.
    cout << "Starting simulation loop ... " << endl;
    cout << randomWalkInputTable.size( ) << " random walk simulations queued for execution ..." 
         << endl;
    cout << endl;    

    // Loop over input table.
#pragma omp parallel for num_threads( numberOfThreads )
    for ( unsigned int i = 0; i < randomWalkInputTable.size( ); i++ )
    {
        ///////////////////////////////////////////////////////////////////////////

        // Set input table iterator and emit output message.

        // Set input table iterator for current simulation wrt to start of input table and counter.
        RandomWalkInputTable::iterator iteratorRandomWalkInputTable 
            = randomWalkInputTable.begin( );
        advance( iteratorRandomWalkInputTable, i );

        // Emit output message.
#pragma omp critical( outputToConsole )
        {
            cout << "Random walk simulation " 
                 << iteratorRandomWalkInputTable->randomWalkSimulationId 
                 << " on thread " << omp_get_thread_num( ) + 1 << " / " 
                 << omp_get_num_threads( ) << endl;
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Fetch test particle kick table based on test particle simulation IDs for random walk 
        // simulation.
        TestParticleKickTable testParticleKickTable;
#pragma omp critical( databaseOperations )
        {        
            testParticleKickTable = getTestParticleKickTable( 
                databasePath, testParticleCaseData->randomWalkSimulationPeriod,
                iteratorRandomWalkInputTable->testParticleSimulationIds, 
                testParticleKickTableName );
        }

        // Check if output mode is set to "FILE".
        // If so, open output file and write test particle kick table data.
        // Check if the output directory exists: if not, create it.
        if ( iequals( outputMode, "FILE" ) )
        {
            // Check if output directory exists.
            if ( !exists( fileOutputDirectory ) )
            {
               cerr << "Directory does not exist. Will be created." << endl;
               create_directories( fileOutputDirectory );
            }        

            // Declare file handler.
            ofstream testParticleKickTableFile;

            // Set up and write file header to file.
            ostringstream testParticleKickTableFilename;
            testParticleKickTableFilename << fileOutputDirectory << "randomWalkSimulation" 
                                          << iteratorRandomWalkInputTable->randomWalkSimulationId 
                                          << "_testParticleKickTable.csv";    

            testParticleKickTableFile.open( testParticleKickTableFilename.str( ).c_str( ) );

            testParticleKickTableFile 
                << "kickId,simulationId,conjunctionEpoch,conjunctionDistance,"
                << "preConjunctionEpoch,preConjunctionDistance,"
                << "preConjunctionSemiMajorAxis,preConjunctionEccentricity,"
                << "preConjunctionInclination,preConjunctionArgumentOfPeriapsis,"
                << "preConjunctionLongitudeOfAscendingNode,preConjunctionTrueAnomaly"
                << "postConjunctionEpoch,postConjunctionDistance,"
                << "postConjunctionSemiMajorAxis,postConjunctionEccentricity,"
                << "postConjunctionInclination,postConjunctionArgumentOfPeriapsis,"
                << "postConjunctionLongitudeOfAscendingNode,postConjunctionTrueAnomaly"
                << endl;
            testParticleKickTableFile 
                << "# [-],[-],[s],[m],[s],[m],[m],[-],[rad],[rad],[rad],[rad]," 
                << "[s],[m],[m],[-],[rad],[rad],[rad],[rad]" << endl;       

            // Write test particle kick table to file.
            for ( TestParticleKickTable::iterator iteratorTestParticleKicks 
                    = testParticleKickTable.begin( );
                  iteratorTestParticleKicks != testParticleKickTable.end( );
                  iteratorTestParticleKicks++ )
            {
                testParticleKickTableFile 
                    << iteratorTestParticleKicks->testParticleKickId << "," 
                    << iteratorTestParticleKicks->testParticleSimulationId << ",";
                testParticleKickTableFile
                    << setprecision( numeric_limits< double >::digits10 )
                    << iteratorTestParticleKicks->conjunctionEpoch << ","
                    << iteratorTestParticleKicks->conjunctionDistance << ","
                    << iteratorTestParticleKicks->preConjunctionEpoch << ","
                    << iteratorTestParticleKicks->preConjunctionDistance << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        semiMajorAxisIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        eccentricityIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        inclinationIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        argumentOfPeriapsisIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        longitudeOfAscendingNodeIndex ) << ","
                    << iteratorTestParticleKicks->preConjunctionStateInKeplerianElements( 
                        trueAnomalyIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionEpoch << ","
                    << iteratorTestParticleKicks->postConjunctionDistance << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        semiMajorAxisIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        eccentricityIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        inclinationIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        argumentOfPeriapsisIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        longitudeOfAscendingNodeIndex ) << ","
                    << iteratorTestParticleKicks->postConjunctionStateInKeplerianElements( 
                        trueAnomalyIndex ) << endl;
            }                 

            // Close file handler.
            testParticleKickTableFile.close( );
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Execute random walk simulation.

        // Declare perturbed body propagation history. This stores the propagation history of the
        // action variables only (semi-major axis, eccentricity, inclination).
        DoubleKeyVector3dValueMap keplerianActionElementsHistory;

        // Set perturbed body initial state (actions) in Keplerian elements.
        keplerianActionElementsHistory[ 0.0 ]
                = testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0.segment( 0, 3 );

        // Declare iterator to previous state in Keplerian elements.
        DoubleKeyVector3dValueMap::iterator iteratorPreviousKeplerianElements
                = keplerianActionElementsHistory.begin( );

        // Loop through aggregate kick table and execute kicks on perturbed body. 
        for ( TestParticleKickTable::iterator iteratorKickTable = testParticleKickTable.begin( );
              iteratorKickTable != testParticleKickTable.end( ); iteratorKickTable++ )
        {
            // Execute kick and store results in propagation history.
            keplerianActionElementsHistory[ iteratorKickTable->conjunctionEpoch ]
                    = executeKick( iteratorPreviousKeplerianElements->second,
                                   iteratorKickTable, perturberMassRatio );

            advance( iteratorPreviousKeplerianElements, 1 );
        }

        // Check if output mode is set to "FILE".
        // If so, open output file and write header content.
        if ( iequals( outputMode, "FILE" ) )
        {
            ostringstream keplerianActionElementsFilename;
            keplerianActionElementsFilename << "randomWalkSimulation" 
                                            << iteratorRandomWalkInputTable->randomWalkSimulationId
                                            << "_keplerianActionElements.csv"; 
            
            ostringstream keplerianActionElementsFileHeader;
            keplerianActionElementsFileHeader << "epoch,semiMajorAxis,eccentricity,inclination" 
                                              << endl;
            keplerianActionElementsFileHeader << "# [s],[m],[-],[rad]" << endl;

            writeDataMapToTextFile( keplerianActionElementsHistory,
                                    keplerianActionElementsFilename.str( ),
                                    fileOutputDirectory, 
                                    keplerianActionElementsFileHeader.str( ),
                                    numeric_limits< double >::digits10, 
                                    numeric_limits< double >::digits10,
                                    "," ); 
        }        

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Compute average longitude residual and maximum longitude residual change in observation
        // period.

        // Declare average longitude residual in observation period [-].
        double averageLongitudeResidual = TUDAT_NAN;

        // Declare maximum longitude residual change in observation period [-].
        double maximumLongitudeResidualChange = TUDAT_NAN;

        // Declare map of average longitude residuals per window [rad].
        DoubleKeyDoubleValueMap averageLongitudeResiduals;

        {
            // Populate temporary map with epochs and semi-major axes.
            DoubleKeyDoubleValueMap semiMajorAxisHistory;

            for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements 
                  = keplerianActionElementsHistory.begin( );
                  iteratorKeplerianActionElements != keplerianActionElementsHistory.end( );
                  iteratorKeplerianActionElements++ )
            {
                semiMajorAxisHistory[ iteratorKeplerianActionElements->first ]
                    = iteratorKeplerianActionElements->second( semiMajorAxisIndex );
            }  

            // Compute longitude history.
            DoubleKeyDoubleValueMap longitudeHistory
                    = computeLongitudeHistory( 
                        semiMajorAxisHistory,
                        testParticleCaseData->centralBodyGravitationalParameter );      

            // Compute reduced longitude history (data is reduced to only the epoch windows).
            DoubleKeyDoubleValueMap reducedLongitudeHistory
                    = reduceLongitudeHistory( 
                        longitudeHistory, 
                        iteratorRandomWalkInputTable->observationPeriodStartEpoch,
                        epochWindowSpacing, 
                        randomWalkRun->epochWindowSize,
                        randomWalkRun->numberOfEpochWindows ); 

            // Set input data for simple linear regression.
            SimpleLinearRegression longitudeHistoryRegression( reducedLongitudeHistory );
         
            // Compute linear fit.
            longitudeHistoryRegression.computeFit( );        
                
            // Store longitude residuals history.
            DoubleKeyDoubleValueMap longitudeResidualsHistory;

            // Generate longitude history residuals by subtracting linear fit from data.
            for ( DoubleKeyDoubleValueMap::iterator iteratorReducedLongitudeHistory
                    = reducedLongitudeHistory.begin( );
                  iteratorReducedLongitudeHistory != reducedLongitudeHistory.end( );
                  iteratorReducedLongitudeHistory++ )
            {
                longitudeResidualsHistory[ iteratorReducedLongitudeHistory->first ]
                        = iteratorReducedLongitudeHistory->second
                          - longitudeHistoryRegression.getCoefficientOfConstantTerm( )
                          - longitudeHistoryRegression.getCoefficientOfLinearTerm( )
                          * iteratorReducedLongitudeHistory->first;
            }           

            // Loop over observation period and compute average longitude residuals per epoch window.
            for ( int windowNumber = 0; 
                  windowNumber < randomWalkRun->numberOfEpochWindows; 
                  windowNumber++ )
            {
                const double epochWindowCenter 
                    = iteratorRandomWalkInputTable->observationPeriodStartEpoch 
                      + windowNumber * epochWindowSpacing;

                averageLongitudeResiduals[ epochWindowCenter ] 
                    = computeStepFunctionWindowAverage( 
                        longitudeResidualsHistory, 
                        epochWindowCenter - 0.5 * randomWalkRun->epochWindowSize, 
                        epochWindowCenter + 0.5 * randomWalkRun->epochWindowSize );
            }

             // Compute average longitude residual during propagation history.
            double sumLongitudeResiduals = 0.0;

            for ( DoubleKeyDoubleValueMap::iterator iteratorAverageLongitudeResiduals 
                    = averageLongitudeResiduals.begin( );
                  iteratorAverageLongitudeResiduals != averageLongitudeResiduals.end( );
                  iteratorAverageLongitudeResiduals++ )
            {
                sumLongitudeResiduals += iteratorAverageLongitudeResiduals->second;
            }

            averageLongitudeResidual 
                = sumLongitudeResiduals / randomWalkRun->numberOfEpochWindows;

            // Compute maximum longitude residual change during propagation history.
            maximumLongitudeResidualChange 
                = ( max_element( averageLongitudeResiduals.begin( ), 
                                 averageLongitudeResiduals.end( ),
                                 CompareDoubleKeyDoubleValueMapValues( ) ) )->second
                  - ( min_element( averageLongitudeResiduals.begin( ), 
                                   averageLongitudeResiduals.end( ),
                                   CompareDoubleKeyDoubleValueMapValues( ) ) )->second;            

            // Check if output mode is set to "FILE".
            // If so, open output file and write header content.
            if ( iequals( outputMode, "FILE" ) )
            {
                ostringstream longitudeHistoryFilename;
                longitudeHistoryFilename << "randomWalkSimulation"
                                         << iteratorRandomWalkInputTable->randomWalkSimulationId
                                         << "_longitudeHistory.csv"; 
                
                ostringstream longitudeHistoryFileHeader;
                longitudeHistoryFileHeader << "epoch,longitude" << endl;
                longitudeHistoryFileHeader << "# [s],[rad]" << endl;

                writeDataMapToTextFile( longitudeHistory,
                                        longitudeHistoryFilename.str( ),
                                        fileOutputDirectory, 
                                        longitudeHistoryFileHeader.str( ),
                                        numeric_limits< double >::digits10, 
                                        numeric_limits< double >::digits10,
                                        "," );             

                ostringstream reducedLongitudeHistoryFilename;
                reducedLongitudeHistoryFilename 
                    << "randomWalkSimulation" 
                    << iteratorRandomWalkInputTable->randomWalkSimulationId
                    << "_reducedLongitudeHistory.csv"; 
                
                ostringstream reducedLongitudeHistoryFileHeader;
                reducedLongitudeHistoryFileHeader << "epoch,longitude" << endl;
                reducedLongitudeHistoryFileHeader << "# [s],[rad]" << endl;

                writeDataMapToTextFile( reducedLongitudeHistory,
                                        reducedLongitudeHistoryFilename.str( ),
                                        fileOutputDirectory, 
                                        reducedLongitudeHistoryFileHeader.str( ),
                                        numeric_limits< double >::digits10, 
                                        numeric_limits< double >::digits10,
                                        "," );            

                ostringstream longitudeResidualsFilename;
                longitudeResidualsFilename << "randomWalkSimulation"
                                           << iteratorRandomWalkInputTable->randomWalkSimulationId
                                           << "_longitudeResiduals.csv"; 
                
                ostringstream longitudeResidualsFileHeader;
                longitudeResidualsFileHeader << "epoch,longitudeResidual" << endl;
                longitudeResidualsFileHeader << "# [s],[rad]" << endl;      

                writeDataMapToTextFile( longitudeResidualsHistory,
                                        longitudeResidualsFilename.str( ),
                                        fileOutputDirectory, 
                                        longitudeResidualsFileHeader.str( ),
                                        numeric_limits< double >::digits10, 
                                        numeric_limits< double >::digits10,
                                        "," );                                                 
            }                       
        }

        ///////////////////////////////////////////////////////////////////////////        

        ///////////////////////////////////////////////////////////////////////////

        // Compute average eccentricity and maximum eccentricity change in observation window.

        // Declare average eccentricity in observation period [-].
        double averageEccentricity = TUDAT_NAN;

        // Declare maximum eccentricity change in observation period [-].
        double maximumEccentricityChange = TUDAT_NAN;

        // Declare map of average eccentricities per window [-].
        DoubleKeyDoubleValueMap averageEccentricities;

        {
            // Populate temporary map with epochs and eccentricities.
            DoubleKeyDoubleValueMap eccentricityHistory;

            for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements 
                  = keplerianActionElementsHistory.begin( );
                  iteratorKeplerianActionElements != keplerianActionElementsHistory.end( );
                  iteratorKeplerianActionElements++ )
            {
                eccentricityHistory[ iteratorKeplerianActionElements->first ]
                    = iteratorKeplerianActionElements->second( eccentricityIndex );
            }            

            // Loop over observation period and compute average eccentricities per epoch window.
            for ( int windowNumber = 0; 
                  windowNumber < randomWalkRun->numberOfEpochWindows; 
                  windowNumber++ )
            {
                const double epochWindowCenter 
                    = iteratorRandomWalkInputTable->observationPeriodStartEpoch
                      + windowNumber * epochWindowSpacing;

                averageEccentricities[ epochWindowCenter ] 
                    = computeStepFunctionWindowAverage( 
                        eccentricityHistory, 
                        epochWindowCenter - 0.5 * randomWalkRun->epochWindowSize, 
                        epochWindowCenter + 0.5 * randomWalkRun->epochWindowSize );
            }

            // Compute average eccentricity during propagation history.
            double sumEccentricities = 0.0;

            for ( DoubleKeyDoubleValueMap::iterator iteratorAverageEccentricities 
                    = averageEccentricities.begin( );
                  iteratorAverageEccentricities != averageEccentricities.end( );
                  iteratorAverageEccentricities++ )
            {
                sumEccentricities += iteratorAverageEccentricities->second;
            }

            averageEccentricity = sumEccentricities / randomWalkRun->numberOfEpochWindows;

            // Compute maximum eccentricity change during propagation history.
            maximumEccentricityChange 
                = ( max_element( averageEccentricities.begin( ), 
                                 averageEccentricities.end( ),
                                 CompareDoubleKeyDoubleValueMapValues( ) ) )->second
                  - ( min_element( averageEccentricities.begin( ), 
                                   averageEccentricities.end( ),
                                   CompareDoubleKeyDoubleValueMapValues( ) ) )->second;            
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Compute average inclination and maximum inclination change in observation window.

        // Declare average inclination in observation period [rad].
        double averageInclination = TUDAT_NAN;

        // Declare maximum inclination change in observation period [rad].
        double maximumInclinationChange = TUDAT_NAN;

        // Declare map of average inclinations per window [rad].
        DoubleKeyDoubleValueMap averageInclinations;        

        {
            // Populate temporary map with epochs and inclinations.
            DoubleKeyDoubleValueMap inclinationHistory;

            for ( DoubleKeyVector3dValueMap::iterator iteratorKeplerianActionElements 
                  = keplerianActionElementsHistory.begin( );
                  iteratorKeplerianActionElements != keplerianActionElementsHistory.end( );
                  iteratorKeplerianActionElements++ )
            {
                inclinationHistory[ iteratorKeplerianActionElements->first ]
                    = iteratorKeplerianActionElements->second( inclinationIndex );
            }            

            // Loop over observation period and compute average inclinations per epoch window.
            for ( int windowNumber = 0; 
                  windowNumber < randomWalkRun->numberOfEpochWindows; 
                  windowNumber++ )
            {
                const double epochWindowCenter 
                    = iteratorRandomWalkInputTable->observationPeriodStartEpoch
                      + windowNumber * epochWindowSpacing;

                averageInclinations[ epochWindowCenter ] 
                    = computeStepFunctionWindowAverage( 
                        inclinationHistory, 
                        epochWindowCenter - randomWalkRun->epochWindowSize * 0.5, 
                        epochWindowCenter + randomWalkRun->epochWindowSize * 0.5 );
            }

            // Compute average inclination during propagation history.
            double sumInclinations = 0.0;

            for ( DoubleKeyDoubleValueMap::iterator iteratorAverageInclinations 
                    = averageInclinations.begin( );
                  iteratorAverageInclinations != averageInclinations.end( );
                  iteratorAverageInclinations++ )
            {
                sumInclinations += iteratorAverageInclinations->second;
            }

            averageInclination = sumInclinations / randomWalkRun->numberOfEpochWindows;

            // Compute maximum inclination change during propagation history.
            maximumInclinationChange 
                = ( max_element( averageInclinations.begin( ), 
                                 averageInclinations.end( ),
                                 CompareDoubleKeyDoubleValueMapValues( ) ) )->second
                  - ( min_element( averageInclinations.begin( ), 
                                   averageInclinations.end( ),
                                   CompareDoubleKeyDoubleValueMapValues( ) ) )->second;        
        }

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Write epoch-windoow average values to file.

        // Check if output mode is set to "FILE".
        // If so, open output file and write header content.
        if ( iequals( outputMode, "FILE" ) )
        {
            // Declare file handler.
            ofstream epochWindowAveragesFile;   

            ostringstream epochWindowAveragesFilename;
            epochWindowAveragesFilename << fileOutputDirectory << "randomWalkRun" 
                                        << iteratorRandomWalkInputTable->randomWalkSimulationId
                                        << "_epochWindowAverages.csv";
            
            epochWindowAveragesFile.open( epochWindowAveragesFilename.str( ).c_str( ) );

            epochWindowAveragesFile << "epoch,longitudeResidual,eccentricity,inclination" << endl;
            epochWindowAveragesFile << "# [s],[rad],[-],[rad]" << endl; 

            // Loop through epoch-window averages and write data to file.
            DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageLongitudeResiduals
                = averageLongitudeResiduals.begin( );
            DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageEccentricities
                = averageEccentricities.begin( );
            DoubleKeyDoubleValueMap::iterator iteratorEpochWindowAverageInclinations
                = averageInclinations.begin( );
                                                
            for ( int i = 0; i < randomWalkRun->numberOfEpochWindows; i++ )
            {
                epochWindowAveragesFile 
                    << setprecision( numeric_limits< double >::digits10 )
                    << iteratorEpochWindowAverageLongitudeResiduals->first << ","
                    << iteratorEpochWindowAverageLongitudeResiduals->second << ","
                    << iteratorEpochWindowAverageEccentricities->second << ","
                    << iteratorEpochWindowAverageInclinations->second << endl;

                iteratorEpochWindowAverageLongitudeResiduals++;    
                iteratorEpochWindowAverageEccentricities++;
                iteratorEpochWindowAverageInclinations++;
            }

            // Close file handler.
            epochWindowAveragesFile.close( );
        }        

        ///////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////

        // Write random walk output to database. To avoid locking of the database, this section is
        // thread-critical, so will be executed one-by-one by multiple threads.

        // Check if output mode is set to "DATABASE".
        if ( iequals( outputMode, "DATABASE" ) )
        {
    #pragma omp critical( databaseOperations )
            {
                // Populate output table in database.
                populateRandomWalkOutputTable( 
                    databasePath, iteratorRandomWalkInputTable->randomWalkSimulationId,
                    averageLongitudeResidual, maximumLongitudeResidualChange,
                    averageEccentricity, maximumEccentricityChange,
                    averageInclination, maximumInclinationChange,
                    randomWalkOutputTableName, randomWalkInputTableName );
            }
        }

        /////////////////////////////////////////////////////////////////
    } // simulation for-loop

    ///////////////////////////////////////////////////////////////////
}
示例#15
0
BidirectionalIterator
wait_some(BidirectionalIterator first, BidirectionalIterator last)
{
  using std::advance;

  if (first == last)
    return first;

  typedef typename std::iterator_traits<BidirectionalIterator>::difference_type
    difference_type;

  bool all_trivial_requests = true;
  difference_type n = 0;
  BidirectionalIterator current = first;
  BidirectionalIterator start_of_completed = last;
  while (true) {
    // Check if we have found a completed request.
    if (optional<status> result = current->test()) {
      using std::iter_swap;

      // We're expanding the set of completed requests
      --start_of_completed;

      // If we have hit the end of the list of pending requests, we're
      // done.
      if (current == start_of_completed)
        return start_of_completed;

      // Swap the request we just completed with the last request that
      // has not yet been tested.
      iter_swap(current, start_of_completed);

      continue;
    }

    // Check if this request (and all others before it) are "trivial"
    // requests, e.g., they can be represented with a single
    // MPI_Request.
    all_trivial_requests =
      all_trivial_requests
      && !current->m_handler
      && current->m_requests[1] == MPI_REQUEST_NULL;

    // Move to the next request.
    ++n;
    if (++current == start_of_completed) {
        // If we have satisfied some requests, we're done.
      if (start_of_completed != last)
        return start_of_completed;

      // We have reached the end of the list. If all requests thus far
      // have been trivial, we can call MPI_Waitsome directly, because
      // it may be more efficient than our busy-wait semantics.
      if (all_trivial_requests) {
        std::vector<MPI_Request> requests;
        std::vector<int> indices(n);
        requests.reserve(n);
        for (current = first; current != last; ++current)
          requests.push_back(current->m_requests[0]);

        // Let MPI wait until some of these operations complete.
        int num_completed;
        BOOST_MPI_CHECK_RESULT(MPI_Waitsome,
                               (n, &requests[0], &num_completed, &indices[0],
                                MPI_STATUSES_IGNORE));

        // Translate the index-based result of MPI_Waitsome into a
        // partitioning on the requests.
        int current_offset = 0;
        current = first;
        for (int index = 0; index < num_completed; ++index) {
          using std::iter_swap;

          // Move "current" to the request object at this index
          advance(current, indices[index] - current_offset);
          current_offset = indices[index];

          // Finish up the request and swap it into the "completed
          // requests" partition.
          current->m_requests[0] = requests[indices[index]];
          --start_of_completed;
          iter_swap(current, start_of_completed);
        }

        // We have satisfied some requests, so we are done.
        return start_of_completed;
      }

      // There are some nontrivial requests, so we must continue our
      // busy waiting loop.
      n = 0;
      current = first;
    }
  }

  // We cannot ever get here
  BOOST_ASSERT(false);
}
示例#16
0
std::pair<status, ForwardIterator>
wait_any(ForwardIterator first, ForwardIterator last)
{
  using std::advance;

  BOOST_ASSERT(first != last);

  typedef typename std::iterator_traits<ForwardIterator>::difference_type
    difference_type;

  bool all_trivial_requests = true;
  difference_type n = 0;
  ForwardIterator current = first;
  while (true) {
    // Check if we have found a completed request. If so, return it.
    if (current->m_requests[0] != MPI_REQUEST_NULL &&
        (current->m_requests[1] != MPI_REQUEST_NULL ||
         current->m_handler)) {
      if (optional<status> result = current->test())
        return std::make_pair(*result, current);
    }

    // Check if this request (and all others before it) are "trivial"
    // requests, e.g., they can be represented with a single
    // MPI_Request.
    all_trivial_requests =
      all_trivial_requests
      && !current->m_handler
      && current->m_requests[1] == MPI_REQUEST_NULL;

    // Move to the next request.
    ++n;
    if (++current == last) {
      // We have reached the end of the list. If all requests thus far
      // have been trivial, we can call MPI_Waitany directly, because
      // it may be more efficient than our busy-wait semantics.
      if (all_trivial_requests) {
        std::vector<MPI_Request> requests;
        requests.reserve(n);
        for (current = first; current != last; ++current)
          requests.push_back(current->m_requests[0]);

        // Let MPI wait until one of these operations completes.
        int index;
        status stat;
        BOOST_MPI_CHECK_RESULT(MPI_Waitany,
                               (n, &requests[0], &index, &stat.m_status));

        // We don't have a notion of empty requests or status objects,
        // so this is an error.
        if (index == MPI_UNDEFINED)
          boost::throw_exception(exception("MPI_Waitany", MPI_ERR_REQUEST));

        // Find the iterator corresponding to the completed request.
        current = first;
        advance(current, index);
        current->m_requests[0] = requests[index];
        return std::make_pair(stat, current);
      }

      // There are some nontrivial requests, so we must continue our
      // busy waiting loop.
      n = 0;
      current = first;
      all_trivial_requests = true;
    }
  }

  // We cannot ever get here
  BOOST_ASSERT(false);
}
//! Execute random walk database generator.
void executeRandomWalkDatabaseGenerator( 
    const std::string databasePath, 
    const tudat::input_output::parsed_data_vector_utilities::ParsedDataVectorPtr parsedData )
{
    ///////////////////////////////////////////////////////////////////////////

    // Declare using-statements.

    using std::advance;
    using std::cout;
    using std::endl;
    using std::generate;
    using std::ostringstream;
    using std::numeric_limits;
    using std::runtime_error;
    using std::setprecision;
    using std::string;
    using std::vector;

    using namespace boost::filesystem;
    using namespace boost::random;

    using namespace SQLite;

    using namespace assist::astrodynamics;
    // using namespace assist::input_output;

    using namespace tudat::basic_astrodynamics::orbital_element_conversions;
    using namespace tudat::basic_mathematics;
    using namespace tudat::input_output::dictionary;

    using namespace stomi::database;
    using namespace stomi::input_output;    

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Extract input parameters.

    // Get dictionary.
    const DictionaryPointer dictionary = getRandomWalkDatabaseGeneratorDictionary( );

    // Print database path to console.
    cout << "Database                                                  " 
         << databasePath << endl;

    // Extract required parameters.
    const string randomWalkRunName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ), 
                findEntry( dictionary, "RANDOMWALKRUN" ) );
    cout << "Run                                                       " 
         << randomWalkRunName << endl;

    const string testParticleCaseName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ), 
                findEntry( dictionary, "TESTPARTICLECASE" ) );
    cout << "Test particle case                                        " 
         << testParticleCaseName << endl;

    const unsigned int monteCarloPopulation = extractParameterValue< unsigned int >(
                parsedData->begin( ), parsedData->end( ), 
                findEntry( dictionary, "MONTECARLOPOPULATION" ) );
    cout << "Monte Carlo population                                    "
         << monteCarloPopulation << endl;    

    const double perturberRingNumberDensity = extractParameterValue< double >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "PERTURBERRINGNUMBERDENSITY" ) );    
    cout << "Perturber ring number density                             " 
         << perturberRingNumberDensity << " perturbers per R_Hill" << endl;

    const double perturberRingMass = extractParameterValue< double >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "PERTURBERRINGMASS" ) );    
    cout << "Perturber ring mass                                       "
         << perturberRingMass << " M_PerturbedBody" << endl;      

    const double observationPeriod = extractParameterValue< double >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "OBSERVATIONPERIOD" ),
                TUDAT_NAN, &convertJulianYearsToSeconds );
    cout << "Observation period                                        "
         << convertSecondsToJulianYears( observationPeriod ) << " yrs" << endl; 

    const unsigned int numberOfEpochWindows = extractParameterValue< unsigned int >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "NUMBEROFEPOCHWINDOWS" ) );    
    cout << "Number of epoch windows                                   "
         << numberOfEpochWindows << endl;                                                 

    const double epochWindowSize = extractParameterValue< double >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "EPOCHWINDOWSIZE" ),
                TUDAT_NAN, &convertJulianDaysToSeconds  );
    cout << "Epoch window size                                         "
         << convertSecondsToJulianDays( epochWindowSize ) << " days" << endl;                    

    // Extract optional parameters (parameters that take on default values if they are not  
    // specified in the configuration file).

    const string randomWalkRunTable = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKRUNTABLENAME" ),
                "random_walk_run" );
    cout << "Random walk run table                                     " 
         << randomWalkRunTable << endl;

    const string randomWalkInputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKINPUTTABLENAME" ),
                "random_walk_input" );
    cout << "Random walk input table                                   " 
         << randomWalkInputTableName << endl;          

    const string randomWalkPerturberTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKPERTURBERTABLENAME" ),
                "random_walk_perturbers" );
    cout << "Random walk perturber table                               "
         << randomWalkPerturberTableName << endl;  

    const string randomWalkOutputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "RANDOMWALKOUTPUTTABLENAME" ), "random_walk_output" );
    cout << "Random walk output table                                  "
         << randomWalkOutputTableName << endl;                     

    const string testParticleCaseTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "TESTPARTICLECASETABLENAME" ), "test_particle_case" );
    cout << "Test particle case table                                  "
         << testParticleCaseTableName << endl;

    const string testParticleInputTableName = extractParameterValue< string >(
                parsedData->begin( ), parsedData->end( ),
                findEntry( dictionary, "TESTPARTICLEINPUTTABLENAME" ), "test_particle_input" );
    cout << "Test particle input table                                 "
         << testParticleInputTableName << endl;                

    // Check that all required parameters have been set.
    checkRequiredParameters( dictionary );

    ///////////////////////////////////////////////////////////////////////////  

    ///////////////////////////////////////////////////////////////////////////

    cout << endl;
    cout << "****************************************************************************" << endl;
    cout << "Database operations" << endl;
    cout << "****************************************************************************" << endl;
    cout << endl;

    // Open (and if necessary create) database.

    // Check if database file already exists.
    bool isDatabaseCreated = false;
    if ( exists( databasePath ) )
    {
        cout << "Opening existing database at " << databasePath << " ..." << endl;
    }

    else
    {
        isDatabaseCreated = true;
        cout << "WARNING: Database does not exist!" << endl;
        cout << "Creating database at " << databasePath << " ..." << endl;
    }

    // Create/open database.          
    Database database( databasePath.c_str( ), SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE );

    cout << "SQLite database file '" << database.getFilename( ).c_str( );
    if ( isDatabaseCreated ) { cout << "' created &"; }
    cout << " opened successfully ..." << endl;

    // Fetch test particle case and input data from database.

    // Generate output message.
    cout << "Fetching test particle case data from database ..." << endl;   

    // Retrieve and store test particle case data.
    const TestParticleCasePointer testParticleCaseData = getTestParticleCase( 
        databasePath, testParticleCaseName, testParticleCaseTableName ); 

    // Generate output message to indicate that test particle case data was fetched successfully.
    cout << "Test particle case data fetched successfully from database!" << endl;   

    // Generate output message.
    cout << "Fetching test particle input data from database ..." << endl;   

    // Get entire test particle input table from database. Only test particle simulations that 
    // are complete are fetched for the given test particle case ID.
    const TestParticleInputTable testParticleInputTable 
        = getCompleteTestParticleInputTable( 
            databasePath, testParticleCaseData->testParticleCaseId, 
            testParticleInputTableName, true );    

    // Generate output message to indicate that test particle input table was fetched successfully.
    cout << "Test particle input data (" << testParticleInputTable.size( )
         << " rows) fetched successfully from database!" << endl; 

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Compute derived parameters.

    // Compute mass of perturbed body [kg].
    const double perturbedBodyMass = computeMassOfSphere(
                testParticleCaseData->perturbedBodyRadius, 
                testParticleCaseData->perturbedBodyBulkDensity );

    // Compute perturbed body's gravitational parameter [m^3 s^-2].
    const double perturbedBodyGravitationalParameter
            = computeGravitationalParameter( perturbedBodyMass );

    // Compute perturber population using density and semi-major axis distribution limits.
    // Note, in the floor() function, adding 0.5 is a workaround for the fact that there is no
    // round() function in C++03 (it is available in C++11).
    ConvertHillRadiiToMeters convertHillRadiiToMeters( 
        testParticleCaseData->centralBodyGravitationalParameter, 
        perturbedBodyGravitationalParameter, 
        testParticleCaseData->perturbedBodyStateInKeplerianElementsAtT0( semiMajorAxisIndex ) );
    const double perturberRingNumberDensityInMeters = perturberRingNumberDensity / convertHillRadiiToMeters( 1.0 );
    const unsigned int perturberPopulation = std::floor( 
        2.0 * testParticleCaseData->semiMajorAxisDistributionLimit 
        * perturberRingNumberDensityInMeters + 0.5 );

    // Check if desired perturber population is greater than number of completed simulations 
    // fetched, from the database input table, throw a run-time error.
    if ( perturberPopulation > testParticleInputTable.size( ) )
    {
        throw runtime_error(
            "ERROR: Perturber population > Number of completed test particle simulations" );
    }

    ///////////////////////////////////////////////////////////////////////////  

    ///////////////////////////////////////////////////////////////////////////

    // Define random number generators.

    // Define a random number generator and initialize it with a reproducible seed (current cpu
    // time).
    GlobalRandomNumberGeneratorType randomNumberGenerator = getGlobalRandomNumberGenerator( );

    // Define an uniform random number distribution to randomly select the start epoch of the 
    // observation period during random walk simulation.
    uniform_real_distribution< > observationPeriodStartDistribution(
                epochWindowSize / 2.0, 
                testParticleCaseData->randomWalkSimulationPeriod 
                - observationPeriod - epochWindowSize / 2.0 );

    // Define variate generator for the first epoch in the observation period.
    variate_generator< GlobalRandomNumberGeneratorType&, uniform_real_distribution< > > 
    generateObservationPeriodStartEpoch( 
        randomNumberGenerator, observationPeriodStartDistribution );

    // Define an uniform random number distribution for test particle simulation ID indices in 
    // input table.
    uniform_int_distribution< > testParticleSimulationIdIndexDistribution( 
        0, testParticleInputTable.size( ) - 1 );

    // Define variate generator for test particle simulation ID indices using the random number
    // generator and uniform distribution of test particle simulation ID indices in input table.
    variate_generator< GlobalRandomNumberGeneratorType&, uniform_int_distribution< > > 
    generateTestParticleSimulationId( randomNumberGenerator, 
        testParticleSimulationIdIndexDistribution );

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Set up random walk run table.
    if ( !database.tableExists( randomWalkRunTable.c_str( ) ) )
    {
        cout << "Table '" << randomWalkRunTable << "' does not exist ..." << endl;
        cout << "Creating table ... " << endl;

        // Create table.
        ostringstream randomWalkRunTableCreate;
        randomWalkRunTableCreate
            << "CREATE TABLE IF NOT EXISTS " << randomWalkRunTable << " ("
            << "\"randomWalkRunId\" INTEGER PRIMARY KEY NOT NULL,"
            << "\"randomWalkRunName\" TEXT NOT NULL,"
            << "\"testParticleCaseId\" INTEGER NOT NULL,"
            << "\"perturberRingNumberDensity\" INTEGER NOT NULL,"
            << "\"perturberRingMass\" INTEGER NOT NULL,"            
            << "\"observationPeriod\" REAL NOT NULL,"
            << "\"numberOfEpochWindows\" INTEGER NOT NULL,"
            << "\"epochWindowSize\" REAL NOT NULL);";

        // Execute command to create table.
        database.exec( randomWalkRunTableCreate.str( ).c_str( ) );

        // Check that the table was created successfully.
        if ( database.tableExists( randomWalkRunTable.c_str( ) ) )
        {
            cout << "Table '" << randomWalkRunTable << "' successfully created!" << endl; 
        }

        else
        {
            ostringstream tableCreateError;
            tableCreateError << "ERROR: Creating table '" << randomWalkRunTable 
                             << "'' failed!";
            throw runtime_error( tableCreateError.str( ).c_str( ) );
        }
    }

    else
    {
        cout << "Table '" << randomWalkRunTable 
             << "' already exists ... skipping creating table ..." << endl;
    }

    // Check data present in table.

    // Check if run is already present in table.
    ostringstream randomWalkRunCheck;
    randomWalkRunCheck << "SELECT COUNT(*) FROM " << randomWalkRunTable 
                        << " WHERE \"randomWalkRunName\" = \"" << randomWalkRunName << "\"";
    int numberOfRunRows = database.execAndGet( randomWalkRunCheck.str( ).c_str( ) );

    if ( numberOfRunRows > 1 )
    {
        ostringstream numberOfRunRowsError;
        numberOfRunRowsError << "ERROR: Table '" << randomWalkRunTable << "' contains " 
                              << numberOfRunRows << " rows for random walk run '" 
                              << randomWalkRunName << "'!";
        throw runtime_error( numberOfRunRowsError.str( ).c_str( ) );
    }

    else if ( numberOfRunRows == 1 )
    {
        cout << "Table '" << randomWalkRunTable << "' contains 1 row of data for run '" 
             << randomWalkRunName << "' ... " << "skipping populating table ... " << endl;
    }

    // Write random walk run data to table.
    else if ( numberOfRunRows == 0 )
    {
        cout << "No data present in table '" << randomWalkRunTable << "' for random walk run '" 
             << randomWalkRunName << "' ... " << endl;
        cout << "Populating table ... " << endl;

        // Create stringstream with random walk run data insert command.
        // For floating-point values, ensure the data is written to the stream at full precision.
        ostringstream randomWalkRunDataInsert;
        randomWalkRunDataInsert
            << "INSERT INTO " << randomWalkRunTable << " VALUES ("
            << "NULL,"
            << "\"" << randomWalkRunName << "\","
            << testParticleCaseData->testParticleCaseId << ",";
        randomWalkRunDataInsert 
            << setprecision( numeric_limits< double >::digits10 )
            << perturberRingNumberDensity << ","
            << perturberRingMass << ","
            << observationPeriod << ",";
        randomWalkRunDataInsert
            << numberOfEpochWindows << ",";
        randomWalkRunDataInsert
            << setprecision( numeric_limits< double >::digits10 )
            << epochWindowSize
            << ");";

        // Insert random walk run data.
        database.exec( randomWalkRunDataInsert.str( ).c_str( ) );

        // Check that there is only one row present in the table.
        numberOfRunRows = database.execAndGet( randomWalkRunCheck.str( ).c_str( ) );
        if ( numberOfRunRows == 1 )
        {
            cout << "Table '" << randomWalkRunTable << "' populated successfully!" << endl; 
        }

        else
        {
            ostringstream numberOfRunRowsError;
            numberOfRunRowsError << "ERROR: Table '" << randomWalkRunTable << "' contains "
                                 << numberOfRunRows << " rows for random walk run '" 
                                 << randomWalkRunName << "'!";
            throw runtime_error( numberOfRunRowsError.str( ).c_str( ) );
        }
    }    

    // Retrieve and output run id.
    ostringstream randomWalkRunIdQuery;          
    randomWalkRunIdQuery << "SELECT \"randomWalkRunId\" FROM " << randomWalkRunTable 
                         << " WHERE \"randomWalkRunName\" = \"" << randomWalkRunName << "\"";
    const int randomWalkRunId = database.execAndGet( randomWalkRunIdQuery.str( ).c_str( ) );
    cout << "Run ID is " << randomWalkRunId << " for random walk run '" 
         << randomWalkRunName << "'" << endl;

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Set up random walk perturber table.
    if ( !database.tableExists( randomWalkPerturberTableName.c_str( ) ) )
    {
        cout << "Table '" << randomWalkPerturberTableName << "' does not exist ..." << endl;
        cout << "Creating table ... " << endl;

        // Create table.
        ostringstream randomWalkPerturberTableCreate;
        randomWalkPerturberTableCreate
            << "CREATE TABLE IF NOT EXISTS " << randomWalkPerturberTableName << " ("
            << "\"randomWalkPerturberId\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
            << "\"randomWalkSimulationId\" INTEGER NOT NULL,"
            << "\"testParticleSimulationId\" INTEGER NOT NULL);";

        // Execute command to create table.
        database.exec( randomWalkPerturberTableCreate.str( ).c_str( ) );

        // Check that the table was created successfully.
        if ( database.tableExists( randomWalkPerturberTableName.c_str( ) ) )
        {
            cout << "Table '" << randomWalkPerturberTableName << "' successfully created!" 
                 << endl; 
        }

        else
        {
            ostringstream tableCreateError;
            tableCreateError << "ERROR: Creating table '" << randomWalkPerturberTableName 
                             << "'' failed!";
            throw runtime_error( tableCreateError.str( ).c_str( ) );
        }
    }

    else
    {
        cout << "Table '" << randomWalkPerturberTableName 
             << "' already exists ... skipping creating table ..." << endl;
    }

    ///////////////////////////////////////////////////////////////////////////    

    ///////////////////////////////////////////////////////////////////////////

    // Set up random walk input table.
    if ( !database.tableExists( randomWalkInputTableName.c_str( ) ) )
    {
        cout << "Table '" << randomWalkInputTableName << "' does not exist ..." << endl;
        cout << "Creating table ... " << endl;

        // Create table.
        ostringstream randomWalkInputTableCreate;
        randomWalkInputTableCreate
            << "CREATE TABLE IF NOT EXISTS " << randomWalkInputTableName << " ("
            << "\"randomWalkSimulationId\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
            << "\"randomWalkRunId\" INTEGER NOT NULL,"
            << "\"completed\" INTEGER NOT NULL,"
            << "\"observationPeriodStartEpoch\" REAL NOT NULL);";

        // Execute command to create table.
        database.exec( randomWalkInputTableCreate.str( ).c_str( ) );

        // Check that the table was created successfully.
        if ( database.tableExists( randomWalkInputTableName.c_str( ) ) )
        {
            cout << "Table '" << randomWalkInputTableName << "' successfully created!" << endl; 
        }

        else
        {
            ostringstream tableCreateError;
            tableCreateError << "ERROR: Creating table '" << randomWalkInputTableName 
                             << "'' failed!";
            throw runtime_error( tableCreateError.str( ).c_str( ) );
        }
    }

    else
    {
        cout << "Table '" << randomWalkInputTableName 
             << "' already exists ... skipping creating table ..." << endl;
    }

    // Check data present in table.

    // Check how many rows are present in table.
    ostringstream randomWalkInputRowCount;
    randomWalkInputRowCount << "SELECT COUNT(*) FROM " << randomWalkInputTableName 
                            << " WHERE \"randomWalkRunId\" == " << randomWalkRunId;
    const int inputTableRows = database.execAndGet( randomWalkInputRowCount.str( ).c_str( ) );

    if ( inputTableRows > 0 )
    {
        cout << "Table '" << randomWalkInputTableName << "' contains " << inputTableRows 
             << " rows for random walk run '" << randomWalkRunName 
             << "' ... skipping populating table ..." << endl;
    }

    else
    {
        // Populate table.
        // Table containing list of random walk perturbers is populated simultaneously.
        cout << "Populating input table with " << monteCarloPopulation 
             << " new random walk simulations ... " << endl;
        cout << "Populating perturber table with " << monteCarloPopulation 
             << " new data for random walk simulations ... " << endl;         

        // Set up database transaction.
        Transaction randomWalkInputTableTransaction( database );

        // Set up random walk input table insert statement.
        ostringstream randomWalkInputTableInsert;
        randomWalkInputTableInsert << "INSERT INTO " << randomWalkInputTableName
                                   << " VALUES (NULL, " << randomWalkRunId 
                                   << ", 0, :observationPeriodStartEpoch);";

        // Compile a SQL query.
        Statement randomWalkInputTableInsertQuery( 
            database, randomWalkInputTableInsert.str( ).c_str( ) );

        // Set up random walk perturber table insert statement.
        ostringstream randomWalkPerturberTableInsert;
        randomWalkPerturberTableInsert << "INSERT INTO " << randomWalkPerturberTableName
                                       << " VALUES (NULL, :randomWalkSimulationId" 
                                       << ", :testParticleSimulationId);";

        // Compile a SQL query.
        Statement randomWalkPerturberTableInsertQuery( 
            database, randomWalkPerturberTableInsert.str( ).c_str( ) );

        // Generate random walk input data and populate table.
        // Also populate perturber table for each random walk simulation.
        for ( unsigned int randomWalkSimulation = 0; 
              randomWalkSimulation < monteCarloPopulation; randomWalkSimulation++ )
        { 
            // Bind values to prepared SQLite statement.
            randomWalkInputTableInsertQuery.bind( ":observationPeriodStartEpoch", 
                                                  generateObservationPeriodStartEpoch( ) );

            // Execute insert query.
            randomWalkInputTableInsertQuery.exec( );

            // Reset query.
            randomWalkInputTableInsertQuery.reset( );

            // Get row ID for last input row inserted in table.
            const int lastInputTableRowId = database.getLastInsertRowid( );

            // Get random walk simulation ID corresponding to row ID.
            ostringstream randomWalkSimulationRowIdQuery;
            randomWalkSimulationRowIdQuery << "SELECT \"randomWalkSimulationId\" FROM " 
                                           << randomWalkInputTableName 
                                           << " WHERE rowid == " << lastInputTableRowId;
            const int randomWalkSimulationId = database.execAndGet( 
                randomWalkSimulationRowIdQuery.str( ).c_str( ) );

            // Select test particle simulation ID indices to generate list of random walk 
            // perturbers.

            // Declare vector containing test particle simulation IDs.
            vector< unsigned int > testParticleSimulationIdIndices( perturberPopulation );

            // Generate vector of randomly selected test particle simulation IDs.
            generate( testParticleSimulationIdIndices.begin( ), 
                      testParticleSimulationIdIndices.end( ),
                      generateTestParticleSimulationId );

            // Check if the test particle simulation IDs are unique, and if not, generate new 
            // random number.
            for ( unsigned int i = 0; i < testParticleSimulationIdIndices.size( ); i++ )
            {
                for ( unsigned int j = 0; j < testParticleSimulationIdIndices.size( ); j++ )
                {
                    // If inner and outer loop point to the same element, skip.
                    if ( i == j )
                    {
                        continue;
                    }

                    // Else, check if the elements are equal, and if they are generate a new 
                    // test particle simulation ID index and restart looping.
                    else if ( testParticleSimulationIdIndices.at( j ) 
                              == testParticleSimulationIdIndices.at( i ) )
                    {
                        testParticleSimulationIdIndices.at( j ) 
                            = generateTestParticleSimulationId( );
                        i = 0;
                        break;
                    }
                }
            }       

            // Loop through list of test particle simulation ID indices and write data to 
            // random walk perturber table.
            for ( unsigned int k = 0; k < testParticleSimulationIdIndices.size( ); k++ ) 
            {
                // Bind values to prepared SQLite statement.
                randomWalkPerturberTableInsertQuery.bind( 
                    ":randomWalkSimulationId", randomWalkSimulationId );
                
                TestParticleInputTable::iterator iteratorTestParticleInputTable 
                    = testParticleInputTable.begin( );
                advance( iteratorTestParticleInputTable, testParticleSimulationIdIndices.at( k ) );

                randomWalkPerturberTableInsertQuery.bind( 
                    ":testParticleSimulationId",
                     iteratorTestParticleInputTable->testParticleSimulationId );  

                // Execute insert query.
                randomWalkPerturberTableInsertQuery.exec( );

                // Reset query.
                randomWalkPerturberTableInsertQuery.reset( );            
            }
        }

        // Commit transaction.
        randomWalkInputTableTransaction.commit( );
    }

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Set up random walk output table.
    if ( !database.tableExists( randomWalkOutputTableName.c_str( ) ) )
    {
        cout << "Table '" << randomWalkOutputTableName << "' does not exist ..." << endl;
        cout << "Creating table ... " << endl;

        // Create table.
        ostringstream randomWalkOutputTableCreate;
        randomWalkOutputTableCreate
            << "CREATE TABLE IF NOT EXISTS " << randomWalkOutputTableName << " ("
            << "\"randomWalkOutputId\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
            << "\"randomWalkSimulationId\" INTEGER NOT NULL,"
            << "\"averageLongitudeResidual\" REAL NOT NULL,"
            << "\"maximumLongitudeResidualChange\" REAL NOT NULL,"            
            << "\"averageEccentricity\" REAL NOT NULL,"            
            << "\"maximumEccentricityChange\" REAL NOT NULL,"
            << "\"averageInclination\" REAL NOT NULL,"
            << "\"maximumInclinationChange\" REAL NOT NULL);";

        // Execute command to create table.
        database.exec( randomWalkOutputTableCreate.str( ).c_str( ) );

        // Check that the table was created successfully.
        if ( database.tableExists( randomWalkOutputTableName.c_str( ) ) )
        {
            cout << "Table '" << randomWalkOutputTableName << "' successfully created!" << endl; 
        }

        else
        {
            ostringstream tableCreateError;
            tableCreateError << "ERROR: Creating table '" << randomWalkOutputTableName
                             << "'' failed!";
            throw runtime_error( tableCreateError.str( ).c_str( ) );
        }
    }

    else
    {
        cout << "Table '" << randomWalkOutputTableName 
             << "' already exists ... skipping creating table ..." << endl;
    }

    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////

    // Close database.

    // Database will be automatically closed after the application is terminated. 
    // (when object goes out of scope its destructor will be called).
    cout << "SQLite database file '" << database.getFilename( ).c_str( ) 
         << "' closed successfully ..." << endl;

    ///////////////////////////////////////////////////////////////////////////
}