diff --git a/input/deploy_inst.xml b/input/deploy_inst.xml new file mode 100644 index 0000000000..4512627ecc --- /dev/null +++ b/input/deploy_inst.xml @@ -0,0 +1,75 @@ + + + 10 + 1 + 2018 + never + + + + agentsNullRegion + cycamoreDeployInst + cycamoreSource + cycamoreSink + + + + Source + + + commodity1 + commod_recipe + 1 + + + + + + Sink + + + + commodity1 + + + + + + + Single Region + + + + + + + + Sink + 1 + + + Single Institution + + + + Source + + + 1 + + + 1 + + + + + + + + commod_recipe + mass + 922350000 0.711 + 922380000 99.289 + + + diff --git a/input/growth/deploy_and_manager_insts.xml b/input/growth/deploy_and_manager_insts.xml new file mode 100644 index 0000000000..398b1778e3 --- /dev/null +++ b/input/growth/deploy_and_manager_insts.xml @@ -0,0 +1,118 @@ + + + 10 + 1 + 2018 + never + + + + cycamoreGrowthRegion + cycamoreDeployInst + cycamoreManagerInst + cycamoreSource + cycamoreSink + + + + commodity1 + 1.0 + + + + Source1 + + + commodity1 + commod_recipe + 1 + + + + + + Source2 + + + commodity1 + commod_recipe + 1 + + + + + + Sink + + + + commodity1 + + + + + + + Single Region + + + + + commodity1 + + + 5 + + linear + 0 5 + + + + + + + + + + First Institution + + + Sink + 1 + + + + + + Source2 + + + + + + + Second Institution + + + + Source1 + + + 1 + + + 1 + + + + + + + + commod_recipe + mass + 922350000 0.711 + 922380000 99.289 + + + diff --git a/src/cycamore.h b/src/cycamore.h index f4820e7f2d..a17995e402 100644 --- a/src/cycamore.h +++ b/src/cycamore.h @@ -8,6 +8,7 @@ #include "batch_reactor.h" #include "batch_reactor_tests.h" #include "deploy_inst.h" +#include "deploy_inst_tests.h" #include "enrichment.h" #include "enrichment_tests.h" #if CYCLUS_HAS_COIN diff --git a/src/deploy_inst.cc b/src/deploy_inst.cc index 1b12dcb978..dc26c937cd 100644 --- a/src/deploy_inst.cc +++ b/src/deploy_inst.cc @@ -68,6 +68,57 @@ void DeployInst::EnterNotify() { RecordPosition(); } +void DeployInst::BuildNotify(Agent* a) { + Register_(a); +} + +void DeployInst::DecomNotify(Agent* a) { + Unregister_(a); +} + +void DeployInst::Register_(Agent* a) { + using cyclus::toolkit::CommodityProducer; + using cyclus::toolkit::CommodityProducerManager; + + CommodityProducer* cp_cast = dynamic_cast(a); + if (cp_cast != NULL) { + LOG(cyclus::LEV_INFO3, "mani") << "Registering agent " + << a->prototype() << a->id() + << " as a commodity producer."; + CommodityProducerManager::Register(cp_cast); + } +} + +void DeployInst::Unregister_(Agent* a) { + using cyclus::toolkit::CommodityProducer; + using cyclus::toolkit::CommodityProducerManager; + + CommodityProducer* cp_cast = dynamic_cast(a); + if (cp_cast != NULL) + CommodityProducerManager::Unregister(cp_cast); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DeployInst::WriteProducerInformation( + cyclus::toolkit::CommodityProducer* producer) { + using std::set; + set commodities = + producer->ProducedCommodities(); + set:: + iterator it; + + LOG(cyclus::LEV_DEBUG3, "maninst") << " Clone produces " << commodities.size() + << " commodities."; + for (it = commodities.begin(); it != commodities.end(); it++) { + LOG(cyclus::LEV_DEBUG3, "maninst") << " Commodity produced: " << it->name(); + LOG(cyclus::LEV_DEBUG3, "maninst") << " capacity: " << + producer->Capacity(*it); + LOG(cyclus::LEV_DEBUG3, "maninst") << " cost: " << + producer->Cost(*it); + } +} + void DeployInst::RecordPosition() { std::string specification = this->spec(); context() diff --git a/src/deploy_inst.h b/src/deploy_inst.h index cc6dc3ea15..fd55485a61 100644 --- a/src/deploy_inst.h +++ b/src/deploy_inst.h @@ -19,14 +19,17 @@ typedef std::map > BuildSched; // lifetimes. The same prototype can be specified multiple times with any // combination of the same or different build times, build number, and // lifetimes. -class DeployInst : public cyclus::Institution, +class DeployInst : + public cyclus::Institution, + public cyclus::toolkit::CommodityProducerManager, public cyclus::toolkit::Position { #pragma cyclus note { \ "doc": \ "Builds and manages agents (facilities) according to a manually" \ " specified deployment schedule. Deployed agents are automatically" \ - " decommissioned at the end of their lifetime. The user specifies a" \ - " list of prototypes for" \ + " decommissioned at the end of their lifetime. Deployed and" \ + " decommissioned agents are registered and unregistered with a" \ + " region. The user specifies a list of prototypes for" \ " each and corresponding build times, number to build, and (optionally)" \ " lifetimes. The same prototype can be specified multiple times with" \ " any combination of the same or different build times, build number," \ @@ -45,6 +48,20 @@ class DeployInst : public cyclus::Institution, virtual void EnterNotify(); + virtual void BuildNotify(Agent* m); + virtual void DecomNotify(Agent* m); + /// write information about a commodity producer to a stream + /// @param producer the producer + void WriteProducerInformation(cyclus::toolkit::CommodityProducer* + producer); + + private: + /// register a child + void Register_(cyclus::Agent* agent); + + /// unregister a child + void Unregister_(cyclus::Agent* agent); + protected: #pragma cyclus var { \ "doc": "Ordered list of prototypes to build.", \ diff --git a/src/deploy_inst_tests.cc b/src/deploy_inst_tests.cc index 607876245f..a529f9bc05 100644 --- a/src/deploy_inst_tests.cc +++ b/src/deploy_inst_tests.cc @@ -1,18 +1,31 @@ -#include - -#include "context.h" -#include "deploy_inst.h" -#include "institution_tests.h" -#include "agent_tests.h" +#include "deploy_inst_tests.h" // make sure that the deployed agent's prototype name is identical to the // originally specified prototype name - this is important to test because // DeployInst does some mucking around with registering name-modded prototypes // in order to deal with lifetime setting. +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DeployInstTests::SetUp() { + ctx_ = new cyclus::Context(&ti_, &rec_); + src_inst = new cycamore::DeployInst(ctx_); + producer = new TestProducer(ctx_); + commodity = cyclus::toolkit::Commodity("commod"); + capacity = 5; + producer->cyclus::toolkit::CommodityProducer::Add(commodity); + producer->SetCapacity(commodity, capacity); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DeployInstTests::TearDown() { + delete producer; + delete src_inst; + delete ctx_; +} + using cyclus::QueryResult; -TEST(DeployInstTests, ProtoNames) { +TEST_F(DeployInstTests, ProtoNames) { std::string config = " foobar " " 1 " @@ -32,7 +45,7 @@ TEST(DeployInstTests, ProtoNames) { EXPECT_EQ(3, stmt->GetInt(0)); } -TEST(DeployInstTests, BuildTimes) { +TEST_F(DeployInstTests, BuildTimes) { std::string config = " foobar foobar " " 1 3 " @@ -59,7 +72,7 @@ TEST(DeployInstTests, BuildTimes) { // make sure that specified lifetimes are honored both in agent's table record // and in decommissioning. -TEST(DeployInstTests, FiniteLifetimes) { +TEST_F(DeployInstTests, FiniteLifetimes) { std::string config = " foobar foobar foobar " " 1 1 2 " @@ -112,7 +125,7 @@ TEST(DeployInstTests, FiniteLifetimes) { EXPECT_EQ(8, stmt->GetInt(0)); } -TEST(DeployInstTests, NoDupProtos) { +TEST_F(DeployInstTests, NoDupProtos) { std::string config = " foobar foobar foobar " " 1 1 2 " @@ -141,7 +154,7 @@ TEST(DeployInstTests, NoDupProtos) { EXPECT_EQ(1, stmt->GetInt(0)); } -TEST(DeployInstTests, PositionInitialize) { +TEST_F(DeployInstTests, PositionInitialize) { std::string config = " foobar " " 1 " @@ -158,7 +171,7 @@ TEST(DeployInstTests, PositionInitialize) { EXPECT_EQ(qr.GetVal("Longitude"), 0.0); } -TEST(DeployInstTests, PositionInitialize2) { +TEST_F(DeployInstTests, PositionInitialize2) { std::string config = " foobar " " -20.0 " @@ -177,6 +190,28 @@ TEST(DeployInstTests, PositionInitialize2) { EXPECT_EQ(qr.GetVal("Longitude"), -20.0); } +TEST_F(DeployInstTests, producerexists) { + using std::set; + ctx_->AddPrototype("foop", producer); + set::iterator it; + for (it = src_inst->cyclus::toolkit::CommodityProducerManager:: + producers().begin(); + it != src_inst->cyclus::toolkit::CommodityProducerManager:: + producers().end(); + it++) { + EXPECT_EQ(dynamic_cast(*it)->prototype(), + producer->prototype()); + } +} + +TEST_F(DeployInstTests, productioncapacity) { + EXPECT_EQ(src_inst->TotalCapacity(commodity), 0); + src_inst->BuildNotify(producer); + EXPECT_EQ(src_inst->TotalCapacity(commodity), capacity); + src_inst->DecomNotify(producer); + EXPECT_EQ(src_inst->TotalCapacity(commodity), 0); +} + // required to get functionality in cyclus agent unit tests library cyclus::Agent* DeployInstitutionConstructor(cyclus::Context* ctx) { return new cycamore::DeployInst(ctx); diff --git a/src/deploy_inst_tests.h b/src/deploy_inst_tests.h new file mode 100644 index 0000000000..3ceb6a5fda --- /dev/null +++ b/src/deploy_inst_tests.h @@ -0,0 +1,58 @@ +#ifndef CYCAMORE_SRC_DEPLOY_INST_TESTS_H_ +#define CYCAMORE_SRC_DEPLOY_INST_TESTS_H_ + +#include + +#include "cyclus.h" +#include "timer.h" +#include "test_context.h" +#include "institution_tests.h" +#include "agent_tests.h" +#include "context.h" +#include "deploy_inst.h" + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class TestProducer + : public cyclus::Facility, + public cyclus::toolkit::CommodityProducer { + public: + TestProducer(cyclus::Context* ctx); + ~TestProducer(); + + cyclus::Agent* Clone() { + TestProducer* m = new TestProducer(context()); + m->InitFrom(this); + return m; + } + + void InitFrom(TestProducer* m) { + cyclus::Facility::InitFrom(m); + } + + void InitInv(cyclus::Inventories& inv) {} + + cyclus::Inventories SnapshotInv() { return cyclus::Inventories(); } + + void Tock() {} + void Tick() {} +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class DeployInstTests : public ::testing::Test { + public: + virtual void SetUp(); + virtual void TearDown(); + + protected: + cycamore::DeployInst* src_inst; + TestProducer* producer; + + cyclus::toolkit::Commodity commodity; + double capacity; + cyclus::Context* ctx_; + cyclus::Timer ti_; + cyclus::Recorder rec_; +}; + +#endif // CYCAMORE_SRC_DEPLOY_INST_TESTS_H_ diff --git a/src/manager_inst.h b/src/manager_inst.h index ac86d81f1a..df857e88eb 100644 --- a/src/manager_inst.h +++ b/src/manager_inst.h @@ -44,13 +44,13 @@ class ManagerInst void WriteProducerInformation(cyclus::toolkit::CommodityProducer* producer); - private: + private: /// register a child void Register_(cyclus::Agent* agent); /// unregister a child void Unregister_(cyclus::Agent* agent); - + #pragma cyclus var { \ "tooltip": "producer facility prototypes", \ "uilabel": "Producer Prototype List", \ diff --git a/src/manager_inst_tests.cc b/src/manager_inst_tests.cc index e9f931095d..2f9063407a 100644 --- a/src/manager_inst_tests.cc +++ b/src/manager_inst_tests.cc @@ -5,7 +5,6 @@ TestProducer::TestProducer(cyclus::Context* ctx) : cyclus::Facility(ctx) {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TestProducer::~TestProducer() {} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ManagerInstTests::SetUp() { ctx_ = new cyclus::Context(&ti_, &rec_); diff --git a/tests/test_regression.py b/tests/test_regression.py index c079cd0781..ec4f2aa532 100644 --- a/tests/test_regression.py +++ b/tests/test_regression.py @@ -379,8 +379,10 @@ def test_xaction_specific(self): np.where(self.resource_ids == self.trans_resource[t])] assert_equal(quantity, 2) -class TestGrowth(TestRegression): - """Tests GrowthRegion, ManagerInst, and Source over a 4-time step +class TestGrowth1(TestRegression): + """This class tests the growth.xml + + Tests GrowthRegion, ManagerInst, and Source over a 4-time step simulation. A linear growth demand (y = x + 2) is provided to the growth region. Two @@ -392,16 +394,16 @@ class TestGrowth(TestRegression): to test the demand for multiple commodities. """ def __init__(self, *args, **kwargs): - super(TestGrowth, self).__init__(*args, **kwargs) + super(TestGrowth1, self).__init__(*args, **kwargs) self.inf = "./input/growth.xml" if not cyclus_has_coin(): raise SkipTest('Cyclus not compiled with COIN') def setUp(self): - super(TestGrowth, self).setUp() + super(TestGrowth1, self).setUp() def tearDown(self): - super(TestGrowth, self).tearDown() + super(TestGrowth1, self).tearDown() def test_deployment(self): pass @@ -426,6 +428,88 @@ def test_deployment(self): for x in source3_id: assert_equal(enter_time[np.where(agent_ids == x)], 2) +class TestGrowth2(TestRegression): + """This class tests the ./input/deploy_and_manager_insts.xml + + Tests GrowthRegion, ManagerInst, DeployInst, and Source over a 10-time step + simulation. + + A linear growth demand (y = 5) is provided to the growth region. One + Source is allowed in the ManagerInst, with capacity of 1. + At t=1, a 1-capacity Source1 is built by the DeployInst, and at + t=6, 4 1-capacity Source2s are expected to be built by the ManagerInst. + + """ + def __init__(self, *args, **kwargs): + super(TestGrowth2, self).__init__(*args, **kwargs) + self.inf = "../input/growth/deploy_and_manager_insts.xml" + if not cyclus_has_coin(): + raise SkipTest('Cyclus not compiled with COIN') + + def setUp(self): + super(TestGrowth2, self).setUp() + + def tearDown(self): + super(TestGrowth2, self).tearDown() + + def test_deployment(self): + pass + agent_ids = self.to_ary(self.agent_entry, "AgentId") + proto = self.to_ary(self.agent_entry, "Prototype") + enter_time = self.to_ary(self.agent_entry, "EnterTime") + + source1_id = self.find_ids("Source1", self.agent_entry, + spec_col="Prototype") + source2_id = self.find_ids("Source2", self.agent_entry, + spec_col="Prototype") + + assert_equal(len(source1_id), 1) + assert_equal(len(source2_id), 4) + + assert_equal(enter_time[np.where(agent_ids == source1_id[0])], 1) + assert_equal(enter_time[np.where(agent_ids == source2_id[0])], 6) + +class TestDeployInst(TestRegression): + """This class tests the ../input/deploy_inst.xml + + Tests DeployInst, and NullRegion over a 10-time step + simulation. + + A DeployInst is used to define that a Source agent is to be deployed at + time t=1 within a Null Region. A Sink agent is also deployed as + an initial facility. This input is used to test that the Source and + Sink agents are deployed at their respecitve times and that the correct + number of these agents are deployed. + + """ + def __init__(self, *args, **kwargs): + super(TestDeployInst, self).__init__(*args, **kwargs) + self.inf = "../input/deploy_inst.xml" + if not cyclus_has_coin(): + raise SkipTest('Cyclus not compiled with COIN') + + def setUp(self): + super(TestDeployInst, self).setUp() + + def tearDown(self): + super(TestDeployInst, self).tearDown() + + def test_deployment(self): + pass + agent_ids = self.to_ary(self.agent_entry, "AgentId") + proto = self.to_ary(self.agent_entry, "Prototype") + enter_time = self.to_ary(self.agent_entry, "EnterTime") + + source_id = self.find_ids("Source", self.agent_entry, + spec_col="Prototype") + sink_id = self.find_ids("Sink", self.agent_entry, spec_col="Prototype") + + assert_equal(len(source_id), 1) + assert_equal(len(sink_id), 1) + + assert_equal(enter_time[np.where(agent_ids == source_id[0])], 1) + assert_equal(enter_time[np.where(agent_ids == sink_id[0])], 0) + class _Recycle(TestRegression): """This class tests the input/recycle.xml file. """