text:
//---------------------------------------------------------------------------//
//!
//! \file   tstElectroatomNativeFactory.cpp
//! \author Luke Kersting
//! \brief  Electroatom factory using Native data unit tests
//!
//---------------------------------------------------------------------------//

// Std Lib Includes
#include <iostream>
#include <memory>

// Boost Includes
#include <boost/unordered_set.hpp>

// FRENSIE Includes
#include "MonteCarlo_ElectroatomNativeFactory.hpp"
#include "MonteCarlo_ElectroatomicReactionType.hpp"
#include "MonteCarlo_AtomicRelaxationModelFactory.hpp"
#include "MonteCarlo_BremsstrahlungAngularDistributionType.hpp"
#include "MonteCarlo_CutoffElasticElectronScatteringDistribution.hpp"
#include "MonteCarlo_ElasticElectronScatteringDistributionNativeFactory.hpp"
#include "MonteCarlo_SimulationProperties.hpp"
#include "Data_ElectronPhotonRelaxationDataContainer.hpp"
#include "Utility_InterpolationPolicy.hpp"
#include "Utility_PhysicalConstants.hpp"
#include "Utility_UnitTestHarnessWithMain.hpp"

//---------------------------------------------------------------------------//
// Testing Variables
//---------------------------------------------------------------------------//

std::unique_ptr<Data::ElectronPhotonRelaxationDataContainer> data_container;
std::shared_ptr<const MonteCarlo::AtomicRelaxationModel> relaxation_model;
std::string electroatom_name;
double atomic_weight;

//---------------------------------------------------------------------------//
// Tests.
//---------------------------------------------------------------------------//
/* Check that a electroatom with detailed 2BS photon angular distribution
 * data can be created
 */
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_default )
{
  MonteCarlo::SimulationProperties properties;

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1.0e-5;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.62906011980000019073e+09, 1e-12 );

  energy = 2.0e-1;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.25222252404707632959e+07, 1e-12 );

  energy = 1.0e5;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.95701304790000058711e+06, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2e-1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.21237e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2e-1,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.98241e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.52837e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.23519e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the coupled elastic cross section can be returned
  reaction = MonteCarlo::COUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.11161e+06, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.14554e+06, 1e-12 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.68623e+06, 1e-12 );

  cross_section = atom->getReactionCrossSection( 2e-1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.61118815071382801980e+07, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.10301e+08, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.1309e+08, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.48924e+09, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
/* Check that a electroatom with a decoupled elastic distribution and
 * detailed 2BS photon angular distribution data and can be created */
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_decoupled )
{
  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::TWOBS_DISTRIBUTION );
  properties.setElectronTwoDInterpPolicy( MonteCarlo::LINLINLOG_INTERPOLATION );
  properties.setElasticElectronDistributionMode( MonteCarlo::DECOUPLED_DISTRIBUTION );
  properties.setElasticCutoffAngleCosine( 1.0 );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1.0e-5;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.62906011980000019073e+09, 1e-12 );

  energy = 2.0e-1;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.25222252404707632959e+07, 1e-12 );

  energy = 1.0e5;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.95701304790000058711e+06, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2e-1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.21237e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2e-1,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.98241e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.52837e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.23519e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.11161e+06, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.14554e+06, 1e-12 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.68623e+06, 1e-12 );

  cross_section = atom->getReactionCrossSection( 2e-1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.61118815071382801980e+07, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.10301e+08, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.1309e+08, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.48924e+09, 1e-12 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
/* Check that a electroatom with a cutoff elastic distribution can be created */
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_cutoff )
{
  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::DIPOLE_DISTRIBUTION );
  properties.setElectronTwoDInterpPolicy( MonteCarlo::LOGLOGLOG_INTERPOLATION );
  properties.setElasticElectronDistributionMode( MonteCarlo::CUTOFF_DISTRIBUTION );
  properties.setElasticCutoffAngleCosine( 0.999999 );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1.0e-5;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.62906011980000019073e+09, 1e-12 );

  energy = 2.0e-1;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.25222252404707632959e+07, 1e-12 );

  energy = 1.0e5;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 8.83051e-2+2.8454030479e6, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2e-1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.21237e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2e-1,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.98241e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.52837e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.23519e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the coupled elastic cross section can be returned
  reaction = MonteCarlo::COUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 8.83051e-02, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0571e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 6.30957, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.68623e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.103010e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.1309e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.489240e9, 1e-12 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
// Check that a electroatom with a hybrid elastic distribution can be created
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_hybrid )
{
  double cutoff_angle_cosine = 0.9;
  double evaluation_tol = 1e-15;

  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::DIPOLE_DISTRIBUTION );
  properties.setElectronTwoDInterpPolicy( MonteCarlo::LOGLOGLOG_INTERPOLATION );
  properties.setElectronTwoDGridPolicy( MonteCarlo::CORRELATED_GRID );
  properties.setElasticElectronDistributionMode( MonteCarlo::HYBRID_DISTRIBUTION );
  properties.setElasticCutoffAngleCosine( cutoff_angle_cosine );
  properties.setElectronEvaluationTolerance( evaluation_tol );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );
  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  std::shared_ptr<const MonteCarlo::CutoffElasticElectronScatteringDistribution>
    cutoff_elastic_distribution;

  MonteCarlo::ElasticElectronScatteringDistributionNativeFactory::createCutoffElasticDistribution<Utility::LogLogCosLog,Utility::Correlated>(
        cutoff_elastic_distribution,
        *data_container,
        properties.getElasticCutoffAngleCosine(),
        properties.getElectronEvaluationTolerance() );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1e-5;
  double cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( energy );
  double inelastic = 1.398201198e+08;
  double elastic = 2.48924e9*cross_section_ratio + 1.1063294415585944e+08;

  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, inelastic + elastic, 1e-12 );

  energy = 2e-1;
  cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( energy );
  inelastic = 6.4103437333324831e+06;
  elastic = 1.6111881507138280e+07*cross_section_ratio + 1.8627628267192466e+06;

  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, inelastic + elastic, 1e-12 );

  energy = 1e5;
  cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( energy );
  inelastic = 2.8454030478999997e+06;
  elastic = 8.83051e-2*cross_section_ratio + 2.2037703049967248e-03;

  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, inelastic + elastic, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.528370e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.235190e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1e-5,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the hybrid elastic cross section can be returned
  reaction = MonteCarlo::HYBRID_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( 1e5 );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section,
                          8.83051e-02*cross_section_ratio + 2.2037700886489448e-03,
                          1e-11 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( 1e-3 );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section,
                          2.90281E+8*cross_section_ratio + 1.2584013774057175e+08,
                          1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( 1.995260e-4 );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section,
                          4.8815266556554884e+08,
                          1e-12 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  cross_section_ratio =
    cutoff_elastic_distribution->evaluateCutoffCrossSectionRatio( 1e-5 );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section,
                          2.48924e9*cross_section_ratio + 1.1063294415585944e+08,
                          1e-12 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no screened Rutherford reaction
  reaction = MonteCarlo::SCREENED_RUTHERFORD_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no moment preserving elastic cross section
  reaction = MonteCarlo::MOMENT_PRESERVING_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
// Check that a electroatom with no elastic data can be created
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_no_elastic )
{
  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::DIPOLE_DISTRIBUTION );
  properties.setElectronEvaluationTolerance( 1e-7 );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );
  properties.setElasticModeOff();

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  std::shared_ptr<const MonteCarlo::CutoffElasticElectronScatteringDistribution>
    cutoff_elastic_distribution;

  MonteCarlo::ElasticElectronScatteringDistributionNativeFactory::createCutoffElasticDistribution<Utility::LinLinLog,Utility::Correlated>(
        cutoff_elastic_distribution,
        *data_container,
        1.0,
        properties.getElectronEvaluationTolerance() );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1e-5;
  double inelastic = 1.398201198e8;
  double elastic = 0.0;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, inelastic + elastic, 1e-12 );

  energy = 2e-1;
  inelastic = 6.4103437333324831e+06;
  elastic = 0.0;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, inelastic + elastic, 1e-12 );

  energy = 1e5;
  inelastic = 2.84540304790e6;
  elastic = 0.0;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, inelastic + elastic, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.528370e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.235190e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1e-5,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the coupled elastic cross section can be returned
  reaction = MonteCarlo::COUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the hybrid elastic cross section can be returned
  reaction = MonteCarlo::HYBRID_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no screened Rutherford reaction
  reaction = MonteCarlo::SCREENED_RUTHERFORD_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no moment preserving elastic cross section
  reaction = MonteCarlo::MOMENT_PRESERVING_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
// Check that a electroatom with no electroionization subshell data can be created
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_no_electroionization )
{
  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::DIPOLE_DISTRIBUTION );
  properties.setElasticCutoffAngleCosine( 1.0 );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );
  properties.setElectroionizationModeOff();

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1.0e-5;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.6290601198e9-1.310577e8, 1e-12 );

  energy = 2.0e-1;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.2522225240470763e7-2.1959913233324825e6, 1e-12 );

  energy = 1.0e5;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.9570130479e6-1.2648388779e6, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 1.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.528370e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.235190e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the coupled elastic cross section can be returned
  reaction = MonteCarlo::COUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.11161e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.14554e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.68623e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.103010e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.1309e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.489240e9, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the moment preserving elastic cross section can be returned
  reaction = MonteCarlo::MOMENT_PRESERVING_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no K subshell electroionization cross section
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that tthere is no P3 subshell electroionization cross section
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );
}

//---------------------------------------------------------------------------//
// Check that a electroatom with no bremsstrahlung data can be created
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_no_bremsstrahlung )
{
  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::DIPOLE_DISTRIBUTION );
  properties.setElasticCutoffAngleCosine( 1.0 );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );
  properties.setBremsstrahlungModeOff();

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1.0e-5;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.6290601198e9-4.8698e3, 1e-12 );

  energy = 2.0e-1;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.2522225240470763e+07-1.98241e3, 1e-12 );

  energy = 1.0e5;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.9570130479e6-1.95417e3, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.96517e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.22682e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.16042e9, 1e-12 );

  // Test that there is no bremsstrahlung cross section
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-3,reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4,reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-5,reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the coupled elastic cross section can be returned
  reaction = MonteCarlo::COUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.11161e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.14554e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.68623e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.103010e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.1309e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.489240e9, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
