Skip to content

Commit

Permalink
add random behavior for size of sink request (cyclus#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
nuclearkatie committed Nov 28, 2023
1 parent 35bac61 commit abc9f5c
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 13 deletions.
55 changes: 46 additions & 9 deletions src/sink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Sink::~Sink() {}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Sink::EnterNotify() {
cyclus::Facility::EnterNotify();
LOG(cyclus::LEV_INFO4, "SnkFac") << " using random behavior " << random_size_type;

if (in_commod_prefs.size() == 0) {
for (int i = 0; i < in_commods.size(); ++i) {
Expand All @@ -52,6 +53,10 @@ void Sink::EnterNotify() {
<< " values, expected " << in_commods.size();
throw cyclus::ValueError(ss.str());
}
/// Create first requestAmt. Only used in testing, as a simulation will
/// overwrite this on Tick()
SetRequestAmt();

RecordPosition();
}

Expand Down Expand Up @@ -85,17 +90,21 @@ Sink::GetMatlRequests() {

std::set<RequestPortfolio<Material>::Ptr> ports;
RequestPortfolio<Material>::Ptr port(new RequestPortfolio<Material>());
double amt = RequestAmt();
Material::Ptr mat;

/// for testing
if (requestAmt > SpaceAvailable()) {
SetRequestAmt();
}

if (recipe_name.empty()) {
mat = cyclus::NewBlankMaterial(amt);
mat = cyclus::NewBlankMaterial(requestAmt);
} else {
Composition::Ptr rec = this->context()->GetRecipe(recipe_name);
mat = cyclus::Material::CreateUntracked(amt, rec);
mat = cyclus::Material::CreateUntracked(requestAmt, rec);
}

if (amt > cyclus::eps()) {
if (requestAmt > cyclus::eps()) {
std::vector<Request<Material>*> mutuals;
for (int i = 0; i < in_commods.size(); i++) {
mutuals.push_back(port->AddRequest(mat, this, in_commods[i], in_commod_prefs[i]));
Expand All @@ -118,16 +127,15 @@ Sink::GetGenRsrcRequests() {
std::set<RequestPortfolio<Product>::Ptr> ports;
RequestPortfolio<Product>::Ptr
port(new RequestPortfolio<Product>());
double amt = RequestAmt();

if (amt > cyclus::eps()) {
CapacityConstraint<Product> cc(amt);
if (requestAmt > cyclus::eps()) {
CapacityConstraint<Product> cc(requestAmt);
port->AddConstraint(cc);

std::vector<std::string>::const_iterator it;
for (it = in_commods.begin(); it != in_commods.end(); ++it) {
std::string quality = ""; // not clear what this should be..
Product::Ptr rsrc = Product::CreateUntracked(amt, quality);
Product::Ptr rsrc = Product::CreateUntracked(requestAmt, quality);
port->AddRequest(rsrc, this, *it);
}

Expand Down Expand Up @@ -164,9 +172,15 @@ void Sink::Tick() {
using std::vector;
LOG(cyclus::LEV_INFO3, "SnkFac") << prototype() << " is ticking {";

double requestAmt = RequestAmt();
SetRequestAmt();

LOG(cyclus::LEV_INFO3, "SnkFac") << prototype() << " has default request amount " << requestAmt;

// inform the simulation about what the sink facility will be requesting
if (requestAmt > cyclus::eps()) {
LOG(cyclus::LEV_INFO4, "SnkFac") << prototype()
<< " has request amount " << requestAmt
<< " kg of " << in_commods[0] << ".";
for (vector<string>::iterator commod = in_commods.begin();
commod != in_commods.end();
commod++) {
Expand Down Expand Up @@ -205,6 +219,29 @@ void Sink::RecordPosition() {
->Record();
}

void Sink::SetRequestAmt() {
double amt = SpaceAvailable();
if (amt < cyclus::eps()) {
requestAmt = 0;
}

if (random_size_type == "None") {
requestAmt = amt;
}
else if (random_size_type == "UniformReal") {
requestAmt = context()->random_uniform_real(0, amt);
}
else if (random_size_type == "NormalReal") {
requestAmt = context()->random_normal_real(amt * random_size_mean,
amt * random_size_stddev,
0, amt);
}
else {
requestAmt = amt;
}
return;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
extern "C" cyclus::Agent* ConstructSink(cyclus::Context* ctx) {
return new Sink(ctx);
Expand Down
46 changes: 45 additions & 1 deletion src/sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ class Sink
const std::vector< std::pair<cyclus::Trade<cyclus::Product>,
cyclus::Product::Ptr> >& responses);

/// @brief SinkFacilities update request amount using random behavior
virtual void SetRequestAmt();

/// add a commodity to the set of input commodities
/// @param name the commodity name
inline void AddCommodity(std::string name) { in_commods.push_back(name); }
Expand All @@ -87,7 +90,7 @@ class Sink
inline double InventorySize() const { return inventory.quantity(); }

/// determines the amount to request
inline double RequestAmt() const {
inline double SpaceAvailable() const {
return std::min(capacity, std::max(0.0, inventory.space()));
}

Expand All @@ -107,6 +110,7 @@ class Sink
input_commodity_preferences() const { return in_commod_prefs; }

private:
double requestAmt;
/// all facilities must have at least one input commodity
#pragma cyclus var {"tooltip": "input commodities", \
"doc": "commodities that the sink facility accepts", \
Expand Down Expand Up @@ -154,6 +158,46 @@ class Sink
#pragma cyclus var {'capacity': 'max_inv_size'}
cyclus::toolkit::ResBuf<cyclus::Resource> inventory;

/// random status (size of request)
#pragma cyclus var {"default": "None", \
"tooltip": "type of random behavior when setting the " \
"size of the request", \
"uitype": "combobox", \
"uilabel": "Random Size", \
"categorical": ["None", "UniformReal", "UniformInt", "NormalReal", "NormalInt"], \
"doc": "type of random behavior to use. Default None, " \
"other options are 'UniformReal', 'UniformInt', " \
"'NormalReal', and 'NormalInt'"}
std::string random_size_type;

// random size mean (as a fraction of available space)
#pragma cyclus var {"default": 1.0, \
"tooltip": "fraction of available space to determine the mean", \
"uilabel": "Random Size Mean", \
"uitype": "range", \
"range": [0.0, 1e299], \
"doc": "When a normal distribution is used to determine the " \
"size of the request, this is the fraction of available " \
"space to use as the mean. Default 1.0. Note " \
"that values significantly above 1 without a " \
"correspondingly large std dev may result in " \
"inefficient use of the random number generator."}
double random_size_mean;

// random size std dev (as a fraction of available space)
#pragma cyclus var {"default": 0.1, \
"tooltip": "fraction of available space to determine the std dev", \
"uilabel": "Random Size Std Dev", \
"uitype": "range", \
"range": [0.0, 1e299], \
"doc": "When a normal distribution is used to determine the " \
"size of the request, this is the fraction of available " \
"space to use as the standard deviation. Default 0.1"}
double random_size_stddev;


// random status (frequencing/timing of request)

#pragma cyclus var { \
"default": 0.0, \
"uilabel": "Geographical latitude in degrees as a double", \
Expand Down
74 changes: 71 additions & 3 deletions src/sink_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ TEST_F(SinkTest, InitialState) {
EXPECT_DOUBLE_EQ(0.0, src_facility->InventorySize());
EXPECT_DOUBLE_EQ(capacity_, src_facility->Capacity());
EXPECT_DOUBLE_EQ(inv_, src_facility->MaxInventorySize());
EXPECT_DOUBLE_EQ(capacity_, src_facility->RequestAmt());
EXPECT_DOUBLE_EQ(capacity_, src_facility->SpaceAvailable());
EXPECT_DOUBLE_EQ(0.0, src_facility->InventorySize());
std::string arr[] = {commod1_, commod2_};
std::vector<std::string> vexp (arr, arr + sizeof(arr) / sizeof(arr[0]) );
Expand All @@ -66,7 +66,7 @@ TEST_F(SinkTest, Clone) {
EXPECT_DOUBLE_EQ(0.0, cloned_fac->InventorySize());
EXPECT_DOUBLE_EQ(capacity_, cloned_fac->Capacity());
EXPECT_DOUBLE_EQ(inv_, cloned_fac->MaxInventorySize());
EXPECT_DOUBLE_EQ(capacity_, cloned_fac->RequestAmt());
EXPECT_DOUBLE_EQ(capacity_, cloned_fac->SpaceAvailable());
std::string arr[] = {commod1_, commod2_};
std::vector<std::string> vexp (arr, arr + sizeof(arr) / sizeof(arr[0]) );
EXPECT_EQ(vexp, cloned_fac->input_commodities());
Expand Down Expand Up @@ -104,7 +104,7 @@ TEST_F(SinkTest, DISABLED_XMLInit) {
EXPECT_EQ(vexp, fac.input_commodities());
EXPECT_DOUBLE_EQ(capacity_, fac.Capacity());
EXPECT_DOUBLE_EQ(inv_, fac.MaxInventorySize());
EXPECT_DOUBLE_EQ(capacity_, fac.RequestAmt());
EXPECT_DOUBLE_EQ(capacity_, fac.SpaceAvailable());
EXPECT_DOUBLE_EQ(0.0, fac.InventorySize());
}

Expand Down Expand Up @@ -342,6 +342,74 @@ TEST_F(SinkTest, PositionInitialize2) {

}

TEST_F(SinkTest, RandomUniform) {
using cyclus::QueryResult;
using cyclus::Cond;

std::string config =
" <in_commods>"
" <val>commods_1</val>"
" </in_commods>"
" <capacity>10</capacity>"
" <random_size_type>UniformReal</random_size_type> ";

int simdur = 1;
cyclus::MockSim sim(cyclus::AgentSpec
(":cycamore:Sink"), config, simdur);
sim.AddSource("commods_1").capacity(10).Finalize();
int id = sim.Run();

QueryResult qr = sim.db().Query("Resources", NULL);
EXPECT_EQ(qr.rows.size(), 1);
EXPECT_NEAR(qr.GetVal<double>("Quantity"), 9.41273, 0.0001);
}

TEST_F(SinkTest, RandomNormal) {
using cyclus::QueryResult;
using cyclus::Cond;

std::string config =
" <in_commods>"
" <val>commods_1</val>"
" </in_commods>"
" <capacity>10</capacity>"
" <random_size_type>NormalReal</random_size_type> ";

int simdur = 1;
cyclus::MockSim sim(cyclus::AgentSpec
(":cycamore:Sink"), config, simdur);
sim.AddSource("commods_1").capacity(10).Finalize();
int id = sim.Run();

QueryResult qr = sim.db().Query("Resources", NULL);
EXPECT_EQ(qr.rows.size(), 1);
EXPECT_NEAR(qr.GetVal<double>("Quantity"), 9.60929, 0.0001);
}

TEST_F(SinkTest, RandomNormalWithMeanSttdev) {
using cyclus::QueryResult;
using cyclus::Cond;

std::string config =
" <in_commods>"
" <val>commods_1</val>"
" </in_commods>"
" <capacity>10</capacity>"
" <random_size_type>NormalReal</random_size_type> "
" <random_size_mean>0.5</random_size_mean> "
" <random_size_stddev>0.2</random_size_stddev> ";

int simdur = 1;
cyclus::MockSim sim(cyclus::AgentSpec
(":cycamore:Sink"), config, simdur);
sim.AddSource("commods_1").capacity(10).Finalize();
int id = sim.Run();

QueryResult qr = sim.db().Query("Resources", NULL);
EXPECT_EQ(qr.rows.size(), 1);
EXPECT_NEAR(qr.GetVal<double>("Quantity"), 1.52979, 0.0001);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cyclus::Agent* SinkConstructor(cyclus::Context* ctx) {
return new cycamore::Sink(ctx);
Expand Down

0 comments on commit abc9f5c

Please sign in to comment.