diff --git a/src/storage.cc b/src/storage.cc index 46cc3577d..2e75cdf83 100644 --- a/src/storage.cc +++ b/src/storage.cc @@ -49,7 +49,7 @@ void Storage::InitFrom(cyclus::QueryableBackend* b) { //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Storage::EnterNotify() { cyclus::Facility::EnterNotify(); - buy_policy.Init(this, &inventory, std::string("inventory")); + buy_policy.Init(this, &inventory, std::string("inventory"), throughput, active_buying, dormant_buying); // dummy comp, use in_recipe if provided cyclus::CompMap v; @@ -158,8 +158,13 @@ void Storage::Tock() { std::vector::iterator result; result = std::max_element(in_commod_prefs.begin(), in_commod_prefs.end()); int maxindx = std::distance(in_commod_prefs.begin(), result); - cyclus::toolkit::RecordTimeSeries("demand"+in_commods[maxindx], this, - current_capacity()); + double demand = 0; + if (manager()->context()->time() % (active_buying + dormant_buying) < active_buying) { + demand = current_capacity(); + } + + cyclus::toolkit::RecordTimeSeries("demand"+in_commods[maxindx], this, demand); + // Multiple commodity tracking is not supported, user can only // provide one value for out_commods, despite it being a vector of strings. cyclus::toolkit::RecordTimeSeries("supply"+out_commods[0], this, diff --git a/src/storage.h b/src/storage.h index ace678874..77575b810 100644 --- a/src/storage.h +++ b/src/storage.h @@ -35,6 +35,10 @@ 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 /// /// @section detailed Detailed Behavior /// @@ -202,6 +206,29 @@ 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": 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; + #pragma cyclus var {"tooltip":"Incoming material buffer"} cyclus::toolkit::ResBuf inventory; diff --git a/src/storage_tests.cc b/src/storage_tests.cc index 609c11a7c..4892642c8 100644 --- a/src/storage_tests.cc +++ b/src/storage_tests.cc @@ -23,6 +23,9 @@ void StorageTest::InitParameters(){ max_inv_size = 200; 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; @@ -39,6 +42,8 @@ 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){ @@ -455,6 +460,58 @@ TEST_F(StorageTest, MultipleCommods){ EXPECT_EQ(1, n_trans2) << "expected 1 transactions, got " << n_trans; } +// Should get one transaction in a 2 step simulation when agent is active for +// one step and dormant for one step +TEST_F(StorageTest, ActiveDormant){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " 1" + " 1"; + + int simdur = 2; + + 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(); + + // return all transactions where our storage facility is the acceptor + 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(1, n_trans) << "expected 1 transactions, got " << n_trans; + } + + // Should get two transactions in a 2 step simulation when there is no + // dormant period, i.e. agent is always active +TEST_F(StorageTest, NoDormant){ + std::string config = + " spent_fuel " + " dry_spent " + " 1" + " 1"; + + int simdur = 2; + + 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(2, n_trans) << "expected 2 transactions, got " << n_trans; + } + TEST_F(StorageTest, PositionInitialize){ // Verify Storage behavior diff --git a/src/storage_tests.h b/src/storage_tests.h index f010869e9..83ba5f345 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; + int residence_time, active_buying, dormant_buying; double throughput, max_inv_size; bool discrete_handling; };