Exemple #1
0
std::vector<MOL_SPTR_VECT> EnumerateLibrary::next() {
  PRECONDITION(static_cast<bool>(*this), "No more enumerations");
  const RGROUPS &reactantIndices = m_enumerator->next();
  MOL_SPTR_VECT reactants(m_bbs.size());

  for (size_t i = 0; i < m_bbs.size(); ++i) {
    reactants[i] = m_bbs[i][reactantIndices[i]];
  }

  return m_rxn.runReactants(reactants);
}
  /**
   * Add a single reaction to the mechanism. This routine
   * must be called after init() and before finalize().
   * This function branches on the types of reactions allowed
   * by the interfaceKinetics manager in order to install
   * the reaction correctly in the manager.
   * The manager allows the following reaction types
   *  Elementary
   *  Surface
   *  Global  
   * There is no difference between elementary and surface 
   * reactions.
   */
  void InterfaceKinetics::addReaction(const ReactionData& r) {

    /*
     * Install the rate coefficient for the current reaction
     * in the appropriate data structure.
     */
    addElementaryReaction(r);
    /*
     * Add the reactants and products for  m_ropnet;the current reaction
     * to the various stoichiometric coefficient arrays.
     */
    installReagents(r);
    /* 
     * Save the reaction and product groups, which are
     * part of the ReactionData class, in this class.
     * They aren't used for anything but reaction path
     * analysis.
     */
    //installGroups(reactionNumber(), r.rgroups, r.pgroups);
    /*
     * Increase the internal number of reactions, m_ii, by one.
     * increase the size of m_perturb by one as well.
     */
    incrementRxnCount();
    m_rxneqn.push_back(r.equation);

    m_rxnPhaseIsReactant.resize(m_ii, 0);
    m_rxnPhaseIsProduct.resize(m_ii, 0);
 
    int np = nPhases(); 
    int i = m_ii -1;
    m_rxnPhaseIsReactant[i] = new bool[np];
    m_rxnPhaseIsProduct[i] = new bool[np];

    for (int p = 0; p < np; p++) {
      m_rxnPhaseIsReactant[i][p] = false;
      m_rxnPhaseIsProduct[i][p] = false;
    }

    const vector_int& vr = reactants(i);
    for (int ik = 0; ik < (int) vr.size(); ik++) {
      int k = vr[ik];
      int p = speciesPhaseIndex(k);
      m_rxnPhaseIsReactant[i][p] = true;
    }
    const vector_int& vp = products(i);
    for (int ik = 0; ik < (int) vp.size(); ik++) {
      int k = vp[ik];
      int p = speciesPhaseIndex(k);
      m_rxnPhaseIsProduct[i][p] = true;
    }
 }
