diff --git a/src/fusion_power_plant.cc b/src/fusion_power_plant.cc index 4590cff..af37ee8 100644 --- a/src/fusion_power_plant.cc +++ b/src/fusion_power_plant.cc @@ -1,9 +1,23 @@ #include "fusion_power_plant.h" +using cyclus::Material; +using cyclus::Composition; +using cyclus::IntDistribution; +using cyclus::DoubleDistribution; +using cyclus::FixedIntDist; +using cyclus::FixedDoubleDist; +using cyclus::KeyError; + + + namespace tricycle { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FusionPowerPlant::FusionPowerPlant(cyclus::Context* ctx) : cyclus::Facility(ctx) {} +FusionPowerPlant::FusionPowerPlant(cyclus::Context* ctx) : cyclus::Facility(ctx) { + fuel_tracker.Init({&tritium_storage}, fuel_limit); + blanket_tracker.Init({&blanket_feed}, blanket_limit); + +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::string FusionPowerPlant::str() { @@ -12,45 +26,71 @@ std::string FusionPowerPlant::str() { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FusionPowerPlant::EnterNotify() { - //Pseudocode implementation of EnterNotify() cyclus::Facility::EnterNotify(); - fuel_usage_mass = (burn_rate * (fusion_power / MW_to_GW) / seconds_per_year * context()->dt()); - fuel_usage_atoms = fuel_usage_mass / tritium_atomic_mass; - blanket_turnover = blanket_size * blanket_turnover_rate; - //Create the blanket material for use in the core - const cyclus::Composition::Ptr enriched_li = context->GetRecipe(blanket_inrecipe); - cyclus::Material::Ptr blanket = cyclus::Composition::CreateFromAtom(0.0, enriched_li); + //fuel_usage_mass = (burn_rate * (fusion_power / MW_to_GW) / + // seconds_per_year * context()->dt()); + //fuel_usage_atoms = fuel_usage_mass / tritium_atomic_mass; + blanket_turnover = blanket_size * blanket_turnover_quantity; - //Truncated for readability. It goes on Tritium Storage and gets started, though. - fuel_startup_policy.Init(&tritium_storage).Set(fuel_incommod).Start(); - - //Truncated for readability - blanket_fill_policy.Init(&blanket).Set(blanket_incommod).Start(); + //Create the blanket material for use in the core, no idea if this works... + blanket = Material::Create(this, 0.0, + context()->GetRecipe(blanket_inrecipe)); + + fuel_startup_policy + .Init(this, &tritium_storage, std::string("Tritium Storage"), + &fuel_tracker) + .Set(fuel_incommod) + .Start(); + + blanket_fill_policy + .Init(this, &blanket_feed, std::string("Blanket Startup"), + &blanket_tracker) + .Set(blanket_incommod) + .Start(); - //Tritium Buy Policy Section: + // Tritium Buy Policy Selection: if (refuel_mode == "schedule") { - IntDistribution::Ptr active_dist = - FixedIntDist::Ptr(new FixedIntDist(1)); - IntDistribution::Ptr dormant_dist = - FixedIntDist::Ptr(new FixedIntDist(buy_frequency - 1)); - DoubleDistribution::Ptr size_dist = - FixedDoubleDist::Ptr(new FixedDoubleDist(1)); - //Do not start the policy yet. + IntDistribution::Ptr active_dist = + FixedIntDist::Ptr(new FixedIntDist(1)); + IntDistribution::Ptr dormant_dist = + FixedIntDist::Ptr(new FixedIntDist(buy_frequency - 1)); + DoubleDistribution::Ptr size_dist = + FixedDoubleDist::Ptr(new FixedDoubleDist(1)); + fuel_refill_policy - .Init(&tritium_storage, &fuel_tracker, - buy_quantity, active_dist, dormant_dist, size_dis) + .Init(this, &tritium_storage, std::string("Input"), + &fuel_tracker, + buy_quantity, + active_dist, dormant_dist, size_dist) .Set(fuel_incommod); + } else if (refuel_mode == "fill") { - //otherwise we just do it normally, but still don't start it. - fuel_refill_policy.Init(&tritium_storage).Set(fuel_incommod); + fuel_refill_policy + .Init(this, &tritium_storage, std::string("Input"), + &fuel_tracker).Set(fuel_incommod); + } else { - //This can be more sophisticated later. - throw cyclus::KeyError("Refill mode not recognized!"); + throw KeyError("Refill mode " + refuel_mode + + " not recognized! Try 'schedule' or 'fill'."); } - tritium_sell_policy.Init(&tritium_excess).Set(fuel_incommod).Start(); - helium_sell_policy.Init(&helium_storage).Set(he3).Start(); + tritium_sell_policy + .Init(this, &tritium_excess, std::string("Excess Tritium")) + .Set(fuel_incommod) + .Start(); + + helium_sell_policy.Init(this, &helium_excess, std::string("Helium-3")) + .Set(he3_outcommod) + .Start(); + + //This is going to need some work... The blanket waste recipe is going to be + //different all the time, so we want to just peg it to "depleted lithium" or + //something... Come back to this when you have a second. + blanket_waste_sell_policy + .Init(this, &blanket_waste, std::string("Blanket Waste")) + .Set(blanket_outcommod) + .Start(); } @@ -67,7 +107,7 @@ void FusionPowerPlant::Tick() { } else { //Some way of leaving a record of what is going wrong is helpful info I think - Record(Error); + //Record(Error); } DecayInventories(); @@ -82,7 +122,43 @@ void FusionPowerPlant::Tock() { //longer needed. Leaving a comment to remind myself about that. //Again, not sure about the recording: - RecordInventories(all_of_them.quantity()); + //RecordInventories(all_of_them.quantity()); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FusionPowerPlant::CheckOperatingConditions() { + //Left empty to quickly check if code builds + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FusionPowerPlant::SequesterTritium() { + //Left empty to quickly check if code builds + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FusionPowerPlant::OperateReactor() { + //Left empty to quickly check if code builds + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FusionPowerPlant::DecayInventories() { + //Left empty to quickly check if code builds + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FusionPowerPlant::ExtractHelium() { + //Left empty to quickly check if code builds + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FusionPowerPlant::MoveExcessTritiumToSellBuffer() { + //Left empty to quickly check if code builds } @@ -95,13 +171,15 @@ void FusionPowerPlant::CycleBlanket() { //guarantee blanket has enough material in CheckOperatingConditions() blanket->Absorb(blanket_feed.Pop(blanket_turnover)); - RecordOperationalInfo("Blanket Cycled"); - } else { - RecordOperationalInfo("Blanket Not Cycled"); } } } +bool FusionPowerPlant::BlanketCycleTime(){ + return (context()->time() % blanket_turnover_frequency == 0 + && !blanket_feed.empty()); +} + // WARNING! Do not change the following this function!!! This enables your // archetype to be dynamically loaded and any alterations will cause your // archetype to fail. diff --git a/src/fusion_power_plant.h b/src/fusion_power_plant.h index 65be12f..bed2e57 100644 --- a/src/fusion_power_plant.h +++ b/src/fusion_power_plant.h @@ -4,6 +4,10 @@ #include #include "cyclus.h" +#include "boost/shared_ptr.hpp" +#include "pyne.h" + +using cyclus::Material; namespace tricycle { @@ -18,11 +22,11 @@ namespace tricycle { /// /// @section agentparams Agent Parameters /// Place a description of the required input parameters which define the -/// agent implementation. None so far. +/// agent implementation. Saving for Later. /// /// @section optionalparams Optional Parameters /// Place a description of the optional input parameters to define the -/// agent implementation. None so far. +/// agent implementation. Saving for later. /// /// @section detailed Detailed Behavior /// Place a description of the detailed behavior of the agent. Consider @@ -47,10 +51,10 @@ class FusionPowerPlant : public cyclus::Facility { #pragma cyclus note {"doc": "A stub facility is provided as a skeleton " \ "for the design of new facility agents."} - //Functions: - /// A verbose printer for the FusionPowerPlant - virtual std::string str(); + /// Set up policies and buffers: + virtual void EnterNotify(); + /// The handleTick function specific to the FusionPowerPlant. /// @param time the time of the tick virtual void Tick(); @@ -59,19 +63,148 @@ class FusionPowerPlant : public cyclus::Facility { /// @param time the time of the tock virtual void Tock(); - //Member Variables: + /// A verbose printer for the FusionPowerPlant + virtual std::string str(); + + //State Variables: + #pragma cyclus var { \ + "doc": "Fresh fuel commodity", \ + "tooltip": "Name of fuel commodity requested", \ + "uilabel": "Fuel input commodity" \ + } + std::string fuel_incommod; + + #pragma cyclus var { \ + "default": 'fill', \ + "doc": "Method of refueling the reactor", \ + "tooltip": "Options: 'schedule' or 'fill'", \ + "uitype": "combobox", \ + "categorical": ['schedule', 'fill'], \ + "uilabel": "Refuel Mode" \ + } + std::string refuel_mode; + + #pragma cyclus var { \ + "default": 0.1, \ + "doc": "Quantity of fuel reactor tries to purchase in schedule mode", \ + "tooltip": "Defaults to 100g/purchase", \ + "units": "kg", \ + "uitype": "range", \ + "range": [0, 1e299], \ + "uilabel": "Buy quantity" \ + } + double buy_quantity; + + #pragma cyclus var { \ + "default": 1, \ + "doc": "Frequency which reactor tries to purchase new fuel", \ + "tooltip": "Reactor is active for 1 timestep, then dormant for buy_frequency-1 timesteps", \ + "units": "Timesteps", \ + "uitype": "range", \ + "range": [0, 1e299], \ + "uilabel": "Buy frequency" \ + } + int buy_frequency; + + #pragma cyclus var { \ + "doc": "Helium-3 output commodity Designation", \ + "tooltip": "He-3 output commodity", \ + "uilabel": "He-3 output commodity" \ + } + std::string he3_outcommod; + + #pragma cyclus var { \ + "doc": "Recipe for blanket feed material", \ + "tooltip": "Recipe for blanket feed material", \ + "uilabel": "Recipe for blanket feed material" \ + } + std::string blanket_inrecipe; + + #pragma cyclus var { \ + "doc": "Blanket feed commodity designation", \ + "tooltip": "Blanket feed commodity", \ + "uilabel": "Blanket feed commodity" \ + } + std::string blanket_incommod; + + #pragma cyclus var { \ + "doc": "Blanket waste commodity designation", \ + "tooltip": "Blanket waste commodity", \ + "uilabel": "Blanket waste commodity" \ + } + std::string blanket_outcommod; + + #pragma cyclus var { \ + "default": 1000.0, \ + "doc": "Initial mass of full blanket material", \ + "tooltip": "Only blanket material mass, not structural mass", \ + "units": "kg", \ + "uitype": "range", \ + "range": [0, 10000], \ + "uilabel": "Initial Mass of Blanket" \ + } + double blanket_size; + + #pragma cyclus var { \ + "default": 0.05, \ + "doc": "Percent of blanket that gets recycled every blanket turnover period", \ + "tooltip": "Defaults to 0.05 (5%), must be between 0 and 15%", \ + "units": "dimensionless", \ + "uitype": "range", \ + "range": [0, 0.15], \ + "uilabel": "Blanket Turnover Rate" \ + } + double blanket_turnover_quantity; + + #pragma cyclus var { \ + "default": 1, \ + "doc": "number of timesteps between blanket recycles", \ + "tooltip": "Defaults to 0.05 (5%), must be between 0 and 15%", \ + "units": "dimensionless", \ + "uitype": "range", \ + "range": [0, 1000], \ + "uilabel": "Blanket Turnover Rate" \ + } + int blanket_turnover_frequency; //Functions: void CycleBlanket(); + bool BlanketCycleTime(); + bool CheckOperatingConditions(); + void SequesterTritium(); + void OperateReactor(); + void DecayInventories(); + void ExtractHelium(); + void MoveExcessTritiumToSellBuffer(); - //Resource Buffers: + + private: + //Resource Buffers and Trackers: cyclus::toolkit::ResBuf tritium_storage; cyclus::toolkit::ResBuf tritium_excess; cyclus::toolkit::ResBuf helium_excess; cyclus::toolkit::ResBuf blanket_feed; cyclus::toolkit::ResBuf blanket_waste; - //PyneIDs + cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; + cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; + cyclus::toolkit::MatlBuyPolicy blanket_fill_policy; + + cyclus::toolkit::MatlSellPolicy tritium_sell_policy; + cyclus::toolkit::MatlSellPolicy helium_sell_policy; + cyclus::toolkit::MatlSellPolicy blanket_waste_sell_policy; + + cyclus::toolkit::TotalInvTracker fuel_tracker; + cyclus::toolkit::TotalInvTracker blanket_tracker; + + //This is to correctly instantiate the TotalInvTracker(s) + double fuel_limit = 1000.0; + double blanket_limit = 100000.0; + Material::Ptr blanket; + double blanket_turnover; + + + //NucIDs for Pyne const int tritium_id = 10030000; //Compositions: