diff --git a/src/dryad/format/endf.hpp b/src/dryad/format/endf.hpp index d62cee14..90f3ec2e 100644 --- a/src/dryad/format/endf.hpp +++ b/src/dryad/format/endf.hpp @@ -11,6 +11,8 @@ #include "dryad/format/endf/createTabulatedMultiplicity.hpp" #include "dryad/format/endf/createMultiplicity.hpp" #include "dryad/format/endf/createTabulatedCrossSection.hpp" +#include "dryad/format/endf/createLegendreAngularDistribution.hpp" +#include "dryad/format/endf/createLegendreAngularDistributions.hpp" #include "dryad/format/endf/createTabulatedAngularDistribution.hpp" #include "dryad/format/endf/createTabulatedAngularDistributions.hpp" #include "dryad/format/endf/createTabulatedEnergyDistribution.hpp" diff --git a/src/dryad/format/endf/createLegendreAngularDistribution.hpp b/src/dryad/format/endf/createLegendreAngularDistribution.hpp new file mode 100644 index 00000000..bc58760b --- /dev/null +++ b/src/dryad/format/endf/createLegendreAngularDistribution.hpp @@ -0,0 +1,48 @@ +#ifndef NJOY_DRYAD_FORMAT_ENDF_CREATELEGENDREANGULARDISTRIBUTION +#define NJOY_DRYAD_FORMAT_ENDF_CREATELEGENDREANGULARDISTRIBUTION + +// system includes +#include + +// other includes +#include "tools/Log.hpp" +#include "dryad/format/createVector.hpp" +#include "dryad/format/endf/createBoundaries.hpp" +#include "dryad/format/endf/createInterpolants.hpp" +#include "dryad/LegendreAngularDistribution.hpp" +#include "ENDFtk/section/6.hpp" + +namespace njoy { +namespace dryad { +namespace format { +namespace endf { + + /** + * @brief Create a LegendreAngularDistribution from a range of coefficients + */ + template < typename Range > + LegendreAngularDistribution createLegendreAngularDistribution( const Range& range, bool addOrderZero ) { + + try { + + auto coefficients = createVector( range ); + if ( addOrderZero ) { coefficients.insert( coefficients.begin(), 1. ); } + for ( std::size_t index = 0; index < coefficients.size(); ++index ) { + + coefficients[index] *= 0.5 * ( 2 * index + 1 ); + } + return LegendreAngularDistribution( std::move( coefficients ) ); + } + catch ( ... ) { + + Log::info( "Error encountered while creating an energy distribution table" ); + throw; + } + } + +} // endf namespace +} // format namespace +} // dryad namespace +} // njoy namespace + +#endif diff --git a/src/dryad/format/endf/createLegendreAngularDistributions.hpp b/src/dryad/format/endf/createLegendreAngularDistributions.hpp new file mode 100644 index 00000000..785a6d9e --- /dev/null +++ b/src/dryad/format/endf/createLegendreAngularDistributions.hpp @@ -0,0 +1,56 @@ +#ifndef NJOY_DRYAD_FORMAT_ENDF_CREATELEGENDREANGULARDISTRIBUTIONS +#define NJOY_DRYAD_FORMAT_ENDF_CREATELEGENDREANGULARDISTRIBUTIONS + +// system includes +#include + +// other includes +#include "tools/Log.hpp" +#include "dryad/format/createVector.hpp" +#include "dryad/format/endf/createBoundaries.hpp" +#include "dryad/format/endf/createInterpolants.hpp" +#include "dryad/format/endf/createLegendreAngularDistribution.hpp" +#include "dryad/LegendreAngularDistributions.hpp" +#include "ENDFtk/section/4.hpp" + +namespace njoy { +namespace dryad { +namespace format { +namespace endf { + + /** + * @brief Create a LegendreAngularDistributions instance from a parsed + * ENDF MF4 section + */ + LegendreAngularDistributions + createLegendreAngularDistributions( + const ENDFtk::section::Type< 4 >::LegendreDistributions& distribution ) { + + try { + + auto energies = createVector( distribution.incidentEnergies() ); + std::vector< LegendreAngularDistribution > distributions; + distributions.reserve( energies.size() ); + for ( auto&& entry : distribution.angularDistributions() ) { + + distributions.emplace_back( createLegendreAngularDistribution( entry.coefficients(), true ) ); + } + auto boundaries = createBoundaries( distribution.boundaries() ); + auto interpolants = createInterpolants( distribution.interpolants() ); + return LegendreAngularDistributions( + std::move( energies ), std::move( distributions ), + std::move( boundaries ), std::move( interpolants ) ); + } + catch ( ... ) { + + Log::info( "Error encountered while creating a Legendre angular distribution table" ); + throw; + } + } + +} // endf namespace +} // format namespace +} // dryad namespace +} // njoy namespace + +#endif diff --git a/src/dryad/format/endf/createReactionProduct.hpp b/src/dryad/format/endf/createReactionProduct.hpp index 85f128db..8c57fbce 100644 --- a/src/dryad/format/endf/createReactionProduct.hpp +++ b/src/dryad/format/endf/createReactionProduct.hpp @@ -10,6 +10,7 @@ #include "dryad/format/endf/createMultiplicity.hpp" #include "dryad/format/endf/createTabulatedEnergyDistributions.hpp" #include "dryad/format/endf/createTabulatedAngularDistributions.hpp" +#include "dryad/format/endf/createLegendreAngularDistributions.hpp" #include "dryad/format/endf/createTabulatedAverageEnergy.hpp" #include "dryad/format/endf/createTabulatedFormFactor.hpp" #include "dryad/format/endf/createTabulatedScatteringFunction.hpp" @@ -22,6 +23,25 @@ namespace dryad { namespace format { namespace endf { + /** + * @brief Create a ReactionProduct from a parsed ENDF MF4 LegendreDistributions + * + * @param[in] projectile the projectile identifier + * @param[in] target the target identifier + * @param[in] distributions the MF4 LegendreDistributions + */ + ReactionProduct + createReactionProduct( const id::ParticleID& projectile, const id::ParticleID& target, + const ENDFtk::section::Type< 4 >::LegendreDistributions& distributions ) { + + id::ParticleID id = createProductIdentifier( 1, 0 ); + Log::info( "Reading reaction product data for \'{}\'", id ); + int multiplicity = 1; + auto distribution = TwoBodyDistributionData( ReferenceFrame::CentreOfMass, + createLegendreAngularDistributions( distributions ) ); + return ReactionProduct( std::move( id ), std::move( multiplicity ), std::move( distribution ) ); + } + /** * @brief Create a ReactionProduct from a parsed ENDF MF6 reaction product * diff --git a/src/dryad/format/endf/createReactionProducts.hpp b/src/dryad/format/endf/createReactionProducts.hpp index 496a2a3d..c6bd0dc0 100644 --- a/src/dryad/format/endf/createReactionProducts.hpp +++ b/src/dryad/format/endf/createReactionProducts.hpp @@ -29,7 +29,34 @@ namespace endf { if ( material.hasSection( 4, mt ) || material.hasSection( 5, mt ) ) { - Log::info( "Reading reaction product data from MF4 and/or MF5 is not implemented yet" ); + switch ( mt ) { + + case 2 : { + + auto section = material.section( 4, mt ).parse< 4 >(); + switch ( section.LTT() ) { + + case 1 : { + + using LegendreDistributions = ENDFtk::section::Type< 4 >::LegendreDistributions; + auto distributions = std::get< LegendreDistributions >( section.distributions() ); + products.emplace_back( createReactionProduct( projectile, target, distributions ) ); + break; + } + default : { + + Log::info( "Any MF4 LTT different from 1 is not implemented yet" ); + break; + } + } + break; + } + default : { + + Log::info( "Reading reaction product data from MF4 and/or MF5 is not implemented yet" ); + break; + } + } } else if ( material.hasSection( 6, mt ) ) { diff --git a/src/dryad/format/endf/createTabulatedEnergyDistribution.hpp b/src/dryad/format/endf/createTabulatedEnergyDistribution.hpp index 45db8cc2..ea23d191 100644 --- a/src/dryad/format/endf/createTabulatedEnergyDistribution.hpp +++ b/src/dryad/format/endf/createTabulatedEnergyDistribution.hpp @@ -10,6 +10,7 @@ #include "dryad/format/endf/createBoundaries.hpp" #include "dryad/format/endf/createInterpolants.hpp" #include "dryad/TabulatedEnergyDistribution.hpp" +#include "ENDFtk/section/6.hpp" #include "ENDFtk/section/26.hpp" namespace njoy { @@ -17,6 +18,31 @@ namespace dryad { namespace format { namespace endf { + /** + * @brief Create a TabulatedEnergyDistribution from a parsed ENDF MF6 LAW = 1 + * LegendreCoefficients entry + */ + TabulatedEnergyDistribution + createTabulatedEnergyDistribution( + const ENDFtk::section::Type< 6 >::ContinuumEnergyAngle::LegendreCoefficients& distribution ) { + + //! @todo interpolants and boundaries on LegendreCoefficients for interpolation on + //! outgoing energy? + //! @todo what is the interpolation type over the outgoing energy axis? + + try { + + auto energies = createVector( distribution.energies() ); + auto values = createVector( distribution.totalEmissionProbabilities() ); + return TabulatedEnergyDistribution( std::move( energies ), std::move( values ) ); + } + catch ( ... ) { + + Log::info( "Error encountered while creating an energy distribution table" ); + throw; + } + } + /** * @brief Create a TabulatedEnergyDistribution from a parsed ENDF MF26 LAW = 1 * LegendreCoefficients entry (with NA = 0) @@ -44,7 +70,7 @@ namespace endf { } catch ( ... ) { - Log::info( "Error encountered while creating an average reaction product energy table" ); + Log::info( "Error encountered while creating an energy distribution table" ); throw; } } diff --git a/src/dryad/format/endf/test/CMakeLists.txt b/src/dryad/format/endf/test/CMakeLists.txt index 668fa0c2..075422b8 100644 --- a/src/dryad/format/endf/test/CMakeLists.txt +++ b/src/dryad/format/endf/test/CMakeLists.txt @@ -10,6 +10,8 @@ add_cpp_test( format.endf.createReactionType createReactionType.test.cpp add_cpp_test( format.endf.createTabulatedCrossSection createTabulatedCrossSection.test.cpp ) add_cpp_test( format.endf.createTabulatedMultiplicity createTabulatedMultiplicity.test.cpp ) add_cpp_test( format.endf.createMultiplicity createMultiplicity.test.cpp ) +add_cpp_test( format.endf.createLegendreAngularDistribution createLegendreAngularDistribution.test.cpp ) +add_cpp_test( format.endf.createLegendreAngularDistributions createLegendreAngularDistributions.test.cpp ) add_cpp_test( format.endf.createTabulatedAngularDistribution createTabulatedAngularDistribution.test.cpp ) add_cpp_test( format.endf.createTabulatedAngularDistributions createTabulatedAngularDistributions.test.cpp ) add_cpp_test( format.endf.createTabulatedEnergyDistribution createTabulatedEnergyDistribution.test.cpp ) diff --git a/src/dryad/format/endf/test/createLegendreAngularDistribution.test.cpp b/src/dryad/format/endf/test/createLegendreAngularDistribution.test.cpp new file mode 100644 index 00000000..72cba1d8 --- /dev/null +++ b/src/dryad/format/endf/test/createLegendreAngularDistribution.test.cpp @@ -0,0 +1,159 @@ +// include Catch2 +#include +#include +using Catch::Matchers::WithinRel; + +// what we are testing +#include "dryad/format/endf/createLegendreAngularDistribution.hpp" + +// other includes +#include "ENDFtk/tree/fromFile.hpp" + +// convenience typedefs +using namespace njoy::dryad; + +void verifyMF4Chunk( const LegendreAngularDistribution& ); +void verifyMF6LAW1Chunk( const LegendreAngularDistribution& ); +void verifyMF6LAW2Chunk( const LegendreAngularDistribution& ); + +SCENARIO( "createLegendreAngularDistribution" ) { + + GIVEN( "ENDF MF4 LegendreCoefficients" ) { + + using LegendreDistributions = njoy::ENDFtk::section::Type< 4 >::LegendreDistributions; + + auto tape = njoy::ENDFtk::tree::fromFile( "n-001_H_001.endf" ); + auto section = tape.materials().front().section( 4, 2 ).parse< 4 >(); + auto distribution = std::get< LegendreDistributions >( section.distributions() ); + + WHEN( "a single parsed MF4 LegendreCoefficients is given" ) { + + THEN( "it can be converted" ) { + + auto coefficients = distribution.angularDistributions()[0].coefficients(); + auto chunk = format::endf::createLegendreAngularDistribution( coefficients, true ); + + verifyMF4Chunk( chunk ); + } // THEN + } // WHEN + } // GIVEN + + GIVEN( "ENDF MF6 LAW=1 LegendreCoefficients" ) { + + using ContinuumEnergyAngle = njoy::ENDFtk::section::Type< 6 >::ContinuumEnergyAngle; + using LegendreCoefficients = ContinuumEnergyAngle::LegendreCoefficients; + + auto tape = njoy::ENDFtk::tree::fromFile( "n-009_F_019.endf" ); + auto section = tape.materials().front().section( 6, 16 ).parse< 6 >(); + auto product = section.reactionProduct( 1 ); + auto distribution = std::get< ContinuumEnergyAngle >( product.distribution() ); + auto entry = std::get< LegendreCoefficients >( distribution.distributions()[0] ); + + WHEN( "a single parsed MF6 LAW=1 LegendreCoefficients is given" ) { + + THEN( "it can be converted" ) { + + auto coefficients = entry.coefficients()[0]; + auto chunk = format::endf::createLegendreAngularDistribution( coefficients, false ); + + verifyMF6LAW1Chunk( chunk ); + } // THEN + } // WHEN + } // GIVEN + + GIVEN( "ENDF MF6 LAW=2 LegendreCoefficients" ) { + + using DiscreteTwoBodyScattering = njoy::ENDFtk::section::Type< 6 >::DiscreteTwoBodyScattering; + using LegendreCoefficients = DiscreteTwoBodyScattering::LegendreCoefficients; + + auto tape = njoy::ENDFtk::tree::fromFile( "n-001_H_001.endf" ); + auto section = tape.materials().front().section( 6, 102 ).parse< 6 >(); + auto distribution = std::get< DiscreteTwoBodyScattering >( section.reactionProduct( 0 ).distribution() ); + auto entry = std::get< LegendreCoefficients >( distribution.distributions()[0] ); + + WHEN( "a single parsed MF6 LAW=2 LegendreCoefficients is given" ) { + + THEN( "it can be converted" ) { + + auto coefficients = entry.coefficients(); + auto chunk = format::endf::createLegendreAngularDistribution( coefficients, true ); + + verifyMF6LAW2Chunk( chunk ); + } // THEN + } // WHEN + } // GIVEN +} // SCENARIO + +void verifyMF4Chunk( const LegendreAngularDistribution& chunk ) { + + auto pdf = chunk.pdf(); + CHECK_THAT( -1., WithinRel( pdf.lowerCosineLimit() ) ); + CHECK_THAT( 1., WithinRel( pdf.upperCosineLimit() ) ); + CHECK( 6 == pdf.order() ); + CHECK( 7 == pdf.coefficients().size() ); + CHECK_THAT( 0.5 , WithinRel( pdf.coefficients()[0] ) ); + CHECK_THAT( -1.7511000E-14, WithinRel( pdf.coefficients()[1] ) ); + CHECK_THAT( -2.5280750E-16, WithinRel( pdf.coefficients()[2] ) ); + CHECK_THAT( -6.4002050E-17, WithinRel( pdf.coefficients()[3] ) ); + CHECK_THAT( 1.3653765E-16, WithinRel( pdf.coefficients()[4] ) ); + CHECK_THAT( -1.7067215E-17, WithinRel( pdf.coefficients()[5] ) ); + CHECK_THAT( 2.5600835E-17, WithinRel( pdf.coefficients()[6] ) ); + + auto cdf = chunk.cdf(); + CHECK_THAT( -1., WithinRel( cdf.lowerCosineLimit() ) ); + CHECK_THAT( 1., WithinRel( cdf.upperCosineLimit() ) ); + CHECK( 7 == cdf.order() ); + CHECK( 8 == cdf.coefficients().size() ); + CHECK_THAT( 0.5 , WithinRel( cdf.coefficients()[0] ) ); + CHECK_THAT( 0.5 , WithinRel( cdf.coefficients()[1] ) ); + CHECK_THAT( -5.82785685e-15, WithinRel( cdf.coefficients()[2] ) ); + CHECK_THAT( -6.57323500e-17, WithinRel( cdf.coefficients()[3] ) ); + CHECK_THAT( -7.59158500e-18, WithinRel( cdf.coefficients()[4] ) ); + CHECK_THAT( 1.32015550e-17, WithinRel( cdf.coefficients()[5] ) ); + CHECK_THAT( -1.55156500e-18, WithinRel( cdf.coefficients()[6] ) ); + CHECK_THAT( 1.96929500e-18, WithinRel( cdf.coefficients()[7] ) ); +} + +void verifyMF6LAW1Chunk( const LegendreAngularDistribution& chunk ) { + + auto pdf = chunk.pdf(); + CHECK_THAT( -1., WithinRel( pdf.lowerCosineLimit() ) ); + CHECK_THAT( 1., WithinRel( pdf.upperCosineLimit() ) ); + CHECK( 2 == pdf.order() ); + CHECK( 3 == pdf.coefficients().size() ); + CHECK_THAT( 0.5 , WithinRel( pdf.coefficients()[0] ) ); + CHECK_THAT( 4.52220e-2, WithinRel( pdf.coefficients()[1] ) ); + CHECK_THAT( 4.24225e-2, WithinRel( pdf.coefficients()[2] ) ); + + auto cdf = chunk.cdf(); + CHECK_THAT( -1., WithinRel( cdf.lowerCosineLimit() ) ); + CHECK_THAT( 1., WithinRel( cdf.upperCosineLimit() ) ); + CHECK( 3 == cdf.order() ); + CHECK( 4 == cdf.coefficients().size() ); + CHECK_THAT( 0.484926 , WithinRel( cdf.coefficients()[0] ) ); + CHECK_THAT( 0.4915155 , WithinRel( cdf.coefficients()[1] ) ); + CHECK_THAT( 0.015074 , WithinRel( cdf.coefficients()[2] ) ); + CHECK_THAT( 0.0084845 , WithinRel( cdf.coefficients()[3] ) ); +} + +void verifyMF6LAW2Chunk( const LegendreAngularDistribution& chunk ) { + + auto pdf = chunk.pdf(); + CHECK_THAT( -1., WithinRel( pdf.lowerCosineLimit() ) ); + CHECK_THAT( 1., WithinRel( pdf.upperCosineLimit() ) ); + CHECK( 2 == pdf.order() ); + CHECK( 3 == pdf.coefficients().size() ); + CHECK_THAT( 0.5 , WithinRel( pdf.coefficients()[0] ) ); + CHECK_THAT( -5.6557125e-08, WithinRel( pdf.coefficients()[1] ) ); + CHECK_THAT( -2.1856500e-12, WithinRel( pdf.coefficients()[2] ) ); + + auto cdf = chunk.cdf(); + CHECK_THAT( -1., WithinRel( cdf.lowerCosineLimit() ) ); + CHECK_THAT( 1., WithinRel( cdf.upperCosineLimit() ) ); + CHECK( 3 == cdf.order() ); + CHECK( 4 == cdf.coefficients().size() ); + CHECK_THAT( 0.500000018852375, WithinRel( cdf.coefficients()[0] ) ); + CHECK_THAT( 0.500000000000437, WithinRel( cdf.coefficients()[1] ) ); + CHECK_THAT( -1.88523750000e-08, WithinRel( cdf.coefficients()[2] ) ); + CHECK_THAT( -4.37130000000e-13, WithinRel( cdf.coefficients()[3] ) ); +} diff --git a/src/dryad/format/endf/test/createLegendreAngularDistributions.test.cpp b/src/dryad/format/endf/test/createLegendreAngularDistributions.test.cpp new file mode 100644 index 00000000..ab714e70 --- /dev/null +++ b/src/dryad/format/endf/test/createLegendreAngularDistributions.test.cpp @@ -0,0 +1,117 @@ +// include Catch2 +#include +#include +using Catch::Matchers::WithinRel; + +// what we are testing +#include "dryad/format/endf/createLegendreAngularDistributions.hpp" + +// other includes +#include "ENDFtk/tree/fromFile.hpp" + +// convenience typedefs +using namespace njoy::dryad; + +void verifyChunk( const LegendreAngularDistributions& ); + +SCENARIO( "createLegendreAngularDistribution" ) { + + GIVEN( "ENDF MF4 LegendreDistributions" ) { + + using LegendreDistributions = njoy::ENDFtk::section::Type< 4 >::LegendreDistributions; + + auto tape = njoy::ENDFtk::tree::fromFile( "n-001_H_001.endf" ); + auto section = tape.materials().front().section( 4, 2 ).parse< 4 >(); + auto distribution = std::get< LegendreDistributions >( section.distributions() ); + + WHEN( "a single parsed MF4 LegendreDistributions is given" ) { + + THEN( "it can be converted" ) { + + auto chunk = format::endf::createLegendreAngularDistributions( distribution ); + + verifyChunk( chunk ); + } // THEN + } // WHEN + } // GIVEN +} // SCENARIO + +void verifyChunk( const LegendreAngularDistributions& chunk ) { + + CHECK( 153 == chunk.numberPoints() ); + CHECK( 1 == chunk.numberRegions() ); + CHECK( 153 == chunk.grid().size() ); + CHECK( 153 == chunk.distributions().size() ); + CHECK( 1 == chunk.boundaries().size() ); + CHECK( 1 == chunk.interpolants().size() ); + CHECK_THAT( 1e-5 , WithinRel( chunk.grid()[0] ) ); + CHECK_THAT( 2e-5 , WithinRel( chunk.grid()[1] ) ); + CHECK_THAT( 1.95e+7, WithinRel( chunk.grid()[151] ) ); + CHECK_THAT( 2e+7 , WithinRel( chunk.grid()[152] ) ); + CHECK( 7 == chunk.distributions()[0].pdf().coefficients().size() ); + CHECK( 7 == chunk.distributions()[1].pdf().coefficients().size() ); + CHECK( 7 == chunk.distributions()[151].pdf().coefficients().size() ); + CHECK( 7 == chunk.distributions()[152].pdf().coefficients().size() ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[0].pdf().coefficients()[0] ) ); + CHECK_THAT( -1.7511000E-14 , WithinRel( chunk.distributions()[0].pdf().coefficients()[1] ) ); + CHECK_THAT( -2.5280750E-16 , WithinRel( chunk.distributions()[0].pdf().coefficients()[2] ) ); + CHECK_THAT( -6.4002050E-17 , WithinRel( chunk.distributions()[0].pdf().coefficients()[3] ) ); + CHECK_THAT( 1.3653765E-16 , WithinRel( chunk.distributions()[0].pdf().coefficients()[4] ) ); + CHECK_THAT( -1.7067215E-17 , WithinRel( chunk.distributions()[0].pdf().coefficients()[5] ) ); + CHECK_THAT( 2.5600835E-17 , WithinRel( chunk.distributions()[0].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[1].pdf().coefficients()[0] ) ); + CHECK_THAT( -3.4846950E-14 , WithinRel( chunk.distributions()[1].pdf().coefficients()[1] ) ); + CHECK_THAT( -1.7387225E-16 , WithinRel( chunk.distributions()[1].pdf().coefficients()[2] ) ); + CHECK_THAT( -9.1736400E-17 , WithinRel( chunk.distributions()[1].pdf().coefficients()[3] ) ); + CHECK_THAT( -2.9867625E-17 , WithinRel( chunk.distributions()[1].pdf().coefficients()[4] ) ); + CHECK_THAT( -3.4134430E-17 , WithinRel( chunk.distributions()[1].pdf().coefficients()[5] ) ); + CHECK_THAT( 1.8773950E-16 , WithinRel( chunk.distributions()[1].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[151].pdf().coefficients()[0] ) ); + CHECK_THAT( -2.4240045E-02 , WithinRel( chunk.distributions()[151].pdf().coefficients()[1] ) ); + CHECK_THAT( 1.7942750E-02 , WithinRel( chunk.distributions()[151].pdf().coefficients()[2] ) ); + CHECK_THAT( -2.54685165E-03 , WithinRel( chunk.distributions()[151].pdf().coefficients()[3] ) ); + CHECK_THAT( 1.54781595E-03 , WithinRel( chunk.distributions()[151].pdf().coefficients()[4] ) ); + CHECK_THAT( 4.91773975E-05 , WithinRel( chunk.distributions()[151].pdf().coefficients()[5] ) ); + CHECK_THAT( 3.82748535E-05 , WithinRel( chunk.distributions()[151].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[152].pdf().coefficients()[0] ) ); + CHECK_THAT( -2.41945200E-02 , WithinRel( chunk.distributions()[152].pdf().coefficients()[1] ) ); + CHECK_THAT( 1.95173075E-02 , WithinRel( chunk.distributions()[152].pdf().coefficients()[2] ) ); + CHECK_THAT( -2.71943700E-03 , WithinRel( chunk.distributions()[152].pdf().coefficients()[3] ) ); + CHECK_THAT( 1.69449750E-03 , WithinRel( chunk.distributions()[152].pdf().coefficients()[4] ) ); + CHECK_THAT( 5.25219970E-05 , WithinRel( chunk.distributions()[152].pdf().coefficients()[5] ) ); + CHECK_THAT( 4.48370065E-05 , WithinRel( chunk.distributions()[152].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[0].cdf().coefficients()[0] ) ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[0].cdf().coefficients()[1] ) ); + CHECK_THAT( -5.82785685e-15 , WithinRel( chunk.distributions()[0].cdf().coefficients()[2] ) ); + CHECK_THAT( -6.57323500e-17 , WithinRel( chunk.distributions()[0].cdf().coefficients()[3] ) ); + CHECK_THAT( -7.59158500e-18 , WithinRel( chunk.distributions()[0].cdf().coefficients()[4] ) ); + CHECK_THAT( 1.32015550e-17 , WithinRel( chunk.distributions()[0].cdf().coefficients()[5] ) ); + CHECK_THAT( -1.55156500e-18 , WithinRel( chunk.distributions()[0].cdf().coefficients()[6] ) ); + CHECK_THAT( 1.96929500e-18 , WithinRel( chunk.distributions()[0].cdf().coefficients()[7] ) ); + CHECK_THAT( 0.50000000000001, WithinRel( chunk.distributions()[1].cdf().coefficients()[0] ) ); + CHECK_THAT( 0.5 , WithinRel( chunk.distributions()[1].cdf().coefficients()[1] ) ); + CHECK_THAT( -1.16025448e-14 , WithinRel( chunk.distributions()[1].cdf().coefficients()[2] ) ); + CHECK_THAT( -3.14558250e-17 , WithinRel( chunk.distributions()[1].cdf().coefficients()[3] ) ); + CHECK_THAT( -1.00020700e-17 , WithinRel( chunk.distributions()[1].cdf().coefficients()[4] ) ); + CHECK_THAT( -1.77601250e-17 , WithinRel( chunk.distributions()[1].cdf().coefficients()[5] ) ); + CHECK_THAT( -3.10313000e-18 , WithinRel( chunk.distributions()[1].cdf().coefficients()[6] ) ); + CHECK_THAT( 1.44415000e-17 , WithinRel( chunk.distributions()[1].cdf().coefficients()[7] ) ); + CHECK_THAT( 5.08080015e-01 , WithinRel( chunk.distributions()[151].cdf().coefficients()[0] ) ); + CHECK_THAT( 4.96411450e-01 , WithinRel( chunk.distributions()[151].cdf().coefficients()[1] ) ); + CHECK_THAT( -7.71617905e-03 , WithinRel( chunk.distributions()[151].cdf().coefficients()[2] ) ); + CHECK_THAT( 3.41657045e-03 , WithinRel( chunk.distributions()[151].cdf().coefficients()[3] ) ); + CHECK_THAT( -3.683066225e-04, WithinRel( chunk.distributions()[151].cdf().coefficients()[4] ) ); + CHECK_THAT( 1.690353305e-04, WithinRel( chunk.distributions()[151].cdf().coefficients()[5] ) ); + CHECK_THAT( 4.47067250e-06 , WithinRel( chunk.distributions()[151].cdf().coefficients()[6] ) ); + CHECK_THAT( 2.94421950e-06 , WithinRel( chunk.distributions()[151].cdf().coefficients()[7] ) ); + CHECK_THAT( 5.08064840e-01 , WithinRel( chunk.distributions()[152].cdf().coefficients()[0] ) ); + CHECK_THAT( 4.960965385e-01, WithinRel( chunk.distributions()[152].cdf().coefficients()[1] ) ); + CHECK_THAT( -7.67634900e-03 , WithinRel( chunk.distributions()[152].cdf().coefficients()[2] ) ); + CHECK_THAT( 3.71518400e-03 , WithinRel( chunk.distributions()[152].cdf().coefficients()[3] ) ); + CHECK_THAT( -3.93265727e-04 , WithinRel( chunk.distributions()[152].cdf().coefficients()[4] ) ); + CHECK_THAT( 1.848284995e-04, WithinRel( chunk.distributions()[152].cdf().coefficients()[5] ) ); + CHECK_THAT( 4.77472700e-06 , WithinRel( chunk.distributions()[152].cdf().coefficients()[6] ) ); + CHECK_THAT( 3.44900050e-06 , WithinRel( chunk.distributions()[152].cdf().coefficients()[7] ) ); + CHECK( 152 == chunk.boundaries()[0] ); + CHECK( InterpolationType::LinearLinear == chunk.interpolants()[0] ); +} diff --git a/src/dryad/format/endf/test/test_verification_functions.hpp b/src/dryad/format/endf/test/test_verification_functions.hpp index 22651f53..2cca5310 100644 --- a/src/dryad/format/endf/test/test_verification_functions.hpp +++ b/src/dryad/format/endf/test/test_verification_functions.hpp @@ -39,7 +39,7 @@ void verifyNeutronElasticReaction( const Reaction& elastic ) { CHECK( id::ReactionID( "2" ) == elastic.identifier() ); CHECK( ReactionType::Primary == elastic.type() ); - CHECK( false == elastic.hasProducts() ); + CHECK( true == elastic.hasProducts() ); CHECK( true == elastic.isLinearised() ); CHECK( std::nullopt != elastic.massDifferenceQValue() ); @@ -61,7 +61,98 @@ void verifyNeutronElasticReaction( const Reaction& elastic ) { CHECK_THAT( 2.043608e+1, WithinRel( elastic.crossSection().values()[0] ) ); CHECK_THAT( 4.818408e-1, WithinRel( elastic.crossSection().values()[152] ) ); - CHECK( 0 == elastic.products().size() ); + CHECK( 1 == elastic.products().size() ); + auto neutron = elastic.products()[0]; + CHECK( id::ParticleID( "n" ) == neutron.identifier() ); + CHECK( true == neutron.isLinearised() ); + CHECK( false == neutron.hasAverageEnergy() ); + CHECK( true == neutron.hasDistributionData() ); + CHECK( true == std::holds_alternative< int >( neutron.multiplicity() ) ); + auto multiplicity = std::get< int >( neutron.multiplicity() ); + CHECK( 1 == multiplicity ); + CHECK( std::nullopt == neutron.averageEnergy() ); + CHECK( std::nullopt != neutron.distributionData() ); + CHECK( true == std::holds_alternative< TwoBodyDistributionData >( neutron.distributionData().value() ) ); + auto data = std::get< TwoBodyDistributionData >( neutron.distributionData().value() ); + CHECK( DistributionDataType::TwoBody == data.type() ); + CHECK( true == std::holds_alternative< LegendreAngularDistributions >( data.angle() ) ); + auto angle = std::get< LegendreAngularDistributions >( data.angle() ); + CHECK( 153 == angle.numberPoints() ); + CHECK( 1 == angle.numberRegions() ); + CHECK( 153 == angle.grid().size() ); + CHECK( 153 == angle.distributions().size() ); + CHECK( 1 == angle.boundaries().size() ); + CHECK( 1 == angle.interpolants().size() ); + CHECK_THAT( 1e-5 , WithinRel( angle.grid()[0] ) ); + CHECK_THAT( 2e-5 , WithinRel( angle.grid()[1] ) ); + CHECK_THAT( 1.95e+7, WithinRel( angle.grid()[151] ) ); + CHECK_THAT( 2e+7 , WithinRel( angle.grid()[152] ) ); + CHECK( 7 == angle.distributions()[0].pdf().coefficients().size() ); + CHECK( 7 == angle.distributions()[1].pdf().coefficients().size() ); + CHECK( 7 == angle.distributions()[151].pdf().coefficients().size() ); + CHECK( 7 == angle.distributions()[152].pdf().coefficients().size() ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[0].pdf().coefficients()[0] ) ); + CHECK_THAT( -1.7511000E-14 , WithinRel( angle.distributions()[0].pdf().coefficients()[1] ) ); + CHECK_THAT( -2.5280750E-16 , WithinRel( angle.distributions()[0].pdf().coefficients()[2] ) ); + CHECK_THAT( -6.4002050E-17 , WithinRel( angle.distributions()[0].pdf().coefficients()[3] ) ); + CHECK_THAT( 1.3653765E-16 , WithinRel( angle.distributions()[0].pdf().coefficients()[4] ) ); + CHECK_THAT( -1.7067215E-17 , WithinRel( angle.distributions()[0].pdf().coefficients()[5] ) ); + CHECK_THAT( 2.5600835E-17 , WithinRel( angle.distributions()[0].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[1].pdf().coefficients()[0] ) ); + CHECK_THAT( -3.4846950E-14 , WithinRel( angle.distributions()[1].pdf().coefficients()[1] ) ); + CHECK_THAT( -1.7387225E-16 , WithinRel( angle.distributions()[1].pdf().coefficients()[2] ) ); + CHECK_THAT( -9.1736400E-17 , WithinRel( angle.distributions()[1].pdf().coefficients()[3] ) ); + CHECK_THAT( -2.9867625E-17 , WithinRel( angle.distributions()[1].pdf().coefficients()[4] ) ); + CHECK_THAT( -3.4134430E-17 , WithinRel( angle.distributions()[1].pdf().coefficients()[5] ) ); + CHECK_THAT( 1.8773950E-16 , WithinRel( angle.distributions()[1].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[151].pdf().coefficients()[0] ) ); + CHECK_THAT( -2.4240045E-02 , WithinRel( angle.distributions()[151].pdf().coefficients()[1] ) ); + CHECK_THAT( 1.7942750E-02 , WithinRel( angle.distributions()[151].pdf().coefficients()[2] ) ); + CHECK_THAT( -2.54685165E-03 , WithinRel( angle.distributions()[151].pdf().coefficients()[3] ) ); + CHECK_THAT( 1.54781595E-03 , WithinRel( angle.distributions()[151].pdf().coefficients()[4] ) ); + CHECK_THAT( 4.91773975E-05 , WithinRel( angle.distributions()[151].pdf().coefficients()[5] ) ); + CHECK_THAT( 3.82748535E-05 , WithinRel( angle.distributions()[151].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[152].pdf().coefficients()[0] ) ); + CHECK_THAT( -2.41945200E-02 , WithinRel( angle.distributions()[152].pdf().coefficients()[1] ) ); + CHECK_THAT( 1.95173075E-02 , WithinRel( angle.distributions()[152].pdf().coefficients()[2] ) ); + CHECK_THAT( -2.71943700E-03 , WithinRel( angle.distributions()[152].pdf().coefficients()[3] ) ); + CHECK_THAT( 1.69449750E-03 , WithinRel( angle.distributions()[152].pdf().coefficients()[4] ) ); + CHECK_THAT( 5.25219970E-05 , WithinRel( angle.distributions()[152].pdf().coefficients()[5] ) ); + CHECK_THAT( 4.48370065E-05 , WithinRel( angle.distributions()[152].pdf().coefficients()[6] ) ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[0].cdf().coefficients()[0] ) ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[0].cdf().coefficients()[1] ) ); + CHECK_THAT( -5.82785685e-15 , WithinRel( angle.distributions()[0].cdf().coefficients()[2] ) ); + CHECK_THAT( -6.57323500e-17 , WithinRel( angle.distributions()[0].cdf().coefficients()[3] ) ); + CHECK_THAT( -7.59158500e-18 , WithinRel( angle.distributions()[0].cdf().coefficients()[4] ) ); + CHECK_THAT( 1.32015550e-17 , WithinRel( angle.distributions()[0].cdf().coefficients()[5] ) ); + CHECK_THAT( -1.55156500e-18 , WithinRel( angle.distributions()[0].cdf().coefficients()[6] ) ); + CHECK_THAT( 1.96929500e-18 , WithinRel( angle.distributions()[0].cdf().coefficients()[7] ) ); + CHECK_THAT( 0.50000000000001, WithinRel( angle.distributions()[1].cdf().coefficients()[0] ) ); + CHECK_THAT( 0.5 , WithinRel( angle.distributions()[1].cdf().coefficients()[1] ) ); + CHECK_THAT( -1.16025448e-14 , WithinRel( angle.distributions()[1].cdf().coefficients()[2] ) ); + CHECK_THAT( -3.14558250e-17 , WithinRel( angle.distributions()[1].cdf().coefficients()[3] ) ); + CHECK_THAT( -1.00020700e-17 , WithinRel( angle.distributions()[1].cdf().coefficients()[4] ) ); + CHECK_THAT( -1.77601250e-17 , WithinRel( angle.distributions()[1].cdf().coefficients()[5] ) ); + CHECK_THAT( -3.10313000e-18 , WithinRel( angle.distributions()[1].cdf().coefficients()[6] ) ); + CHECK_THAT( 1.44415000e-17 , WithinRel( angle.distributions()[1].cdf().coefficients()[7] ) ); + CHECK_THAT( 5.08080015e-01 , WithinRel( angle.distributions()[151].cdf().coefficients()[0] ) ); + CHECK_THAT( 4.96411450e-01 , WithinRel( angle.distributions()[151].cdf().coefficients()[1] ) ); + CHECK_THAT( -7.71617905e-03 , WithinRel( angle.distributions()[151].cdf().coefficients()[2] ) ); + CHECK_THAT( 3.41657045e-03 , WithinRel( angle.distributions()[151].cdf().coefficients()[3] ) ); + CHECK_THAT( -3.683066225e-04, WithinRel( angle.distributions()[151].cdf().coefficients()[4] ) ); + CHECK_THAT( 1.690353305e-04, WithinRel( angle.distributions()[151].cdf().coefficients()[5] ) ); + CHECK_THAT( 4.47067250e-06 , WithinRel( angle.distributions()[151].cdf().coefficients()[6] ) ); + CHECK_THAT( 2.94421950e-06 , WithinRel( angle.distributions()[151].cdf().coefficients()[7] ) ); + CHECK_THAT( 5.08064840e-01 , WithinRel( angle.distributions()[152].cdf().coefficients()[0] ) ); + CHECK_THAT( 4.960965385e-01, WithinRel( angle.distributions()[152].cdf().coefficients()[1] ) ); + CHECK_THAT( -7.67634900e-03 , WithinRel( angle.distributions()[152].cdf().coefficients()[2] ) ); + CHECK_THAT( 3.71518400e-03 , WithinRel( angle.distributions()[152].cdf().coefficients()[3] ) ); + CHECK_THAT( -3.93265727e-04 , WithinRel( angle.distributions()[152].cdf().coefficients()[4] ) ); + CHECK_THAT( 1.848284995e-04, WithinRel( angle.distributions()[152].cdf().coefficients()[5] ) ); + CHECK_THAT( 4.77472700e-06 , WithinRel( angle.distributions()[152].cdf().coefficients()[6] ) ); + CHECK_THAT( 3.44900050e-06 , WithinRel( angle.distributions()[152].cdf().coefficients()[7] ) ); + CHECK( 152 == angle.boundaries()[0] ); + CHECK( InterpolationType::LinearLinear == angle.interpolants()[0] ); } void verifyNeutronCaptureReaction( const Reaction& capture ) {