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

Source can package #613

Merged
merged 4 commits into from
Jul 18, 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 @@ -7,6 +7,7 @@ Since last release

**Added:**
* Added package parameter to storage (#603, #612)
* Added package parameter to source (#613)

**Changed:**

Expand Down
102 changes: 84 additions & 18 deletions src/source.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ Source::Source(cyclus::Context* ctx)
inventory_size(std::numeric_limits<double>::max()),
latitude(0.0),
longitude(0.0),
package(cyclus::Package::unpackaged_name()),
transport_unit(cyclus::TransportUnit::unrestricted_name()),
coordinates(latitude, longitude) {}

Source::~Source() {}

void Source::InitFrom(Source* m) {
#pragma cyclus impl initfromcopy cycamore::Source
cyclus::toolkit::CommodityProducer::Copy(m);
RecordPosition();
gonuke marked this conversation as resolved.
Show resolved Hide resolved
}

void Source::InitFrom(cyclus::QueryableBackend* b) {
#pragma cyclus impl initfromdb cycamore::Source
namespace tk = cyclus::toolkit;
tk::CommodityProducer::Add(tk::Commodity(outcommod),
tk::CommodInfo(throughput, throughput));
RecordPosition();
}

std::string Source::str() {
Expand All @@ -47,18 +47,39 @@ std::string Source::str() {
<< " commod producer members: "
<< " produces " << outcommod << "?: " << ans
<< " throughput: " << cyclus::toolkit::CommodityProducer::Capacity(outcommod)
<< " with package type: " << package
<< " and transport unit type: " << transport_unit
<< " cost: " << cyclus::toolkit::CommodityProducer::Cost(outcommod);
return ss.str();
}

void Source::EnterNotify() {
using cyclus::CompMap;
using cyclus::Composition;
using cyclus::Material;
cyclus::Facility::EnterNotify();
RecordPosition();

// create all source inventory and place into buf
cyclus::Material::Ptr all_inv;
Composition::Ptr blank_comp = Composition::CreateFromMass(CompMap());

all_inv = (outrecipe.empty() || context() == NULL) ? \
Material::Create(this, inventory_size, blank_comp) : \
Material::Create(this, inventory_size, context()->GetRecipe(outrecipe));
inventory.Push(all_inv);
}

std::set<cyclus::BidPortfolio<cyclus::Material>::Ptr> Source::GetMatlBids(
cyclus::CommodMap<cyclus::Material>::type& commod_requests) {
using cyclus::BidPortfolio;
using cyclus::CapacityConstraint;
using cyclus::Material;
using cyclus::Package;
using cyclus::Request;
using cyclus::TransportUnit;

double max_qty = std::min(throughput, inventory_size);
double max_qty = std::min(throughput, inventory.quantity());
cyclus::toolkit::RecordTimeSeries<double>("supply"+outcommod, this,
max_qty);
LOG(cyclus::LEV_INFO3, "Source") << prototype() << " is bidding up to "
Expand All @@ -79,11 +100,35 @@ std::set<cyclus::BidPortfolio<cyclus::Material>::Ptr> Source::GetMatlBids(
Request<Material>* req = *it;
Material::Ptr target = req->target();
double qty = std::min(target->quantity(), max_qty);
Material::Ptr m = Material::CreateUntracked(qty, target->comp());
if (!outrecipe.empty()) {
m = Material::CreateUntracked(qty, context()->GetRecipe(outrecipe));

// calculate packaging
double bid_qty = context()->GetPackage(package)->GetFillMass(qty);
int n_full_bids = static_cast<int>(std::floor(qty / bid_qty));
Package::ExceedsSplitLimits(n_full_bids);

std::vector<double> bids;
bids.assign(n_full_bids, bid_qty);

double remaining_qty = qty - (n_full_bids * bid_qty);
if ((remaining_qty > cyclus::eps()) && (remaining_qty >= context()->GetPackage(package)->fill_min())) {
bids.push_back(remaining_qty);
}
gonuke marked this conversation as resolved.
Show resolved Hide resolved

// calculate transport units
int shippable_pkgs = context()->GetTransportUnit(transport_unit)
->MaxShippablePackages(bids.size());
if (shippable_pkgs < bids.size()) {
bids.erase(bids.begin() + shippable_pkgs, bids.end());
}

std::vector<double>::iterator bit;
for (bit = bids.begin(); bit != bids.end(); ++bit) {
Material::Ptr m;
m = outrecipe.empty() ? \
Material::CreateUntracked(*bit, target->comp()) : \
Material::CreateUntracked(*bit, context()->GetRecipe(outrecipe));
port->AddBid(req, m, this);
}
port->AddBid(req, m, this);
}

CapacityConstraint<Material> cc(max_qty);
Expand All @@ -99,20 +144,41 @@ void Source::GetMatlTrades(
using cyclus::Material;
using cyclus::Trade;

int shippable_trades = context()->GetTransportUnit(transport_unit)
->MaxShippablePackages(trades.size());

std::vector<Trade<Material> >::const_iterator it;
for (it = trades.begin(); it != trades.end(); ++it) {
double qty = it->amt;
inventory_size -= qty;

Material::Ptr response;
if (!outrecipe.empty()) {
response = Material::Create(this, qty, context()->GetRecipe(outrecipe));
} else {
response = Material::Create(this, qty, it->request->target()->comp());
if (shippable_trades > 0) {
double qty = it->amt;

Material::Ptr m = inventory.Pop(qty);

std::vector<Material::Ptr> m_pkgd = m->Package<Material>(context()->GetPackage(package));

if (m->quantity() > cyclus::eps()) {
// If not all material is packaged successfully, return the excess
// amount to the inventory
inventory.Push(m);
}

Material::Ptr response;
if (m_pkgd.size() > 0) {
// Because we responded (in GetMatlBids) with individual package-sized
// bids, each packaged vector is guaranteed to have no more than one
// package in it. This single packaged resource is our response
response = m_pkgd[0];
gonuke marked this conversation as resolved.
Show resolved Hide resolved
shippable_trades -= 1;
}

if (outrecipe.empty() && response->comp() != it->request->target()->comp()) {
response->Transmute(it->request->target()->comp());
}

responses.push_back(std::make_pair(*it, response));
LOG(cyclus::LEV_INFO5, "Source") << prototype() << " sent an order"
<< " for " << response->quantity() << " of " << outcommod;
}
responses.push_back(std::make_pair(*it, response));
LOG(cyclus::LEV_INFO5, "Source") << prototype() << " sent an order"
<< " for " << qty << " of " << outcommod;
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/source.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class Source : public cyclus::Facility,
GetMatlBids(cyclus::CommodMap<cyclus::Material>::type&
commod_requests);

virtual void EnterNotify();

virtual void GetMatlTrades(
const std::vector< cyclus::Trade<cyclus::Material> >& trades,
std::vector<std::pair<cyclus::Trade<cyclus::Material>,
Expand Down Expand Up @@ -116,6 +118,28 @@ class Source : public cyclus::Facility,
}
double throughput;

#pragma cyclus var { \
"default": "unpackaged", \
"tooltip": "name of package to provide material in", \
"doc": "Name of package that this source provides. Offers will only be" \
"made in packagable quantities of material.", \
"uilabel": "Output Package Type", \
"uitype": "package", \
}
std::string package;

#pragma cyclus var { \
"default": "unrestricted", \
"tooltip": "name of transport unit to ship packages in", \
"doc": "Name of transport unit that this source uses to ship packages of " \
"material. Offers will only be made in shippable quantities of " \
"packages. Optional if packaging is used, but use of transport " \
"units requires packaging type to also be set", \
"uilabel": "Output Transport Unit Type", \
"uitype": "transportunit", \
}
std::string transport_unit;

#pragma cyclus var { \
"default": 0.0, \
"uilabel": "Geographical latitude in degrees as a double", \
Expand All @@ -132,9 +156,14 @@ class Source : public cyclus::Facility,
}
double longitude;

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

cyclus::toolkit::Position coordinates;

void RecordPosition();
void SetPackage();
};

} // namespace cycamore
Expand Down
68 changes: 68 additions & 0 deletions src/source_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ void SourceTest::SetUp() {
trader = tc.trader();
InitParameters();
SetUpSource();
src_facility->EnterNotify();
}

void SourceTest::TearDown() {
Expand All @@ -24,6 +25,8 @@ void SourceTest::TearDown() {
void SourceTest::InitParameters() {
commod = "commod";
recipe_name = "recipe";
package_name = "testpackage";
tu_name = "testtu";
capacity = 5; // some magic number..

recipe = cyclus::Composition::CreateFromAtom(cyclus::CompMap());
Expand Down Expand Up @@ -64,6 +67,8 @@ TEST_F(SourceTest, AddBids) {
boost::shared_ptr< ExchangeContext<Material> >
ec = GetContext(nreqs, commod);

src_facility->EnterNotify();

std::set<BidPortfolio<Material>::Ptr> ports =
src_facility->GetMatlBids(ec.get()->commod_requests);

Expand Down Expand Up @@ -153,6 +158,69 @@ TEST_F(SourceTest, Longitude) {

}

TEST_F(SourceTest, Package) {
using cyclus::QueryResult;
using cyclus::Cond;

std::string config =
"<outcommod>commod</outcommod>"
"<package>testpackage</package>"
"<throughput>5</throughput>";

int simdur = 3;
cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Source"), config, simdur);

sim.context()->AddPackage(package_name, 3, 4, "first");
package = sim.context()->GetPackage(package_name);

sim.AddSink("commod").Finalize();

EXPECT_NO_THROW(sim.Run());

QueryResult qr_tr = sim.db().Query("Transactions", NULL);
EXPECT_EQ(qr_tr.rows.size(), 3);

std::vector<Cond> conds;
conds.push_back(Cond("PackageName", "==", package->name()));
QueryResult qr_res = sim.db().Query("Resources", &conds);

EXPECT_EQ(qr_res.rows.size(), 3);
}

TEST_F(SourceTest, TransportUnit) {
using cyclus::QueryResult;
using cyclus::Cond;

std::string config =
"<outcommod>commod</outcommod>"
"<package>testpackage</package>"
"<transport_unit>testtu</transport_unit>"
"<throughput>10</throughput>";

int simdur = 2;
cyclus::MockSim sim(cyclus::AgentSpec (":cycamore:Source"), config, simdur);

sim.context()->AddPackage(package_name, 3, 4, "equal");
package = sim.context()->GetPackage(package_name);
sim.context()->AddTransportUnit(tu_name, 2, 2);
tu = sim.context()->GetTransportUnit(tu_name);

sim.AddSink("commod").Finalize();

EXPECT_NO_THROW(sim.Run());

QueryResult qr_tr = sim.db().Query("Transactions", NULL);
EXPECT_EQ(qr_tr.rows.size(), 4);

std::vector<Cond> conds;
conds.push_back(Cond("PackageName", "==", package->name()));
QueryResult qr_res = sim.db().Query("Resources", &conds);

EXPECT_EQ(qr_res.rows.size(), 4);

QueryResult qr_allres = sim.db().Query("Resources", NULL);
}

boost::shared_ptr< cyclus::ExchangeContext<cyclus::Material> >
SourceTest::GetContext(int nreqs, std::string commod) {
using cyclus::Material;
Expand Down
4 changes: 3 additions & 1 deletion src/source_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ class SourceTest : public ::testing::Test {
cyclus::TestContext tc;
TestFacility* trader;
cycamore::Source* src_facility;
std::string commod, recipe_name;
std::string commod, recipe_name, package_name, tu_name;
double capacity;
cyclus::Composition::Ptr recipe;
cyclus::Package::Ptr package;
cyclus::TransportUnit::Ptr tu;

virtual void SetUp();
virtual void TearDown();
Expand Down
Loading