Exemple #3
0
int main( int argc, char* argv[] )
{
  if ( argc != 2 ) {
    showUsage();
    return 0;
  }

  // Start the rng.
  RandomGenerator rng( 41u );
  UniformRandomSize sizeTypeRng( rng, boost::uniform_int< std::size_t >( 0,
    std::numeric_limits< std::size_t >::max() ) );

  // Parse the input file.
  std::ifstream input( argv[1] );
  std::string line;

  // The interaction database file.
  std::string xmlDatabaseFile;
  input >> xmlDatabaseFile; getline( input, line );
  InteractionDatabase myDatabase( xmlDatabaseFile );

  // Time and time step.
  double deltaTime, endTime, outputDeltaTime;
  input >> deltaTime; getline( input, line );
  input >> endTime; getline( input, line );

  // Output info.
  input >> outputDeltaTime; getline( input, line );
  std::size_t numberOfOutputBins;
  input >> numberOfOutputBins; getline( input, line );

    // Volume of the domain.
  double cellVolumeCubicMeters;
  input >> cellVolumeCubicMeters; getline( input, line );

  // Particle species, counts, and temperatures.
  std::multimap< std::string, ParticleInputSpec > particleInitialConditions;
  while ( true ) {
    std::string speciesName;
    std::size_t particleCount;
    double particleTemperature;
    Vec3 commonVelocity;
    input >> speciesName >> particleCount >> particleTemperature >> commonVelocity;
    if ( ! input.good() ) {
      break;
    } else {
      getline( input, line );
    }

    ParticleInputSpec inputSpec = { particleCount, particleTemperature, commonVelocity };
    particleInitialConditions.insert( std::make_pair( speciesName, inputSpec ) );
  }

  input.close();

  // Add all species types to the database.
  typedef std::multimap< std::string, ParticleInputSpec >::const_iterator ConstSpecIterator;
  for ( ConstSpecIterator speciesIterator = particleInitialConditions.begin();
    speciesIterator != particleInitialConditions.end();
    speciesIterator = particleInitialConditions.upper_bound( speciesIterator->first ) ) {
    myDatabase.addParticleType( speciesIterator->first );
  }

  // Throw away all interactions except elastic reactions.
//  myDatabase.filter = boost::make_shared< chimp::interaction::filter::Elastic >();

  // Finalize the database and do housekeeping.
  myDatabase.initBinaryInteractions();
  myDatabase.xmlDb.close();

  // Now make up some particles. We use the same indexing as the particle database to ease bookkeeping.
  typedef std::vector< Particle > AllParticlesOfOneSpecies;
  std::vector< AllParticlesOfOneSpecies > speciesSets( myDatabase.getProps().size() );
  for ( int i = 0; i < myDatabase.getProps().size(); ++i ) {

    // Find the pertinent particle specs.
    std::string speciesName = myDatabase[i].name::value;

    for ( ConstSpecIterator speciesIterator = particleInitialConditions.lower_bound( speciesName );
      speciesIterator != particleInitialConditions.upper_bound( speciesName ); ++speciesIterator ) {

      const ParticleInputSpec& spec = speciesIterator->second;

      // Give the particles some random velocities plus the common velocity.
      for ( std::size_t particleIndex = 0; particleIndex < spec.count; ++particleIndex ) {
        Particle particle;
        particle.velocity =
          randomVelocityFromMaxwellian( rng, spec.temperatureInKelvin, myDatabase[i].mass::value );
        particle.velocity += spec.driftVelocity;
        speciesSets[i].push_back( particle );
      }
    }
  }

  // Write some info for the reaction set.
  std::cout << "BEGIN INTERACTION TABLE" << std::endl;
  BOOST_FOREACH( const InteractionDatabase::Set& reactionBranches, myDatabase.getInteractions() ) {

    if ( reactionBranches.rhs.size() == 0 ) continue;

    std::cout << "  Reactions of "
      << myDatabase[ reactionBranches.lhs.A.species ].name::value << " with "
      << myDatabase[ reactionBranches.lhs.B.species ].name::value << std::endl;
    BOOST_FOREACH( const InteractionDatabase::Set::Equation& eq, reactionBranches.rhs ) {
      eq.print( std::cout << "    ", myDatabase ) << std::endl;
    }
  }
  std::cout << "END  INTERACTION  TABLE" << std::endl;

  // Loop over time steps.
  const double beginTime = 0.;
  for ( double time = beginTime; time < endTime; time += deltaTime ) {

    // Update particle positions, max speeds, and temperatures.
    std::vector< double > maxSpeedMetersPerSecond;
    std::vector< double > speciesTemperatures;
    std::size_t collisionCount = 0;
    std::size_t particleCount = 0;
    for ( int speciesIndex = 0; speciesIndex < speciesSets.size(); ++speciesIndex ) {
      maxSpeedMetersPerSecond.push_back( 0. );
      speciesTemperatures.push_back( 0. );
      BOOST_FOREACH( Particle& particle, speciesSets[ speciesIndex ] ) {
        // v = v + E * dt;
        // x = x + v * dt;
        double particleSpeedSquared = magnitudeSquared( particle.velocity );
        maxSpeedMetersPerSecond.back() =
          std::max( maxSpeedMetersPerSecond.back(), sqrt( particleSpeedSquared ) );
        speciesTemperatures.back() += particleSpeedSquared;
        ++particleCount;
      }
      speciesTemperatures.back() *= 0.5 * myDatabase[ speciesIndex ].mass::value; // kinetic energy
      speciesTemperatures.back() /= 1.5 * physical::constant::si::K_B * speciesSets[ speciesIndex ].size();
    }

    if ( time == beginTime ) {
      printConsoleData( myDatabase, speciesTemperatures, 0.0, 0, particleCount, true );
    }

    // Collide a few particles. This is done by looping over all reactions, choosing a few pairs of
    // the pertinent 2 species, and doing a null-collision algorithm on these pairs.
    BOOST_FOREACH( const InteractionDatabase::Set& reactionBranches, myDatabase.getInteractions() ) {

      if ( reactionBranches.rhs.size() == 0 ) continue;

      std::vector< std::size_t > particlesPerSpecies;
      std::vector< int > reactantIndices;
      reactantIndices.push_back( reactionBranches.lhs.A.species );
      reactantIndices.push_back( reactionBranches.lhs.B.species );
      std::size_t numberOfCollisions = 1;
      BOOST_FOREACH( const int& reactantIndex, reactantIndices ) {
        particlesPerSpecies.push_back( speciesSets[ reactantIndex ].size() );
        numberOfCollisions *= particlesPerSpecies.back();
      }

      // Round the number of collisions based on the remainder using MC method.
      double maxRelativeSpeed = std::accumulate( maxSpeedMetersPerSecond.begin(),
        maxSpeedMetersPerSecond.end(), 0. );
      double maxSigmaSpeedProduct = reactionBranches.findMaxSigmaVProduct( maxRelativeSpeed );
      double fractionalCollisions =
        numberOfCollisions * maxSigmaSpeedProduct * deltaTime / cellVolumeCubicMeters;
      numberOfCollisions = static_cast< std::size_t >( std::floor( fractionalCollisions ) );
      double partialCollision = fractionalCollisions - numberOfCollisions;
      UniformRandomDouble remainderSelector( rng, boost::uniform_real<>( 0., 1. ) );
      if ( remainderSelector() < partialCollision ) {
        ++numberOfCollisions;
      }

      // Setup some dummy vectors to hold arguments.
      std::vector< InteractionDatabase::options::Particle > reactants( 2 );
      std::vector< const InteractionDatabase::options::Particle* > reactantPointers( 2 );
      for ( int i = 0; i < 2; ++i ) {
        reactantPointers[i] = &reactants[i];
      }

      // Loop over all of the chosen collision pairs.
      for ( std::size_t collisionPair = 0; collisionPair < numberOfCollisions; ++collisionPair ) {

        // Choose the particles randomly, making sure we don't pick the same particle twice if this
        // is a like-pair collision.
        boost::array< std::size_t, 2 > particleIndex;
        particleIndex[0] = sizeTypeRng() % particlesPerSpecies[0];
        particleIndex[1] = sizeTypeRng() % particlesPerSpecies[1];
        if ( reactantIndices[0] == reactantIndices[1] ) {
          while ( particleIndex[1] == particleIndex[0] ) {
            particleIndex[1] = sizeTypeRng() % particlesPerSpecies[1];
          }
        }

        // Copy over the velocities.
        for ( int i = 0; i < 2; ++i ) {
          for ( int j = 0; j < 3; ++j )
            reactants[i].v[j] =
              speciesSets[ reactantIndices[i] ][ particleIndex[i] ].velocity[j];
        }

        double relativeSpeed = magnitude( reactants[0].v - reactants[1].v );
        if ( relativeSpeed == 0.0 ) {
          continue;
        }

        // Find which branch to take using null collision method.
        std::pair< int, double > path =
          reactionBranches.calculateOutPath( maxSigmaSpeedProduct, relativeSpeed );

        // Skip it if there is no collision.
        if ( path.first < 0 ) {
          continue;
        }

        const InteractionDatabase::Set::Equation& selectedPath = reactionBranches.rhs[ path.first ];

        InteractionDatabase::Interaction::ParticleParam defaultParam;
        defaultParam.is_set = false; // because it doesn't have a default constructor yet.
        std::vector< InteractionDatabase::Interaction::ParticleParam > products( 5, defaultParam );
        selectedPath.interaction->interact( reactantPointers, products );
        ++collisionCount;

        // For elastic collisions, we just copy the velocities of the products.
        for ( int i = 0; i < 2; ++i ) {
          std::vector< Particle >& species = speciesSets[ reactantIndices[i] ];
          if ( products[i].is_set ) {
            // The original reactant was modified, but was not consumed.
            for ( int j = 0; j < 3; ++j ) {
              species[ particleIndex[i] ].velocity[j] = products[i].particle.v[j];
            }
          } else {
            // The reactant was consumed. Remove it.
            species.erase( species.begin() + particleIndex[i] );
          }
        }

        // Add the new particles if there were any created.
        for ( int i = 2; i < 5; ++i ) {
          if ( products[i].is_set ) {
            Particle newParticle;
            for ( int j = 0; j < 3; ++j ) {
              newParticle.velocity[j] = products[i].particle.v[j];
            }
            speciesSets[ selectedPath.products[i-2].species ].push_back( newParticle );
          }
        }

      } // collisionPair
    } // interaction