From 3d61c48596c1370234e8b6a2d552dfac6e9b8c07 Mon Sep 17 00:00:00 2001 From: Wim Haeck Date: Wed, 8 May 2024 14:02:15 -0600 Subject: [PATCH] Adding outgoing group structure metadata --- python/src/multigroup/Metadata.python.cpp | 18 +++- .../Test_NDItk_multigroup_Metadata.py | 10 +- src/NDItk/MultigroupTable/src/ctor.hpp | 2 +- src/NDItk/multigroup/Metadata.hpp | 97 +++++++++++++++---- src/NDItk/multigroup/Metadata/src/ctor.hpp | 10 +- .../Metadata/src/generateSecondaryGroups.hpp | 14 +++ .../Metadata/test/Metadata.test.cpp | 14 ++- 7 files changed, 138 insertions(+), 27 deletions(-) create mode 100644 src/NDItk/multigroup/Metadata/src/generateSecondaryGroups.hpp diff --git a/python/src/multigroup/Metadata.python.cpp b/python/src/multigroup/Metadata.python.cpp index e47f63a..c4de86c 100644 --- a/python/src/multigroup/Metadata.python.cpp +++ b/python/src/multigroup/Metadata.python.cpp @@ -34,11 +34,12 @@ void wrapMetadata( python::module& module, python::module& ) { python::init< std::string, std::string, std::string, std::string, double, double, double, double, - unsigned int, unsigned int >(), + unsigned int, std::map< unsigned int, unsigned int >, + unsigned int >(), python::arg( "zaid" ), python::arg( "libname" ), python::arg( "source" ), python::arg( "process" ), python::arg( "awr" ), python::arg( "weight" ), python::arg( "temperature" ), python::arg( "dilution" ), python::arg( "groups" ), - python::arg( "reactions" ), + python::arg( "outgoing" ), python::arg( "reactions" ), "Initialise the record\n\n" "Arguments:\n" " self the metadata\n" @@ -52,6 +53,7 @@ void wrapMetadata( python::module& module, python::module& ) { " temperature the temperature of the target\n" " dilution the dilution (aka sigma0)\n" " groups the number of groups in the primary group structure\n" + " outgoing the number of groups in the outgoing group structures\n" " reactions the number of reactions defined in the table" ) .def_property_readonly( @@ -108,6 +110,16 @@ void wrapMetadata( python::module& module, python::module& ) { &Record::numberGroups, "The number of groups defined by this record" ) + .def( + + "number_outgoing_groups", + &Record::numberOutgoingGroups, + python::arg( "particle" ), + "The number of outgoing groups defined by this record for the particle\n\n" + "Arguments:\n" + " self the metadata\n" + " particle the outgoing particle identifier" + ) .def_property_readonly( "number_reactions", @@ -126,7 +138,7 @@ void wrapMetadata( python::module& module, python::module& ) { }, "Return the string representation of the subrecord\n\n" "Arguments:\n" - " self the subrecord" + " self the metadata" ); } diff --git a/python/test/multigroup/Test_NDItk_multigroup_Metadata.py b/python/test/multigroup/Test_NDItk_multigroup_Metadata.py index 72fb379..5f14d64 100644 --- a/python/test/multigroup/Test_NDItk_multigroup_Metadata.py +++ b/python/test/multigroup/Test_NDItk_multigroup_Metadata.py @@ -27,6 +27,10 @@ class Test_NDItk_multigroup_Metadata( unittest.TestCase ) : ' 10000000000\n' 'num_grps\n' ' 618\n' + 'num_grps_0\n' + ' 30\n' + 'num_grps_1001\n' + ' 250\n' 'num_reac\n' ' 7\n' ) @@ -44,6 +48,8 @@ def verify_chunk( self, chunk ) : self.assertAlmostEqual( 2.53e-8, chunk.temperature ) self.assertAlmostEqual( 1e+10, chunk.dilution ) self.assertEqual( 618, chunk.number_groups ) + self.assertEqual( 30, chunk.number_outgoing_groups( 0 ) ) + self.assertEqual( 250, chunk.number_outgoing_groups( 1001 ) ) self.assertEqual( 7, chunk.number_reactions ) self.assertEqual( self.chunk_string, chunk.to_string() ) @@ -51,8 +57,8 @@ def verify_chunk( self, chunk ) : # the data is given explicitly chunk = Metadata( zaid = '92235.711nm', libname = 'mendf71x', source = '12/22/2011', process = '08/07/2013', awr = 233.0248, weight = 235.043937521619, - temperature = 2.53e-8, dilution = 1e+10, groups = 618, - reactions = 7 ) + temperature = 2.53e-8, dilution = 1e+10, groups = 618, + outgoing = { 0 : 30, 1001 : 250 }, reactions = 7 ) verify_chunk( self, chunk ) diff --git a/src/NDItk/MultigroupTable/src/ctor.hpp b/src/NDItk/MultigroupTable/src/ctor.hpp index 3fb9842..5bca59c 100644 --- a/src/NDItk/MultigroupTable/src/ctor.hpp +++ b/src/NDItk/MultigroupTable/src/ctor.hpp @@ -30,7 +30,7 @@ MultigroupTable( std::string zaid, std::string libname, std::string source, std::optional< multigroup::AverageFissionEnergyRelease > release = std::nullopt ) : metadata_( std::move( zaid ), std::move( libname ), std::move( source ), std::move( process ), awr, weight, temperature, dilution, - xs.numberGroups(), xs.numberReactions() ), + xs.numberGroups(), {}, xs.numberReactions() ), structure_( std::move( structure ) ), weights_( std::move( weigths ) ), xs_( std::move( xs ) ), diff --git a/src/NDItk/multigroup/Metadata.hpp b/src/NDItk/multigroup/Metadata.hpp index 4d5ff6a..140593a 100644 --- a/src/NDItk/multigroup/Metadata.hpp +++ b/src/NDItk/multigroup/Metadata.hpp @@ -2,6 +2,7 @@ #define NJOY_NDITK_MULTIGROUP_METADATA // system includes +#include // other includes #include "tools/Log.hpp" @@ -28,11 +29,13 @@ class Metadata { base::SingleRealRecord atomic_weight_; base::SingleRealRecord temperature_; base::SingleRealRecord dilution_; - base::SingleIntegerRecord groups_; base::SingleIntegerRecord reactions_; + base::SingleIntegerRecord primary_groups_; + std::vector< base::SingleIntegerRecord > secondary_groups_; /* auxiliary functions */ + #include "NDItk/multigroup/Metadata/src/generateSecondaryGroups.hpp" #include "NDItk/multigroup/Metadata/src/readRecord.hpp" public: @@ -48,10 +51,16 @@ class Metadata { */ bool isMetadataKey( const std::string& keyword ) const { - return ( keyword == "zaid" ) || ( keyword == "library_name" ) || ( keyword == "date_source" ) || - ( keyword == "date_processed" ) || ( keyword == "awr" ) || ( keyword == "at_wgt" ) || - ( keyword == "temp" ) || ( keyword == "sig_0" ) || ( keyword == "num_grps" ) || - ( keyword == "num_reac" ); + return ( keyword == this->zaid_.keyword() ) || + ( keyword == this->library_name_.keyword() ) || + ( keyword == this->source_date_.keyword() ) || + ( keyword == this->process_date_.keyword() ) || + ( keyword == this->awr_.keyword() ) || + ( keyword == this->atomic_weight_.keyword() ) || + ( keyword == this->temperature_.keyword() ) || + ( keyword == this->dilution_.keyword() ) || + ( keyword == this->reactions_.keyword() || + ( keyword.find( this->primary_groups_.keyword() ) == 0 ) ); } /** @@ -98,7 +107,33 @@ class Metadata { /** * @brief Return the number of groups in the primary group structure */ - decltype(auto) numberGroups() const { return this->groups_.data(); } + decltype(auto) numberGroups() const { return this->primary_groups_.data(); } + + /** + * @brief Return the number of groups in the outgoing group structure + * for a given particle + * + * @param[int] particle the outgoing particle identifier + */ + decltype(auto) numberOutgoingGroups( unsigned int particle ) const { + + auto pos = std::lower_bound( this->secondary_groups_.begin(), + this->secondary_groups_.end(), + particle, + [] ( auto&& left, auto&& right ) { + + return left.particle() < right; + } ); + if ( pos != this->secondary_groups_.end() ) { + + if ( pos->particle() == particle ) { + + return pos->data(); + } + } + Log::error( "The requested outgoing particle \'{}\' is not present", particle ); + throw std::exception(); + } /** * @brief Return the number of reactions defined in the table @@ -113,16 +148,43 @@ class Metadata { template< typename Iterator > void read( const std::string& keyword, Iterator& iter, const Iterator& end ) { - if ( keyword == this->zaid_.keyword() ) { readRecord( this->zaid_, iter, end ); } - else if ( keyword == this->library_name_.keyword() ) { readRecord( this->library_name_, iter, end ); } - else if ( keyword == this->source_date_.keyword() ) { readRecord( this->source_date_, iter, end ); } - else if ( keyword == this->process_date_.keyword() ) { readRecord( this->process_date_, iter, end ); } - else if ( keyword == this->awr_.keyword() ) { readRecord( this->awr_, iter, end ); } - else if ( keyword == this->atomic_weight_.keyword() ) { readRecord( this->atomic_weight_, iter, end ); } - else if ( keyword == this->temperature_.keyword() ) { readRecord( this->temperature_, iter, end ); } - else if ( keyword == this->dilution_.keyword() ) { readRecord( this->dilution_, iter, end ); } - else if ( keyword == this->groups_.keyword() ) { readRecord( this->groups_, iter, end ); } - else if ( keyword == this->reactions_.keyword() ) { readRecord( this->reactions_, iter, end ); } + if ( keyword == this->zaid_.keyword() ) { readRecord( this->zaid_, iter, end ); } + else if ( keyword == this->library_name_.keyword() ) { readRecord( this->library_name_, iter, end ); } + else if ( keyword == this->source_date_.keyword() ) { readRecord( this->source_date_, iter, end ); } + else if ( keyword == this->process_date_.keyword() ) { readRecord( this->process_date_, iter, end ); } + else if ( keyword == this->awr_.keyword() ) { readRecord( this->awr_, iter, end ); } + else if ( keyword == this->atomic_weight_.keyword() ) { readRecord( this->atomic_weight_, iter, end ); } + else if ( keyword == this->temperature_.keyword() ) { readRecord( this->temperature_, iter, end ); } + else if ( keyword == this->dilution_.keyword() ) { readRecord( this->dilution_, iter, end ); } + else if ( keyword == this->reactions_.keyword() ) { readRecord( this->reactions_, iter, end ); } + else if ( keyword.find( this->primary_groups_.keyword() ) == 0 ) { + + if ( keyword == this->primary_groups_.keyword() ) { + + readRecord( this->primary_groups_, iter, end ); + } + else { + + base::Keyword secondary( keyword ); + auto pos = std::lower_bound( this->secondary_groups_.begin(), + this->secondary_groups_.end(), + secondary.particle(), + [] ( auto&& left, auto&& right ) { + + return left.particle() < right; + } ); + if ( pos != this->secondary_groups_.end() ) { + + if ( pos->particle() == secondary.particle() ) { + + Log::error( "Duplicate keyword found: \'{}\'", secondary.keyword() ); + throw std::exception(); + } + } + pos = this->secondary_groups_.insert( pos, base::SingleIntegerRecord( std::move( secondary ) ) ); + readRecord( *pos, iter, end ); + } + } else { Log::error( "Record with keyword \'{}\' is not part of the " @@ -147,7 +209,8 @@ class Metadata { this->atomic_weight_.print( iter ); this->temperature_.print( iter ); this->dilution_.print( iter ); - this->groups_.print( iter ); + this->primary_groups_.print( iter ); + for ( const auto& entry : this->secondary_groups_ ) { entry.print( iter ); } this->reactions_.print( iter ); }; }; diff --git a/src/NDItk/multigroup/Metadata/src/ctor.hpp b/src/NDItk/multigroup/Metadata/src/ctor.hpp index 1aaedd9..b299411 100644 --- a/src/NDItk/multigroup/Metadata/src/ctor.hpp +++ b/src/NDItk/multigroup/Metadata/src/ctor.hpp @@ -9,7 +9,7 @@ Metadata() : zaid_( base::Keyword( "zaid" ) ), atomic_weight_( base::Keyword( "at_wgt" ) ), temperature_( base::Keyword( "temp" ) ), dilution_( base::Keyword( "sig_0" ) ), - groups_( base::Keyword( "num_grps" ) ), + primary_groups_( base::Keyword( "num_grps" ) ), reactions_( base::Keyword( "num_reac" ) ) {} /** @@ -25,11 +25,14 @@ Metadata() : zaid_( base::Keyword( "zaid" ) ), * @param[in] temperature the temperature of the target * @param[in] dilution the dilution (aka sigma0) * @param[in] groups the number of groups in the primary group structure + * @param[in] outgoing the number of groups in the outgoing group structures * @param[in] reactions the number of reactions defined in the table */ Metadata( std::string zaid, std::string libname, std::string source, std::string process, double awr, double weight, double temperature, double dilution, - unsigned int groups, unsigned int reactions ) : + unsigned int groups, + const std::map< unsigned int, unsigned int >& outgoing, + unsigned int reactions ) : zaid_( base::Keyword( "zaid" ), std::move( zaid ) ), library_name_( base::Keyword( "library_name" ), std::move( libname ) ), source_date_( base::Keyword( "date_source" ), std::move( source ) ), @@ -38,5 +41,6 @@ Metadata( std::string zaid, std::string libname, std::string source, std::string atomic_weight_( base::Keyword( "at_wgt" ), weight ), temperature_( base::Keyword( "temp" ), temperature ), dilution_( base::Keyword( "sig_0" ), dilution ), - groups_( base::Keyword( "num_grps" ), groups ), + primary_groups_( base::Keyword( "num_grps" ), groups ), + secondary_groups_( generateSecondaryGroups( outgoing ) ), reactions_( base::Keyword( "num_reac" ), reactions ) {} diff --git a/src/NDItk/multigroup/Metadata/src/generateSecondaryGroups.hpp b/src/NDItk/multigroup/Metadata/src/generateSecondaryGroups.hpp new file mode 100644 index 0000000..731d9be --- /dev/null +++ b/src/NDItk/multigroup/Metadata/src/generateSecondaryGroups.hpp @@ -0,0 +1,14 @@ +/** + * @brief A helper function to generate the secondary group recors + */ +static std::vector< base::SingleIntegerRecord > +generateSecondaryGroups( const std::map< unsigned int, unsigned int >& outgoing ) { + + std::vector< base::SingleIntegerRecord > data; + data.reserve( outgoing.size() ); + for ( auto&& entry : outgoing ) { + + data.emplace_back( base::Keyword( "num_grps", entry.first ), entry.second ); + } + return data; +} diff --git a/src/NDItk/multigroup/Metadata/test/Metadata.test.cpp b/src/NDItk/multigroup/Metadata/test/Metadata.test.cpp index 5cd3e18..95588ff 100644 --- a/src/NDItk/multigroup/Metadata/test/Metadata.test.cpp +++ b/src/NDItk/multigroup/Metadata/test/Metadata.test.cpp @@ -32,11 +32,13 @@ SCENARIO( "Metadata" ) { double temperature = 2.53e-8; double dilution = 1e+10; unsigned int groups = 618; + std::map< unsigned int, unsigned int > outgoing = { { 0, 30 }, { 1001, 250 } }; unsigned int reactions = 7; + Metadata chunk( std::move( zaid ), std::move( name ), std::move( source ), std::move( process ), awr, weight, temperature, dilution, - groups, reactions ); + groups, outgoing, reactions ); THEN( "a Metadata can be constructed and members can " "be tested" ) { @@ -75,6 +77,8 @@ SCENARIO( "Metadata" ) { chunk.read( readKey( iter, end ), iter, end ); chunk.read( readKey( iter, end ), iter, end ); chunk.read( readKey( iter, end ), iter, end ); + chunk.read( readKey( iter, end ), iter, end ); + chunk.read( readKey( iter, end ), iter, end ); THEN( "a Metadata can be constructed and members can " "be tested" ) { @@ -114,6 +118,10 @@ std::string chunk() { " 10000000000\n" "num_grps\n" " 618\n" + "num_grps_0\n" + " 30\n" + "num_grps_1001\n" + " 250\n" "num_reac\n" " 7\n"; } @@ -129,5 +137,9 @@ void verifyChunk( const Metadata& chunk ) { CHECK_THAT( 2.53e-8, WithinRel( chunk.temperature().value() ) ); CHECK_THAT( 1e+10, WithinRel( chunk.dilution().value() ) ); CHECK( 618 == chunk.numberGroups().value() ); + CHECK( 30 == chunk.numberOutgoingGroups( 0 ).value() ); + CHECK( 250 == chunk.numberOutgoingGroups( 1001 ).value() ); CHECK( 7 == chunk.numberReactions().value() ); + + CHECK_THROWS( chunk.numberOutgoingGroups( 1 ) ); }