// Check that a electroatom with no atomic excitation data can be created
FRENSIE_UNIT_TEST( ElectroatomNativeFactory, createElectroatom_no_atomic_excitation )
{
  MonteCarlo::SimulationProperties properties;
  properties.setBremsstrahlungAngularDistributionFunction( MonteCarlo::DIPOLE_DISTRIBUTION );
  properties.setElasticCutoffAngleCosine( 1.0 );
  properties.setAtomicRelaxationModeOn( MonteCarlo::ELECTRON );
  properties.setNumberOfElectronHashGridBins( 100 );
  properties.setAtomicExcitationModeOff();

  std::shared_ptr<const MonteCarlo::Electroatom> atom;

  MonteCarlo::ElectroatomNativeFactory::createElectroatom( *data_container,
                                                           electroatom_name,
                                                           atomic_weight,
                                                           relaxation_model,
                                                           properties,
                                                           atom );

  // Test the electroatom properties
  FRENSIE_CHECK_EQUAL( atom->getAtomName(), "Pb-Native" );
  FRENSIE_CHECK_EQUAL( atom->getAtomicNumber(), 82 );
  FRENSIE_CHECK_FLOATING_EQUALITY( atom->getAtomicWeight(), 207.1999470456033, 1e-12 );

  // Test that the total cross section can be returned
  double energy = 1.0e-5;
  double cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.6290601198e9-8.757550e6, 1e-12 );

  energy = 2.0e-1;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.2522225240470763e7-4.21237e6, 1e-12 );

  energy = 1.0e5;
  cross_section = atom->getTotalCrossSection( energy );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.9570130479e6-1.57861e6, 1e-12 );

  // Test that the absorption cross section can be returned
  cross_section = atom->getAbsorptionCrossSection( 1.0e-2 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 2.0e-3 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 4.0e-4 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getAbsorptionCrossSection( 9.0e-5 );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  MonteCarlo::ElectroatomicReactionType reaction;

  // Test that the atomic excitation cross section can be returned
  reaction = MonteCarlo::ATOMIC_EXCITATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 2.0e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 4.0e-4, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the bremsstrahlung cross section can be returned
  reaction = MonteCarlo::BREMSSTRAHLUNG_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.528370e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 5.520610e-4,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 9.235190e3, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5,reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 4.8698e3, 1e-12 );

  // Test that the coupled elastic cross section can be returned
  reaction = MonteCarlo::COUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.11161e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.14554e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.68623e6, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.103010e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 6.1309e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.489240e9, 1e-12 );

  // Test that the decoupled elastic cross section can be returned
  reaction = MonteCarlo::DECOUPLED_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no cutoff elastic cross section
  reaction = MonteCarlo::CUTOFF_ELASTIC_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e1, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 6.309570e0, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-3, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.995260e-4, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that there is no total electroionization
  reaction = MonteCarlo::TOTAL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  // Test that the K subshell electroionization cross section can be returned
  reaction = MonteCarlo::K_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_EQUAL( cross_section, 0.0 );

  cross_section = atom->getReactionCrossSection( 9.121750e-2, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 2.500920e-1, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.649190e1, 1e-12 );

  // Test that the P3 subshell electroionization cross section can be returned
  reaction = MonteCarlo::P3_SUBSHELL_ELECTROIONIZATION_ELECTROATOMIC_REACTION;
  cross_section = atom->getReactionCrossSection( 1.0e-5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.0653e8, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e-3, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 3.248850e7, 1e-12 );

  cross_section = atom->getReactionCrossSection( 1.0e5, reaction );
  FRENSIE_CHECK_FLOATING_EQUALITY( cross_section, 1.82234e5, 1e-12 );
}

//---------------------------------------------------------------------------//
// Custom setup
//---------------------------------------------------------------------------//
FRENSIE_CUSTOM_UNIT_TEST_SETUP_BEGIN();

std::string test_native_file_name;

FRENSIE_CUSTOM_UNIT_TEST_COMMAND_LINE_OPTIONS()
{
  ADD_STANDARD_OPTION_AND_ASSIGN_VALUE( "test_native_file",
                                        test_native_file_name, "",
                                        "Test native file name" );
}

FRENSIE_CUSTOM_UNIT_TEST_INIT()
{
  // Create the native data file container
  data_container.reset( new Data::ElectronPhotonRelaxationDataContainer(
                             test_native_file_name ) );

  // Create the atomic relaxation model
  MonteCarlo::AtomicRelaxationModelFactory::createAtomicRelaxationModel(
                               *data_container,
                               relaxation_model,
                               1e-3,
                               1e-5,
                               true );

  // Initialize the remaining electroatom data
  electroatom_name = "Pb-Native";
  atomic_weight = 207.1999470456033;

  // Initialize the random number generator
  Utility::RandomNumberGenerator::createStreams();
}

FRENSIE_CUSTOM_UNIT_TEST_SETUP_END();

//---------------------------------------------------------------------------//
// end tstElectroatomNativeFactory.cpp
//---------------------------------------------------------------------------//


text:
//    |  /           |
//    ' /   __| _` | __|  _ \   __|
//    . \  |   (   | |   (   |\__ `
//   _|\_\_|  \__,_|\__|\___/ ____/
//                   Multi-Physics
//
//  License:		 BSD License
//					 Kratos default license: kratos/license.txt
//
//  Main authors:    Author Julio Marti
//
// System includes

// External includes
//#include <boost/python.hpp>
//#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
//#include <boost/timer.hpp>
#include <pybind11/pybind11.h>

// Project includes
#include "includes/define.h"
#include "custom_python/add_custom_strategies_to_python.h"

#include "spaces/ublas_space.h"

//strategies
#include "solving_strategies/strategies/solving_strategy.h"
#include "solving_strategies/strategies/residualbased_linear_strategy.h"

//convergence criterias
//#include "custom_strategies/strategies/residualbased_convdiffr_strategy.h"
#include "custom_strategies/strategies/residualbased_convdiffr_strategy_nonlinear.h"

//linear solvers
#include "linear_solvers/linear_solver.h"

namespace Kratos
{

	namespace Python
	{
		namespace py = pybind11;

		void  AddCustomStrategiesToPython(pybind11::module& m)
		{
			typedef UblasSpace<double, CompressedMatrix, Vector> SparseSpaceType;
			typedef UblasSpace<double, Matrix, Vector> LocalSpaceType;

			typedef LinearSolver<SparseSpaceType, LocalSpaceType > LinearSolverType;
			typedef SolvingStrategy< SparseSpaceType, LocalSpaceType, LinearSolverType > BaseSolvingStrategyType;
			typedef Scheme< SparseSpaceType, LocalSpaceType > BaseSchemeType;

			//********************************************************************
			//********************************************************************
			//

		py::class_< ResidualBasedConvectionDiffusionrStrategyNonLinear< SparseSpaceType, LocalSpaceType, LinearSolverType >,ResidualBasedConvectionDiffusionrStrategyNonLinear< SparseSpaceType, LocalSpaceType, LinearSolverType >::Pointer,BaseSolvingStrategyType> (m,"ResidualBasedConvectionDiffusionrStrategyNonLinear").def(init<ModelPart&, LinearSolverType::Pointer,	bool, int, int ,double	>() );

		}

	}  // namespace Python.

} // Namespace Kratos

