Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add packaging to storage #603

Merged
merged 6 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Since last release
* Rely on ``python3`` in environment instead of ``python`` (#602)
* Link against ``libxml++`` imported target in CMake instead of ``LIBXMLXX_LIBRARIES`` (#608)
* Cleaned up ``using`` declarations throughout archetypes (#610)
* Added package parameter to storage (#603)

**Fixed:**

Expand Down
4 changes: 3 additions & 1 deletion src/storage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,10 @@ void Storage::EnterNotify() {
}
buy_policy.Start();

std::string package_name_ = context()->GetPackage(package)->name();
if (out_commods.size() == 1) {
sell_policy.Init(this, &stocks, std::string("stocks"), 1e+299, false, sell_quantity)
sell_policy.Init(this, &stocks, std::string("stocks"), 1e+299, false,
sell_quantity, package_name_)
.Set(out_commods.front())
.Start();

Expand Down
8 changes: 8 additions & 0 deletions src/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ namespace cycamore {
/// 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
/// package is the name of the package type to ship
///
/// @section detailed Detailed Behavior
///
Expand Down Expand Up @@ -429,6 +430,13 @@ class Storage
"uilabel": "Cumulative Cap"}
double cumulative_cap;

#pragma cyclus var {"default": "unpackaged", \
"tooltip": "Output package", \
"doc": "Outgoing material will be packaged when trading.", \
"uitype": "package", \
"uilabel": "Package"}
std::string package;

#pragma cyclus var {"tooltip":"Incoming material buffer"}
cyclus::toolkit::ResBuf<cyclus::Material> inventory;

Expand Down
159 changes: 159 additions & 0 deletions src/storage_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void StorageTest::InitParameters(){
max_inv_size = 200;
throughput = 20;
discrete_handling = 0;
package = "foo";
// Active period longer than any of the residence time related-tests needs


Expand All @@ -42,13 +43,15 @@ void StorageTest::SetUpStorage(){
src_facility_->inventory_tracker.set_capacity(max_inv_size);
src_facility_->throughput = throughput;
src_facility_->discrete_handling = discrete_handling;
src_facility_->package = package;
}

void StorageTest::TestInitState(Storage* fac){
EXPECT_EQ(residence_time, fac->residence_time);
EXPECT_EQ(max_inv_size, fac->max_inv_size);
EXPECT_EQ(throughput, fac->throughput);
EXPECT_EQ(in_r1, fac->in_recipe);
EXPECT_EQ(package, fac->package);
}

void StorageTest::TestAddMat(Storage* fac,
Expand Down Expand Up @@ -869,6 +872,162 @@ TEST_F(StorageTest, CCap_Inventory) {
EXPECT_EQ(1, qr.GetVal<double>("Quantity", 4));
}

TEST_F(StorageTest, PackageExactly) {
// resource can be packaged without splitting or merging
std::string config =
" <in_commods> <val>spent_fuel</val> </in_commods> "
" <out_commods> <val>dry_spent</val> </out_commods> "
" <package>foo</package>";

int simdur = 3;

cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur);
sim.context()->AddPackage("foo", 1, 2, "first");
cyclus::Package::Ptr p = sim.context()->GetPackage("foo");

sim.AddSource("spent_fuel").capacity(2).Finalize();
sim.AddSink("dry_spent").Finalize();

int id = sim.Run();

std::vector<cyclus::Cond> tr_conds;
tr_conds.push_back(cyclus::Cond("Commodity", "==", std::string("dry_spent")));
cyclus::QueryResult qr_trans = sim.db().Query("Transactions", &tr_conds);
// two transactions out of storage, happening at time 1 and 2
EXPECT_EQ(2, qr_trans.rows.size());

EXPECT_EQ(1, qr_trans.GetVal<int>("Time", 0));
EXPECT_EQ(2, qr_trans.GetVal<int>("Time", 1));

std::vector<cyclus::Cond> res_conds;
res_conds.push_back(cyclus::Cond("PackageName", "==", p->name()));
cyclus::QueryResult qr_res = sim.db().Query("Resources", &res_conds);
// two resources that have been packaged, each of size two
EXPECT_EQ(qr_res.rows.size(), 2);
EXPECT_EQ(qr_res.GetVal<double>("Quantity", 0), 2);
EXPECT_EQ(qr_res.GetVal<double>("Quantity", 1), 2);
}

TEST_F(StorageTest, PackageSplitEqual) {
// Resources must be split into two to package. Packaging strategy equal
std::string config =
" <in_commods> <val>commodity</val> </in_commods> "
" <out_commods> <val>commodity1</val> </out_commods> "
" <package>foo</package>";

int simdur = 3;

cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur);
sim.context()->AddPackage("foo", 1, 2, "equal");
cyclus::Package::Ptr p = sim.context()->GetPackage("foo");

sim.AddSource("commodity").capacity(3).Finalize();
sim.AddSink("commodity1").Finalize();

int id = sim.Run();

std::vector<cyclus::Cond> tr_conds;
tr_conds.push_back(cyclus::Cond("Commodity", "==", std::string("commodity1")));
cyclus::QueryResult qr_trans = sim.db().Query("Transactions", &tr_conds);
// four transactions out of storage. Each resource is split, so two
// transactions at time 1, two at time 2
EXPECT_EQ(4, qr_trans.rows.size());

EXPECT_EQ(1, qr_trans.GetVal<int>("Time", 0));
EXPECT_EQ(1, qr_trans.GetVal<int>("Time", 1));
EXPECT_EQ(2, qr_trans.GetVal<int>("Time", 2));
EXPECT_EQ(2, qr_trans.GetVal<int>("Time", 3));

std::vector<cyclus::Cond> res_conds;
res_conds.push_back(cyclus::Cond("PackageName", "==", p->name()));
cyclus::QueryResult qr_res = sim.db().Query("Resources", &res_conds);
// because package does split-equally, resources are all of size 1.5 (3/2)
EXPECT_EQ(qr_res.rows.size(), 4);
EXPECT_EQ(1.5, qr_res.GetVal<double>("Quantity", 0));
EXPECT_EQ(1.5, qr_res.GetVal<double>("Quantity", 1));
EXPECT_EQ(1.5, qr_res.GetVal<double>("Quantity", 2));
EXPECT_EQ(1.5, qr_res.GetVal<double>("Quantity", 3));
}

TEST_F(StorageTest, PackageSplitFirst) {
// Resources must be split into two to package. Packaging strategy first
std::string config =
" <in_commods> <val>commodity</val> </in_commods> "
" <out_commods> <val>commodity1</val> </out_commods> "
" <package>foo</package>";

int simdur = 3;

cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur);
sim.context()->AddPackage("foo", 1, 2, "first");
cyclus::Package::Ptr p = sim.context()->GetPackage("foo");

sim.AddSource("commodity").capacity(3).Finalize();
sim.AddSink("commodity1").Finalize();

int id = sim.Run();

std::vector<cyclus::Cond> tr_conds;
tr_conds.push_back(cyclus::Cond("Commodity", "==", std::string("commodity1")));
cyclus::QueryResult qr_trans = sim.db().Query("Transactions", &tr_conds);
// four transactions out of storage. Each resource is split, so two
// transactions at time 1, two at time 2
EXPECT_EQ(4, qr_trans.rows.size());

EXPECT_EQ(1, qr_trans.GetVal<int>("Time", 0));
EXPECT_EQ(1, qr_trans.GetVal<int>("Time", 1));
EXPECT_EQ(2, qr_trans.GetVal<int>("Time", 2));
EXPECT_EQ(2, qr_trans.GetVal<int>("Time", 3));

std::vector<cyclus::Cond> res_conds;
res_conds.push_back(cyclus::Cond("PackageName", "==", p->name()));
cyclus::QueryResult qr_res = sim.db().Query("Resources", &res_conds);
// because package does split-first, resources are size 2 and 1
EXPECT_EQ(qr_res.rows.size(), 4);
EXPECT_EQ(2, qr_res.GetVal<double>("Quantity", 0));
EXPECT_EQ(1, qr_res.GetVal<double>("Quantity", 1));
EXPECT_EQ(2, qr_res.GetVal<double>("Quantity", 2));
EXPECT_EQ(1, qr_res.GetVal<double>("Quantity", 3));
}

TEST_F(StorageTest, PackageMerge) {
nuclearkatie marked this conversation as resolved.
Show resolved Hide resolved
std::string config =
" <in_commods> <val>commodity</val> </in_commods> "
" <out_commods> <val>commodity1</val> </out_commods> "
" <throughput>1</throughput> "
" <package>foo</package>";

int simdur = 5;

cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Storage"), config, simdur);
sim.context()->AddPackage("foo", 1, 2, "first");
cyclus::Package::Ptr p = sim.context()->GetPackage("foo");

sim.AddSource("commodity").capacity(0.5).Finalize();
sim.AddSink("commodity1").Finalize();

int id = sim.Run();

std::vector<cyclus::Cond> tr_conds;
tr_conds.push_back(cyclus::Cond("Commodity", "==", std::string("commodity1")));

cyclus::QueryResult qr_trans = sim.db().Query("Transactions", &tr_conds);
// two transactions out of storage. Because the source only provides 0.5 each
// time step, it takes two time steps to acquire enough material to package.
// Therefore transactions at time 2 and 4
EXPECT_EQ(2, qr_trans.rows.size());

EXPECT_EQ(2, qr_trans.GetVal<int>("Time", 0));
EXPECT_EQ(4, qr_trans.GetVal<int>("Time", 1));

std::vector<cyclus::Cond> res_conds;
res_conds.push_back(cyclus::Cond("PackageName", "==", p->name()));
cyclus::QueryResult qr_res = sim.db().Query("Resources", &res_conds);
// Combines two 0.5 mass resources to make packages with mass 1
EXPECT_EQ(qr_res.rows.size(), 2);
EXPECT_EQ(qr_res.GetVal<double>("Quantity", 0), 1);
EXPECT_EQ(qr_res.GetVal<double>("Quantity", 1), 1);
}

} // namespace cycamore

Expand Down
1 change: 1 addition & 0 deletions src/storage_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class StorageTest : public ::testing::Test {
int residence_time;
double throughput, max_inv_size;
bool discrete_handling;
std::string package;
};
} // namespace cycamore
#endif // STORAGE_TESTS_H_
Expand Down
Loading