diff --git a/cmake/unit_testing.cmake b/cmake/unit_testing.cmake index bb33417..2f3ad9f 100644 --- a/cmake/unit_testing.cmake +++ b/cmake/unit_testing.cmake @@ -48,6 +48,8 @@ add_subdirectory( src/NDItk/multigroup/AverageFissionEnergyRelease/test ) add_subdirectory( src/NDItk/multigroup/Velocities/test ) add_subdirectory( src/NDItk/multigroup/HeatingNumbers/test ) add_subdirectory( src/NDItk/multigroup/Kerma/test ) +add_subdirectory( src/NDItk/multigroup/FissionNeutronMultiplicity/test ) +add_subdirectory( src/NDItk/multigroup/FissionNeutronProduction/test ) add_subdirectory( src/NDItk/multigroup/OutgoingParticleTypes/test ) add_subdirectory( src/NDItk/multigroup/OutgoingParticleTransportData/test ) add_subdirectory( src/NDItk/multigroup/LegendreMoment/test ) diff --git a/src/NDItk.hpp b/src/NDItk.hpp index 1e1b817..7ef4a92 100644 --- a/src/NDItk.hpp +++ b/src/NDItk.hpp @@ -1,6 +1,8 @@ #include "NDItk/multigroup/AverageFissionEnergyRelease.hpp" #include "NDItk/multigroup/CrossSection.hpp" #include "NDItk/multigroup/EnergyGroupStructure.hpp" +#include "NDItk/multigroup/FissionNeutronMultiplicity.hpp" +#include "NDItk/multigroup/FissionNeutronProduction.hpp" #include "NDItk/multigroup/FluxWeights.hpp" #include "NDItk/multigroup/HeatingNumbers.hpp" #include "NDItk/multigroup/Kerma.hpp" diff --git a/src/NDItk/multigroup/FissionNeutronMultiplicity.hpp b/src/NDItk/multigroup/FissionNeutronMultiplicity.hpp new file mode 100644 index 0000000..d2e4b9f --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronMultiplicity.hpp @@ -0,0 +1,59 @@ +#ifndef NJOY_NDITK_MULTIGROUP_FISSIONNEUTRONMULTIPLICITY +#define NJOY_NDITK_MULTIGROUP_FISSIONNEUTRONMULTIPLICITY + +// system includes + +// other includes +#include "tools/Log.hpp" +#include "NDItk/base/RealListRecord.hpp" +#include "NDItk/multigroup/FissionType.hpp" + +namespace njoy { +namespace NDItk { +namespace multigroup { + +/** + * @brief A fission nubar record for multigroup neutron and photon data + */ +class FissionNeutronMultiplicity : protected base::RealListRecord { + + /* fields */ + + /* auxiliary functions */ + + #include "NDItk/multigroup/FissionNeutronMultiplicity/src/verify.hpp" + +public: + + /* constructor */ + + #include "NDItk/multigroup/FissionNeutronMultiplicity/src/ctor.hpp" + + /* methods */ + + /** + * @brief Return the fission type defined by this record + */ + FissionType type() const { return this->key().fissionType().value(); } + + /** + * @brief Return the number of groups defined by this record + */ + unsigned int numberGroups() const { return this->size(); } + + using base::RealListRecord::keyword; + using base::RealListRecord::values; + using base::RealListRecord::size; + using base::RealListRecord::empty; + using base::RealListRecord::begin; + using base::RealListRecord::end; + using base::RealListRecord::print; + + #include "NDItk/multigroup/FissionNeutronMultiplicity/src/read.hpp" +}; + +} // multigroup namespace +} // NDItk namespace +} // njoy namespace + +#endif diff --git a/src/NDItk/multigroup/FissionNeutronMultiplicity/src/ctor.hpp b/src/NDItk/multigroup/FissionNeutronMultiplicity/src/ctor.hpp new file mode 100644 index 0000000..10f6729 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronMultiplicity/src/ctor.hpp @@ -0,0 +1,16 @@ +/** + * @brief Default constructor + */ +FissionNeutronMultiplicity( FissionType type ) : RealListRecord( base::Keyword( "nu", type ) ) {} + +/** + * @brief Constructor + * + * @param[in] weights the flux weights + */ +FissionNeutronMultiplicity( FissionType type, + std::vector< double > values ) : + RealListRecord( base::Keyword( "nu", type ), std::move( values ) ) { + + verify( this->values() ); +} diff --git a/src/NDItk/multigroup/FissionNeutronMultiplicity/src/read.hpp b/src/NDItk/multigroup/FissionNeutronMultiplicity/src/read.hpp new file mode 100644 index 0000000..1b79ef3 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronMultiplicity/src/read.hpp @@ -0,0 +1,16 @@ +/** + * @brief Read the record data + * + * This function overrides the base record read() function to enable + * verification of the read data. + * + * @param[in,out] iter an iterator to the current position in the input + * @param[in,out] end an iterator to the end of the input + * @param[in,out] number the number of nu values + */ +template< typename Iterator > +void read( Iterator& iter, const Iterator& end, std::size_t number ) { + + base::RealListRecord::read( iter, end, number ); + verify( this->values() ); +}; diff --git a/src/NDItk/multigroup/FissionNeutronMultiplicity/src/verify.hpp b/src/NDItk/multigroup/FissionNeutronMultiplicity/src/verify.hpp new file mode 100644 index 0000000..0d9263d --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronMultiplicity/src/verify.hpp @@ -0,0 +1,18 @@ +/** + * @brief Verify the nu values + * + * The following verification tests are performed: + * - there is at least one value + * + * @param[in] values the nu values to be verified + */ +template < typename Range > +static void verify( const Range& values ) { + + if ( values.size() < 1 ) { + + Log::error( "Expected at least one nu value, found {}", + values.size() ); + throw std::exception(); + } +} diff --git a/src/NDItk/multigroup/FissionNeutronMultiplicity/test/CMakeLists.txt b/src/NDItk/multigroup/FissionNeutronMultiplicity/test/CMakeLists.txt new file mode 100644 index 0000000..6b079d0 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronMultiplicity/test/CMakeLists.txt @@ -0,0 +1 @@ +add_cpp_test( multigroup.FissionNeutronMultiplicity FissionNeutronMultiplicity.test.cpp ) \ No newline at end of file diff --git a/src/NDItk/multigroup/FissionNeutronMultiplicity/test/FissionNeutronMultiplicity.test.cpp b/src/NDItk/multigroup/FissionNeutronMultiplicity/test/FissionNeutronMultiplicity.test.cpp new file mode 100644 index 0000000..11c5dbe --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronMultiplicity/test/FissionNeutronMultiplicity.test.cpp @@ -0,0 +1,129 @@ +// include Catch2 +#include +#include +using Catch::Matchers::WithinRel; + +// what we are testing +#include "NDItk/multigroup/FissionNeutronMultiplicity.hpp" + +// other includes + +// convenience typedefs +using namespace njoy::NDItk; +using FissionNeutronMultiplicity = multigroup::FissionNeutronMultiplicity; +using FissionType = multigroup::FissionType; + +std::string chunk(); +void verifyChunk( const FissionNeutronMultiplicity& ); +std::string chunkWithInsufficientNumberValues(); + +SCENARIO( "FissionNeutronMultiplicity" ) { + + GIVEN( "valid data for a FissionNeutronMultiplicity instance" ) { + + std::string record = chunk(); + + WHEN( "the data is given explicitly" ) { + + std::vector< double > values = { 2., 2.1, 2.2, 2.3, 2.4, 5.0, 7.0 }; + + FissionNeutronMultiplicity chunk( FissionType::Prompt, std::move( values ) ); + + THEN( "a FissionNeutronMultiplicity can be constructed and members can " + "be tested" ) { + + verifyChunk( chunk ); + } // THEN + + THEN( "the record can be printed" ) { + + std::string buffer; + auto output = std::back_inserter( buffer ); + chunk.print( output ); + + CHECK( buffer == record ); + } // THEN + } // WHEN + + WHEN( "the data is read using iterators" ) { + + auto iter = record.begin() + 5; + auto end = record.end(); + + FissionNeutronMultiplicity chunk( FissionType::Prompt ); + chunk.read( iter, end, 7 ); + + THEN( "a FissionNeutronMultiplicity can be constructed and members can " + "be tested" ) { + + verifyChunk( chunk ); + } // THEN + + THEN( "the record can be printed" ) { + + std::string buffer; + auto output = std::back_inserter( buffer ); + chunk.print( output ); + + CHECK( buffer == record ); + } // THEN + } // WHEN + } // GIVEN + + GIVEN( "invalid data for a FissionNeutronMultiplicity instance" ) { + + WHEN( "the number of weight values is insufficient" ) { + + THEN( "an exception is thrown" ) { + + std::vector< double > empty = {}; + + CHECK_THROWS( FissionNeutronMultiplicity( FissionType::Prompt, std::move( empty ) ) ); + } // THEN + } // WHEN + + WHEN( "reading the data of the record and the number of " + "values is insufficient" ) { + + std::string record = chunkWithInsufficientNumberValues(); + auto iter = record.begin() + 5; + auto end = record.end(); + FissionNeutronMultiplicity chunk( FissionType::Prompt ); + + THEN( "an exception is thrown" ) { + + CHECK_THROWS( chunk.read( iter, end, 0 ) ); + } // THEN + } // WHEN + } // GIVEN +} // SCENARIO + +std::string chunk() { + + return "nu_pr\n" + " 2 2.1 2.2 2.3 2.4\n" + " 5 7\n"; +} + +void verifyChunk( const FissionNeutronMultiplicity& chunk ) { + + CHECK( "nu_pr" == chunk.keyword() ); + CHECK_THAT( 2, WithinRel( chunk.values()[0] ) ); + CHECK_THAT( 2.1, WithinRel( chunk.values()[1] ) ); + CHECK_THAT( 2.2, WithinRel( chunk.values()[2] ) ); + CHECK_THAT( 2.3, WithinRel( chunk.values()[3] ) ); + CHECK_THAT( 2.4, WithinRel( chunk.values()[4] ) ); + CHECK_THAT( 5, WithinRel( chunk.values()[5] ) ); + CHECK_THAT( 7, WithinRel( chunk.values()[6] ) ); + + CHECK( false == chunk.empty() ); + CHECK( 7 == chunk.size() ); + + CHECK( FissionType::Prompt == chunk.type() ); + CHECK( 7 == chunk.numberGroups() ); +} + +std::string chunkWithInsufficientNumberValues() { + + return "nu_pr\n"; +} diff --git a/src/NDItk/multigroup/FissionNeutronProduction.hpp b/src/NDItk/multigroup/FissionNeutronProduction.hpp new file mode 100644 index 0000000..bd04e4b --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronProduction.hpp @@ -0,0 +1,59 @@ +#ifndef NJOY_NDITK_MULTIGROUP_FISSIONNEUTRONPRODUCTION +#define NJOY_NDITK_MULTIGROUP_FISSIONNEUTRONPRODUCTION + +// system includes + +// other includes +#include "tools/Log.hpp" +#include "NDItk/base/RealListRecord.hpp" +#include "NDItk/multigroup/FissionType.hpp" + +namespace njoy { +namespace NDItk { +namespace multigroup { + +/** + * @brief A fission neutron production record for multigroup neutron and photon data + */ +class FissionNeutronProduction : protected base::RealListRecord { + + /* fields */ + + /* auxiliary functions */ + + #include "NDItk/multigroup/FissionNeutronProduction/src/verify.hpp" + +public: + + /* constructor */ + + #include "NDItk/multigroup/FissionNeutronProduction/src/ctor.hpp" + + /* methods */ + + /** + * @brief Return the fission type defined by this record + */ + FissionType type() const { return this->key().fissionType().value(); } + + /** + * @brief Return the number of groups defined by this record + */ + unsigned int numberGroups() const { return this->size(); } + + using base::RealListRecord::keyword; + using base::RealListRecord::values; + using base::RealListRecord::size; + using base::RealListRecord::empty; + using base::RealListRecord::begin; + using base::RealListRecord::end; + using base::RealListRecord::print; + + #include "NDItk/multigroup/FissionNeutronProduction/src/read.hpp" +}; + +} // multigroup namespace +} // NDItk namespace +} // njoy namespace + +#endif diff --git a/src/NDItk/multigroup/FissionNeutronProduction/src/ctor.hpp b/src/NDItk/multigroup/FissionNeutronProduction/src/ctor.hpp new file mode 100644 index 0000000..c1cf1da --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronProduction/src/ctor.hpp @@ -0,0 +1,16 @@ +/** + * @brief Default constructor + */ +FissionNeutronProduction( FissionType type ) : RealListRecord( base::Keyword( "nu_sig_f", type ) ) {} + +/** + * @brief Constructor + * + * @param[in] weights the flux weights + */ +FissionNeutronProduction( FissionType type, + std::vector< double > values ) : + RealListRecord( base::Keyword( "nu_sig_f", type ), std::move( values ) ) { + + verify( this->values() ); +} diff --git a/src/NDItk/multigroup/FissionNeutronProduction/src/read.hpp b/src/NDItk/multigroup/FissionNeutronProduction/src/read.hpp new file mode 100644 index 0000000..1b79ef3 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronProduction/src/read.hpp @@ -0,0 +1,16 @@ +/** + * @brief Read the record data + * + * This function overrides the base record read() function to enable + * verification of the read data. + * + * @param[in,out] iter an iterator to the current position in the input + * @param[in,out] end an iterator to the end of the input + * @param[in,out] number the number of nu values + */ +template< typename Iterator > +void read( Iterator& iter, const Iterator& end, std::size_t number ) { + + base::RealListRecord::read( iter, end, number ); + verify( this->values() ); +}; diff --git a/src/NDItk/multigroup/FissionNeutronProduction/src/verify.hpp b/src/NDItk/multigroup/FissionNeutronProduction/src/verify.hpp new file mode 100644 index 0000000..b751e39 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronProduction/src/verify.hpp @@ -0,0 +1,18 @@ +/** + * @brief Verify the production values + * + * The following verification tests are performed: + * - there is at least one value + * + * @param[in] values the production values to be verified + */ +template < typename Range > +static void verify( const Range& values ) { + + if ( values.size() < 1 ) { + + Log::error( "Expected at least one production value, found {}", + values.size() ); + throw std::exception(); + } +} diff --git a/src/NDItk/multigroup/FissionNeutronProduction/test/CMakeLists.txt b/src/NDItk/multigroup/FissionNeutronProduction/test/CMakeLists.txt new file mode 100644 index 0000000..445ea49 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronProduction/test/CMakeLists.txt @@ -0,0 +1 @@ +add_cpp_test( multigroup.FissionNeutronProduction FissionNeutronProduction.test.cpp ) \ No newline at end of file diff --git a/src/NDItk/multigroup/FissionNeutronProduction/test/FissionNeutronProduction.test.cpp b/src/NDItk/multigroup/FissionNeutronProduction/test/FissionNeutronProduction.test.cpp new file mode 100644 index 0000000..adad6b3 --- /dev/null +++ b/src/NDItk/multigroup/FissionNeutronProduction/test/FissionNeutronProduction.test.cpp @@ -0,0 +1,129 @@ +// include Catch2 +#include +#include +using Catch::Matchers::WithinRel; + +// what we are testing +#include "NDItk/multigroup/FissionNeutronProduction.hpp" + +// other includes + +// convenience typedefs +using namespace njoy::NDItk; +using FissionNeutronProduction = multigroup::FissionNeutronProduction; +using FissionType = multigroup::FissionType; + +std::string chunk(); +void verifyChunk( const FissionNeutronProduction& ); +std::string chunkWithInsufficientNumberValues(); + +SCENARIO( "FissionNeutronProduction" ) { + + GIVEN( "valid data for a FissionNeutronProduction instance" ) { + + std::string record = chunk(); + + WHEN( "the data is given explicitly" ) { + + std::vector< double > values = { 2., 2.1, 2.2, 2.3, 2.4, 5.0, 7.0 }; + + FissionNeutronProduction chunk( FissionType::Prompt, std::move( values ) ); + + THEN( "a FissionNeutronProduction can be constructed and members can " + "be tested" ) { + + verifyChunk( chunk ); + } // THEN + + THEN( "the record can be printed" ) { + + std::string buffer; + auto output = std::back_inserter( buffer ); + chunk.print( output ); + + CHECK( buffer == record ); + } // THEN + } // WHEN + + WHEN( "the data is read using iterators" ) { + + auto iter = record.begin() + 11; + auto end = record.end(); + + FissionNeutronProduction chunk( FissionType::Prompt ); + chunk.read( iter, end, 7 ); + + THEN( "a FissionNeutronProduction can be constructed and members can " + "be tested" ) { + + verifyChunk( chunk ); + } // THEN + + THEN( "the record can be printed" ) { + + std::string buffer; + auto output = std::back_inserter( buffer ); + chunk.print( output ); + + CHECK( buffer == record ); + } // THEN + } // WHEN + } // GIVEN + + GIVEN( "invalid data for a FissionNeutronProduction instance" ) { + + WHEN( "the number of weight values is insufficient" ) { + + THEN( "an exception is thrown" ) { + + std::vector< double > empty = {}; + + CHECK_THROWS( FissionNeutronProduction( FissionType::Prompt, std::move( empty ) ) ); + } // THEN + } // WHEN + + WHEN( "reading the data of the record and the number of " + "values is insufficient" ) { + + std::string record = chunkWithInsufficientNumberValues(); + auto iter = record.begin() + 11; + auto end = record.end(); + FissionNeutronProduction chunk( FissionType::Prompt ); + + THEN( "an exception is thrown" ) { + + CHECK_THROWS( chunk.read( iter, end, 0 ) ); + } // THEN + } // WHEN + } // GIVEN +} // SCENARIO + +std::string chunk() { + + return "nu_sig_f_pr\n" + " 2 2.1 2.2 2.3 2.4\n" + " 5 7\n"; +} + +void verifyChunk( const FissionNeutronProduction& chunk ) { + + CHECK( "nu_sig_f_pr" == chunk.keyword() ); + CHECK_THAT( 2, WithinRel( chunk.values()[0] ) ); + CHECK_THAT( 2.1, WithinRel( chunk.values()[1] ) ); + CHECK_THAT( 2.2, WithinRel( chunk.values()[2] ) ); + CHECK_THAT( 2.3, WithinRel( chunk.values()[3] ) ); + CHECK_THAT( 2.4, WithinRel( chunk.values()[4] ) ); + CHECK_THAT( 5, WithinRel( chunk.values()[5] ) ); + CHECK_THAT( 7, WithinRel( chunk.values()[6] ) ); + + CHECK( false == chunk.empty() ); + CHECK( 7 == chunk.size() ); + + CHECK( FissionType::Prompt == chunk.type() ); + CHECK( 7 == chunk.numberGroups() ); +} + +std::string chunkWithInsufficientNumberValues() { + + return "nu_sig_f_pr\n"; +}