ext: cpp

max_stars_repo_name: lcirrott/Kratos

max_issues_repo_name: lcirrott/Kratos

max_forks_repo_name: lcirrott/Kratos


text:
#include "HTTPClient.h"
#include "core/BinaryData.h"
#include "components/Exceptions.h"
#include "utils/Log.h"

#include <chrono>
#include <limits>
#include <regex>

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#if defined(_WIN32)
#define CARTO_HTTP_SOCKET_IMPL WinSockImpl
#include "network/HTTPClientWinSockImpl.h"
#elif defined(__APPLE__)
#define CARTO_HTTP_SOCKET_IMPL IOSImpl
#include "network/HTTPClientIOSImpl.h"
#elif defined(__ANDROID__)
#define CARTO_HTTP_SOCKET_IMPL AndroidImpl
#include "network/HTTPClientAndroidImpl.h"
#else
#define CARTO_HTTP_SOCKET_IMPL PionImpl
#include "HTTPClientPionImpl.h"
#endif

namespace carto {

    HTTPClient::HTTPClient(bool log) :
        _log(log),
        _impl(new CARTO_HTTP_SOCKET_IMPL(log))
    {
    }

    void HTTPClient::setTimeout(int milliseconds) {
        _impl->setTimeout(milliseconds);
    }

    int HTTPClient::get(const std::string& url, const std::map<std::string, std::string>& requestHeaders, std::map<std::string, std::string>& responseHeaders, std::shared_ptr<BinaryData>& responseData, int* statusCode) const {
        Request request("GET", url);
        request.headers.insert(requestHeaders.begin(), requestHeaders.end());
        if (request.headers.count("Accept") == 0) {
            request.headers["Accept"] = "*/*";
        }

        std::vector<unsigned char> content;
        content.reserve(65536);
        auto handlerFn = [&content](std::uint64_t offset, std::uint64_t length, const unsigned char* buf, std::size_t size) -> bool {
            if (content.size() != offset) {
                content.resize(static_cast<std::size_t>(offset));
            }
            content.insert(content.end(), buf, buf + size);
            return true;
        };

        Response response;
        int code = makeRequest(request, response, handlerFn, 0);
        responseHeaders.insert(response.headers.begin(), response.headers.end());
        responseData = std::make_shared<BinaryData>(std::move(content));
        if (statusCode) {
            *statusCode = response.statusCode;
        }
        return code;
    }

    int HTTPClient::post(const std::string& url, const std::string& contentType, const std::shared_ptr<BinaryData>& requestData, const std::map<std::string, std::string>& requestHeaders, std::map<std::string, std::string>& responseHeaders, std::shared_ptr<BinaryData>& responseData) {
        Request request("POST", url);
        request.contentType = contentType;
        request.headers["Content-Type"] = contentType;
        request.headers.insert(requestHeaders.begin(), requestHeaders.end());
        if (request.headers.count("Accept") == 0) {
            request.headers["Accept"] = "*/*";
        }
        request.body = *requestData->getDataPtr();

        std::vector<unsigned char> content;
        content.reserve(65536);
        auto handlerFn = [&content](std::uint64_t offset, std::uint64_t length, const unsigned char* buf, std::size_t size) -> bool {
            if (content.size() != offset) {
                content.resize(static_cast<std::size_t>(offset));
            }
            content.insert(content.end(), buf, buf + size);
            return true;
        };

        Response response;
        int code = makeRequest(request, response, handlerFn, 0);
        responseHeaders.insert(response.headers.begin(), response.headers.end());
        responseData = std::make_shared<BinaryData>(std::move(content));
        return code;
    }

    int HTTPClient::streamResponse(const std::string& method, const std::string& url, const std::map<std::string, std::string>& requestHeaders, std::map<std::string, std::string>& responseHeaders, HandlerFunc handlerFn, std::uint64_t offset) const {
        Request request(method, url);
        request.headers.insert(requestHeaders.begin(), requestHeaders.end());
        if (request.headers.count("Accept") == 0) {
            request.headers["Accept"] = "*/*";
        }
        if (offset > 0) {
            request.headers["Range"] = "bytes=" + boost::lexical_cast<std::string>(offset) + "-";
        }

        Response response;
        int code = makeRequest(request, response, handlerFn, offset);
        responseHeaders.insert(response.headers.begin(), response.headers.end());
        return code;
    }

