diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 1993dd269..e6b63ae93 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -53,5 +53,5 @@ jobs: - name: Cycamore Python Tests run: | - export PYTHONPATH=$(find /root/.local/lib -type d -name 'cyclus-*-*.egg' -print -quit) + export PYTHONPATH=$(find /root/.local/lib -type d -name 'python*.*' -print -quit)/site-packages cd tests && python -m pytest diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 15eee6de8..cae4a8351 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,7 +12,7 @@ cycamore Change Log **Changed:** * Updated build procedure to use newer versions of packages in 2023 (#549) - +* Added active/dormant and request size variation from buy policy to Storage (#546, #568) v1.5.5 ==================== diff --git a/src/sink_tests.cc b/src/sink_tests.cc index 2d727a30f..22cad4c15 100644 --- a/src/sink_tests.cc +++ b/src/sink_tests.cc @@ -539,7 +539,7 @@ TEST_F(SinkTest, RandomNormalFreqMultipleCycles) { int second_trans_time = qr.GetVal("Time", 1); EXPECT_EQ(7, second_trans_time); int third_trans_time = qr.GetVal("Time", 2); - EXPECT_EQ(10, third_trans_time); + EXPECT_EQ(11, third_trans_time); } // Check that randomness can be implemented in both size of request and diff --git a/src/storage.cc b/src/storage.cc index 2e75cdf83..8939539e2 100644 --- a/src/storage.cc +++ b/src/storage.cc @@ -46,10 +46,95 @@ void Storage::InitFrom(cyclus::QueryableBackend* b) { cyclus::toolkit::CommodityProducer::SetCapacity(commod, throughput); } +void Storage::InitBuyPolicyParameters() { + /// set up active buying distribution + if (active_buying_min > active_buying_max) { + throw cyclus::ValueError("Active min larger than max."); + } + if (dormant_buying_min > dormant_buying_max) { + throw cyclus::ValueError("Dormant min larger than max."); + } + if (buying_size_min > buying_size_max) { + throw cyclus::ValueError("Buying size min larger than max."); + } + + if (active_buying_frequency_type == "Fixed") { + active_dist_ = boost::shared_ptr(new cyclus::FixedIntDist(active_buying_val)); + } + else if (active_buying_frequency_type == "Uniform") { + if ((active_buying_min == -1) || (active_buying_max == -1)) { + throw cyclus::ValueError("Invalid active buying frequency range. Please provide both a min and max value."); + } + active_dist_ = boost::shared_ptr(new cyclus::UniformIntDist(active_buying_min, active_buying_max)); + } + else if (active_buying_frequency_type == "Normal") { + if ((active_buying_mean == -1) || (active_buying_stddev == -1)) { + throw cyclus::ValueError("Invalid active buying frequency range. Please provide both a mean and standard deviation value."); + } + if (active_buying_min == -1) {active_buying_min = 1;} + if (active_buying_max == -1) { + active_buying_max = std::numeric_limits::max();} + + active_dist_ = boost::shared_ptr(new cyclus::NormalIntDist(active_buying_mean, active_buying_stddev, + active_buying_min, active_buying_max)); + } + else { + throw cyclus::ValueError("Invalid active buying frequency type");} + + /// set up dormant buying distribution + if (dormant_buying_frequency_type == "Fixed") { + dormant_dist_ = boost::shared_ptr(new cyclus::FixedIntDist(dormant_buying_val)); + } + else if (dormant_buying_frequency_type == "Uniform") { + if ((dormant_buying_min == -1) || (dormant_buying_max == -1)) { + throw cyclus::ValueError("Invalid dormant buying frequency range. Please provide both a min and max value."); + } + dormant_dist_ = boost::shared_ptr(new cyclus::UniformIntDist(dormant_buying_min, dormant_buying_max)); + } + else if (dormant_buying_frequency_type == "Normal") { + if ((dormant_buying_mean == -1) || (dormant_buying_stddev == -1)) { + throw cyclus::ValueError("Invalid dormant buying frequency range. Please provide both a mean and standard deviation value."); + } + if (dormant_buying_min == -1) {dormant_buying_min = 1;} + if (dormant_buying_max == -1) { + dormant_buying_max = std::numeric_limits::max();} + dormant_dist_ = boost::shared_ptr(new cyclus::NormalIntDist(dormant_buying_mean, dormant_buying_stddev, + dormant_buying_min, dormant_buying_max)); + } + else { + throw cyclus::ValueError("Invalid dormant buying frequency type");} + + /// set up buying size distribution + if (buying_size_type == "Fixed") { + size_dist_ = boost::shared_ptr(new cyclus::FixedDoubleDist(buying_size_val)); + } + else if (buying_size_type == "Uniform") { + if ((buying_size_min == -1) || (buying_size_max == -1)) { + throw cyclus::ValueError("Invalid buying size range. Please provide both a min and max value."); + } + size_dist_ = boost::shared_ptr(new cyclus::UniformDoubleDist(buying_size_min, buying_size_max)); + } + else if (buying_size_type == "Normal") { + if ((buying_size_mean == -1) || (buying_size_stddev == -1)) { + throw cyclus::ValueError("Invalid buying size range. Please provide both a mean and standard deviation value."); + } + if (buying_size_min == -1) {buying_size_min = 0;} + if (buying_size_max == -1) {buying_size_max = 1;} + size_dist_ = boost::shared_ptr(new cyclus::NormalDoubleDist(buying_size_mean, buying_size_stddev, + buying_size_min, buying_size_max)); + } + else { + throw cyclus::ValueError("Invalid buying size type");} +} + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Storage::EnterNotify() { cyclus::Facility::EnterNotify(); - buy_policy.Init(this, &inventory, std::string("inventory"), throughput, active_buying, dormant_buying); + + InitBuyPolicyParameters(); + + buy_policy.Init(this, &inventory, std::string("inventory"), throughput, + active_dist_, dormant_dist_, size_dist_); // dummy comp, use in_recipe if provided cyclus::CompMap v; @@ -159,9 +244,7 @@ void Storage::Tock() { result = std::max_element(in_commod_prefs.begin(), in_commod_prefs.end()); int maxindx = std::distance(in_commod_prefs.begin(), result); double demand = 0; - if (manager()->context()->time() % (active_buying + dormant_buying) < active_buying) { - demand = current_capacity(); - } + demand = current_capacity(); cyclus::toolkit::RecordTimeSeries("demand"+in_commods[maxindx], this, demand); diff --git a/src/storage.h b/src/storage.h index 77575b810..4c01957de 100644 --- a/src/storage.h +++ b/src/storage.h @@ -8,6 +8,7 @@ #include "cyclus.h" #include "cycamore_version.h" +#include "boost/shared_ptr.hpp" namespace cycamore { /// @class Storage @@ -35,10 +36,28 @@ namespace cycamore { /// sell_quantity restricts selling to only integer multiples of this value /// max_inv_size is the maximum capacity of the inventory storage /// throughput is the maximum processing capacity per timestep -/// active_buying is the number of time steps in a row where the agent -/// exhibits default behavior -/// dormant_buying is the number of time steps in a row where the agent is -/// not requesting any new material +/// active_buying_frequency_type is the type of distribution used to determine the length of the active buying period +/// active_buying_val is the length of the active buying period if active_buying_frequency_type is Fixed +/// active_buying_min is the minimum length of the active buying period if active_buying_frequency_type is Uniform (required) or +/// Normal (optional) +/// active_buying_max is the maximum length of the active buying period if active_buying_frequency_type is Uniform (required) or +/// Normal (optional) +/// active_buying_mean is the mean length of the active buying period if active_buying_frequency_type is Normal +/// active_buying_std is the standard deviation of the active buying period if active_buying_frequency_type is Normal +/// dormant_buying_frequency_type is the type of distribution used to determine the length of the dormant buying period +/// dormant_buying_val is the length of the dormant buying period if dormant_buying_frequency_type is Fixed +/// dormant_buying_min is the minimum length of the dormant buying period if dormant_buying_frequency_type is Uniform (required) or +/// Normal (optional) +/// dormant_buying_max is the maximum length of the dormant buying period if dormant_buying_frequency_type is Uniform (required) or +/// Normal (optional) +/// dormant_buying_mean is the mean length of the dormant buying period if dormant_buying_frequency_type is Normal +/// dormant_buying_std is the standard deviation of the dormant buying period if dormant_buying_frequency_type is Normal +/// buying_size_type is the type of distribution used to determine the size of buy requests, as a fraction of the current capacity +/// buying_size_val is the size of the buy request for Fixed buying_size_type +/// buying_size_min is the minimum size of the buy request if buying_size_type is Uniform (required) or Normal (optional) +/// buying_size_max is the maximum size of the buy request if buying_size_type is Uniform (required) or Normal (optional) +/// buying_size_mean is the mean size of the buy request if buying_size_type is Normal +/// buying_size_stddev is the standard deviation of the buy request if buying_size_type is Normal /// /// @section detailed Detailed Behavior /// @@ -103,6 +122,8 @@ class Storage virtual std::string version() { return CYCAMORE_VERSION; } protected: + /// @brief sets up the distributions for the buy policy + void InitBuyPolicyParameters(); /// @brief adds a material into the incoming commodity inventory /// @param mat the material to add to the incoming inventory. /// @throws if there is trouble with pushing to the inventory buffer. @@ -206,28 +227,179 @@ class Storage "uilabel":"Batch Handling"} bool discrete_handling; - #pragma cyclus var {"default": 1,\ - "tooltip": "Length of the active buying "\ - "period",\ - "doc":"During the length of the active buying "\ - "period, agent exhibits regular behavior. "\ - "If paired with dormant buying period, "\ - "alternates between buying and not buying, "\ - "regardless if space is available",\ - "uilabel":"Active Buying Period"} - int active_buying; + #pragma cyclus var {"default": "Fixed",\ + "tooltip": "Type of active buying frequency",\ + "doc": "Options: Fixed, Uniform, Normal. Fixed requires active_buying_val. Uniform "\ + "requires active_buying_min and active_buying_max. Normal "\ + "requires active_buying_mean and active_buying_std, with optional "\ + "active_buying_min and active_buying_max.",\ + "uitype": "combobox",\ + "categorical": ["Fixed", "Uniform", "Normal"],\ + "uilabel": "Active Buying Frequency Type"} + std::string active_buying_frequency_type; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Fixed active buying frequency",\ + "doc": "The length in time steps of the active buying period. Required for fixed "\ + "active_buying_frequency_type. Must be greater than or equal to 1 (i.e., agent "\ + "cannot always be dormant)",\ + "uitype": "range", \ + "range": [1, 1e299], \ + "uilabel": "Active Buying Frequency Value"} + int active_buying_val; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Active buying distribution minimum",\ + "doc": "The minimum length in time steps of the active buying period. Required for "\ + "Uniform and optional for Normal active_buying_frequency_type. Must be greater than "\ + "or equal to 1 ",\ + "uitype": "range", \ + "range": [1, 1e299], \ + "uilabel": "Active Buying Frequency Minimum"} + int active_buying_min; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Active buying distribution maximum",\ + "doc": "The maximum length in time steps of the active buying period. Required for "\ + "Uniform active_buying_frequency_type, optional for Normal. Must be greater than or equal to active_buying_min ",\ + "uitype": "range", \ + "range": [1, 1e299], \ + "uilabel": "Active Buying Frequency Maximum"} + int active_buying_max; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Active buying distribution mean",\ + "doc": "The mean length in time steps of the active buying period. Required for "\ + "Normal active_buying_frequency_type. Must be greater than or equal to 1 ",\ + "uitype": "range", \ + "range": [1.0, 1e299], \ + "uilabel": "Active Buying Frequency Mean"} + double active_buying_mean; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Active buying distribution standard deviation",\ + "doc": "The standard deviation of the length in time steps of the active buying period. "\ + "Required for Normal active_buying_frequency_type. Must be greater than or equal to 0 ",\ + "uitype": "range", \ + "range": [0.0, 1e299], \ + "uilabel": "Active Buying Frequency Standard Deviation"} + double active_buying_stddev; + + #pragma cyclus var {"default": "Fixed",\ + "tooltip": "Type of dormant buying frequency",\ + "doc": "Options: Fixed, Uniform, Normal. Fixed requires dormant_buying_val. Uniform "\ + "requires dormant_buying_min and dormant_buying_max. Normal requires "\ + "dormant_buying_mean and dormant_buying_std, with optional dormant_buying_min "\ + "and dormant_buying_max.",\ + "uitype": "combobox",\ + "categorical": ["Fixed", "Uniform", "Normal"],\ + "uilabel": "Dormant Buying Frequency Type"} + std::string dormant_buying_frequency_type; #pragma cyclus var {"default": 0,\ - "tooltip": "Length of the dormant buying "\ - "period",\ - "doc":"During the length of the dormant buying "\ - "period, agent will not request any new "\ - "material from the DRE. Paired with active "\ - "buying period, alternates between buying "\ - "and not buying, regardless if space is "\ - "available",\ - "uilabel":"Dormant (No Buying) Period"} - int dormant_buying; + "tooltip": "Fixed dormant buying frequency",\ + "doc": "The length in time steps of the dormant buying period. Required for fixed "\ + "dormant_buying_frequency_type. Can be zero and agent will only be active (default behavior)",\ + "uitype": "range", \ + "range": [-1, 1e299], \ + "uilabel": "Dormant Buying Frequency Value"} + int dormant_buying_val; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Dormant buying distribution minimum",\ + "doc": "The minimum length in time steps of the dormant buying period. Required for Uniform and optional for "\ + "Normal dormant_buying_frequency_type.",\ + "uitype": "range", \ + "range": [0, 1e299], \ + "uilabel": "Dormant Buying Frequency Minimum"} + int dormant_buying_min; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Dormant buying distribution maximum",\ + "doc": "The maximum length in time steps of the dormant buying period. Required for "\ + "Uniform dormant_buying_frequency_type, optional for Normal. Must be greater than or equal to dormant_buying_min ",\ + "uitype": "range", \ + "range": [0, 1e299], \ + "uilabel": "Dormant Buying Frequency Maximum"} + int dormant_buying_max; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Dormant buying distribution mean",\ + "doc": "The mean length in time steps of the dormant buying period. Required for "\ + "Normal dormant_buying_frequency_type. Must be greater than or equal to 0 ",\ + "uitype": "range", \ + "range": [0.0, 1e299], \ + "uilabel": "Dormant Buying Frequency Mean"} + double dormant_buying_mean; + + #pragma cyclus var {"default": -1,\ + "tooltip": "Dormant buying distribution standard deviation",\ + "doc": "The standard deviation of the length in time steps of the dormant buying period. "\ + "Required for Normal dormant_buying_frequency_type. Must be greater than or equal to 0 ",\ + "uitype": "range", \ + "range": [0.0, 1e299], \ + "uilabel": "Dormant Buying Frequency Standard Deviation"} + double dormant_buying_stddev; + + #pragma cyclus var {"default": "Fixed",\ + "tooltip": "Type of behavior used to determine size of buy request",\ + "doc": "Behavior function used to determine the size of requests made. All values are "\ + "a fraction of maximum capacity, determined by the throughput and capacity remaining."\ + " Options: Fixed, Uniform, Normal. Fixed is default behavior. Uniform requires "\ + "buying_size_min and buying_size_max. Normal requires "\ + "buying_size_mean and buying_size_stddev, optional buying_size_min and "\ + "buying_size_max.",\ + "uitype": "combobox",\ + "categorical": ["Fixed", "Uniform", "Normal"],\ + "uilabel": "Buying Size Type"} + std::string buying_size_type; + + #pragma cyclus var {"default": 1.0,\ + "tooltip": "Fixed buying size",\ + "doc": "The size of the buy request as a fraction of maximum capacity. Optional for Fixed "\ + "buying_size_type. Must be greater than or equal to 0.0",\ + "uitype": "range", \ + "range": [0.0, 1.0], \ + "uilabel": "Buying Size Value"} + double buying_size_val; + + #pragma cyclus var {"default": -1.0,\ + "tooltip": "Buying size distribution minimum",\ + "doc": "The minimum size of the buy request as a fraction of maximum capacity. "\ + "Required for Uniform and optional for Normal buying_size_type. Must be greater than "\ + "or equal to zero.",\ + "uitype": "range", \ + "range": [0.0, 1.0], \ + "uilabel": "Buying Size Minimum"} + double buying_size_min; + + #pragma cyclus var {"default": -1.0,\ + "tooltip": "Buying size distribution maximum",\ + "doc": "The maximum size of the buy request as a fraction of maximum capacity. "\ + "Required for Uniform buying_size_type, optional for Normal. Must be greater than "\ + "or equal to buying_size_min ",\ + "uitype": "range", \ + "range": [0.0, 1.0], \ + "uilabel": "Buying Size Maximum"} + double buying_size_max; + + #pragma cyclus var {"default": -1.0,\ + "tooltip": "Buying size distribution mean",\ + "doc": "The mean size of the buy request as a fraction of maximum capacity. "\ + "Required for Normal buying_size_type.",\ + "uitype": "range", \ + "range": [0.0, 1.0], \ + "uilabel": "Buying Size Mean"} + double buying_size_mean; + + #pragma cyclus var {"default": -1.0,\ + "tooltip": "Buying size distribution standard deviation",\ + "doc": "The standard deviation of the size of the buy request as a fraction of "\ + "maximum capacity. Required for Normal buying_size_type.",\ + "uitype": "range", \ + "range": [0.0, 1.0], \ + "uilabel": "Buying Size Standard Deviation"} + double buying_size_stddev; #pragma cyclus var {"tooltip":"Incoming material buffer"} cyclus::toolkit::ResBuf inventory; @@ -268,6 +440,10 @@ class Storage } double longitude; + boost::shared_ptr active_dist_ = NULL; + boost::shared_ptr dormant_dist_ = NULL; + boost::shared_ptr size_dist_ = NULL; + cyclus::toolkit::Position coordinates; void RecordPosition(); diff --git a/src/storage_tests.cc b/src/storage_tests.cc index 4892642c8..b0c383467 100644 --- a/src/storage_tests.cc +++ b/src/storage_tests.cc @@ -24,8 +24,7 @@ void StorageTest::InitParameters(){ throughput = 20; discrete_handling = 0; // Active period longer than any of the residence time related-tests needs - active_buying = 20; - dormant_buying = 1; + cyclus::CompMap v; v[922350000] = 1; @@ -42,8 +41,6 @@ void StorageTest::SetUpStorage(){ src_facility_->max_inv_size = max_inv_size; src_facility_->throughput = throughput; src_facility_->discrete_handling = discrete_handling; - src_facility_->active_buying = active_buying; - src_facility_->dormant_buying = dormant_buying; } void StorageTest::TestInitState(Storage* fac){ @@ -467,8 +464,8 @@ TEST_F(StorageTest, ActiveDormant){ " spent_fuel " " dry_spent " " 1" - " 1" - " 1"; + " 1" + " 1"; int simdur = 2; @@ -494,9 +491,12 @@ TEST_F(StorageTest, NoDormant){ " spent_fuel " " dry_spent " " 1" - " 1"; + " Fixed" + " 1" + " Fixed" + " -1"; - int simdur = 2; + int simdur = 3; cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur); @@ -509,9 +509,202 @@ TEST_F(StorageTest, NoDormant){ conds.push_back(cyclus::Cond("Commodity", "==", std::string("spent_fuel"))); cyclus::QueryResult qr = sim.db().Query("Transactions", &conds); int n_trans = qr.rows.size(); - EXPECT_EQ(2, n_trans) << "expected 2 transactions, got " << n_trans; + EXPECT_EQ(3, n_trans) << "expected 3 transactions, got " << n_trans; } +TEST_F(StorageTest, UniformActiveNormalDormant){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " Uniform" + " 2" + " 3" + " Normal" + " 5" + " 1"; + + int simdur = 20; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur); + + sim.AddSource("spent_fuel").capacity(5).Finalize(); + sim.AddSink("dry_spent").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(cyclus::Cond("Commodity", "==", std::string("spent_fuel"))); + cyclus::QueryResult qr = sim.db().Query("Transactions", &conds); + // confirm that transactions are only occurring during active periods + // first cycle includes time steps 0 and 1 + EXPECT_EQ(0, qr.GetVal("Time", 0)); + EXPECT_EQ(1, qr.GetVal("Time", 1)); + // second cycle (lines 2, 3 and 4) includes time steps 7, 8, and 9 + EXPECT_EQ(7, qr.GetVal("Time", 2)); + EXPECT_EQ(8, qr.GetVal("Time", 3)); + EXPECT_EQ(9, qr.GetVal("Time", 4)); +} + +TEST_F(StorageTest, FixedBuyingSize){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " Fixed" + " 0.5"; + + int simdur = 2; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur); + + sim.AddSource("spent_fuel").Finalize(); + int id = sim.Run(); + + cyclus::QueryResult qr = sim.db().Query("Resources", NULL); + EXPECT_NEAR(0.5, qr.GetVal("Quantity", 0), 0.00001); + EXPECT_NEAR(0.5, qr.GetVal("Quantity", 1), 0.00001); +} + +TEST_F(StorageTest, UniformBuyingSize){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " Uniform" + " 0.5" + " 0.7"; + + int simdur = 2; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur); + + sim.AddSource("spent_fuel").Finalize(); + int id = sim.Run(); + + cyclus::QueryResult qr = sim.db().Query("Resources", NULL); + EXPECT_NEAR(0.56393, qr.GetVal("Quantity", 0), 0.00001); + EXPECT_NEAR(0.68825, qr.GetVal("Quantity", 1), 0.00001); +} + +TEST_F(StorageTest, NormalBuyingSize){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " Normal" + " 0.5" + " 0.1"; + + int simdur = 2; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur); + + sim.AddSource("spent_fuel").Finalize(); + + int id = sim.Run(); + + cyclus::QueryResult qr = sim.db().Query("Resources", NULL); + EXPECT_NEAR(0.64083, qr.GetVal("Quantity", 0), 0.00001); + EXPECT_NEAR(0.32648, qr.GetVal("Quantity", 1), 0.00001); +} + +TEST_F(StorageTest, NormalActiveDormantBuyingSize){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " Normal" + " 3" + " 1" + " Normal" + " 2" + " 1" + " Normal" + " 0.5" + " 0.1"; + + int simdur = 15; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur); + + sim.AddSource("spent_fuel").capacity(5).Finalize(); + sim.AddSink("dry_spent").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(cyclus::Cond("Commodity", "==", std::string("spent_fuel"))); + cyclus::QueryResult qr = sim.db().Query("Transactions", &conds); + int n_trans = qr.rows.size(); + EXPECT_EQ(10, n_trans) << "expected 10 transactions, got " << n_trans; + // confirm that transactions are only occurring during active periods + // first cycle includes time steps 0 - 3 + EXPECT_EQ(0, qr.GetVal("Time", 0)); + EXPECT_EQ(3, qr.GetVal("Time", 3)); + // second cycle (rows 4 and 4) include time steps 6 and 7 + EXPECT_EQ(6, qr.GetVal("Time", 4)); + EXPECT_EQ(7, qr.GetVal("Time", 5)); + // third cycle (row 6) includes time step 8 -9 + EXPECT_EQ(8, qr.GetVal("Time", 6)); + EXPECT_EQ(9, qr.GetVal("Time", 7)); + // fourth cycle (rows 8, 9) includes time steps 13 - 14 + EXPECT_EQ(13, qr.GetVal("Time", 8)); + EXPECT_EQ(14, qr.GetVal("Time", 9)); + + qr = sim.db().Query("Resources", NULL); + EXPECT_NEAR(0.61256, qr.GetVal("Quantity", 0), 0.00001); + EXPECT_NEAR(0.62217, qr.GetVal("Quantity", 1), 0.00001); + EXPECT_NEAR(0.39705, qr.GetVal("Quantity", 2), 0.00001); +} + +TEST_F(StorageTest, IncorrectBuyPolSetupUniform) { + // uniform missing min and max + std::string config_uniform = + " spent_fuel " + " dry_spent " + " 1" + " Uniform"; + + int simdur = 15; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config_uniform, + simdur); + EXPECT_THROW(sim.Run(), cyclus::ValueError); +} + +TEST_F(StorageTest, IncorrectBuyPolSetupNormal) { + // normal missing mean and std dev + std::string config_normal = + " spent_fuel " + " dry_spent " + " 1" + " Normal"; + int simdur = 15; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config_normal, + simdur); + EXPECT_THROW(sim.Run(), cyclus::ValueError); +} + +TEST_F(StorageTest, IncorrectBuyPolSetupMinMax) { + // tries to set min > max + std::string config_uniform_min_bigger_max = + " spent_fuel " + " dry_spent " + " 1" + " Uniform" + " 3" + " 2"; + + int simdur = 15; + + cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), + config_uniform_min_bigger_max, simdur); + EXPECT_THROW(sim.Run(), cyclus::ValueError); + +} + TEST_F(StorageTest, PositionInitialize){ // Verify Storage behavior diff --git a/src/storage_tests.h b/src/storage_tests.h index 83ba5f345..f010869e9 100644 --- a/src/storage_tests.h +++ b/src/storage_tests.h @@ -33,7 +33,7 @@ class StorageTest : public ::testing::Test { std::vector in_c1, out_c1; std::string in_r1; - int residence_time, active_buying, dormant_buying; + int residence_time; double throughput, max_inv_size; bool discrete_handling; };