Skip to content

Commit 8924cc3

Browse files
authored
Merge pull request #657 from dean-krueger/conversion
Add Conversion Facility to Cycamore
2 parents e4ec85c + 2cf9932 commit 8924cc3

File tree

4 files changed

+329
-0
lines changed

4 files changed

+329
-0
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Since last release
66
======================
77

88
**Added:**
9+
* Added Conversion Facility (#657)
910
* Replaced manual matl_buy/sell_policy code in storage with code injection (#639)
1011
* Added package parameter to storage (#603, #612, #616)
1112
* Added package parameter to source (#613, #617, #621, #623, #630)

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ SET(CYCLUS_CUSTOM_HEADERS "cycamore_version.h")
66

77
USE_CYCLUS("cycamore" "reactor")
88

9+
USE_CYCLUS("cycamore" "conversion")
10+
911
USE_CYCLUS("cycamore" "fuel_fab")
1012

1113
USE_CYCLUS("cycamore" "mixer")

src/conversion.cc

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#include <algorithm>
2+
#include <sstream>
3+
4+
#include <boost/lexical_cast.hpp>
5+
#include "toolkit/mat_query.h"
6+
7+
#include "conversion.h"
8+
9+
using cyclus::RequestPortfolio;
10+
using cyclus::BidPortfolio;
11+
using cyclus::CommodMap;
12+
using cyclus::Request;
13+
using cyclus::Trade;
14+
using cyclus::Material;
15+
using cyclus::CapacityConstraint;
16+
using cyclus::toolkit::ResBuf;
17+
using cyclus::toolkit::RecordTimeSeries;
18+
19+
namespace cycamore {
20+
21+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22+
Conversion::Conversion(cyclus::Context* ctx)
23+
: cyclus::Facility(ctx) {
24+
25+
// Make our Resource Buffers bulk buffers
26+
input = ResBuf<Material>(true);
27+
output = ResBuf<Material>(true);
28+
}
29+
30+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
31+
Conversion::~Conversion() {}
32+
33+
#pragma cyclus def schema cycamore::Conversion
34+
#pragma cyclus def annotations cycamore::Conversion
35+
#pragma cyclus def infiletodb cycamore::Conversion
36+
#pragma cyclus def snapshot cycamore::Conversion
37+
#pragma cyclus def snapshotinv cycamore::Conversion
38+
#pragma cyclus def initinv cycamore::Conversion
39+
#pragma cyclus def clone cycamore::Conversion
40+
#pragma cyclus def initfromdb cycamore::Conversion
41+
#pragma cyclus def initfromcopy cycamore::Conversion
42+
43+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44+
void Conversion::EnterNotify() {
45+
cyclus::Facility::EnterNotify();
46+
InitializePosition();
47+
}
48+
49+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50+
std::string Conversion::str() {
51+
using std::string;
52+
using std::vector;
53+
std::stringstream ss;
54+
ss << cyclus::Facility::str();
55+
56+
string msg = "";
57+
msg += "accepts commodities ";
58+
for (vector<string>::iterator commod = incommods.begin();
59+
commod != incommods.end();
60+
commod++) {
61+
msg += (commod == incommods.begin() ? "{" : ", ");
62+
msg += (*commod);
63+
}
64+
msg += "} until its input is full at ";
65+
msg += std::to_string(input.capacity());
66+
msg += " kg.";
67+
68+
msg += "} and converts ";
69+
msg += std::to_string(throughput);
70+
msg += " kg/timestep into commodity ";
71+
ss << msg << outcommod;
72+
return "" + ss.str();
73+
}
74+
75+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
76+
void Conversion::Tick() {
77+
Convert();
78+
}
79+
80+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81+
void Conversion::Tock() {}
82+
83+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
84+
double Conversion::AvailableFeedstockCapacity() {
85+
return input.capacity() - input.quantity();
86+
}
87+
88+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89+
void Conversion::Convert() {
90+
if (input.quantity() > 0) {
91+
output.Push(input.Pop(std::min(input.quantity(), throughput)));
92+
}
93+
}
94+
95+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96+
std::set<RequestPortfolio<Material>::Ptr> Conversion::GetMatlRequests() {
97+
std::set<RequestPortfolio<Material>::Ptr> ports;
98+
99+
// Check if we need material
100+
double available_capacity = AvailableFeedstockCapacity();
101+
if (available_capacity <= 0) return ports;
102+
103+
// Create request portfolio
104+
RequestPortfolio<Material>::Ptr port(new RequestPortfolio<Material>());
105+
106+
// Create material request with no recipe
107+
Material::Ptr mat = cyclus::NewBlankMaterial(available_capacity);
108+
109+
110+
// Add request for all commodities using default preference
111+
for (std::vector<std::string>::iterator it = incommods.begin();
112+
it != incommods.end(); ++it) {
113+
Request<Material>* req = port->AddRequest(mat, this, *it);
114+
}
115+
116+
// Add capacity constraint to ensure we never get more feed than capacity
117+
CapacityConstraint<Material> cc(available_capacity);
118+
port->AddConstraint(cc);
119+
120+
ports.insert(port);
121+
return ports;
122+
}
123+
124+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
125+
std::set<BidPortfolio<Material>::Ptr> Conversion::GetMatlBids(
126+
CommodMap<Material>::type& commod_requests) {
127+
std::set<BidPortfolio<Material>::Ptr> ports;
128+
129+
// Check if we have material to offer
130+
if (output.quantity() <= 0) return ports;
131+
132+
// Create bid portfolio
133+
BidPortfolio<Material>::Ptr port(new BidPortfolio<Material>());
134+
135+
// Respond to requests for our commodity
136+
std::vector<Request<Material>*>& requests = commod_requests[outcommod];
137+
for (std::vector<Request<Material>*>::iterator it = requests.begin();
138+
it != requests.end(); ++it) {
139+
140+
double available = output.quantity();
141+
double requested = (*it)->target()->quantity();
142+
double offer_qty = std::min(available, requested);
143+
144+
if (offer_qty > 0) {
145+
Material::Ptr offer = Material::CreateUntracked(offer_qty, output.Peek()->comp());
146+
port->AddBid(*it, offer, this); // Note: *it, not **it
147+
}
148+
}
149+
150+
// Add capacity constraint so we never give out more than we have
151+
CapacityConstraint<Material> cc(output.quantity());
152+
port->AddConstraint(cc);
153+
154+
ports.insert(port);
155+
return ports;
156+
}
157+
158+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
159+
void Conversion::AcceptMatlTrades(
160+
const std::vector<std::pair<Trade<Material>, Material::Ptr>>& responses) {
161+
162+
for (std::vector<std::pair<Trade<Material>, Material::Ptr>>::const_iterator it =
163+
responses.begin(); it != responses.end(); ++it) {
164+
165+
166+
// Add material to the input buffer
167+
input.Push(it->second);
168+
169+
}
170+
}
171+
172+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
173+
void Conversion::GetMatlTrades(
174+
const std::vector<Trade<Material>>& trades,
175+
std::vector<std::pair<Trade<Material>, Material::Ptr>>& responses) {
176+
177+
for (std::vector<Trade<Material>>::const_iterator it = trades.begin();
178+
it != trades.end(); ++it) {
179+
180+
Material::Ptr response = output.Pop(it->amt);
181+
182+
responses.push_back(std::make_pair(*it, response));
183+
}
184+
}
185+
186+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187+
extern "C" cyclus::Agent* ConstructConversion(cyclus::Context* ctx) {
188+
return new Conversion(ctx);
189+
}
190+
191+
} // namespace cycamore
192+

src/conversion.h

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#ifndef CYCAMORE_SRC_CONVERSION_H_
2+
#define CYCAMORE_SRC_CONVERSION_H_
3+
4+
#include <algorithm>
5+
#include <string>
6+
#include <utility>
7+
#include <vector>
8+
9+
#include "cyclus.h"
10+
#include "cycamore_version.h"
11+
12+
// clang-format off
13+
#pragma cyclus exec from cyclus.system import CY_LARGE_DOUBLE, CY_LARGE_INT, CY_NEAR_ZERO
14+
// clang-format on
15+
16+
namespace cycamore {
17+
18+
class Context;
19+
20+
/// This facility acts as a simple conversion facility from its input commodity
21+
/// to its output commodity. It has a fixed throughput (per time step), and
22+
/// converts without regard to the composition of the input material.
23+
class Conversion
24+
: public cyclus::Facility,
25+
public cyclus::toolkit::Position {
26+
public:
27+
Conversion(cyclus::Context* ctx);
28+
29+
virtual ~Conversion();
30+
31+
virtual std::string version() { return CYCAMORE_VERSION; }
32+
33+
// clanag-format off
34+
#pragma cyclus note { \
35+
"doc": \
36+
" A conversion facility that accepts materials and products and with a \n"\
37+
" fixed throughput (per time step) converts them into its outcommod. " \
38+
}
39+
40+
#pragma cyclus decl
41+
// clang-format on
42+
43+
virtual std::string str();
44+
45+
virtual void EnterNotify();
46+
47+
virtual void Tick();
48+
49+
virtual void Tock();
50+
51+
double AvailableFeedstockCapacity();
52+
53+
void Convert();
54+
55+
56+
/// @brief Conversion Facilities request Materials of their given commodity.
57+
virtual std::set<cyclus::RequestPortfolio<cyclus::Material>::Ptr>
58+
GetMatlRequests();
59+
60+
virtual std::set<cyclus::BidPortfolio<cyclus::Material>::Ptr>
61+
GetMatlBids(cyclus::CommodMap<cyclus::Material>::type&
62+
commod_requests);
63+
64+
virtual void GetMatlTrades(
65+
const std::vector< cyclus::Trade<cyclus::Material> >& trades,
66+
std::vector<std::pair<cyclus::Trade<cyclus::Material>,
67+
cyclus::Material::Ptr> >& responses);
68+
69+
/// @brief Conversion Facilities place accepted trade Materials in their Inventory
70+
virtual void AcceptMatlTrades(
71+
const std::vector< std::pair<cyclus::Trade<cyclus::Material>,
72+
cyclus::Material::Ptr> >& responses);
73+
74+
75+
76+
private:
77+
// Code Injection:
78+
#include "toolkit/position.cycpp.h"
79+
80+
// clang-format off
81+
/// all facilities must have at least one input commodity
82+
#pragma cyclus var { \
83+
"tooltip": "input commodities", \
84+
"doc": "commodities that the conversion facility accepts", \
85+
"uilabel": "List of Input Commodities", \
86+
"uitype": ["oneormore", "incommodity"] \
87+
}
88+
std::vector<std::string> incommods;
89+
90+
#pragma cyclus var { \
91+
"tooltip": "output commodity", \
92+
"doc": "Output commodity on which the conversion facility offers material.", \
93+
"uilabel": "Output Commodity", \
94+
"uitype": "outcommodity", \
95+
}
96+
std::string outcommod;
97+
98+
/// Conversion throughput per timestep
99+
#pragma cyclus var { \
100+
"default": CY_LARGE_DOUBLE, \
101+
"tooltip": "conversion throughput per timestep", \
102+
"uilabel": "Maximum conversion throughput", \
103+
"uitype": "range", \
104+
"range": [0.0, CY_LARGE_DOUBLE], \
105+
"doc": "throughput the facility can convert at each time step" \
106+
}
107+
double throughput;
108+
109+
#pragma cyclus var { \
110+
"default": CY_LARGE_DOUBLE, \
111+
"tooltip": "input buffer capacity", \
112+
"uilabel": "Maximum Storage of Input Buffer", \
113+
"uitype": "range", \
114+
"range": [0.0, CY_LARGE_DOUBLE], \
115+
"doc": "Total capacity of the input buffer. The amount requested per " \
116+
"time step is the minimum the conversion throughput and this capacity " \
117+
"minus the amount of material in the input buffer." \
118+
}
119+
double input_capacity;
120+
121+
/// this facility holds a certain amount of material
122+
#pragma cyclus var {'capacity': 'input_capacity'}
123+
cyclus::toolkit::ResBuf<cyclus::Material> input;
124+
125+
/// a buffer for outgoing material
126+
cyclus::toolkit::ResBuf<cyclus::Material> output;
127+
// clang-format on
128+
129+
};
130+
131+
} // namespace cycamore
132+
133+
#endif // CYCAMORE_SRC_CONVERSION_H_
134+

0 commit comments

Comments
 (0)