    int HTTPClient::makeRequest(Request request, Response& response, HandlerFunc handlerFn, std::uint64_t offset) const {
        std::uint64_t contentOffset = 0;
        std::uint64_t contentLength = std::numeric_limits<std::uint64_t>::max();

        auto headersFn = [&](int statusCode, const std::map<std::string, std::string>& headers) {
            response.statusCode = statusCode;
            response.headers.insert(headers.begin(), headers.end());

            // Read Content-Range
            if (statusCode == 206) {
                auto it = response.headers.find("Content-Range");
                if (it != response.headers.end()) {
                    std::cmatch what;
                    if (std::regex_match(it->second.c_str(), what, std::regex("bytes ([0-9]+)-.*"))) {
                        contentOffset = boost::lexical_cast<std::uint64_t>(what[1]);
                    }
                }
                if (contentOffset != offset) {
                    if (_log) {
                        Log::Errorf("HTTPClient::makeRequest: Content range mismatch: %d/%d, URL: %s", static_cast<int>(contentOffset), static_cast<int>(offset), request.url.c_str());
                    }
                    return false;
                }
            }

            // Read Content-Length
            auto it = response.headers.find("Content-Length");
            if (it != response.headers.end()) {
                contentLength = boost::lexical_cast<std::uint64_t>(it->second);
            }

            return true;
        };

        std::uint64_t originalOffset = offset;
        auto dataFn = [&](const unsigned char* data, std::size_t size) {
            bool result = handlerFn(offset, contentOffset + contentLength, data, size);
            offset += size;
            return result;
        };

        if (!_impl->makeRequest(request, headersFn, dataFn)) {
            return -1; // request was cancelled
        }

        if (response.statusCode >= 300 && response.statusCode < 400) {
            auto it = response.headers.find("Location");
            if (it != response.headers.end()) {
                std::string location = it->second;
                if (_log) {
                    Log::Infof("HTTPClient::makeRequest: Redirection from URL: %s to URL: %s", request.url.c_str(), location.c_str());
                }
                Request redirectedRequest(request);
                redirectedRequest.url = location;
                response = Response();
                return makeRequest(redirectedRequest, response, handlerFn, originalOffset);
            }
        }

        if (response.statusCode < 200 || response.statusCode >= 300) {
            if (_log) {
                Log::Errorf("HTTPClient::makeRequest: Bad status code: %d, URL: %s", response.statusCode, request.url.c_str());
            }
            return response.statusCode;
        }

        return 0;
    }

    HTTPClient::Impl::~Impl() {
    }

}

max_stars_repo_name: ArtronicsGame/mobile-sdk

max_issues_repo_name: ArtronicsGame/mobile-sdk

max_forks_repo_name: ArtronicsGame/mobile-sdk


text:
// Copyright 2013 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"

#include "../helpers/test.hpp"

namespace noexcept_tests
{
    // Test the noexcept is set correctly for the move constructor.

    struct hash_possible_exception : boost::hash<int>
    {
        hash_possible_exception(hash_possible_exception const&) {}
    };

    struct equal_to_possible_exception : std::equal_to<int>
    {
        equal_to_possible_exception(equal_to_possible_exception const&) {}
    };

    // Test that the move constructor does actually move without throwing
    // an exception when it claims to.

    struct test_exception {};

    bool throwing_test_exception = false;
    void test_throw(char const* name) {
        if (throwing_test_exception) {
            std::cerr << "Throw exception in: " << name << std::endl;
            throw test_exception();
        }
    }

    class hash_nothrow_move : boost::hash<int>
    {
        BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)

        typedef boost::hash<int> base;
    public:
        hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
            BOOST_NOEXCEPT {}

        hash_nothrow_move() { test_throw("Constructor"); }
        hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
        hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move))
        { test_throw("Assign"); return *this; }
        hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move))
        { test_throw("Move Assign"); return *this; }
        std::size_t operator()(int x) const
        { test_throw("Operator"); return static_cast<base const&>(*this)(x); }
    };

    class equal_to_nothrow_move : std::equal_to<int>
    {
        BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)

        typedef std::equal_to<int> base;
    public:
        equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move))
            BOOST_NOEXCEPT {}
        equal_to_nothrow_move() { test_throw("Constructor"); }
        equal_to_nothrow_move(equal_to_nothrow_move const&)
        { test_throw("Copy"); }
        equal_to_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move))
        { test_throw("Assign"); return *this; }
        equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move))
        { test_throw("Move Assign"); return *this; }
        std::size_t operator()(int x, int y) const
        { test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
    };

    bool have_is_nothrow_move = false;

    UNORDERED_AUTO_TEST(check_is_nothrow_move)
    {
        BOOST_TEST(!boost::is_nothrow_move_constructible<hash_possible_exception>::value);
        have_is_nothrow_move = boost::is_nothrow_move_constructible<hash_nothrow_move>::value;

        // Copied from boost::is_nothrow_move_constructible implementation
        // to make sure this does actually detect it when expected.
        //
        // The type trait is also available when BOOST_IS_NOTHROW_MOVE_CONSTRUCT
        // is defined (for some versions of Visual C++?) but detects 'throw()',
        // not noexcept.
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
        BOOST_TEST(have_is_nothrow_move);
#endif
    }

    UNORDERED_AUTO_TEST(test_noexcept)
    {
        if (have_is_nothrow_move) {
            BOOST_TEST((boost::is_nothrow_move_constructible<
                        boost::unordered_set<int> >::value));
            BOOST_TEST((boost::is_nothrow_move_constructible<
                        boost::unordered_multiset<int> >::value));
            BOOST_TEST((boost::is_nothrow_move_constructible<
                        boost::unordered_map<int, int> >::value));
            BOOST_TEST((boost::is_nothrow_move_constructible<
                        boost::unordered_multimap<int, int> >::value));
        }

        BOOST_TEST((!boost::is_nothrow_move_constructible<
                    boost::unordered_set<int, hash_possible_exception>
                >::value));
        BOOST_TEST((!boost::is_nothrow_move_constructible<
                    boost::unordered_multiset<int, boost::hash<int>,
                    equal_to_possible_exception>
                >::value));
    }

    UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
    {
        typedef boost::unordered_set<int,
                hash_nothrow_move, equal_to_nothrow_move> throwing_set;

        if (have_is_nothrow_move)
        {
            BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);

            throwing_test_exception = false;

            throwing_set x1;
            x1.insert(10);
            x1.insert(50);

            try {
                throwing_test_exception = true;

                throwing_set x2 = boost::move(x1);
                BOOST_TEST(x2.size() == 2);
                BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
            } catch(test_exception) {
                BOOST_TEST(false);
            }

            throwing_test_exception = false;
        }
    }
}

RUN_TESTS()

max_stars_repo_name: metux/boost

max_issues_repo_name: metux/boost

max_forks_repo_name: metux/boost


text:
#include "util.h"
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <cpprest/http_client.h>
#include <cpprest/streams.h>
#include <darabonba/util.hpp>
#include <json/json.h>
#include <regex>
#include <sstream>
#include <string>

using namespace std;

string url_encode(const string &str) {
  ostringstream escaped;
  escaped.fill('0');
  escaped << hex;

  for (char c : str) {
    if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
      escaped << c;
      continue;
    }
    escaped << uppercase;
    escaped << '%' << setw(2) << int((unsigned char)c);
    escaped << nouppercase;
  }

  return escaped.str();
}

string implode(const vector<string> &vec, const string &glue) {
  string res;
  int n = 0;
  for (const auto &str : vec) {
    if (n == 0) {
      res = str;
    } else {
      res += glue + str;
    }
    n++;
  }
  return res;
}

vector<uint8_t> Darabonba_Util::Client::toBytes(const shared_ptr<string> &val) {
  string v = !val ? "" : *val;
  vector<uint8_t> vec(v.begin(), v.end());
  return vec;
}

string
Darabonba_Util::Client::toString(const shared_ptr<vector<uint8_t>> &val) {
  vector<uint8_t> v = !val ? vector<uint8_t>() : *val;
  string str(v.begin(), v.end());
  return str;
}

boost::any parse_json(boost::property_tree::ptree pt) {
  if (pt.empty()) {
    if (pt.data() == "true" || pt.data() == "false") {
      return boost::any(pt.get_value<bool>());
    } else if (regex_search(pt.data(), regex("^-?\\d+$"))) {
      long ln = atol(pt.data().c_str());
      if (ln > 2147483647 || ln < -2147483648) {
        return boost::any(ln);
      } else {
        return boost::any(atoi(pt.data().c_str()));
      }
    } else if (regex_search(pt.data(), regex(R"(^-?\d+\.{1}\d+$)"))) {
      return boost::any(atof(pt.data().c_str()));
    }
    return boost::any(pt.data());
  }
  vector<boost::any> vec;
  map<string, boost::any> m;
  for (const auto &it : pt) {
    if (!it.first.empty()) {
      m[it.first] = parse_json(it.second);
    } else {
      vec.push_back(parse_json(it.second));
    }
  }
  return vec.empty() ? boost::any(m) : boost::any(vec);
}

boost::any Darabonba_Util::Client::parseJSON(const shared_ptr<string> &val) {
  string v = !val ? "" : *val;
  stringstream ss(v);
  using namespace boost::property_tree;
  ptree pt;
  read_json(ss, pt);
  return parse_json(pt);
}

void json_encode(boost::any val, stringstream &ss) {
  if (typeid(map<string, boost::any>) == val.type()) {
    map<string, boost::any> m = boost::any_cast<map<string, boost::any>>(val);
    ss << '{';
    if (!m.empty()) {
      int n = 0;
      for (const auto &it : m) {
        if (n != 0) {
          ss << ", ";
        }
        ss << '"' << it.first << '"' << ": ";
        json_encode(it.second, ss);
        n++;
      }
    }
    ss << '}';
  } else if (typeid(vector<boost::any>) == val.type()) {
    vector<boost::any> v = boost::any_cast<vector<boost::any>>(val);
    ss << '[';
    if (!v.empty()) {
      int n = 0;
      for (const auto &it : v) {
        if (n != 0) {
          ss << ", ";
        }
        json_encode(it, ss);
        n++;
      }
    }
    ss << ']';
  } else if (typeid(int) == val.type()) {
    int i = boost::any_cast<int>(val);
    ss << to_string(i);
  } else if (typeid(long) == val.type()) {
    long l = boost::any_cast<long>(val);
    ss << to_string(l);
  } else if (typeid(double) == val.type()) {
    auto d = boost::any_cast<double>(val);
    ss << to_string(d);
  } else if (typeid(float) == val.type()) {
    auto f = boost::any_cast<float>(val);
    ss << to_string(f);
  } else if (typeid(string) == val.type()) {
    auto s = boost::any_cast<string>(val);
    ss << '"' << s << '"';
  } else if (typeid(bool) == val.type()) {
    auto b = boost::any_cast<bool>(val);
    string c = b ? "true" : "false";
    ss << c;
  } else if (typeid(const char *) == val.type()) {
    auto s = boost::any_cast<const char *>(val);
    ss << '"' << s << '"';
  } else if (typeid(char *) == val.type()) {
    auto s = boost::any_cast<char *>(val);
    ss << '"' << s << '"';
  }
}

string Darabonba_Util::Client::toJSONString(const boost::any &value) {
  boost::any json_object;
  if (typeid(shared_ptr<vector<boost::any>>) == value.type()) {
    shared_ptr<vector<boost::any>> vec_ptr = cast_any<vector<boost::any>>(value);
    if (vec_ptr) {
      json_object = *vec_ptr;
    }
  } else if (typeid(shared_ptr<map<string, boost::any>>) == value.type() ||
  typeid(shared_ptr<void>) == value.type()) {
    shared_ptr<map<string, boost::any>> map_ptr = cast_any<map<string, boost::any>>(value);
    if (map_ptr) {
      json_object = *map_ptr;
    }
  } else {
    throw runtime_error("Failed to parse the value as json format.");
  }
  stringstream s;
  json_encode(json_object, s);
  return s.str();
}

vector<uint8_t> Darabonba_Util::Client::readAsBytes(
    const shared_ptr<Darabonba::Stream> &stream) {
  if (!stream) {
    return vector<uint8_t>();
  }
  string str = readAsString(stream);
  vector<uint8_t> buffer(str.begin(), str.end());
  return buffer;
}

string Darabonba_Util::Client::readAsString(
    const shared_ptr<Darabonba::Stream> &stream) {
  if (!stream) {
    return string("");
  }
  return stream->read();
  ;
}

boost::any Darabonba_Util::Client::readAsJSON(
    const shared_ptr<Darabonba::Stream> &stream) {
  string json = readAsString(stream);
  return Client::parseJSON(make_shared<string>(json));
}

string
Darabonba_Util::Client::toFormString(shared_ptr<map<string, boost::any>> val) {
  if (!val || val->empty()) {
    return string("");
  }
  vector<string> tmp;
  for (const auto &it : *val) {
    string v = boost::any_cast<string>(it.second);
    v = url_encode(v);
    string str;
    str.append(it.first).append("=").append(v);
    tmp.push_back(str);
  }
  return implode(tmp, "&");
}

map<string, boost::any> Darabonba_Util::Client::anyifyMapValue(
    const shared_ptr<map<string, string>> &m) {
  if (!m) {
    return map<string, boost::any>();
  }
  map<string, boost::any> data;
  if (m->empty()) {
    return data;
  }
  for (const auto &it : *m) {
    data[it.first] = boost::any(it.second);
  }
  return data;
}

map<string, string> Darabonba_Util::Client::stringifyMapValue(
    const shared_ptr<map<string, boost::any>> &m) {
  if (nullptr == m) {
    return map<string, string>();
  }

  map<string, string> data;
  if (m->empty()) {
    return data;
  }

  for (const auto &it : *m) {
    if (typeid(int) == it.second.type()) {
      data[it.first] = to_string(boost::any_cast<int>(it.second));
    } else if (typeid(long) == it.second.type()) {
      data[it.first] = to_string(boost::any_cast<long>(it.second));
    } else if (typeid(double) == it.second.type()) {
      data[it.first] = to_string(boost::any_cast<double>(it.second));
    } else if (typeid(float) == it.second.type()) {
      data[it.first] = to_string(boost::any_cast<float>(it.second));
    } else if (typeid(bool) == it.second.type()) {
      string v = boost::any_cast<bool>(it.second) ? "true" : "false";
      data[it.first] = v;
    } else if (typeid(string) == it.second.type()) {
      string v = boost::any_cast<string>(it.second);
      data[it.first] = v;
    }
  }
  return data;
}


text:
#pragma once
#include "Core/Common.hpp"
#include "Vulkan/Utils.hpp"
#include <Eigen/Dense>

#define PI_CONST 3.141592653589f

struct TracingParameters
{
	SHADER_ALIGN Eigen::Vector3f CameraPosition;
	SHADER_ALIGN Eigen::Vector3f RayMin;
	SHADER_ALIGN Eigen::Vector3f RayDDx;
	SHADER_ALIGN Eigen::Vector3f RayDDy;
	SHADER_ALIGN Eigen::Vector3f MousePosition;
	int SelectionDiameter;
};

struct CameraSetup
{
	Eigen::Vector3f Position;
	Eigen::Vector3f Forward;
	Eigen::Vector3f Right;
};

class Camera
{
public:
	Camera(const Eigen::Vector3f& position, const Eigen::Vector3f& forward, const Eigen::Vector3f& right, float fov);
	Camera() = default;
	~Camera() = default;

	void Set(const CameraSetup& setup);
	void Rotate(const Eigen::Vector3f& axis, const float angle);
	void RotateLocal(const Eigen::Vector3f& axis, const float angle);

	void Move(const Eigen::Vector3f& offset);
	void MoveLocal(const Eigen::Vector3f& offset);

	Eigen::Vector3f& Position();
	Eigen::Vector3f& Forward();
	Eigen::Vector3f& Right();
	Eigen::Vector3f& Up();
	float& Fov();

	static float DegToRad(float value);
	static float RadToDeg(float value);

	void GetTracingParameters(uint32_t imageWidth, uint32_t imageHeight, TracingParameters& tracingParameters) const;

private:
	Eigen::Matrix3f GetLocalToGlobalMatrix() const;

	Eigen::Vector3f position_;
	Eigen::Vector3f forward_;
	Eigen::Vector3f right_;
	Eigen::Vector3f up_;
	float fov_;
};

ext: hpp

max_stars_repo_name: handsomePirate/VoxelViewer

max_issues_repo_name: handsomePirate/VoxelViewer

max_forks_repo_name: handsomePirate/VoxelViewer


text:
#ifndef LINESEARCH_HPP_
#define LINESEARCH_HPP_

/*
* LEGAL NOTICE
* This computer software was prepared by Battelle Memorial Institute,
* hereinafter the Contractor, under Contract No. DE-AC05-76RL0 1830
* with the Department of Energy (DOE). NEITHER THE GOVERNMENT NOR THE
* CONTRACTOR MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY
* LIABILITY FOR THE USE OF THIS SOFTWARE. This notice including this
* sentence must appear on any copies of this computer software.
*
* EXPORT CONTROL
* User agrees that the Software will not be shipped, transferred or
* exported into any country or used in any manner prohibited by the
* United States Export Administration Act or any other applicable
* export laws, restrictions or regulations (collectively the "Export Laws").
* Export of the Software may require some form of license or other
* authority from the U.S. Government, and failure to obtain such
* export control license may result in criminal liability under
* U.S. laws. In addition, if the Software is identified as export controlled
* items under the Export Laws, User represents and warrants that User
* is not a citizen, or otherwise located within, an embargoed nation
* (including without limitation Iran, Syria, Sudan, Cuba, and North Korea)
*     and that User is not otherwise prohibited
* under the Export Laws from receiving the Software.
*
* Copyright 2011 Battelle Memorial Institute.  All Rights Reserved.
* Distributed as open-source under the terms of the Educational Community
* License version 2.0 (ECL 2.0). http://www.opensource.org/licenses/ecl2.php
*
* For further details, see: http://www.globalchange.umd.edu/models/gcam/
*
*/

/*!
 * \file linesearch.hpp
 * \ingroup Solution
 * \brief Line search helper function for multidimensional root finders
 * \remark Because this function is defined as a template, we have to put the entire body in
 *         the header file.  It's ugly, and I don't like it, but the alternatives are worse,
 *         and nonportable to boot.
 */

#include "util/base/include/util.h"
#include "functor.hpp"
#include <boost/numeric/ublas/vector.hpp>
#include <algorithm>
#include <iostream>

#define UBLAS boost::numeric::ublas

/*!
 * Perform a line search for use in multidimensional root finders.  This is NOT a 1-D
 * minimization routine!
 * \tparam FTYPE: floating point type.  Note we require the function have the same input and
 *                output types
 * \param[in]  f: A function adaptor for computing f(x) = F*F (for vector-valued F)
 * \param[in] x0: Starting point for the step
 * \param[in] f0: Value of f(x0)
 * \param[in] g0: Value of grad-f(x0)
 * \param[in] dx: Proposed step from the root finder
 * \param[out] x: Final step determined by the search
 * \param[out]fx: Value of f(x)
 * \param[inout]neval: number of function evaluations. The subroutine
 * adds whatever value is passed in, allowing the caller to keep a
 * running total.
 * \return : 0= success, anything else= fail
 *
 */
template <class FTYPE>
int linesearch(SclFVec<FTYPE,FTYPE> &f, const UBLAS::vector<FTYPE> &x0,
               FTYPE f0, const UBLAS::vector<FTYPE> &g0,
               const UBLAS::vector<FTYPE> &dx, UBLAS::vector<FTYPE> &x,
               FTYPE &fx, int &neval, std::ostream *solverlog = 0)
{
  const FTYPE lseps = 1.0e-7;   // part of the definition of "sufficient" decrease
  const FTYPE TOLX = 1.0e-6;    // tolerance for x values
  // NB: This value of TOLX is way too small for single-precision,
  // but we're running GCAM in double precision anyhow, and the small
  // tolerance seems to be necessary for solving global unconventional
  // oil, which has a nasty step function in its demand.  If we ever
  // contemplate using this function in a single-precision
  // application, we are going to have to adjust this tolerance.
  int n = x0.size();
  FTYPE g0dx=inner_prod(g0,dx); // initial rate of decrease, df/dlambda
  FTYPE lambda = 1.0;           // start with full step
  FTYPE maxval = 0.0;

  if(g0dx >= 0) {
    if(solverlog)
      (*solverlog) << "Linesearch aborted.  Not an initial descent direction.  g0dx= "
                   << g0dx << "\n";
    return 1;                   // If we're being called by Broyden's
                                // method, this will trigger a recalc
                                // on the Jacobian
  }

  // set lmin (minimum admissable value for lambda)
  for(int i=0; i<n; ++i) {
    FTYPE tmp = fabs(dx[i] / (x0[i] + TOLX)); // fractional change in ith component of x over a unit step
    maxval = std::max(tmp,maxval);          // pick the largest
  }
  FTYPE lmin = TOLX / maxval;     // when lambda gets this small, even
                                // the fastest changing x is changing
                                // by less than TOLX

  if(solverlog)
    (*solverlog) << "Beginning linesearch: lmin = " << lmin << "  f0 = " << f0 << "\n";

  while(lambda > lmin) {
    x  = x0 + lambda*dx;
    fx = f(x);
    neval++;

    if(solverlog) {
        (*solverlog) << "\tlambda = " << lambda << "  fx = " << fx << std::endl;
      if(fx > 10.0*f0) {
        f.prn_diagnostic(solverlog);
        (*solverlog) << std::endl;
      }
    }

    // check for exit condition.  The term after the + is negative, so
    // it specifies a minimum rate of decrease.  lseps is set fairly
    // small, so we're biased toward accepting steps unless their rate
    // of decrease is painfully slow
    if(fx <= f0 + lseps*lambda*g0dx)
      // SUCCESS
      return 0;

    // last step increased or decreased too slowly --- backtrack
    FTYPE tl0 = 0.1*lambda; // never decrease lambda by more than a factor of 10
    FTYPE tl1 = 0.5*lambda; // always decrease lambda by at least half
    // We fit a quadratic approximation to f(lambda) using the values
    // we've computed already, and we try the minimum of the quadratic
    // as our next lambda (subject to the constraints above).  NR
    // suggests that on iterations after the first we fit a cubic, but
    // it's not clear that that buys us a whole lot, so we'll try just
    // using the quadratic every time for now.
    FTYPE denom = fx - f0 - g0dx*lambda;
    if(denom != 0.0)
      lambda = -g0dx * (lambda*lambda)/(2.0 * denom);
    else
      lambda = 0.5*lambda;

    lambda = std::max(tl0, std::min(tl1,lambda));
  }

  // If we get here, then the line search failed.  Depending on the
  // multidimensional solver we're using, we may just need to refresh
  // the Jacobian.  Otherwise, try starting with a new initial guess.
  return 1;
}

#undef UBLAS

#endif

max_stars_repo_name: cmcormack/gcam-core

max_issues_repo_name: cmcormack/gcam-core

max_forks_repo_name: cmcormack/gcam-core


text:
/*
 *             Copyright Andrey Semashev 2018.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   critical_section_abi.cpp
 * \author Andrey Semashev
 * \date   09.03.2018
 *
 * \brief  This file contains ABI test for critical_section.hpp
 */

#include <boost/winapi/critical_section.hpp>
#include <windows.h>
#include "abi_test_tools.hpp"

int main()
{
    BOOST_WINAPI_TEST_STRUCT(CRITICAL_SECTION, (DebugInfo)(LockCount)(RecursionCount)(OwningThread)(LockSemaphore)(SpinCount));

    return boost::report_errors();
}