From 800dfc028c3159934b1a1be2eeec3f039ba7b2b2 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Fri, 19 Jan 2024 14:49:57 -0600 Subject: [PATCH 01/43] Starting point based on cyclus_fusion --- .gitignore | 4 + CMakeLists.txt | 138 ++++++++++++++++++++++ README.rst | 110 +++++++++++++++++ install.py | 137 +++++++++++++++++++++ src/CMakeLists.txt | 7 ++ src/reactor.cc | 276 +++++++++++++++++++++++++++++++++++++++++++ src/reactor.h | 215 +++++++++++++++++++++++++++++++++ src/reactor_tests.cc | 68 +++++++++++ 8 files changed, 955 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.rst create mode 100644 install.py create mode 100644 src/CMakeLists.txt create mode 100644 src/reactor.cc create mode 100644 src/reactor.h create mode 100644 src/reactor_tests.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98e9bbb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +cmake +input +*.sh \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f7979aa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,138 @@ +# DO NOT DELETE THIS LINE:: .:tricycle:Reactor + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +# taken from http://geant4.cern.ch/support/source/geant4/CMakeLists.txt +IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) + message(STATUS "Stub requires an out-of-source build.") + message(STATUS "Please remove these files from ${CMAKE_BINARY_DIR} first:") + message(STATUS "CMakeCache.txt") + message(STATUS "CMakeFiles") + message(STATUS "Once these files are removed, create a separate directory") + message(STATUS "and run CMake from there") + message(FATAL_ERROR "in-source build detected") +ENDIF() + +PROJECT(tricycle) + +# check for and enable c++11 support +INCLUDE(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +IF(COMPILER_SUPPORTS_CXX11) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +ELSE() + MESSAGE(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 + support. Please use a different C++ compiler.") +ENDIF() + +# quiets fortify_source warnings when not compiling with optimizations +# in linux distros where compilers were compiled with fortify_source enabled by +# default (e.g. Arch linux). +MESSAGE("${CMAKE_BUILD_TYPE}") +STRING(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE) +IF(NOT ${BUILD_TYPE} STREQUAL "release") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0") +ENDIF() +# no overflow warnings because of silly coin-ness +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overflow") + +# Direct any out-of-source builds to this directory +SET(STUB_SOURCE_DIR ${CMAKE_SOURCE_DIR}) + +# Direct any binary installation paths to this directory +SET(STUB_BINARY_DIR ${CMAKE_BINARY_DIR}) + +# This makes all the libraries build as SHARED +SET(BUILD_SHARED_LIBS true) + +# Setup build locations. +IF(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${STUB_BINARY_DIR}/bin) +endif() +IF(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${STUB_BINARY_DIR}/lib) +endif() +IF(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${STUB_BINARY_DIR}/lib) +ENDIF() + +SET(STUB_EXECUTABLE_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + +# use, i.e. don't skip the full RPATH for the build tree +SET(CMAKE_SKIP_BUILD_RPATH FALSE) + +# when building, don't use the install RPATH already +# (but later on when installing) +SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + +SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + +# add the automatically determined parts of the RPATH +# which point to directories outside the build tree to the install RPATH +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +# the RPATH to be used when installing, but only if it's not a system directory +LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) +IF("${isSystemDir}" STREQUAL "-1") + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib/cyclus") + GET_FILENAME_COMPONENT(cxxCompilerRoot ${CMAKE_CXX_COMPILER} DIRECTORY) + GET_FILENAME_COMPONENT(cxxCompilerRoot ${cxxCompilerRoot} DIRECTORY) + IF (NOT "${CMAKE_INSTALL_RPATH}" STREQUAL "${cxxCompilerRoot}") + SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:${cxxCompilerRoot}/lib:${cxxCompilerRoot}/lib/cyclus") + ENDIF (NOT "${CMAKE_INSTALL_RPATH}" STREQUAL "${cxxCompilerRoot}") + SET(CMAKE_BUILD_RPATH "${CMAKE_INSTALL_RPATH}") +ENDIF("${isSystemDir}" STREQUAL "-1") + +# Tell CMake where the modules are +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_INSTALL_PREFIX}/share/cyclus/cmake") +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${STUB_SOURCE_DIR}/cmake) +MESSAGE("--CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}") + +# Find cyclus +FIND_PACKAGE(Cyclus REQUIRED) +SET(STUB_INCLUDE_DIRS ${STUB_INCLUDE_DIRS} ${CYCLUS_CORE_INCLUDE_DIR}) +SET(LIBS ${LIBS} ${CYCLUS_CORE_LIBRARIES}) + +# Include macros +INCLUDE(UseCyclus) + +MESSAGE("--LD_LIBRARY_PATH: $ENV{LD_LIBRARY_PATH}") + +# Include the boost header files, system, and filesystem libraries +SET(Boost_USE_STATIC_LIBS OFF) +SET(Boost_USE_STATIC_RUNTIME OFF) +FIND_PACKAGE(Boost COMPONENTS filesystem system REQUIRED) +SET(STUB_INCLUDE_DIRS ${STUB_INCLUDE_DIRS} ${Boost_INCLUDE_DIR}) +SET(LIBS ${LIBS} ${Boost_FILESYSTEM_LIBRARY}) +SET(LIBS ${LIBS} ${Boost_SYSTEM_LIBRARY}) + +# Find HDF5 +FIND_PACKAGE(HDF5 REQUIRED) +ADD_DEFINITIONS(${HDF5_DEFINITIONS}) +SET(STUB_INCLUDE_DIRS ${STUB_INCLUDE_DIRS} ${HDF5_INCLUDE_DIR}) +set(LIBS ${LIBS} ${HDF5_LIBRARIES}) +MESSAGE("-- HDF5 Root: ${HDF5_ROOT}") +MESSAGE("-- HDF5 Include directory: ${HDF5_INCLUDE_DIR}") +MESSAGE("-- HDF5 Library directories: ${HDF5_LIBRARY_DIRS}") +MESSAGE("-- HDF5 Libraries: ${HDF5_LIBRARIES}") + +# find Coin +FIND_PACKAGE(COIN REQUIRED) +SET(STUB_INCLUDE_DIRS ${STUB_INCLUDE_DIRS} ${COIN_INCLUDE_DIR}) +set(LIBS ${LIBS} ${COIN_LIBRARIES}) + + +# include all the directories we just found +INCLUDE_DIRECTORIES(${STUB_INCLUDE_DIRS}) + + +# add the agents +ADD_SUBDIRECTORY(src) + +# uninstall target +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..1e0467a --- /dev/null +++ b/README.rst @@ -0,0 +1,110 @@ +.. _hello_world: + +Hello, Cyclus! +============== +This pages walks you through a very simple hello world example using +|cyclus| agents. First make sure that you have the dependencies installed, +namely |Cyclus|, CMake, and a recent version of Python (2.7 or 3.3+). + +First, you need to get the ``cycstub`` code. Cycstub is a skeleton code base +that you can use to quick-start new |cyclus| module development projects. +You can grab cycstub from |cyclus|. + +Let's put this code in a ``tutorial`` directory and go into it. + +**Getting cycstub via Cyclus:** + +.. code-block:: bash + + $ mkdir tutorial + $ cd tutorial/ + $ cycstub --type facility .:fusion:tutorialfacility + +------------ + +Let's now change the behavior of the TutorialFacility's ``Tick()`` & +``Tock()`` member functions to print "Hello" and "World" respectively. To do +this, please open up the :file:`src/tutorial_facility.cc` file in your +favorite text editor (vim, emacs, gedit, `notepad++ `_). +Change the original functions to look like: + +**Original Tick() and Tock() in src/tutorial_facility.cc:** + +.. code-block:: c++ + + void TutorialFacility::Tick() {} + + void TutorialFacility::Tock() {} + +**New Tick() and Tock() in src/tutorial_facility.cc:** + +.. code-block:: c++ + + void TutorialFacility::Tick() {std::cout << "Hello, ";} + + void TutorialFacility::Tock() {std::cout << "World!\n";} + +------------ + +Now that we have altered the behavior of the TutorialFacility, let's compile and +install the ``tutorial`` project. This done with the install.py script. +The install script puts the project into your cyclus userspace, +``${HOME}/.local/lib/cyclus``. + +.. code-block:: bash + + tutorial $ python install.py + +------------ + +Let's run |cyclus| with the TutorialFacility! In the directory there is +an :file:`example.xml`. Running |cyclus| on this file with the command +``cyclus example.xml`` should produce the following output. + +.. code-block:: bash + + tutorial $ cyclus example.xml + : + .CL:CC CC _Q _Q _Q_Q _Q _Q _Q + CC;CCCCCCCC:C; /_\) /_\)/_/\\) /_\) /_\) /_\) + CCCCCCCCCCCCCl __O|/O___O|/O_OO|/O__O|/O__O|/O____________O|/O__ + CCCCCCf iCCCLCC ///////////////////////////////////////////////// + iCCCt ;;;;;. CCCC + CCCC ;;;;;;;;;. CClL. c + CCCC ,;; ;;: CCCC ; : CCCCi + CCC ;; ;; CC ;;: CCC` `C; + lCCC ;; CCCC ;;;: :CC .;;. C; ; : ; :;; + CCCC ;. CCCC ;;;, CC ; ; Ci ; : ; : ; + iCC :; CC ;;;, ;C ; CC ; : ; . + CCCi ;; CCC ;;;. .C ; tf ; : ; ;. + CCC ;; CCC ;;;;;;; fC : lC ; : ; ;: + iCf ;; CC :;;: tC ; CC ; : ; ; + fCCC :; LCCf ;;;: LC :. ,: C ; ; ; ; ; + CCCC ;; CCCC ;;;: CCi `;;` CC. ;;;; :;.;. ; ,; + CCl ;; CC ;;;; CCC CCL + tCCC ;; ;; CCCL ;;; tCCCCC. + CCCC ;; :;; CCCCf ; ,L + lCCC ;;;;;; CCCL + CCCCCC :;; fCCCCC + . CCCC CCCC . + .CCCCCCCCCCCCCi + iCCCCCLCf + . C. , + : + Hello, World! + Hello, World! + Hello, World! + Hello, World! + Hello, World! + Hello, World! + Hello, World! + Hello, World! + Hello, World! + Hello, World! + + Status: Cyclus run successful! + Output location: cyclus.sqlite + Simulation ID: 0ae730e0-a9a8-4576-afaa-d1db6399d5a2 + +If you look in the input file you'll see that the simulation duration was set +to 10. This is why "Hello, World!" is printed ten times. diff --git a/install.py b/install.py new file mode 100644 index 0000000..dba1439 --- /dev/null +++ b/install.py @@ -0,0 +1,137 @@ +#! /usr/bin/env python +import os +import sys +import subprocess +import shutil + +try: + import argparse as ap +except ImportError: + import pyne._argparse as ap + +absexpanduser = lambda x: os.path.abspath(os.path.expanduser(x)) + + +def check_windows_cmake(cmake_cmd): + if os.name == 'nt': + files_on_path = set() + for p in os.environ['PATH'].split(';')[::-1]: + if os.path.exists(p): + files_on_path.update(os.listdir(p)) + if 'cl.exe' in files_on_path: + pass + elif 'sh.exe' in files_on_path: + cmake_cmd += ['-G "MSYS Makefiles"'] + elif 'gcc.exe' in files_on_path: + cmake_cmd += ['-G "MinGW Makefiles"'] + cmake_cmd = ' '.join(cmake_cmd) + + +def install(args): + if not os.path.exists(args.build_dir): + os.mkdir(args.build_dir) + elif args.clean_build: + shutil.rmtree(args.build_dir) + os.mkdir(args.build_dir) + + root_dir = os.path.split(__file__)[0] + makefile = os.path.join(args.build_dir, 'Makefile') + + if not os.path.exists(makefile): + rtn = subprocess.call(['which', 'cmake'], shell=(os.name == 'nt')) + if rtn != 0: + sys.exit("CMake could not be found, " + "please install CMake before developing Cyclus.") + cmake_cmd = ['cmake', os.path.abspath(root_dir)] + if args.prefix: + cmake_cmd += ['-DCMAKE_INSTALL_PREFIX=' + + absexpanduser(args.prefix)] + if args.cmake_prefix_path: + cmake_cmd += ['-DCMAKE_PREFIX_PATH=' + + absexpanduser(args.cmake_prefix_path)] + if args.coin_root: + cmake_cmd += ['-DCOIN_ROOT_DIR=' + absexpanduser(args.coin_root)] + if args.cyclus_root: + cmake_cmd += ['-DCYCLUS_ROOT_DIR='+absexpanduser(args.cyclus_root)] + if args.boost_root: + cmake_cmd += ['-DBOOST_ROOT=' + absexpanduser(args.boost_root)] + if args.build_type: + cmake_cmd += ['-DCMAKE_BUILD_TYPE=' + args.build_type] + check_windows_cmake(cmake_cmd) + rtn = subprocess.check_call(cmake_cmd, cwd=args.build_dir, + shell=(os.name == 'nt')) + + make_cmd = ['make'] + if args.threads: + make_cmd += ['-j' + str(args.threads)] + rtn = subprocess.check_call(make_cmd, cwd=args.build_dir, + shell=(os.name == 'nt')) + + if args.test: + make_cmd += ['test'] + elif not args.build_only: + make_cmd += ['install'] + + rtn = subprocess.check_call(make_cmd, cwd=args.build_dir, + shell=(os.name == 'nt')) + +def uninstall(args): + makefile = os.path.join(args.build_dir, 'Makefile') + if not os.path.exists(args.build_dir) or not os.path.exists(makefile): + sys.exist("May not uninstall Cyclus since it has not yet been built.") + rtn = subprocess.check_call(['make', 'uninstall'], cwd=args.build_dir, + shell=(os.name == 'nt')) + + +def main(): + localdir = absexpanduser('~/.local') + + description = "An installation helper script. " +\ + "For more information, please see fuelcycle.org." + parser = ap.ArgumentParser(description=description) + + build_dir = 'where to place the build directory' + parser.add_argument('--build_dir', help=build_dir, default='build') + + uninst = 'uninstall' + parser.add_argument('--uninstall', action='store_true', help=uninst, default=False) + + clean = 'attempt to remove the build directory before building' + parser.add_argument('--clean-build', action='store_true', help=clean) + + threads = "the number of threads to use in the make step" + parser.add_argument('-j', '--threads', type=int, help=threads) + + prefix = "the relative path to the installation directory" + parser.add_argument('--prefix', help=prefix, default=localdir) + + build_only = 'only build the package, do not install' + parser.add_argument('--build-only', action='store_true', help=build_only) + + test = 'run tests after building' + parser.add_argument('--test', action='store_true', help=test) + + coin = "the relative path to the Coin-OR libraries directory" + parser.add_argument('--coin_root', help=coin) + + cyclus = "the relative path to Cyclus installation directory" + parser.add_argument('--cyclus_root',help=cyclus, default=localdir) + + boost = "the relative path to the Boost libraries directory" + parser.add_argument('--boost_root', help=boost) + + cmake_prefix_path = "the cmake prefix path for use with FIND_PACKAGE, " + \ + "FIND_PATH, FIND_PROGRAM, or FIND_LIBRARY macros" + parser.add_argument('--cmake_prefix_path', help=cmake_prefix_path) + + build_type = "the CMAKE_BUILD_TYPE" + parser.add_argument('--build_type', help=build_type) + + args = parser.parse_args() + if args.uninstall: + uninstall(args) + else: + install(args) + +if __name__ == "__main__": + main() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..0f0cf78 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,7 @@ +### DO NOT DELETE THIS COMMENT: INSERT_ARCHETYPES_HERE ### +USE_CYCLUS("tricycle" "reactor") + +INSTALL_CYCLUS_MODULE("tricycle" "") + +# install header files +FILE(GLOB h_files "${CMAKE_CURRENT_SOURCE_DIR}/*.h") diff --git a/src/reactor.cc b/src/reactor.cc new file mode 100644 index 0000000..4ad680d --- /dev/null +++ b/src/reactor.cc @@ -0,0 +1,276 @@ +#include "reactor.h" + +namespace tricycle { + +//-----------------------------------------------------------// +// Constructor // +//-----------------------------------------------------------// +Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) {} + +std::string Reactor::str() { + return Facility::str(); +} + +//-----------------------------------------------------------// +// Tick and Tock // +//-----------------------------------------------------------// +void Reactor::Tick() { + std::cout << "Timestep: " << context()->time() <comp()->atom(); + cyclus::compmath::Normalize(&c, 1); + for(std::map::const_iterator it = c.begin();it != c.end(); ++it){ + std::cout << it->first << " " << it->second << "\n"; + } + +} + +//-----------------------------------------------------------// +// Fusion Functions // +//-----------------------------------------------------------// + +void Reactor::Startup(){ + cyclus::Material::Ptr initial_reserve = tritium_storage.Pop(); + try{ + cyclus::Material::Ptr initial_core = initial_reserve->ExtractQty(startup_inventory); + tritium_core.Push(initial_core); + tritium_storage.Push(initial_reserve); + } + catch (const std::exception& e) { + std::cerr << "Exception caught: " << e.what() << std::endl; + tritium_storage.Push(initial_reserve); + throw e; + } +} + +void Reactor::DecayInventory(cyclus::toolkit::ResBuf &inventory){ + if(!inventory.empty()){ + cyclus::Material::Ptr mat = inventory.Pop(); + mat->Decay(context()->time()); + inventory.Push(mat); + } + else{ + std::cout<<"Resource Buffer is Empty!"< &inventory){ + cyclus::Material::Ptr base = inventory.Pop(); + int count = inventory.count(); + for(int i=0; iAbsorb(m); + } + + inventory.Push(base); +} + +void Reactor::ExtractHelium(cyclus::Material::Ptr mat){ + cyclus::CompMap c = mat->comp()->atom(); + cyclus::compmath::Normalize(&c,mat->quantity()); + + cyclus::CompMap He3 = {{20030000, 1}}; + + cyclus::Material::Ptr helium = mat->ExtractComp(c[20030000], cyclus::Composition::CreateFromAtom(He3)); + helium_storage.Push(helium); +} + +void Reactor::Record(std::string status, double power){ + context() + ->NewDatum("ReactorData") + ->AddVal("AgentId", id()) + ->AddVal("Time", context()->time()) + ->AddVal("Status", status) + ->AddVal("Power", power) + ->Record(); +} + +void Reactor::DepleteBlanket(double bred_tritium_mass){ + cyclus::Material::Ptr blanket_mat = blanket.Pop(); + + //normalize the compmap to the correct masses of the constituent parts + cyclus::CompMap b = blanket_mat->comp()->mass(); + cyclus::compmath::Normalize(&b, blanket_mat->quantity()); + + double Li7_contribution = 0; + + + + //Define the new composition of the blanket + cyclus::CompMap depleted_comp = {{30070000, b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass}, \ + {30060000, b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass}, \ + {10030000, b[10030000] + bred_tritium_mass},\ + {20040000, b[20040000] + 4.0/3.0*bred_tritium_mass}}; + + + //Account for the added mass of the absorbed neutrons + double neutron_mass_correction = 1.0/3.0*bred_tritium_mass*(1-Li7_contribution); + cyclus::Material::Ptr additional_mass = cyclus::Material::Create(this, neutron_mass_correction, cyclus::Composition::CreateFromMass(depleted_comp)); + + blanket_mat->Transmute(cyclus::Composition::CreateFromMass(depleted_comp)); + blanket_mat->Absorb(additional_mass); + + + blanket.Push(blanket_mat); +} + +cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR){ + + DepleteBlanket(fuel_usage*TBR); + + + cyclus::Material::Ptr mat = blanket.Pop(); + + cyclus::CompMap c = mat->comp()->mass(); + cyclus::compmath::Normalize(&c,mat->quantity()); + + cyclus::CompMap T = {{10030000, 1}}; + + cyclus::Material::Ptr bred_fuel = mat->ExtractComp(c[10030000], cyclus::Composition::CreateFromAtom(T)); + blanket.Push(mat); + + return bred_fuel; + + +} + +void Reactor::OperateReactor(double TBR, double burn_rate){ + int seconds_per_year = 31536000; + double fuel_usage = burn_rate * (fusion_power / 1000) / seconds_per_year * context()->dt(); + + //If more fuel is bred than burned, add the difference to storage + if(TBR >= 1){ + //Pull all the fuel out so we can work with it: + cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); + cyclus::Material::Ptr core_fuel = tritium_core.Pop(); + + //This will break if fuel_usage > core_fuel, which may not be what we want... Fix Later? + + //Burn the appropriate amount of fuel then replenish it with the bread fuel + cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); + core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); + storage_fuel->Absorb(core_fuel); + + ExtractHelium(storage_fuel); + + cyclus::Material::Ptr homoginized_core_fuel = storage_fuel->ExtractQty(startup_inventory); + + //Add all the fuel back to the core/storage + tritium_core.Push(homoginized_core_fuel); + tritium_storage.Push(storage_fuel); + + Reactor::Record("Online", fusion_power); + + } + //If more fuel is burned than bred, remove the difference from the core, and + //then replenish the core from storage + else{ + //Calculate how much fuel we need to remove + //double fuel_qty_to_remove = fuel_usage - bred_fuel_qty; + + //Pull all the fuel out + cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); + cyclus::Material::Ptr core_fuel = tritium_core.Pop(); + + //Burn the appropriate amount of fuel then replenish it with the bread fuel + cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); + core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); + + //Extract Helium: + ExtractHelium(storage_fuel); + ExtractHelium(core_fuel); + + //test that there's at least enough tritium in the system to start-up the reactor + if(((storage_fuel->quantity() + core_fuel->quantity()) > startup_inventory)){ + //cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_qty_to_remove); + double core_deficit = startup_inventory - core_fuel->quantity(); + + cyclus::Material::Ptr fuel_to_core; + + if(storage_fuel->quantity() >= core_deficit){ + fuel_to_core = storage_fuel->ExtractQty(core_deficit); + } + else{ + fuel_to_core = storage_fuel->ExtractQty(storage_fuel->quantity()); + } + //Take the difference out of storage and put it into the core + core_fuel->Absorb(fuel_to_core); + + //Put the fuel back + tritium_core.Push(core_fuel); + tritium_storage.Push(storage_fuel); + + Reactor::Record("Online", fusion_power); + } + else{ + //We don't have enough fuel to replenish the core, so we shutdown + + storage_fuel->Absorb(core_fuel); + tritium_storage.Push(storage_fuel); + fuel_schedule_policy.Stop(); + fuel_startup_policy.Start(); + operational = false; + Reactor::Record("Shut-down", 0); + } + } + +} + +// 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. +extern "C" cyclus::Agent* ConstructReactor(cyclus::Context* ctx) { + return new Reactor(ctx); +} + +} // namespace tricycle diff --git a/src/reactor.h b/src/reactor.h new file mode 100644 index 0000000..094d2c9 --- /dev/null +++ b/src/reactor.h @@ -0,0 +1,215 @@ +#ifndef CYCLUS_TRICYCLE_REACTOR_H_ +#define CYCLUS_TRICYCLE_REACTOR_H_ + +#include + +#include "cyclus.h" + +namespace tricycle { + +/// @class Reactor +/// +/// This Facility is intended +/// as a skeleton to guide the implementation of new Facility +/// agents. +/// The Reactor class inherits from the Facility class and is +/// dynamically loaded by the Agent class when requested. +/// +/// @section intro Introduction +/// Place an introduction to the agent here. +/// +/// @section agentparams Agent Parameters +/// Place a description of the required input parameters which define the +/// agent implementation. +/// +/// @section optionalparams Optional Parameters +/// Place a description of the optional input parameters to define the +/// agent implementation. +/// +/// @section detailed Detailed Behavior +/// Place a description of the detailed behavior of the agent. Consider +/// describing the behavior at the tick and tock as well as the behavior +/// upon sending and receiving materials and messages. +class Reactor : public cyclus::Facility { + public: + /// Constructor for Reactor Class + /// @param ctx the cyclus context for access to simulation-wide parameters + explicit Reactor(cyclus::Context* ctx); + + /// The Prime Directive + /// Generates code that handles all input file reading and restart operations + /// (e.g., reading from the database, instantiating a new object, etc.). + /// @warning The Prime Directive must have a space before it! (A fix will be + /// in 2.0 ^TM) + + #pragma cyclus + + #pragma cyclus note {"doc": "A stub facility is provided as a skeleton " \ + "for the design of new facility agents."} + + /// A verbose printer for the Reactor + virtual std::string str(); + + /// Set up policies and buffers: + virtual void EnterNotify(); + + /// The handleTick function specific to the Reactor. + /// @param time the time of the tick + virtual void Tick(); + + /// The handleTick function specific to the Reactor. + /// @param time the time of the tock + virtual void Tock(); + + +//-----------------------------------------------------------// +// State Variables // +//-----------------------------------------------------------// + + #pragma cyclus var { \ + "doc": "Nameplate fusion power of the reactor", \ + "tooltip": "Nameplate fusion power", \ + "units": "MW", \ + "uilabel": "Fusion Power" \ + } + double fusion_power; + + #pragma cyclus var { \ + "doc": "Achievable system tritium breeding ratio before decay", \ + "tooltip": "Achievable system tritium breeding ratio before decay", \ + "units": "non-dimensional", \ + "uilabel": "Tritium Breeding Ratio" \ + } + double TBR; + + #pragma cyclus var { \ + "doc": "Minimum tritium inventory to hold in reserve in case of tritium recovery system failure", \ + "tooltip": "Minimum tritium inventory to hold in reserve (excluding core invneotry)", \ + "units": "kg", \ + "uilabel": "Reserve Inventory" \ + } + double reserve_inventory; + + #pragma cyclus var { \ + "doc": "Tritium core inventory required to start reactor", \ + "tooltip": "Tritium core inventory required to start reactor", \ + "units": "kg", \ + "uilabel": "Start-up Inventory" \ + } + double startup_inventory; + + + #pragma cyclus var { \ + "doc": "Quantity of fuel which reactor tries to purchase", \ + "tooltip": "Defaults to fill reserve inventory", \ + "units": "kg", \ + "uilabel": "Buy quantity" \ + } + double buy_quantity; + + #pragma cyclus var { \ + "doc": "Fresh fuel commodity", \ + "tooltip": "Name of fuel commodity requested", \ + "uilabel": "Fuel input commodity" \ + } + std::string fuel_incommod; + +/* !Marked for deletion! + #pragma cyclus var { \ + "doc": "Fresh fuel recipe", \ + "tooltip": "Fresh fuel recipe", \ + "uilabel": "Fuel Input Recipe" \ + } + std::string fuel_inrecipe; +*/ + #pragma cyclus var { \ + "default": 100.0, \ + "doc": "Initial mass of full blanket material", \ + "tooltip": "Only blanket material mass, not structural mass", \ + "uilabel": "Initial Mass of Blanket" \ + } + double blanket_size; + + #pragma cyclus var { \ + "doc": "Fresh fuel commodity", \ + "tooltip": "Name of fuel commodity requested", \ + "uilabel": "Fuel input commodity" \ + } + std::string blanket_incommod; + + #pragma cyclus var { \ + "doc": "Fresh fuel commodity", \ + "tooltip": "Name of fuel commodity requested", \ + "uilabel": "Fuel input commodity" \ + } + std::string blanket_inrecipe; +/* + + #pragma cyclus var { \ + "doc": "Fresh Fuel recipe", \ + "tooltip": "Fresh fuel recipe", \ + "uilabel": "Fuel Input Recipe" \ + } + std::string blanket_inrecipe; +*/ + + bool operational = false; +//-----------------------------------------------------------// +// Materail Buffers // +//-----------------------------------------------------------// + +/*These must be defined after member variables for some reason?*/ + + //Tritium stored in the core of the reactor + #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + cyclus::toolkit::ResBuf tritium_core; + + //Tritium stored in the reserve system of the reactor + #pragma cyclus var {"capacity" : "1000"} + cyclus::toolkit::ResBuf tritium_storage; + + //helium-3 extracted from decayed tritium and stored by the reactor + #pragma cyclus var {"capacity" : "1000"} + cyclus::toolkit::ResBuf helium_storage; + + //blanket material + #pragma cyclus var {"capacity" : "1000"} + cyclus::toolkit::ResBuf blanket; + +//-----------------------------------------------------------// +// Buy and Sell Policies // +//-----------------------------------------------------------// + cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; + cyclus::toolkit::MatlBuyPolicy fuel_schedule_policy; + cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; + cyclus::toolkit::MatlBuyPolicy blanket_startup_policy; + + + cyclus::toolkit::MatlSellPolicy sell_policy; + +//-----------------------------------------------------------// +// Fusion Functions // +//-----------------------------------------------------------// + + void Startup(); + void OperateReactor(double TBR, double burn_rate=55.8); + void DecayInventory(cyclus::toolkit::ResBuf &inventory); + void CombineInventory(cyclus::toolkit::ResBuf &inventory); + void ExtractHelium(cyclus::Material::Ptr material); + void Record(std::string Status, double power); + void DepleteBlanket(double bred_tritium_mass); + cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); + + + +//-----------------------------------------------------------// +// Test Functions // +//-----------------------------------------------------------// + void PrintComp(cyclus::Material::Ptr mat); + + // And away we go! +}; + +} // namespace tricycle + +#endif // CYCLUS_TRICYCLE_REACTOR_H_ diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc new file mode 100644 index 0000000..8fd21e0 --- /dev/null +++ b/src/reactor_tests.cc @@ -0,0 +1,68 @@ +#include + +#include "reactor.h" + +#include "agent_tests.h" +#include "context.h" +#include "facility_tests.h" +#include "pyhooks.h" + +using tricycle::Reactor; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class ReactorTest : public ::testing::Test { + protected: + cyclus::TestContext tc; + Reactor* facility; + + virtual void SetUp() { + cyclus::PyStart(); + facility = new Reactor(tc.get()); + } + + virtual void TearDown() { + delete facility; + cyclus::PyStop(); + } +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, InitialState) { + // Test things about the initial state of the facility here +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, Print) { + EXPECT_NO_THROW(std::string s = facility->str()); + // Test Reactor specific aspects of the print method here +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, Tick) { + ASSERT_NO_THROW(facility->Tick()); + // Test Reactor specific behaviors of the Tick function here +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, Tock) { + EXPECT_NO_THROW(facility->Tock()); + // Test Reactor specific behaviors of the Tock function here +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Do Not Touch! Below section required for connection with Cyclus +cyclus::Agent* ReactorConstructor(cyclus::Context* ctx) { + return new Reactor(ctx); +} +// Required to get functionality in cyclus agent unit tests library +#ifndef CYCLUS_AGENT_TESTS_CONNECTED +int ConnectAgentTests(); +static int cyclus_agent_tests_connected = ConnectAgentTests(); +#define CYCLUS_AGENT_TESTS_CONNECTED cyclus_agent_tests_connected +#endif // CYCLUS_AGENT_TESTS_CONNECTED +INSTANTIATE_TEST_CASE_P(Reactor, FacilityTests, + ::testing::Values(&ReactorConstructor)); +INSTANTIATE_TEST_CASE_P(Reactor, AgentTests, + ::testing::Values(&ReactorConstructor)); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 64fc99ed748f24a6fb71c3addc306098fed4ffa7 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Tue, 30 Jan 2024 15:03:14 -0600 Subject: [PATCH 02/43] Fixed Lithium over extraction crashing code, simplified OperateReactor --- src/reactor.cc | 269 ++++++++++++++++++++++++------------------------- src/reactor.h | 74 ++++++++++---- 2 files changed, 182 insertions(+), 161 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 4ad680d..0bcbdd3 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -1,26 +1,57 @@ #include "reactor.h" +#include "boost/shared_ptr.hpp" namespace tricycle { -//-----------------------------------------------------------// -// Constructor // -//-----------------------------------------------------------// Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) {} std::string Reactor::str() { return Facility::str(); } -//-----------------------------------------------------------// -// Tick and Tock // -//-----------------------------------------------------------// void Reactor::Tick() { std::cout << "Timestep: " << context()->time() <Absorb(reserve_fuel->ExtractQty(core_deficit)); + cyclus::Material::Ptr excess_tritium = reserve_fuel->ExtractQty(surplus); + + tritium_reserve.Push(reserve_fuel); + tritium_core.Push(core_fuel); + tritium_storage.Push(excess_tritium); + CombineInventory(tritium_storage); + } + + //0.85 is arbitrary, but corresponds to 3 missed purchases at default value for turnover + if(!blanket.empty() && blanket.quantity() > 0.85*blanket_size){ + std::cout<<"Hello"<ExtractQty(blanket_size*blanket_turnover_rate); + blanket.Push(blanket_mat); + } } void Reactor::Tock() { @@ -29,7 +60,7 @@ void Reactor::Tock() { Startup(); fuel_startup_policy.Stop(); blanket_startup_policy.Stop(); - fuel_schedule_policy.Start(); + fuel_refill_policy.Start(); operational = true; } catch (const std::exception& e) { @@ -37,58 +68,61 @@ void Reactor::Tock() { } } - CombineInventory(tritium_storage); + CombineInventory(tritium_reserve); + CombineInventory(blanket); std::cout << "Tritium in Core: " << tritium_core.quantity() << std::endl; + std::cout << "Tritium in Reserve: " << tritium_reserve.quantity() << std::endl; std::cout << "Tritium in Storage: " << tritium_storage.quantity() << std::endl; std::cout << "Lithium in Storage: " << blanket.quantity() < quantity_dist = boost::shared_ptr(new cyclus::random_number_generator::FixedDoubleDist(buy_quantity)); + //boost::shared_ptr active_dist = boost::shared_ptr(new cyclus::FixedIntDist(1)); + //boost::shared_ptr dormant_dist = boost::shared_ptr(new cyclus::FixedIntDist(buy_frequency-1)); + //boost::shared_ptr size_dist = boost::shared_ptr(new cyclus::FixedIntDist(1)); + //fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), quantity_dist, active_dist, dormant_dist, size_dist).Set(fuel_incommod); + } + else if(refuel_mode == "fill"){ + fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), reserve_inventory, reserve_inventory).Set(fuel_incommod); + } + else{ + throw cyclus::KeyError("Refill mode " + refuel_mode + " not recognized! Try 'schedule' or 'fill'."); + } + + tritium_sell_policy.Init(this, &tritium_storage, std::string("Excess Tritium")).Set(fuel_incommod).Start(); + helium_sell_policy.Init(this, &helium_storage, std::string("Helium-3")).Set(he3_outcommod).Start(); } -//---------------------------------------------------------------------------// -// Test Functions // -//---------------------------------------------------------------------------// void Reactor::PrintComp(cyclus::Material::Ptr mat){ cyclus::CompMap c = mat->comp()->atom(); cyclus::compmath::Normalize(&c, 1); for(std::map::const_iterator it = c.begin();it != c.end(); ++it){ std::cout << it->first << " " << it->second << "\n"; } - } -//-----------------------------------------------------------// -// Fusion Functions // -//-----------------------------------------------------------// - void Reactor::Startup(){ - cyclus::Material::Ptr initial_reserve = tritium_storage.Pop(); + cyclus::Material::Ptr initial_reserve = tritium_reserve.Pop(); try{ cyclus::Material::Ptr initial_core = initial_reserve->ExtractQty(startup_inventory); tritium_core.Push(initial_core); - tritium_storage.Push(initial_reserve); + tritium_reserve.Push(initial_reserve); } catch (const std::exception& e) { std::cerr << "Exception caught: " << e.what() << std::endl; - tritium_storage.Push(initial_reserve); + tritium_reserve.Push(initial_reserve); throw e; } } @@ -99,30 +133,33 @@ void Reactor::DecayInventory(cyclus::toolkit::ResBuf &inventor mat->Decay(context()->time()); inventory.Push(mat); } - else{ - std::cout<<"Resource Buffer is Empty!"< &inventory){ - cyclus::Material::Ptr base = inventory.Pop(); - int count = inventory.count(); - for(int i=0; iAbsorb(m); - } + if(!inventory.empty()){ + cyclus::Material::Ptr base = inventory.Pop(); + int count = inventory.count(); + for(int i=0; iAbsorb(m); + } - inventory.Push(base); + inventory.Push(base); + } } -void Reactor::ExtractHelium(cyclus::Material::Ptr mat){ - cyclus::CompMap c = mat->comp()->atom(); - cyclus::compmath::Normalize(&c,mat->quantity()); +void Reactor::ExtractHelium(cyclus::toolkit::ResBuf &inventory){ + if(!inventory.empty()){ + cyclus::Material::Ptr mat = inventory.Pop(); + cyclus::CompMap c = mat->comp()->atom(); + cyclus::compmath::Normalize(&c,mat->quantity()); - cyclus::CompMap He3 = {{20030000, 1}}; - - cyclus::Material::Ptr helium = mat->ExtractComp(c[20030000], cyclus::Composition::CreateFromAtom(He3)); - helium_storage.Push(helium); + cyclus::CompMap He3 = {{20030000, 1}}; + + cyclus::Material::Ptr helium = mat->ExtractComp(c[20030000], cyclus::Composition::CreateFromAtom(He3)); + helium_storage.Push(helium); + inventory.Push(mat); + } } void Reactor::Record(std::string status, double power){ @@ -138,131 +175,83 @@ void Reactor::Record(std::string status, double power){ void Reactor::DepleteBlanket(double bred_tritium_mass){ cyclus::Material::Ptr blanket_mat = blanket.Pop(); - //normalize the compmap to the correct masses of the constituent parts cyclus::CompMap b = blanket_mat->comp()->mass(); cyclus::compmath::Normalize(&b, blanket_mat->quantity()); - double Li7_contribution = 0; + //Percent (as decimal) of T which comes from Li-7 instead of Li-6 + double Li7_contribution = 0.15; + cyclus::CompMap depleted_comp; + //This is ALMOST the correct behavior... Fix later? + if((b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass > 0) && (b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass > 0)){ + depleted_comp = {{30070000, b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass}, \ + {30060000, b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass}, \ + {10030000, b[10030000] + bred_tritium_mass},\ + {20040000, b[20040000] + 4.0/3.0*bred_tritium_mass}}; + + //Account for the added mass of the absorbed neutrons + double neutron_mass_correction = 1.0/3.0*bred_tritium_mass*(1-Li7_contribution); + cyclus::Material::Ptr additional_mass = cyclus::Material::Create(this, neutron_mass_correction, cyclus::Composition::CreateFromMass(depleted_comp)); - //Define the new composition of the blanket - cyclus::CompMap depleted_comp = {{30070000, b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass}, \ - {30060000, b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass}, \ - {10030000, b[10030000] + bred_tritium_mass},\ - {20040000, b[20040000] + 4.0/3.0*bred_tritium_mass}}; - - - //Account for the added mass of the absorbed neutrons - double neutron_mass_correction = 1.0/3.0*bred_tritium_mass*(1-Li7_contribution); - cyclus::Material::Ptr additional_mass = cyclus::Material::Create(this, neutron_mass_correction, cyclus::Composition::CreateFromMass(depleted_comp)); - - blanket_mat->Transmute(cyclus::Composition::CreateFromMass(depleted_comp)); - blanket_mat->Absorb(additional_mass); - - + blanket_mat->Transmute(cyclus::Composition::CreateFromMass(depleted_comp)); + blanket_mat->Absorb(additional_mass); + } + /*else{ + depleted_comp --> pull out any available T. Not sure how I want to do this yet. + }*/ + blanket.Push(blanket_mat); } cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR){ - DepleteBlanket(fuel_usage*TBR); - - cyclus::Material::Ptr mat = blanket.Pop(); cyclus::CompMap c = mat->comp()->mass(); cyclus::compmath::Normalize(&c,mat->quantity()); cyclus::CompMap T = {{10030000, 1}}; - + cyclus::Material::Ptr bred_fuel = mat->ExtractComp(c[10030000], cyclus::Composition::CreateFromAtom(T)); blanket.Push(mat); return bred_fuel; - - } void Reactor::OperateReactor(double TBR, double burn_rate){ int seconds_per_year = 31536000; double fuel_usage = burn_rate * (fusion_power / 1000) / seconds_per_year * context()->dt(); - - //If more fuel is bred than burned, add the difference to storage - if(TBR >= 1){ - //Pull all the fuel out so we can work with it: - cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); - cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - - //This will break if fuel_usage > core_fuel, which may not be what we want... Fix Later? - - //Burn the appropriate amount of fuel then replenish it with the bread fuel - cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); - core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); - storage_fuel->Absorb(core_fuel); - ExtractHelium(storage_fuel); + cyclus::Material::Ptr storage_fuel = tritium_reserve.Pop(); + cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - cyclus::Material::Ptr homoginized_core_fuel = storage_fuel->ExtractQty(startup_inventory); + cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); + core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); - //Add all the fuel back to the core/storage - tritium_core.Push(homoginized_core_fuel); - tritium_storage.Push(storage_fuel); - Reactor::Record("Online", fusion_power); - - } - //If more fuel is burned than bred, remove the difference from the core, and - //then replenish the core from storage - else{ - //Calculate how much fuel we need to remove - //double fuel_qty_to_remove = fuel_usage - bred_fuel_qty; - - //Pull all the fuel out - cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); - cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - - //Burn the appropriate amount of fuel then replenish it with the bread fuel - cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); - core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); - - //Extract Helium: - ExtractHelium(storage_fuel); - ExtractHelium(core_fuel); - - //test that there's at least enough tritium in the system to start-up the reactor - if(((storage_fuel->quantity() + core_fuel->quantity()) > startup_inventory)){ - //cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_qty_to_remove); - double core_deficit = startup_inventory - core_fuel->quantity(); - - cyclus::Material::Ptr fuel_to_core; - - if(storage_fuel->quantity() >= core_deficit){ - fuel_to_core = storage_fuel->ExtractQty(core_deficit); - } - else{ - fuel_to_core = storage_fuel->ExtractQty(storage_fuel->quantity()); - } - //Take the difference out of storage and put it into the core - core_fuel->Absorb(fuel_to_core); - - //Put the fuel back - tritium_core.Push(core_fuel); - tritium_storage.Push(storage_fuel); + if(((storage_fuel->quantity() + core_fuel->quantity()) > startup_inventory)){ + storage_fuel->Absorb(core_fuel); - Reactor::Record("Online", fusion_power); + if(storage_fuel->quantity() >= startup_inventory){ + tritium_core.Push(storage_fuel->ExtractQty(startup_inventory)); } else{ - //We don't have enough fuel to replenish the core, so we shutdown - - storage_fuel->Absorb(core_fuel); - tritium_storage.Push(storage_fuel); - fuel_schedule_policy.Stop(); - fuel_startup_policy.Start(); - operational = false; - Reactor::Record("Shut-down", 0); + tritium_core.Push(storage_fuel->ExtractQty(storage_fuel->quantity())); } + + tritium_reserve.Push(storage_fuel); + + } + else{ + storage_fuel->Absorb(core_fuel); + tritium_reserve.Push(storage_fuel); + fuel_refill_policy.Stop(); + blanket_refill_policy.Stop(); + fuel_startup_policy.Start(); + operational = false; } + //} } diff --git a/src/reactor.h b/src/reactor.h index 094d2c9..fd61514 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -4,6 +4,7 @@ #include #include "cyclus.h" +#include "boost/shared_ptr.hpp" namespace tricycle { @@ -98,15 +99,32 @@ class Reactor : public cyclus::Facility { } double startup_inventory; + #pragma cyclus var { \ + "default": 'fill', \ + "doc": "Method of refueling the reactor", \ + "tooltip": "Options: 'schedule' or 'fill'", \ + "uilabel": "Refuel Mode" \ + } + std::string refuel_mode; #pragma cyclus var { \ + "default": 0.1, \ "doc": "Quantity of fuel which reactor tries to purchase", \ - "tooltip": "Defaults to fill reserve inventory", \ + "tooltip": "Defaults to 100g/purchase", \ "units": "kg", \ "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", \ + "uilabel": "Buy frequency" \ + } + double buy_frequency; + #pragma cyclus var { \ "doc": "Fresh fuel commodity", \ "tooltip": "Name of fuel commodity requested", \ @@ -114,16 +132,15 @@ class Reactor : public cyclus::Facility { } std::string fuel_incommod; -/* !Marked for deletion! #pragma cyclus var { \ - "doc": "Fresh fuel recipe", \ - "tooltip": "Fresh fuel recipe", \ - "uilabel": "Fuel Input Recipe" \ + "doc": "Fresh fuel commodity", \ + "tooltip": "Name of fuel commodity requested", \ + "uilabel": "Fuel input commodity" \ } - std::string fuel_inrecipe; -*/ + std::string he3_outcommod; + #pragma cyclus var { \ - "default": 100.0, \ + "default": 1000.0, \ "doc": "Initial mass of full blanket material", \ "tooltip": "Only blanket material mass, not structural mass", \ "uilabel": "Initial Mass of Blanket" \ @@ -143,15 +160,26 @@ class Reactor : public cyclus::Facility { "uilabel": "Fuel input commodity" \ } std::string blanket_inrecipe; -/* - #pragma cyclus var { \ - "doc": "Fresh Fuel recipe", \ - "tooltip": "Fresh fuel recipe", \ - "uilabel": "Fuel Input Recipe" \ + #pragma cyclus var { \ + "default": 0.3, \ + "doc": "Li-6 enrichment requirement percent as a decimal", \ + "tooltip": "Defaults to 30% (0.3)", \ + "units": "%", \ + "uilabel": "Minimum Blanket Enrichment" \ + } + double min_blanket_enrichment; + + + //WARNING: The default on this is completely arbitrary! + #pragma cyclus var { \ + "default": 0.05, \ + "doc": "Percent of blanket that gets recycled every timestep", \ + "tooltip": "Defaults to 5% (0.05)", \ + "units": "%", \ + "uilabel": "Blanket Turnover Rate" \ } - std::string blanket_inrecipe; -*/ + double blanket_turnover_rate; bool operational = false; //-----------------------------------------------------------// @@ -164,7 +192,11 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily cyclus::toolkit::ResBuf tritium_core; - //Tritium stored in the reserve system of the reactor + //Tritium reserve for the reactor: + #pragma cyclus var {"capacity" : "1000"} + cyclus::toolkit::ResBuf tritium_reserve; + + //Excess tritium in the reactor to be sold off: #pragma cyclus var {"capacity" : "1000"} cyclus::toolkit::ResBuf tritium_storage; @@ -173,19 +205,19 @@ class Reactor : public cyclus::Facility { cyclus::toolkit::ResBuf helium_storage; //blanket material - #pragma cyclus var {"capacity" : "1000"} + #pragma cyclus var {"capacity" : "100000"} cyclus::toolkit::ResBuf blanket; //-----------------------------------------------------------// // Buy and Sell Policies // //-----------------------------------------------------------// cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; - cyclus::toolkit::MatlBuyPolicy fuel_schedule_policy; cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; cyclus::toolkit::MatlBuyPolicy blanket_startup_policy; + cyclus::toolkit::MatlBuyPolicy blanket_refill_policy; - - cyclus::toolkit::MatlSellPolicy sell_policy; + cyclus::toolkit::MatlSellPolicy tritium_sell_policy; + cyclus::toolkit::MatlSellPolicy helium_sell_policy; //-----------------------------------------------------------// // Fusion Functions // @@ -195,7 +227,7 @@ class Reactor : public cyclus::Facility { void OperateReactor(double TBR, double burn_rate=55.8); void DecayInventory(cyclus::toolkit::ResBuf &inventory); void CombineInventory(cyclus::toolkit::ResBuf &inventory); - void ExtractHelium(cyclus::Material::Ptr material); + void ExtractHelium(cyclus::toolkit::ResBuf &inventory); void Record(std::string Status, double power); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); From 7a281f1899d9a0b01ee2bc92ca06344b4be4a048 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 11 Feb 2024 12:56:30 -0600 Subject: [PATCH 03/43] Added some unit tests, fixed some bugs --- src/reactor.cc | 107 +++++++-- src/reactor.h | 6 +- src/reactor_tests.cc | 541 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 630 insertions(+), 24 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 0bcbdd3..d9cbd3c 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -10,14 +10,14 @@ std::string Reactor::str() { } void Reactor::Tick() { - std::cout << "Timestep: " << context()->time() <time() < 0.85*blanket_size){ - std::cout<<"Hello"<ExtractQty(blanket_size*blanket_turnover_rate); blanket.Push(blanket_mat); @@ -64,27 +63,44 @@ void Reactor::Tock() { operational = true; } catch (const std::exception& e) { - std::cerr << "Exception caught: " << e.what() << std::endl; + RecordEvent("Startup Error", e.what()); + LOG(cyclus::LEV_INFO2, "Reactor") << e.what(); } } CombineInventory(tritium_reserve); CombineInventory(blanket); - std::cout << "Tritium in Core: " << tritium_core.quantity() << std::endl; - std::cout << "Tritium in Reserve: " << tritium_reserve.quantity() << std::endl; - std::cout << "Tritium in Storage: " << tritium_storage.quantity() << std::endl; - std::cout << "Lithium in Storage: " << blanket.quantity() <comp()->atom(); cyclus::compmath::Normalize(&c, 1); for(std::map::const_iterator it = c.begin();it != c.end(); ++it){ - std::cout << it->first << " " << it->second << "\n"; + comp = comp + std::string("{") + std::to_string(it->first) + std::string(",") + std::to_string(it->second) + std::string("},"); } + comp.pop_back(); + comp = comp + std::string("}"); + return comp; } void Reactor::Startup(){ + double reserve_qty = tritium_reserve.quantity(); cyclus::Material::Ptr initial_reserve = tritium_reserve.Pop(); - try{ + cyclus::CompMap c = initial_reserve->comp()->atom(); + cyclus::compmath::Normalize(&c, 1); + + if((reserve_qty >= (startup_inventory + reserve_inventory)) && (c[10030000] == 1)){ cyclus::Material::Ptr initial_core = initial_reserve->ExtractQty(startup_inventory); tritium_core.Push(initial_core); tritium_reserve.Push(initial_reserve); + RecordEvent("Startup", "Core Loaded with " + std::to_string(tritium_core.quantity()) + " kg of Tritium."); + } + else if(c[10030000] != 1){ + tritium_reserve.Push(initial_reserve); + throw cyclus::ValueError("Startup Failed: Fuel incommod not as expected. " \ + + std::string("Expected Composition: {{10030000,1}}. ") \ + + std::string("Fuel Incommod Composition: ") \ + + std::string(GetComp(initial_reserve))); } - catch (const std::exception& e) { - std::cerr << "Exception caught: " << e.what() << std::endl; + else{ tritium_reserve.Push(initial_reserve); - throw e; + throw cyclus::ValueError("Startup Failed: " \ + + std::to_string(tritium_reserve.quantity()) \ + + " kg in reserve is less than required " \ + + std::to_string(startup_inventory+reserve_inventory) \ + + " kg to start-up!" ); } } @@ -162,9 +202,19 @@ void Reactor::ExtractHelium(cyclus::toolkit::ResBuf &inventory } } -void Reactor::Record(std::string status, double power){ +void Reactor::RecordEvent(std::string name, std::string val) { + context() + ->NewDatum("ReactorEvents") + ->AddVal("AgentId", id()) + ->AddVal("Time", context()->time()) + ->AddVal("Event", name) + ->AddVal("Value", val) + ->Record(); +} + +void Reactor::RecordStatus(std::string status, double power){ context() - ->NewDatum("ReactorData") + ->NewDatum("ReactorStatus") ->AddVal("AgentId", id()) ->AddVal("Time", context()->time()) ->AddVal("Status", status) @@ -172,6 +222,19 @@ void Reactor::Record(std::string status, double power){ ->Record(); } +void Reactor::RecordInventories(double core, double reserve, double storage, double blanket, double helium){ + context() + ->NewDatum("ReactorInventories") + ->AddVal("AgentId", id()) + ->AddVal("Time", context()->time()) + ->AddVal("TritiumCore", core) + ->AddVal("TritiumReserve", reserve) + ->AddVal("TritiumStorage", storage) + ->AddVal("LithiumBlanket", blanket) + ->AddVal("HeliumStorage", helium) + ->Record(); +} + void Reactor::DepleteBlanket(double bred_tritium_mass){ cyclus::Material::Ptr blanket_mat = blanket.Pop(); diff --git a/src/reactor.h b/src/reactor.h index fd61514..410396a 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -228,7 +228,9 @@ class Reactor : public cyclus::Facility { void DecayInventory(cyclus::toolkit::ResBuf &inventory); void CombineInventory(cyclus::toolkit::ResBuf &inventory); void ExtractHelium(cyclus::toolkit::ResBuf &inventory); - void Record(std::string Status, double power); + void RecordEvent(std::string name, std::string val); + void RecordStatus(std::string Status, double power); + void RecordInventories(double core, double reserve, double storage, double blanket, double helium); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); @@ -237,7 +239,7 @@ class Reactor : public cyclus::Facility { //-----------------------------------------------------------// // Test Functions // //-----------------------------------------------------------// - void PrintComp(cyclus::Material::Ptr mat); + std::string GetComp(cyclus::Material::Ptr mat); // And away we go! }; diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 8fd21e0..5e2f7c3 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -7,8 +7,38 @@ #include "facility_tests.h" #include "pyhooks.h" + + using tricycle::Reactor; +using cyclus::QueryResult; +using cyclus::Cond; +using cyclus::CompMap; +using cyclus::toolkit::MatQuery; +using pyne::nucname::id; +using cyclus::Material; + +Composition::Ptr tritium() { + cyclus::CompMap m; + m[10030000] = 1.0; + return Composition::CreateFromAtom(m); +}; + +Composition::Ptr decayed_tritium() { + cyclus::CompMap m; + m[10030000] = 0.9; + m[20030000] = 0.1; + return Composition::CreateFromAtom(m); +}; + +Composition::Ptr enriched_lithium() { + cyclus::CompMap m; + m[30060000] = 0.3; + m[30070000] = 0.7; + return Composition::CreateFromAtom(m); +}; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class ReactorTest : public ::testing::Test { protected: @@ -46,9 +76,520 @@ TEST_F(ReactorTest, Tick) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, Tock) { EXPECT_NO_THROW(facility->Tock()); + // Test Reactor specific behaviors of the Tock function here } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, NormalStartup) { + // Test normal startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 1; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + + sim.AddSource("Tritium") + .recipe("tritium") + .Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + //under these conditions, we expect the reactor to be able to startup on timestep 0 + std::vector conds; + conds.push_back(Cond("Time", "==", std::string("0"))); + QueryResult qr = sim.db().Query("ReactorEvents", &conds); + std::string event = qr.GetVal("Event"); + + EXPECT_EQ("Startup", event); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, FuelConstrainedStartup) { + // Test normal startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + + sim.AddSource("Tritium") + .recipe("tritium") + .capacity(8.0) + .Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + //Under these conditions, we expect the reactor to be able to startup on timestep 1 + //but not before then (buys 8kg of T on each timestep, and needs 8.121kg to startup). + //NOTE: startup occurs after DRE. + std::vector conds0; + conds0.push_back(Cond("Time", "==", std::string("0"))); + QueryResult qr0 = sim.db().Query("ReactorEvents", &conds0); + std::string event0 = qr0.GetVal("Event"); + + EXPECT_EQ("Startup Error", event0); + + + std::vector conds1; + conds1.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr1 = sim.db().Query("ReactorEvents", &conds1); + std::string event1 = qr1.GetVal("Event"); + + EXPECT_EQ("Startup", event1); + + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, NoFuelStartup) { + // Test normal startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + //Under these conditions, we expect the reactor to never start, and to record + //that it failed to start every timestep. + std::vector conds; + conds.push_back(Cond("Event", "==", std::string("Startup Error"))); + QueryResult qr = sim.db().Query("ReactorEvents", &conds); + double qr_rows = qr.rows.size(); + + EXPECT_EQ(10, qr_rows); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, WrongFuelStartup) { + // Test normal startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Enriched_Lithium" + " Enriched_Lithium" + " Lithium" + " 1000" + " Helium_3"; + + int simdur = 3; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + //Under these conditions, we expect the reactor to never start, and to record + //that it failed to start every timestep. + std::vector conds; + conds.push_back(Cond("Event", "==", std::string("Startup Error"))); + QueryResult qr = sim.db().Query("ReactorEvents", &conds); + double qr_rows = qr.rows.size(); + + EXPECT_EQ(3, qr_rows); + + //We also expect that it will record a specific message to show that the fuel + //input commodity is wrong: + + std::vector conds2; + conds2.push_back(Cond("Event", "==", std::string("Startup Error"))); + QueryResult qr2 = sim.db().Query("ReactorEvents", &conds2); + std::string value = qr2.GetVal("Value"); + + std::string expected_message = "Startup Failed: Fuel incommod not as expected. " + "Expected Composition: {{10030000,1}}. Fuel Incommod " + "Composition: {{30060000,0.300000},{30070000,0.700000}}"; + EXPECT_EQ(value, expected_message); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, DecayInventory) { + // Test behaviors of the DecayInventory function here + EXPECT_NO_THROW(facility->DecayInventory(facility->tritium_core)); + + + //We use unintuitive values for reserve inventory and startup inventory here because + //they were the values we were originally testing with, and we had already done + //all the calculations. + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " Lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + + sim.AddSource("Tritium") + .recipe("tritium") + .Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr = sim.db().Query("ReactorInventories", &conds); + double he3 = qr.GetVal("HeliumStorage"); + + + //calculator only gave me 7 decimals, otherwise this should probably + //be 1e-10. + EXPECT_NEAR(0.0379868, he3, 1e-7); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, GetComp) { + // Test behaviors of the GetComp function here + + cyclus::Material::Ptr Li = cyclus::Material::CreateUntracked(1, enriched_lithium()); + cyclus::Material::Ptr T = cyclus::Material::CreateUntracked(1, tritium()); + std::string comp_Li = facility->GetComp(Li); + std::string comp_T = facility->GetComp(T); + + EXPECT_EQ("{{30060000,0.300000},{30070000,0.700000}}", comp_Li); + EXPECT_EQ("{{10030000,1.000000}}", comp_T); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, CombineInventory) { + // Test behaviors of the CombineInventory function here + + + //do I need the pragma here? + //#pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + cyclus::toolkit::ResBuf test_buf; + + cyclus::Material::Ptr T1 = cyclus::Material::CreateUntracked(2.5, tritium()); + cyclus::Material::Ptr T2 = cyclus::Material::CreateUntracked(1, tritium()); + + test_buf.Push(T1); + test_buf.Push(T2); + + EXPECT_EQ(3.5, test_buf.quantity()); + + cyclus::Material::Ptr mat = test_buf.Pop(); + + EXPECT_EQ(2.5, mat->quantity()); + + test_buf.Push(mat); + + facility->CombineInventory(test_buf); + + EXPECT_EQ(3.5, test_buf.quantity()); + + cyclus::Material::Ptr combined_mat = test_buf.Pop(); + + EXPECT_EQ(3.5, combined_mat->quantity()); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, CombineInventoryOneElement) { + // Test behaviors of the CombineInventory function here + + + //do I need the pragma here? + //#pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + cyclus::toolkit::ResBuf test_buf; + + cyclus::Material::Ptr T1 = cyclus::Material::CreateUntracked(2.5, tritium()); + + test_buf.Push(T1); + + EXPECT_NO_THROW(facility->CombineInventory(test_buf)); + + EXPECT_EQ(2.5, test_buf.quantity()); + + cyclus::Material::Ptr combined_mat = test_buf.Pop(); + + EXPECT_EQ(2.5, combined_mat->quantity()); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, CombineEmptyInventory) { + // Test behaviors of the CombineInventory function here + + //do I need the pragma here? + //#pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + cyclus::toolkit::ResBuf test_buf; + + EXPECT_NO_THROW(facility->CombineInventory(test_buf)); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, ExtractHelium) { + // Test behaviors of the ExtractHelium function here + + cyclus::toolkit::ResBuf test_buf; + cyclus::Material::Ptr test_mat = cyclus::Material::CreateUntracked(1.0, decayed_tritium()); + + std::string comp_original = facility->GetComp(test_mat); + + EXPECT_EQ("{{10030000,0.900000},{20030000,0.100000}}", comp_original); + + test_buf.Push(test_mat); + facility->ExtractHelium(test_buf); + cyclus::Material::Ptr extracted_mat = test_buf.Pop(); + + std::string comp_extracted = facility->GetComp(extracted_mat); + EXPECT_EQ("{{10030000,1.000000}}", comp_extracted); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, ExtractNoHelium) { + // Test behaviors of the ExtractHelium function here + + cyclus::toolkit::ResBuf test_buf; + cyclus::Material::Ptr test_mat = cyclus::Material::CreateUntracked(1.0, tritium()); + + std::string comp_original = facility->GetComp(test_mat); + + EXPECT_EQ("{{10030000,1.000000}}", comp_original); + + test_buf.Push(test_mat); + facility->ExtractHelium(test_buf); + cyclus::Material::Ptr extracted_mat = test_buf.Pop(); + + std::string comp_extracted = facility->GetComp(extracted_mat); + EXPECT_EQ("{{10030000,1.000000}}", comp_extracted); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, RecordEvent) { + // Test behaviors of the RecordEvent function here + // This test is identical to Normal Startup... Redundant? + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 1; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + + sim.AddSource("Tritium") + .recipe("tritium") + .Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Time", "==", std::string("0"))); + QueryResult qr = sim.db().Query("ReactorEvents", &conds); + std::string event = qr.GetVal("Event"); + + EXPECT_EQ("Startup", event); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, RecordInventories) { + // Test behaviors of the RecordEvent function here + // This test is identical to Normal Startup... Redundant? + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 1; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + + sim.AddSource("Tritium") + .recipe("tritium") + .Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Time", "==", std::string("0"))); + QueryResult qr = sim.db().Query("ReactorInventories", &conds); + double tritium_core = qr.GetVal("TritiumCore"); + double tritium_reserve = qr.GetVal("TritiumReserve"); + double tritium_storage = qr.GetVal("TritiumStorage"); + double blanket = qr.GetVal("LithiumBlanket"); + double helium_storage = qr.GetVal("HeliumStorage"); + + EXPECT_EQ(2.121, tritium_core); + EXPECT_EQ(6.0, tritium_reserve); + EXPECT_EQ(0.0, tritium_storage); + EXPECT_EQ(1000.0, blanket); + EXPECT_EQ(0.0, helium_storage); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, RecordStatus) { + // Test behaviors of the RecordEvent function here + // This test is identical to Normal Startup... Redundant? + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec + (":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + + sim.AddSource("Tritium") + .recipe("tritium") + .Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .Finalize(); + + int id = sim.Run(); + + std::vector conds0; + conds0.push_back(Cond("Time", "==", std::string("0"))); + QueryResult qr0 = sim.db().Query("ReactorStatus", &conds0); + std::string status0 = qr0.GetVal("Status"); + double power0 = qr0.GetVal("Power"); + + + EXPECT_EQ("Shut-down", status0); + EXPECT_EQ(0.0, power0); + + std::vector conds1; + conds1.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr1 = sim.db().Query("ReactorStatus", &conds1); + std::string status1 = qr1.GetVal("Status"); + double power1 = qr1.GetVal("Power"); + + + EXPECT_EQ("Online", status1); + EXPECT_EQ(300.0, power1); + + +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Do Not Touch! Below section required for connection with Cyclus From 56d94b55f2ddabe4e2f2ff2c298eb411f0cb009f Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 25 Feb 2024 10:44:40 -0600 Subject: [PATCH 04/43] added unit tests and fixed the formatting mistake of last week --- src/reactor.cc | 124 +++--- src/reactor.h | 6 +- src/reactor_tests.cc | 874 +++++++++++++++++++++++++++++++------------ 3 files changed, 725 insertions(+), 279 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index d9cbd3c..9c77220 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -10,11 +10,14 @@ std::string Reactor::str() { } void Reactor::Tick() { - //std::cout << "Timestep: " << context()->time() <Absorb(reserve_fuel->ExtractQty(core_deficit)); - cyclus::Material::Ptr excess_tritium = reserve_fuel->ExtractQty(surplus); - + tritium_storage.Push(reserve_fuel->ExtractQty(surplus)); + + RecordOperationalInfo("Tritium Moved", std::to_string(core_deficit) + "kg of T moved from reserve to core"); + if(surplus>0.0){ + RecordOperationalInfo("Tritium Moved", std::to_string(surplus) + "kg of T moved from reserve to storage"); + } tritium_reserve.Push(reserve_fuel); tritium_core.Push(core_fuel); - tritium_storage.Push(excess_tritium); - CombineInventory(tritium_storage); + + CombineInventory(tritium_storage); } - - //0.85 is arbitrary, but corresponds to 3 missed purchases at default value for turnover - if(!blanket.empty() && blanket.quantity() > 0.85*blanket_size){ + + //This pulls out some of the blanket each timestep so that fresh blanket can be added. + if(!blanket.empty() && blanket.quantity() >= blanket_size*blanket_turnover_rate){ cyclus::Material::Ptr blanket_mat = blanket.Pop(); cyclus::Material::Ptr spent_blanket = blanket_mat->ExtractQty(blanket_size*blanket_turnover_rate); + RecordOperationalInfo("Blanket Cycled", std::to_string(spent_blanket->quantity()) + "kg of blanket removed"); blanket.Push(blanket_mat); + } else if (!blanket.empty() && blanket.quantity() < blanket_size*blanket_turnover_rate) { + RecordOperationalInfo("Blanket Not Cycled", "Total blanket material ("+ std::to_string(blanket.quantity())+") insufficient to extract " + std::to_string(blanket_size*blanket_turnover_rate) + "kg!"); } } void Reactor::Tock() { - if(!operational){ + if(!core_loaded){ try { Startup(); fuel_startup_policy.Stop(); blanket_startup_policy.Stop(); fuel_refill_policy.Start(); - operational = true; + core_loaded = true; } catch (const std::exception& e) { - RecordEvent("Startup Error", e.what()); + RecordOperationalInfo("Startup Error", e.what()); LOG(cyclus::LEV_INFO2, "Reactor") << e.what(); } } @@ -120,6 +133,9 @@ void Reactor::EnterNotify() { } else{ throw cyclus::KeyError("Refill mode " + refuel_mode + " not recognized! Try 'schedule' or 'fill'."); + RecordOperationalInfo("Transaction Error", + "Refill mode " + refuel_mode + + " not recognized! Try 'schedule' or 'fill'."); } tritium_sell_policy.Init(this, &tritium_storage, std::string("Excess Tritium")).Set(fuel_incommod).Start(); @@ -144,16 +160,16 @@ void Reactor::Startup(){ cyclus::CompMap c = initial_reserve->comp()->atom(); cyclus::compmath::Normalize(&c, 1); - if((reserve_qty >= (startup_inventory + reserve_inventory)) && (c[10030000] == 1)){ + if((reserve_qty >= (startup_inventory + reserve_inventory)) && (GetComp(initial_reserve) == "{{10030000,1.000000}}")){ cyclus::Material::Ptr initial_core = initial_reserve->ExtractQty(startup_inventory); tritium_core.Push(initial_core); tritium_reserve.Push(initial_reserve); RecordEvent("Startup", "Core Loaded with " + std::to_string(tritium_core.quantity()) + " kg of Tritium."); } - else if(c[10030000] != 1){ + else if(GetComp(initial_reserve) != "{{10030000,1.000000}}"){ tritium_reserve.Push(initial_reserve); throw cyclus::ValueError("Startup Failed: Fuel incommod not as expected. " \ - + std::string("Expected Composition: {{10030000,1}}. ") \ + + std::string("Expected Composition: {{10030000,1.000000}}. ") \ + std::string("Fuel Incommod Composition: ") \ + std::string(GetComp(initial_reserve))); } @@ -196,7 +212,10 @@ void Reactor::ExtractHelium(cyclus::toolkit::ResBuf &inventory cyclus::CompMap He3 = {{20030000, 1}}; - cyclus::Material::Ptr helium = mat->ExtractComp(c[20030000], cyclus::Composition::CreateFromAtom(He3)); + //A threshold of 1e-5 was set to allow tritium_reserve inventories up to 1000kg + //A 1 decade lower threshold prevents tritium_reserve inventories above 33kg. + cyclus::Material::Ptr helium = mat->ExtractComp(c[20030000], cyclus::Composition::CreateFromAtom(He3), 1e-5); + helium_storage.Push(helium); inventory.Push(mat); } @@ -212,6 +231,16 @@ void Reactor::RecordEvent(std::string name, std::string val) { ->Record(); } +void Reactor::RecordOperationalInfo(std::string name, std::string val) { + context() + ->NewDatum("ReactorOperationsLog") + ->AddVal("AgentId", id()) + ->AddVal("Time", context()->time()) + ->AddVal("Event", name) + ->AddVal("Value", val) + ->Record(); +} + void Reactor::RecordStatus(std::string status, double power){ context() ->NewDatum("ReactorStatus") @@ -246,7 +275,8 @@ void Reactor::DepleteBlanket(double bred_tritium_mass){ cyclus::CompMap depleted_comp; - //This is ALMOST the correct behavior... Fix later? + // This is ALMOST the correct behavior, but "scraping the bottom of the + // barrel" is a little too complex for this implementation. if((b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass > 0) && (b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass > 0)){ depleted_comp = {{30070000, b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass}, \ {30060000, b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass}, \ @@ -259,11 +289,14 @@ void Reactor::DepleteBlanket(double bred_tritium_mass){ blanket_mat->Transmute(cyclus::Composition::CreateFromMass(depleted_comp)); blanket_mat->Absorb(additional_mass); + + RecordOperationalInfo("Blanket Depletion", "Tritium bred at perscribed rate"); + } + else{ + RecordOperationalInfo("Breeding Error", + "Blanket composition lacks sufficient lithium to continue " + "breeding at perscribed rate"); } - /*else{ - depleted_comp --> pull out any available T. Not sure how I want to do this yet. - }*/ - blanket.Push(blanket_mat); } @@ -279,6 +312,9 @@ cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR){ cyclus::Material::Ptr bred_fuel = mat->ExtractComp(c[10030000], cyclus::Composition::CreateFromAtom(T)); blanket.Push(mat); + RecordOperationalInfo("Bred Tritium", std::to_string(bred_fuel->quantity()) + + " kg of T bred from blanket"); + return bred_fuel; } @@ -286,35 +322,35 @@ void Reactor::OperateReactor(double TBR, double burn_rate){ int seconds_per_year = 31536000; double fuel_usage = burn_rate * (fusion_power / 1000) / seconds_per_year * context()->dt(); - cyclus::Material::Ptr storage_fuel = tritium_reserve.Pop(); + cyclus::Material::Ptr reserve_fuel = tritium_reserve.Pop(); cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); - core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); + if(core_fuel->quantity() > fuel_usage){ + cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); + core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); - if(((storage_fuel->quantity() + core_fuel->quantity()) > startup_inventory)){ - storage_fuel->Absorb(core_fuel); + if(((reserve_fuel->quantity() + core_fuel->quantity()) >= startup_inventory)){ + reserve_fuel->Absorb(core_fuel); + tritium_core.Push(reserve_fuel->ExtractQty(startup_inventory)); + tritium_reserve.Push(reserve_fuel); - if(storage_fuel->quantity() >= startup_inventory){ - tritium_core.Push(storage_fuel->ExtractQty(startup_inventory)); } else{ - tritium_core.Push(storage_fuel->ExtractQty(storage_fuel->quantity())); + reserve_fuel->Absorb(core_fuel); + tritium_reserve.Push(reserve_fuel); + fuel_refill_policy.Stop(); + blanket_refill_policy.Stop(); + fuel_startup_policy.Start(); + RecordEvent("Core Shut-down", "Not enough tritium to operate"); + core_loaded = false; } - - tritium_reserve.Push(storage_fuel); - - } - else{ - storage_fuel->Absorb(core_fuel); - tritium_reserve.Push(storage_fuel); - fuel_refill_policy.Stop(); - blanket_refill_policy.Stop(); - fuel_startup_policy.Start(); + } else { operational = false; + RecordOperationalInfo("Operational Error", "core startup_inventory of "+ std::to_string(startup_inventory)+ " kg insufficient to support fuel_usage of " + std::to_string(fuel_usage) + "kg/timestep!"); + tritium_reserve.Push(reserve_fuel); + tritium_core.Push(core_fuel); } - //} } diff --git a/src/reactor.h b/src/reactor.h index 410396a..7af827c 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -175,13 +175,14 @@ class Reactor : public cyclus::Facility { #pragma cyclus var { \ "default": 0.05, \ "doc": "Percent of blanket that gets recycled every timestep", \ - "tooltip": "Defaults to 5% (0.05)", \ + "tooltip": "Defaults to 5% (0.05), must be between 0 and 15%", \ "units": "%", \ "uilabel": "Blanket Turnover Rate" \ } double blanket_turnover_rate; - bool operational = false; + bool operational = true; + bool core_loaded = false; //-----------------------------------------------------------// // Materail Buffers // //-----------------------------------------------------------// @@ -231,6 +232,7 @@ class Reactor : public cyclus::Facility { void RecordEvent(std::string name, std::string val); void RecordStatus(std::string Status, double power); void RecordInventories(double core, double reserve, double storage, double blanket, double helium); + void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 5e2f7c3..315482c 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -1,22 +1,19 @@ #include -#include "reactor.h" - #include "agent_tests.h" #include "context.h" #include "facility_tests.h" #include "pyhooks.h" - - +#include "reactor.h" using tricycle::Reactor; -using cyclus::QueryResult; -using cyclus::Cond; using cyclus::CompMap; +using cyclus::Cond; +using cyclus::Material; +using cyclus::QueryResult; using cyclus::toolkit::MatQuery; using pyne::nucname::id; -using cyclus::Material; Composition::Ptr tritium() { cyclus::CompMap m; @@ -38,7 +35,6 @@ Composition::Ptr enriched_lithium() { return Composition::CreateFromAtom(m); }; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class ReactorTest : public ::testing::Test { protected: @@ -68,202 +64,364 @@ TEST_F(ReactorTest, Print) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(ReactorTest, Tick) { - ASSERT_NO_THROW(facility->Tick()); - // Test Reactor specific behaviors of the Tick function here +TEST_F(ReactorTest, TickCoreNotLoaded) { + // Test Reactor specific behaviors of the Tick function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds; + conds.push_back(Cond("Status", "==", std::string("Shut-down"))); + QueryResult qr = sim.db().Query("ReactorStatus", &conds); + double qr_rows = qr.rows.size(); + + EXPECT_EQ(simdur, qr_rows); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, TickNotOperational) { + // Test Reactor specific behaviors of the Tick function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 0.1" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds; + conds.push_back(Cond("Status", "==", std::string("Shut-down"))); + QueryResult qr = sim.db().Query("ReactorStatus", &conds); + double qr_rows = qr.rows.size(); + + EXPECT_EQ(simdur, qr_rows); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, TickCoreReplenish) { + // Test Reactor specific behaviors of the Tick function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 4; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds; + conds.push_back(Cond("TritiumCore", "==", std::string("2.121"))); + QueryResult qr = sim.db().Query("ReactorInventories", &conds); + double qr_rows = qr.rows.size(); + + //If the core isn't replenished during tick it will report less than + //startup_inventory during some timestep. This checks that in every + //timestep it's what it should be + + EXPECT_EQ(simdur, qr_rows); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, TickBlanketCycle) { + // Test Reactor specific behaviors of the Tick function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " 0.03" + " Helium_3"; + + int simdur = 4; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds; + conds.push_back(Cond("Event", "==", std::string("Blanket Cycled"))); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); + std::string msg = qr.GetVal("Value"); + + std::string expected_msg = "30.000000kg of blanket removed"; + EXPECT_EQ(expected_msg, msg); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, TickBlanketOverCycle) { + // Test Reactor specific behaviors of the Tick function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " 0.65" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + sim.AddSource("Enriched_Lithium").capacity(500).recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds; + conds.push_back(Cond("Event", "==", std::string("Blanket Not Cycled"))); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); + std::string msg = qr.GetVal("Value"); + + std::string expected_msg = "Total blanket material (498.999548) insufficient to extract 650.000000kg!"; + EXPECT_EQ(expected_msg, msg); + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, Tock) { + // Test Reactor specific behaviors of the Tock function here + // Note: All specific tock functionality tested in other places. + EXPECT_NO_THROW(facility->Tock()); - // Test Reactor specific behaviors of the Tock function here } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, NormalStartup) { // Test normal startup behavior of the Startup function - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; int simdur = 1; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); + sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Tritium") - .recipe("tritium") - .Finalize(); - - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); - //under these conditions, we expect the reactor to be able to startup on timestep 0 + // under these conditions, we expect the reactor to be able to startup on + // timestep 0 std::vector conds; conds.push_back(Cond("Time", "==", std::string("0"))); QueryResult qr = sim.db().Query("ReactorEvents", &conds); std::string event = qr.GetVal("Event"); EXPECT_EQ("Startup", event); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, FuelConstrainedStartup) { - // Test normal startup behavior of the Startup function - - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; + // Test fuel constrained startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); + sim.AddSource("Tritium").recipe("tritium").capacity(8.0).Finalize(); - sim.AddSource("Tritium") - .recipe("tritium") - .capacity(8.0) - .Finalize(); - - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); - //Under these conditions, we expect the reactor to be able to startup on timestep 1 - //but not before then (buys 8kg of T on each timestep, and needs 8.121kg to startup). - //NOTE: startup occurs after DRE. + // Under these conditions, we expect the reactor to be able to startup on + // timestep 1 but not before then (buys 8kg of T on each timestep, and + // needs 8.121kg to startup). NOTE: startup occurs after DRE. std::vector conds0; conds0.push_back(Cond("Time", "==", std::string("0"))); - QueryResult qr0 = sim.db().Query("ReactorEvents", &conds0); + QueryResult qr0 = sim.db().Query("ReactorOperationsLog", &conds0); std::string event0 = qr0.GetVal("Event"); EXPECT_EQ("Startup Error", event0); - - + std::vector conds1; conds1.push_back(Cond("Time", "==", std::string("1"))); QueryResult qr1 = sim.db().Query("ReactorEvents", &conds1); std::string event1 = qr1.GetVal("Event"); EXPECT_EQ("Startup", event1); - - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, NoFuelStartup) { - // Test normal startup behavior of the Startup function - - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; + // Test no fuel startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; int simdur = 10; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); - //Under these conditions, we expect the reactor to never start, and to record - //that it failed to start every timestep. + // Under these conditions, we expect the reactor to never start, and to record + // that it failed to start every timestep. std::vector conds; conds.push_back(Cond("Event", "==", std::string("Startup Error"))); - QueryResult qr = sim.db().Query("ReactorEvents", &conds); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); double qr_rows = qr.rows.size(); - EXPECT_EQ(10, qr_rows); + EXPECT_EQ(simdur, qr_rows); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, WrongFuelStartup) { - // Test normal startup behavior of the Startup function - - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Enriched_Lithium" - " Enriched_Lithium" - " Lithium" - " 1000" - " Helium_3"; + // Test wrong fuel startup behavior of the Startup function + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Enriched_Lithium" + " Enriched_Lithium" + " Lithium" + " 1000" + " Helium_3"; int simdur = 3; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); - //Under these conditions, we expect the reactor to never start, and to record - //that it failed to start every timestep. + // Under these conditions, we expect the reactor to never start, and to record + // that it failed to start every timestep. std::vector conds; conds.push_back(Cond("Event", "==", std::string("Startup Error"))); - QueryResult qr = sim.db().Query("ReactorEvents", &conds); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); double qr_rows = qr.rows.size(); EXPECT_EQ(3, qr_rows); - //We also expect that it will record a specific message to show that the fuel - //input commodity is wrong: + // We also expect that it will record a specific message to show that the fuel + // input commodity is wrong: std::vector conds2; conds2.push_back(Cond("Event", "==", std::string("Startup Error"))); - QueryResult qr2 = sim.db().Query("ReactorEvents", &conds2); + QueryResult qr2 = sim.db().Query("ReactorOperationsLog", &conds2); std::string value = qr2.GetVal("Value"); - std::string expected_message = "Startup Failed: Fuel incommod not as expected. " - "Expected Composition: {{10030000,1}}. Fuel Incommod " - "Composition: {{30060000,0.300000},{30070000,0.700000}}"; + std::string expected_message = + "Startup Failed: Fuel incommod not as expected. " + "Expected Composition: {{10030000,1.000000}}. Fuel Incommod " + "Composition: {{30060000,0.300000},{30070000,0.700000}}"; EXPECT_EQ(value, expected_message); } @@ -272,36 +430,29 @@ TEST_F(ReactorTest, DecayInventory) { // Test behaviors of the DecayInventory function here EXPECT_NO_THROW(facility->DecayInventory(facility->tritium_core)); - - //We use unintuitive values for reserve inventory and startup inventory here because - //they were the values we were originally testing with, and we had already done - //all the calculations. - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " Lithium" - " 1000" - " Helium_3"; + // We use unintuitive values for reserve inventory and startup inventory here + // because they were the values we were originally testing with, and we had + // already done all the calculations. + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " Lithium" + " 1000" + " Helium_3"; int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); + sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Tritium") - .recipe("tritium") - .Finalize(); - - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -309,35 +460,30 @@ TEST_F(ReactorTest, DecayInventory) { conds.push_back(Cond("Time", "==", std::string("1"))); QueryResult qr = sim.db().Query("ReactorInventories", &conds); double he3 = qr.GetVal("HeliumStorage"); - - //calculator only gave me 7 decimals, otherwise this should probably - //be 1e-10. + // calculator only gave me 7 decimals, otherwise this should probably + // be 1e-10. EXPECT_NEAR(0.0379868, he3, 1e-7); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, GetComp) { // Test behaviors of the GetComp function here - cyclus::Material::Ptr Li = cyclus::Material::CreateUntracked(1, enriched_lithium()); + cyclus::Material::Ptr Li = + cyclus::Material::CreateUntracked(1, enriched_lithium()); cyclus::Material::Ptr T = cyclus::Material::CreateUntracked(1, tritium()); std::string comp_Li = facility->GetComp(Li); std::string comp_T = facility->GetComp(T); EXPECT_EQ("{{30060000,0.300000},{30070000,0.700000}}", comp_Li); EXPECT_EQ("{{10030000,1.000000}}", comp_T); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, CombineInventory) { // Test behaviors of the CombineInventory function here - - //do I need the pragma here? - //#pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily cyclus::toolkit::ResBuf test_buf; cyclus::Material::Ptr T1 = cyclus::Material::CreateUntracked(2.5, tritium()); @@ -361,16 +507,14 @@ TEST_F(ReactorTest, CombineInventory) { cyclus::Material::Ptr combined_mat = test_buf.Pop(); EXPECT_EQ(3.5, combined_mat->quantity()); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, CombineInventoryOneElement) { // Test behaviors of the CombineInventory function here - - //do I need the pragma here? - //#pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + // do I need the pragma here? + // #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily cyclus::toolkit::ResBuf test_buf; cyclus::Material::Ptr T1 = cyclus::Material::CreateUntracked(2.5, tritium()); @@ -384,19 +528,17 @@ TEST_F(ReactorTest, CombineInventoryOneElement) { cyclus::Material::Ptr combined_mat = test_buf.Pop(); EXPECT_EQ(2.5, combined_mat->quantity()); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, CombineEmptyInventory) { // Test behaviors of the CombineInventory function here - //do I need the pragma here? - //#pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + // do I need the pragma here? + // #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily cyclus::toolkit::ResBuf test_buf; EXPECT_NO_THROW(facility->CombineInventory(test_buf)); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -404,7 +546,8 @@ TEST_F(ReactorTest, ExtractHelium) { // Test behaviors of the ExtractHelium function here cyclus::toolkit::ResBuf test_buf; - cyclus::Material::Ptr test_mat = cyclus::Material::CreateUntracked(1.0, decayed_tritium()); + cyclus::Material::Ptr test_mat = + cyclus::Material::CreateUntracked(1.0, decayed_tritium()); std::string comp_original = facility->GetComp(test_mat); @@ -416,7 +559,6 @@ TEST_F(ReactorTest, ExtractHelium) { std::string comp_extracted = facility->GetComp(extracted_mat); EXPECT_EQ("{{10030000,1.000000}}", comp_extracted); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -424,7 +566,8 @@ TEST_F(ReactorTest, ExtractNoHelium) { // Test behaviors of the ExtractHelium function here cyclus::toolkit::ResBuf test_buf; - cyclus::Material::Ptr test_mat = cyclus::Material::CreateUntracked(1.0, tritium()); + cyclus::Material::Ptr test_mat = + cyclus::Material::CreateUntracked(1.0, tritium()); std::string comp_original = facility->GetComp(test_mat); @@ -436,7 +579,6 @@ TEST_F(ReactorTest, ExtractNoHelium) { std::string comp_extracted = facility->GetComp(extracted_mat); EXPECT_EQ("{{10030000,1.000000}}", comp_extracted); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -444,32 +586,26 @@ TEST_F(ReactorTest, RecordEvent) { // Test behaviors of the RecordEvent function here // This test is identical to Normal Startup... Redundant? - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; int simdur = 1; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); + sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Tritium") - .recipe("tritium") - .Finalize(); - - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -483,35 +619,28 @@ TEST_F(ReactorTest, RecordEvent) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, RecordInventories) { - // Test behaviors of the RecordEvent function here - // This test is identical to Normal Startup... Redundant? - - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; + // Test behaviors of the RecordInventories function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; int simdur = 1; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); + sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Tritium") - .recipe("tritium") - .Finalize(); - - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -523,46 +652,38 @@ TEST_F(ReactorTest, RecordInventories) { double tritium_storage = qr.GetVal("TritiumStorage"); double blanket = qr.GetVal("LithiumBlanket"); double helium_storage = qr.GetVal("HeliumStorage"); - + EXPECT_EQ(2.121, tritium_core); EXPECT_EQ(6.0, tritium_reserve); EXPECT_EQ(0.0, tritium_storage); EXPECT_EQ(1000.0, blanket); EXPECT_EQ(0.0, helium_storage); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, RecordStatus) { - // Test behaviors of the RecordEvent function here - // This test is identical to Normal Startup... Redundant? - - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; + // Test behaviors of the RecordStatus function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec - (":tricycle:Reactor"), config, simdur); - + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); + sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Tritium") - .recipe("tritium") - .Finalize(); - - sim.AddSource("Enriched_Lithium") - .recipe("enriched_lithium") - .Finalize(); + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -571,8 +692,7 @@ TEST_F(ReactorTest, RecordStatus) { QueryResult qr0 = sim.db().Query("ReactorStatus", &conds0); std::string status0 = qr0.GetVal("Status"); double power0 = qr0.GetVal("Power"); - - + EXPECT_EQ("Shut-down", status0); EXPECT_EQ(0.0, power0); @@ -580,15 +700,303 @@ TEST_F(ReactorTest, RecordStatus) { conds1.push_back(Cond("Time", "==", std::string("1"))); QueryResult qr1 = sim.db().Query("ReactorStatus", &conds1); std::string status1 = qr1.GetVal("Status"); - double power1 = qr1.GetVal("Power"); - - + double power1 = qr1.GetVal("Power"); + EXPECT_EQ("Online", status1); EXPECT_EQ(300.0, power1); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, DepleteBlanket) { + // Test behaviors of the DepleteBlanket function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); + std::string event = qr.GetVal("Event"); + + EXPECT_EQ("Blanket Depletion", event); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, OverDepleteBlanket) { + // Test behaviors of the DepleteBlanket function here + + std::string config = + " 300 " + " 1.50 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium") + .recipe("enriched_lithium") + .capacity(10) + .Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); + std::string event = qr.GetVal("Event"); + + EXPECT_EQ("Breeding Error", event); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, BreedTritium) { + // Test behaviors of the BreedTritium function here + + std::string config = + " 300 " + " 1.05 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Event", "==", std::string("Bred Tritium"))); + QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); + std::string msg = qr.GetVal("Value"); + + double val = (55.8 * (300.0 / 1000.0) / 31536000.0 * 2629846.0) * 1.05; + std::string expected_msg = std::to_string(val) + " kg of T bred from blanket"; + + EXPECT_EQ(expected_msg, msg); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, OperateReactorSustainingTBR) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 1.05 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds_1; + conds_1.push_back(Cond("Status", "==", std::string("Online"))); + QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); + double qr_1_rows = qr_1.rows.size(); + + //Reactor always starts offline for initial fuel loading + EXPECT_EQ(9, qr_1_rows); + + std::vector conds_2; + conds_2.push_back(Cond("Time", "==", std::string("9"))); + QueryResult qr_2 = sim.db().Query("ReactorInventories", &conds_2); + double storage_quantity = qr_2.GetVal("TritiumStorage"); + + //We should have extra Tritium + EXPECT_LT(0, storage_quantity); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { + // Test behaviors of the OperateReactor function here + // Expect very similar behavior to Sustaining scenario + // except no tritium in storage. + + std::string config = + " 300 " + " 0.8 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds_1; + conds_1.push_back(Cond("Status", "==", std::string("Online"))); + QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); + double qr_1_rows = qr_1.rows.size(); + + //Reactor always starts offline for initial fuel loading + EXPECT_EQ(9, qr_1_rows); + + std::vector conds_2; + conds_2.push_back(Cond("Time", "==", std::string("9"))); + QueryResult qr_2 = sim.db().Query("ReactorInventories", &conds_2); + double storage_quantity = qr_2.GetVal("TritiumStorage"); + + //We should have extra Tritium + EXPECT_EQ(0, storage_quantity); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 0.0 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 25; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").capacity(1).Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + std::vector conds; + conds.push_back(Cond("Event", "==", std::string("Core Shut-down"))); + QueryResult qr = sim.db().Query("ReactorEvents", &conds); + std::string msg = qr.GetVal("Value"); + + std::string expected_msg = "Not enough tritium to operate"; + EXPECT_EQ(expected_msg, msg); + } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, OperateReactorCoreSizeTooSmall) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 1.05 " + " 6" + " 0.1" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds_1; + conds_1.push_back(Cond("Status", "==", std::string("Shut-down"))); + QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); + double qr_1_rows = qr_1.rows.size(); + + EXPECT_EQ(simdur, qr_1_rows); + + std::vector conds_2; + conds_2.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr_2 = sim.db().Query("ReactorOperationsLog", &conds_2); + std::string event = qr_2.GetVal("Event"); + std::string msg = qr_2.GetVal("Value"); + + std::string expected_event = "Operational Error"; + std::string expected_msg = "core startup_inventory of 0.100000 kg insufficient to support fuel_usage of 1.395980kg/timestep!"; + + EXPECT_EQ(expected_event, event); + EXPECT_EQ(expected_msg, msg); + +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -606,4 +1014,4 @@ INSTANTIATE_TEST_CASE_P(Reactor, FacilityTests, ::testing::Values(&ReactorConstructor)); INSTANTIATE_TEST_CASE_P(Reactor, AgentTests, ::testing::Values(&ReactorConstructor)); -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From eefc5fd3b9e67f57f31f79bd78bc48950beee822 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Fri, 1 Mar 2024 15:50:21 -0600 Subject: [PATCH 05/43] Added schedule buy, reworked EnterNotify() to match new cyclus --- .gitignore | 1 + src/reactor.cc | 54 +++++++++++++++++---------------------------- src/reactor.h | 59 +++++++++++++++++++++----------------------------- 3 files changed, 46 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index 98e9bbb..f758c33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build cmake +docker input *.sh \ No newline at end of file diff --git a/src/reactor.cc b/src/reactor.cc index 9c77220..7197f34 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -3,7 +3,14 @@ namespace tricycle { -Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) {} +Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) { + //capacities set somewhat arbitrarily + fuel_tracker.Init({&tritium_reserve}, 1000.0); + blanket_tracker.Init({&blanket}, 100000.0); + excess_tritium_tracker.Init({&tritium_storage}, 1000.0); + helium_tracker.Init({&helium_storage}, 1000.0); + +} std::string Reactor::str() { return Facility::str(); @@ -12,7 +19,7 @@ std::string Reactor::str() { void Reactor::Tick() { if(core_loaded){ OperateReactor(TBR); - blanket_refill_policy.Start(); + blanket_fill_policy.Start(); if(operational){ Reactor::RecordStatus("Online", fusion_power); } else { @@ -71,7 +78,7 @@ void Reactor::Tock() { try { Startup(); fuel_startup_policy.Stop(); - blanket_startup_policy.Stop(); + //blanket_startup_policy.Stop(); fuel_refill_policy.Start(); core_loaded = true; } @@ -94,42 +101,20 @@ void Reactor::Tock() { void Reactor::EnterNotify() { cyclus::Facility::EnterNotify(); - - fuel_startup_policy.Init(this, \ - &tritium_reserve,\ - std::string("Tritium Storage"),\ - reserve_inventory+startup_inventory,\ - reserve_inventory+startup_inventory)\ - .Set(fuel_incommod).Start(); - - blanket_startup_policy.Init(this,\ - &blanket,\ - std::string("Blanket Startup"),\ - blanket_size,\ - blanket_size)\ - .Set(blanket_incommod).Start(); - - blanket_refill_policy.Init(this,\ - &blanket,\ - std::string("Blanket Refill"),\ - blanket_size, blanket_size)\ - .Set(blanket_incommod); + + fuel_startup_policy.Init(this, &tritium_reserve, std::string("Tritium Storage"), &fuel_tracker, std::string("ss"), reserve_inventory+startup_inventory, reserve_inventory+startup_inventory).Set(fuel_incommod).Start(); + blanket_fill_policy.Init(this, &blanket, std::string("Blanket Startup"), &blanket_tracker, std::string("ss"), blanket_size, blanket_size).Set(blanket_incommod).Start(); //Tritium Buy Policy Selection: if(refuel_mode == "schedule"){ //boost::shared_ptr quantity_dist = boost::shared_ptr(new cyclus::random_number_generator::FixedDoubleDist(buy_quantity)); - //boost::shared_ptr active_dist = boost::shared_ptr(new cyclus::FixedIntDist(1)); - //boost::shared_ptr dormant_dist = boost::shared_ptr(new cyclus::FixedIntDist(buy_frequency-1)); - //boost::shared_ptr size_dist = boost::shared_ptr(new cyclus::FixedIntDist(1)); - //fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), quantity_dist, active_dist, dormant_dist, size_dist).Set(fuel_incommod); + cyclus::IntDistribution::Ptr active_dist = cyclus::FixedIntDist::Ptr (new cyclus::FixedIntDist(1)); + cyclus::IntDistribution::Ptr dormant_dist= cyclus::FixedIntDist::Ptr (new cyclus::FixedIntDist(buy_frequency-1)); + cyclus::DoubleDistribution::Ptr size_dist = cyclus::FixedDoubleDist::Ptr (new cyclus::FixedDoubleDist(1)); + fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, buy_quantity, active_dist, dormant_dist, size_dist).Set(fuel_incommod); } else if(refuel_mode == "fill"){ - fuel_refill_policy.Init(this,\ - &tritium_reserve,\ - std::string("Input"),\ - reserve_inventory,\ - reserve_inventory)\ - .Set(fuel_incommod); + fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, std::string("ss"), reserve_inventory, reserve_inventory).Set(fuel_incommod); } else{ throw cyclus::KeyError("Refill mode " + refuel_mode + " not recognized! Try 'schedule' or 'fill'."); @@ -337,10 +322,11 @@ void Reactor::OperateReactor(double TBR, double burn_rate){ } else{ + RecordOperationalInfo("Tritium Moved", std::to_string(core_fuel->quantity()) + "kg of T moved from core to reserve"); reserve_fuel->Absorb(core_fuel); tritium_reserve.Push(reserve_fuel); fuel_refill_policy.Stop(); - blanket_refill_policy.Stop(); + blanket_fill_policy.Stop(); fuel_startup_policy.Start(); RecordEvent("Core Shut-down", "Not enough tritium to operate"); core_loaded = false; diff --git a/src/reactor.h b/src/reactor.h index 7af827c..90bf8df 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -62,11 +62,6 @@ class Reactor : public cyclus::Facility { /// @param time the time of the tock virtual void Tock(); - -//-----------------------------------------------------------// -// State Variables // -//-----------------------------------------------------------// - #pragma cyclus var { \ "doc": "Nameplate fusion power of the reactor", \ "tooltip": "Nameplate fusion power", \ @@ -183,46 +178,48 @@ class Reactor : public cyclus::Facility { bool operational = true; bool core_loaded = false; -//-----------------------------------------------------------// -// Materail Buffers // -//-----------------------------------------------------------// - -/*These must be defined after member variables for some reason?*/ - //Tritium stored in the core of the reactor - #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily + #pragma cyclus var {"tooltip":"Buffer for handling tritium kept in the core"} cyclus::toolkit::ResBuf tritium_core; - //Tritium reserve for the reactor: - #pragma cyclus var {"capacity" : "1000"} + #pragma cyclus var {"tooltip":"Buffer for handling tritium kept in reserve"} cyclus::toolkit::ResBuf tritium_reserve; - //Excess tritium in the reactor to be sold off: - #pragma cyclus var {"capacity" : "1000"} + #pragma cyclus var {"tooltip":"Buffer for handling excess tritium material to be sold"} cyclus::toolkit::ResBuf tritium_storage; - //helium-3 extracted from decayed tritium and stored by the reactor - #pragma cyclus var {"capacity" : "1000"} + #pragma cyclus var {"tooltip":"Buffer for handling helium-3 byproduct material"} cyclus::toolkit::ResBuf helium_storage; - //blanket material - #pragma cyclus var {"capacity" : "100000"} + #pragma cyclus var {"tooltip":"Buffer for handling enriched lithium blanket material"} cyclus::toolkit::ResBuf blanket; -//-----------------------------------------------------------// -// Buy and Sell Policies // -//-----------------------------------------------------------// + #pragma cyclus var {"tooltip":"Tracker to handle on-hand tritium"} + cyclus::toolkit::TotalInvTracker fuel_tracker; + + #pragma cyclus var {"tooltip":"Tracker to handle blanket material"} + cyclus::toolkit::TotalInvTracker blanket_tracker; + + #pragma cyclus var {"tooltip":"Tracker to handle excess tritium to be sold"} + cyclus::toolkit::TotalInvTracker excess_tritium_tracker; + + #pragma cyclus var {"tooltip":"Tracker to handle on-hand helium"} + cyclus::toolkit::TotalInvTracker helium_tracker; + cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; - cyclus::toolkit::MatlBuyPolicy blanket_startup_policy; - cyclus::toolkit::MatlBuyPolicy blanket_refill_policy; + + //These two may be redundant (only one may be needed) + //cyclus::toolkit::MatlBuyPolicy blanket_startup_policy; + cyclus::toolkit::MatlBuyPolicy blanket_fill_policy; cyclus::toolkit::MatlSellPolicy tritium_sell_policy; cyclus::toolkit::MatlSellPolicy helium_sell_policy; -//-----------------------------------------------------------// -// Fusion Functions // -//-----------------------------------------------------------// + //For the schedule buy policy + //cyclus::IntDistribution::Ptr active_dist = NULL; + //cyclus::IntDistribution::Ptr dormant_dist = NULL; + //cyclus::IntDistribution::Ptr size_dist = NULL; void Startup(); void OperateReactor(double TBR, double burn_rate=55.8); @@ -235,12 +232,6 @@ class Reactor : public cyclus::Facility { void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); - - - -//-----------------------------------------------------------// -// Test Functions // -//-----------------------------------------------------------// std::string GetComp(cyclus::Material::Ptr mat); // And away we go! From 97289fddddb9167110a0c5ee529f71e9f26fbd5e Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 3 Mar 2024 11:31:55 -0600 Subject: [PATCH 06/43] added EnterNotify() unit tests --- src/reactor_tests.cc | 188 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 315482c..50d270c 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -851,7 +851,7 @@ TEST_F(ReactorTest, OperateReactorSustainingTBR) { double qr_1_rows = qr_1.rows.size(); //Reactor always starts offline for initial fuel loading - EXPECT_EQ(9, qr_1_rows); + EXPECT_EQ(simdur-1, qr_1_rows); std::vector conds_2; conds_2.push_back(Cond("Time", "==", std::string("9"))); @@ -998,6 +998,192 @@ TEST_F(ReactorTest, OperateReactorCoreSizeTooSmall) { } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds_1; + conds_1.push_back(Cond("Time", "==", std::string("0"))); + conds_1.push_back(Cond("Commodity", "==", std::string("Tritium"))); + QueryResult qr_1 = sim.db().Query("Transactions", &conds_1); + int resource_id_1 = qr_1.GetVal("ResourceId"); + + std::vector conds_2; + conds_2.push_back(Cond("ResourceId", "==", std::to_string(resource_id_1))); + QueryResult qr_2 = sim.db().Query("Resources", &conds_2); + double quantity = qr_2.GetVal("Quantity"); + + EXPECT_EQ(8.121, quantity); + + std::vector conds_3; + conds_3.push_back(Cond("Time", "==", std::string("1"))); + conds_3.push_back(Cond("Commodity", "==", std::string("Tritium"))); + QueryResult qr_3 = sim.db().Query("Transactions", &conds_3); + int resource_id_2 = qr_3.GetVal("ResourceId"); + + std::vector conds_4; + conds_4.push_back(Cond("ResourceId", "==", std::to_string(resource_id_2))); + QueryResult qr_4 = sim.db().Query("Resources", &conds_4); + double quantity_2 = qr_4.GetVal("Quantity"); + + EXPECT_NEAR(0.0379868, quantity_2, 1e-7); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, EnterNotifyScheduleFill) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " 0.1" + " 1" + " schedule" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds_1; + conds_1.push_back(Cond("Time", "==", std::string("0"))); + conds_1.push_back(Cond("Commodity", "==", std::string("Tritium"))); + QueryResult qr_1 = sim.db().Query("Transactions", &conds_1); + int resource_id_1 = qr_1.GetVal("ResourceId"); + + std::vector conds_2; + conds_2.push_back(Cond("ResourceId", "==", std::to_string(resource_id_1))); + QueryResult qr_2 = sim.db().Query("Resources", &conds_2); + double quantity = qr_2.GetVal("Quantity"); + + EXPECT_EQ(8.121, quantity); + + std::vector conds_3; + conds_3.push_back(Cond("Time", "==", std::string("1"))); + conds_3.push_back(Cond("Commodity", "==", std::string("Tritium"))); + QueryResult qr_3 = sim.db().Query("Transactions", &conds_3); + int resource_id_2 = qr_3.GetVal("ResourceId"); + + std::vector conds_4; + conds_4.push_back(Cond("ResourceId", "==", std::to_string(resource_id_2))); + QueryResult qr_4 = sim.db().Query("Resources", &conds_4); + double quantity_2 = qr_4.GetVal("Quantity"); + + EXPECT_EQ(0.1, quantity_2); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, EnterNotifyInvalidFill) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 1.00 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " 0.1" + " 1" + " kjnsfdhn" + " Helium_3"; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").recipe("tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + EXPECT_THROW(int id = sim.Run(), cyclus::KeyError); + +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, EnterNotifySellPolicy) { + // Test behaviors of the OperateReactor function here + + std::string config = + " 300 " + " 1.30 " + " 6" + " 2.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3"; + + int simdur = 10; + cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); + + sim.AddRecipe("tritium", tritium()); + sim.AddRecipe("enriched_lithium", enriched_lithium()); + + sim.AddSource("Tritium").capacity(100).recipe("tritium").Finalize(); + sim.AddSink("Tritium").Finalize(); + + sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id = sim.Run(); + + + std::vector conds; + conds.push_back(Cond("TritiumStorage", "==", std::string("0"))); + QueryResult qr = sim.db().Query("ReactorInventories", &conds); + double qr_rows = qr.rows.size(); + + EXPECT_EQ(simdur, qr_rows); + +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Do Not Touch! Below section required for connection with Cyclus From faad81040bd29c359f63550295d79464179780ef Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 3 Mar 2024 12:02:50 -0600 Subject: [PATCH 07/43] Formatted all code except reactor.h, tested correctly with no breaks --- .clang-format | 12 ++ src/reactor.cc | 314 +++++++++++++++++++++++++------------------ src/reactor_tests.cc | 75 ++++------- 3 files changed, 224 insertions(+), 177 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..57070c7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ +--- +Language: Cpp +BasedOnStyle: Google +# only allow single line functions if they are inlined in class def'n +AllowShortFunctionsOnASingleLine: Inline +# do not force new line after template declarations +AlwaysBreakTemplateDeclarations: false +# Automatically detect whether a given fuction's arguments are one-per-line +ExperimentalAutoDetectBinPacking: true +# Use C++11 standard +Standard: Cpp11 +... \ No newline at end of file diff --git a/src/reactor.cc b/src/reactor.cc index 7197f34..076ced5 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -1,15 +1,15 @@ #include "reactor.h" + #include "boost/shared_ptr.hpp" namespace tricycle { Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) { - //capacities set somewhat arbitrarily + // capacities set somewhat arbitrarily fuel_tracker.Init({&tritium_reserve}, 1000.0); blanket_tracker.Init({&blanket}, 100000.0); excess_tritium_tracker.Init({&tritium_storage}, 1000.0); helium_tracker.Init({&helium_storage}, 1000.0); - } std::string Reactor::str() { @@ -17,170 +17,209 @@ std::string Reactor::str() { } void Reactor::Tick() { - if(core_loaded){ + if (core_loaded) { OperateReactor(TBR); blanket_fill_policy.Start(); - if(operational){ + if (operational) { Reactor::RecordStatus("Online", fusion_power); } else { Reactor::RecordStatus("Shut-down", 0); } - } - else{ + } else { Reactor::RecordStatus("Shut-down", 0); } DecayInventory(tritium_core); DecayInventory(tritium_reserve); DecayInventory(tritium_storage); - + ExtractHelium(tritium_core); ExtractHelium(tritium_reserve); ExtractHelium(tritium_storage); - //Pull excesss tritium out of reserve and put it into storage - //Replenish core from Helium Extraction. - if(!tritium_reserve.empty() && core_loaded){ + // Pull excesss tritium out of reserve and put it into storage + // Replenish core from Helium Extraction. + if (!tritium_reserve.empty() && core_loaded) { double core_deficit = startup_inventory - tritium_core.quantity(); - //Excess tritium will always be in tritium_reserve. - double surplus = std::max(tritium_reserve.quantity() - reserve_inventory - core_deficit, 0.0); + // Excess tritium will always be in tritium_reserve. + double surplus = std::max( + tritium_reserve.quantity() - reserve_inventory - core_deficit, 0.0); cyclus::Material::Ptr reserve_fuel = tritium_reserve.Pop(); cyclus::Material::Ptr core_fuel = tritium_core.Pop(); core_fuel->Absorb(reserve_fuel->ExtractQty(core_deficit)); tritium_storage.Push(reserve_fuel->ExtractQty(surplus)); - - RecordOperationalInfo("Tritium Moved", std::to_string(core_deficit) + "kg of T moved from reserve to core"); - if(surplus>0.0){ - RecordOperationalInfo("Tritium Moved", std::to_string(surplus) + "kg of T moved from reserve to storage"); + + RecordOperationalInfo( + "Tritium Moved", + std::to_string(core_deficit) + "kg of T moved from reserve to core"); + if (surplus > 0.0) { + RecordOperationalInfo( + "Tritium Moved", + std::to_string(surplus) + "kg of T moved from reserve to storage"); } tritium_reserve.Push(reserve_fuel); tritium_core.Push(core_fuel); - - CombineInventory(tritium_storage); + + CombineInventory(tritium_storage); } - - //This pulls out some of the blanket each timestep so that fresh blanket can be added. - if(!blanket.empty() && blanket.quantity() >= blanket_size*blanket_turnover_rate){ + + // This pulls out some of the blanket each timestep so that fresh blanket can + // be added. + if (!blanket.empty() && + blanket.quantity() >= blanket_size * blanket_turnover_rate) { cyclus::Material::Ptr blanket_mat = blanket.Pop(); - cyclus::Material::Ptr spent_blanket = blanket_mat->ExtractQty(blanket_size*blanket_turnover_rate); - RecordOperationalInfo("Blanket Cycled", std::to_string(spent_blanket->quantity()) + "kg of blanket removed"); + cyclus::Material::Ptr spent_blanket = + blanket_mat->ExtractQty(blanket_size * blanket_turnover_rate); + RecordOperationalInfo( + "Blanket Cycled", + std::to_string(spent_blanket->quantity()) + "kg of blanket removed"); blanket.Push(blanket_mat); - } else if (!blanket.empty() && blanket.quantity() < blanket_size*blanket_turnover_rate) { - RecordOperationalInfo("Blanket Not Cycled", "Total blanket material ("+ std::to_string(blanket.quantity())+") insufficient to extract " + std::to_string(blanket_size*blanket_turnover_rate) + "kg!"); + } else if (!blanket.empty() && + blanket.quantity() < blanket_size * blanket_turnover_rate) { + RecordOperationalInfo( + "Blanket Not Cycled", + "Total blanket material (" + std::to_string(blanket.quantity()) + + ") insufficient to extract " + + std::to_string(blanket_size * blanket_turnover_rate) + "kg!"); } } void Reactor::Tock() { - if(!core_loaded){ + if (!core_loaded) { try { Startup(); fuel_startup_policy.Stop(); - //blanket_startup_policy.Stop(); + // blanket_startup_policy.Stop(); fuel_refill_policy.Start(); core_loaded = true; - } - catch (const std::exception& e) { + } catch (const std::exception& e) { RecordOperationalInfo("Startup Error", e.what()); LOG(cyclus::LEV_INFO2, "Reactor") << e.what(); } } - + CombineInventory(tritium_reserve); CombineInventory(blanket); - RecordInventories(tritium_core.quantity(),\ - tritium_reserve.quantity(),\ - tritium_storage.quantity(),\ - blanket.quantity(),\ + RecordInventories(tritium_core.quantity(), tritium_reserve.quantity(), + tritium_storage.quantity(), blanket.quantity(), helium_storage.quantity()); - } void Reactor::EnterNotify() { cyclus::Facility::EnterNotify(); - fuel_startup_policy.Init(this, &tritium_reserve, std::string("Tritium Storage"), &fuel_tracker, std::string("ss"), reserve_inventory+startup_inventory, reserve_inventory+startup_inventory).Set(fuel_incommod).Start(); - blanket_fill_policy.Init(this, &blanket, std::string("Blanket Startup"), &blanket_tracker, std::string("ss"), blanket_size, blanket_size).Set(blanket_incommod).Start(); - - //Tritium Buy Policy Selection: - if(refuel_mode == "schedule"){ - //boost::shared_ptr quantity_dist = boost::shared_ptr(new cyclus::random_number_generator::FixedDoubleDist(buy_quantity)); - cyclus::IntDistribution::Ptr active_dist = cyclus::FixedIntDist::Ptr (new cyclus::FixedIntDist(1)); - cyclus::IntDistribution::Ptr dormant_dist= cyclus::FixedIntDist::Ptr (new cyclus::FixedIntDist(buy_frequency-1)); - cyclus::DoubleDistribution::Ptr size_dist = cyclus::FixedDoubleDist::Ptr (new cyclus::FixedDoubleDist(1)); - fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, buy_quantity, active_dist, dormant_dist, size_dist).Set(fuel_incommod); - } - else if(refuel_mode == "fill"){ - fuel_refill_policy.Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, std::string("ss"), reserve_inventory, reserve_inventory).Set(fuel_incommod); - } - else{ - throw cyclus::KeyError("Refill mode " + refuel_mode + " not recognized! Try 'schedule' or 'fill'."); - RecordOperationalInfo("Transaction Error", - "Refill mode " + refuel_mode + - " not recognized! Try 'schedule' or 'fill'."); + fuel_startup_policy + .Init(this, &tritium_reserve, std::string("Tritium Storage"), + &fuel_tracker, std::string("ss"), + reserve_inventory + startup_inventory, + reserve_inventory + startup_inventory) + .Set(fuel_incommod) + .Start(); + blanket_fill_policy + .Init(this, &blanket, std::string("Blanket Startup"), &blanket_tracker, + std::string("ss"), blanket_size, blanket_size) + .Set(blanket_incommod) + .Start(); + + // Tritium Buy Policy Selection: + if (refuel_mode == "schedule") { + cyclus::IntDistribution::Ptr active_dist = + cyclus::FixedIntDist::Ptr(new cyclus::FixedIntDist(1)); + cyclus::IntDistribution::Ptr dormant_dist = + cyclus::FixedIntDist::Ptr(new cyclus::FixedIntDist(buy_frequency - 1)); + cyclus::DoubleDistribution::Ptr size_dist = + cyclus::FixedDoubleDist::Ptr(new cyclus::FixedDoubleDist(1)); + fuel_refill_policy + .Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, + buy_quantity, active_dist, dormant_dist, size_dist) + .Set(fuel_incommod); + } else if (refuel_mode == "fill") { + fuel_refill_policy + .Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, + std::string("ss"), reserve_inventory, reserve_inventory) + .Set(fuel_incommod); + } else { + throw cyclus::KeyError("Refill mode " + refuel_mode + + " not recognized! Try 'schedule' or 'fill'."); + RecordOperationalInfo("Transaction Error", + "Refill mode " + refuel_mode + + " not recognized! Try 'schedule' or 'fill'."); } - tritium_sell_policy.Init(this, &tritium_storage, std::string("Excess Tritium")).Set(fuel_incommod).Start(); - helium_sell_policy.Init(this, &helium_storage, std::string("Helium-3")).Set(he3_outcommod).Start(); + tritium_sell_policy + .Init(this, &tritium_storage, std::string("Excess Tritium")) + .Set(fuel_incommod) + .Start(); + helium_sell_policy.Init(this, &helium_storage, std::string("Helium-3")) + .Set(he3_outcommod) + .Start(); } -std::string Reactor::GetComp(cyclus::Material::Ptr mat){ +std::string Reactor::GetComp(cyclus::Material::Ptr mat) { std::string comp = "{"; cyclus::CompMap c = mat->comp()->atom(); cyclus::compmath::Normalize(&c, 1); - for(std::map::const_iterator it = c.begin();it != c.end(); ++it){ - comp = comp + std::string("{") + std::to_string(it->first) + std::string(",") + std::to_string(it->second) + std::string("},"); + for (std::map::const_iterator it = c.begin(); + it != c.end(); ++it) { + comp = comp + std::string("{") + std::to_string(it->first) + + std::string(",") + std::to_string(it->second) + std::string("},"); } - comp.pop_back(); + comp.pop_back(); comp = comp + std::string("}"); return comp; } -void Reactor::Startup(){ +void Reactor::Startup() { double reserve_qty = tritium_reserve.quantity(); cyclus::Material::Ptr initial_reserve = tritium_reserve.Pop(); cyclus::CompMap c = initial_reserve->comp()->atom(); cyclus::compmath::Normalize(&c, 1); - if((reserve_qty >= (startup_inventory + reserve_inventory)) && (GetComp(initial_reserve) == "{{10030000,1.000000}}")){ - cyclus::Material::Ptr initial_core = initial_reserve->ExtractQty(startup_inventory); + if ((reserve_qty >= (startup_inventory + reserve_inventory)) && + (GetComp(initial_reserve) == "{{10030000,1.000000}}")) { + cyclus::Material::Ptr initial_core = + initial_reserve->ExtractQty(startup_inventory); tritium_core.Push(initial_core); tritium_reserve.Push(initial_reserve); - RecordEvent("Startup", "Core Loaded with " + std::to_string(tritium_core.quantity()) + " kg of Tritium."); - } - else if(GetComp(initial_reserve) != "{{10030000,1.000000}}"){ + RecordEvent("Startup", "Core Loaded with " + + std::to_string(tritium_core.quantity()) + + " kg of Tritium."); + } else if (GetComp(initial_reserve) != "{{10030000,1.000000}}") { tritium_reserve.Push(initial_reserve); - throw cyclus::ValueError("Startup Failed: Fuel incommod not as expected. " \ - + std::string("Expected Composition: {{10030000,1.000000}}. ") \ - + std::string("Fuel Incommod Composition: ") \ - + std::string(GetComp(initial_reserve))); - } - else{ + throw cyclus::ValueError( + "Startup Failed: Fuel incommod not as expected. " + + std::string("Expected Composition: {{10030000,1.000000}}. ") + + std::string("Fuel Incommod Composition: ") + + std::string(GetComp(initial_reserve))); + } else { tritium_reserve.Push(initial_reserve); - throw cyclus::ValueError("Startup Failed: " \ - + std::to_string(tritium_reserve.quantity()) \ - + " kg in reserve is less than required " \ - + std::to_string(startup_inventory+reserve_inventory) \ - + " kg to start-up!" ); + throw cyclus::ValueError( + "Startup Failed: " + std::to_string(tritium_reserve.quantity()) + + " kg in reserve is less than required " + + std::to_string(startup_inventory + reserve_inventory) + + " kg to start-up!"); } } -void Reactor::DecayInventory(cyclus::toolkit::ResBuf &inventory){ - if(!inventory.empty()){ - cyclus::Material::Ptr mat = inventory.Pop(); +void Reactor::DecayInventory( + cyclus::toolkit::ResBuf& inventory) { + if (!inventory.empty()) { + cyclus::Material::Ptr mat = inventory.Pop(); mat->Decay(context()->time()); inventory.Push(mat); } } -void Reactor::CombineInventory(cyclus::toolkit::ResBuf &inventory){ - if(!inventory.empty()){ +void Reactor::CombineInventory( + cyclus::toolkit::ResBuf& inventory) { + if (!inventory.empty()) { cyclus::Material::Ptr base = inventory.Pop(); int count = inventory.count(); - for(int i=0; iAbsorb(m); } @@ -189,17 +228,20 @@ void Reactor::CombineInventory(cyclus::toolkit::ResBuf &invent } } -void Reactor::ExtractHelium(cyclus::toolkit::ResBuf &inventory){ - if(!inventory.empty()){ +void Reactor::ExtractHelium( + cyclus::toolkit::ResBuf& inventory) { + if (!inventory.empty()) { cyclus::Material::Ptr mat = inventory.Pop(); cyclus::CompMap c = mat->comp()->atom(); - cyclus::compmath::Normalize(&c,mat->quantity()); + cyclus::compmath::Normalize(&c, mat->quantity()); cyclus::CompMap He3 = {{20030000, 1}}; - - //A threshold of 1e-5 was set to allow tritium_reserve inventories up to 1000kg - //A 1 decade lower threshold prevents tritium_reserve inventories above 33kg. - cyclus::Material::Ptr helium = mat->ExtractComp(c[20030000], cyclus::Composition::CreateFromAtom(He3), 1e-5); + + // A threshold of 1e-5 was set to allow tritium_reserve inventories up to + // 1000kg. A 1 decade lower threshold prevents tritium_reserve inventories + // above 33kg. + cyclus::Material::Ptr helium = mat->ExtractComp( + c[20030000], cyclus::Composition::CreateFromAtom(He3), 1e-5); helium_storage.Push(helium); inventory.Push(mat); @@ -226,8 +268,8 @@ void Reactor::RecordOperationalInfo(std::string name, std::string val) { ->Record(); } -void Reactor::RecordStatus(std::string status, double power){ - context() +void Reactor::RecordStatus(std::string status, double power) { + context() ->NewDatum("ReactorStatus") ->AddVal("AgentId", id()) ->AddVal("Time", context()->time()) @@ -236,8 +278,9 @@ void Reactor::RecordStatus(std::string status, double power){ ->Record(); } -void Reactor::RecordInventories(double core, double reserve, double storage, double blanket, double helium){ - context() +void Reactor::RecordInventories(double core, double reserve, double storage, + double blanket, double helium) { + context() ->NewDatum("ReactorInventories") ->AddVal("AgentId", id()) ->AddVal("Time", context()->time()) @@ -249,80 +292,90 @@ void Reactor::RecordInventories(double core, double reserve, double storage, dou ->Record(); } -void Reactor::DepleteBlanket(double bred_tritium_mass){ +void Reactor::DepleteBlanket(double bred_tritium_mass) { cyclus::Material::Ptr blanket_mat = blanket.Pop(); cyclus::CompMap b = blanket_mat->comp()->mass(); cyclus::compmath::Normalize(&b, blanket_mat->quantity()); - //Percent (as decimal) of T which comes from Li-7 instead of Li-6 + // Percent (as decimal) of T which comes from Li-7 instead of Li-6 double Li7_contribution = 0.15; - cyclus::CompMap depleted_comp; - + cyclus::CompMap depleted_comp; + // This is ALMOST the correct behavior, but "scraping the bottom of the // barrel" is a little too complex for this implementation. - if((b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass > 0) && (b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass > 0)){ - depleted_comp = {{30070000, b[30070000] - Li7_contribution*7.0/3.0*bred_tritium_mass}, \ - {30060000, b[30060000] - (1-Li7_contribution)*2*bred_tritium_mass}, \ - {10030000, b[10030000] + bred_tritium_mass},\ - {20040000, b[20040000] + 4.0/3.0*bred_tritium_mass}}; - - //Account for the added mass of the absorbed neutrons - double neutron_mass_correction = 1.0/3.0*bred_tritium_mass*(1-Li7_contribution); - cyclus::Material::Ptr additional_mass = cyclus::Material::Create(this, neutron_mass_correction, cyclus::Composition::CreateFromMass(depleted_comp)); + if ((b[30060000] - (1 - Li7_contribution) * 2 * bred_tritium_mass > 0) && + (b[30070000] - Li7_contribution * 7.0 / 3.0 * bred_tritium_mass > 0)) { + depleted_comp = {{30070000, b[30070000] - Li7_contribution * 7.0 / 3.0 * + bred_tritium_mass}, + {30060000, b[30060000] - (1 - Li7_contribution) * 2 * + bred_tritium_mass}, + {10030000, b[10030000] + bred_tritium_mass}, + {20040000, b[20040000] + 4.0 / 3.0 * bred_tritium_mass}}; + + // Account for the added mass of the absorbed neutrons + double neutron_mass_correction = + 1.0 / 3.0 * bred_tritium_mass * (1 - Li7_contribution); + cyclus::Material::Ptr additional_mass = cyclus::Material::Create( + this, neutron_mass_correction, + cyclus::Composition::CreateFromMass(depleted_comp)); blanket_mat->Transmute(cyclus::Composition::CreateFromMass(depleted_comp)); blanket_mat->Absorb(additional_mass); - RecordOperationalInfo("Blanket Depletion", "Tritium bred at perscribed rate"); - } - else{ - RecordOperationalInfo("Breeding Error", - "Blanket composition lacks sufficient lithium to continue " - "breeding at perscribed rate"); + RecordOperationalInfo("Blanket Depletion", + "Tritium bred at perscribed rate"); + } else { + RecordOperationalInfo( + "Breeding Error", + "Blanket composition lacks sufficient lithium to continue " + "breeding at perscribed rate"); } blanket.Push(blanket_mat); } -cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR){ - DepleteBlanket(fuel_usage*TBR); +cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR) { + DepleteBlanket(fuel_usage * TBR); cyclus::Material::Ptr mat = blanket.Pop(); cyclus::CompMap c = mat->comp()->mass(); - cyclus::compmath::Normalize(&c,mat->quantity()); + cyclus::compmath::Normalize(&c, mat->quantity()); cyclus::CompMap T = {{10030000, 1}}; - - cyclus::Material::Ptr bred_fuel = mat->ExtractComp(c[10030000], cyclus::Composition::CreateFromAtom(T)); + + cyclus::Material::Ptr bred_fuel = + mat->ExtractComp(c[10030000], cyclus::Composition::CreateFromAtom(T)); blanket.Push(mat); RecordOperationalInfo("Bred Tritium", std::to_string(bred_fuel->quantity()) + - " kg of T bred from blanket"); + " kg of T bred from blanket"); return bred_fuel; } -void Reactor::OperateReactor(double TBR, double burn_rate){ +void Reactor::OperateReactor(double TBR, double burn_rate) { int seconds_per_year = 31536000; - double fuel_usage = burn_rate * (fusion_power / 1000) / seconds_per_year * context()->dt(); + double fuel_usage = + burn_rate * (fusion_power / 1000) / seconds_per_year * context()->dt(); cyclus::Material::Ptr reserve_fuel = tritium_reserve.Pop(); cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - if(core_fuel->quantity() > fuel_usage){ + if (core_fuel->quantity() > fuel_usage) { cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); - - if(((reserve_fuel->quantity() + core_fuel->quantity()) >= startup_inventory)){ + if (((reserve_fuel->quantity() + core_fuel->quantity()) >= + startup_inventory)) { reserve_fuel->Absorb(core_fuel); tritium_core.Push(reserve_fuel->ExtractQty(startup_inventory)); tritium_reserve.Push(reserve_fuel); - } - else{ - RecordOperationalInfo("Tritium Moved", std::to_string(core_fuel->quantity()) + "kg of T moved from core to reserve"); + } else { + RecordOperationalInfo("Tritium Moved", + std::to_string(core_fuel->quantity()) + + "kg of T moved from core to reserve"); reserve_fuel->Absorb(core_fuel); tritium_reserve.Push(reserve_fuel); fuel_refill_policy.Stop(); @@ -333,11 +386,14 @@ void Reactor::OperateReactor(double TBR, double burn_rate){ } } else { operational = false; - RecordOperationalInfo("Operational Error", "core startup_inventory of "+ std::to_string(startup_inventory)+ " kg insufficient to support fuel_usage of " + std::to_string(fuel_usage) + "kg/timestep!"); + RecordOperationalInfo("Operational Error", + "core startup_inventory of " + + std::to_string(startup_inventory) + + " kg insufficient to support fuel_usage of " + + std::to_string(fuel_usage) + "kg/timestep!"); tritium_reserve.Push(reserve_fuel); tritium_core.Push(core_fuel); } - } // WARNING! Do not change the following this function!!! This enables your diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 50d270c..105482f 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -67,7 +67,7 @@ TEST_F(ReactorTest, Print) { TEST_F(ReactorTest, TickCoreNotLoaded) { // Test Reactor specific behaviors of the Tick function here - std::string config = + std::string config = " 300 " " 1.00 " " 6" @@ -88,21 +88,19 @@ TEST_F(ReactorTest, TickCoreNotLoaded) { int id = sim.Run(); - std::vector conds; conds.push_back(Cond("Status", "==", std::string("Shut-down"))); QueryResult qr = sim.db().Query("ReactorStatus", &conds); double qr_rows = qr.rows.size(); EXPECT_EQ(simdur, qr_rows); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, TickNotOperational) { // Test Reactor specific behaviors of the Tick function here - std::string config = + std::string config = " 300 " " 1.00 " " 6" @@ -124,21 +122,19 @@ TEST_F(ReactorTest, TickNotOperational) { int id = sim.Run(); - std::vector conds; conds.push_back(Cond("Status", "==", std::string("Shut-down"))); QueryResult qr = sim.db().Query("ReactorStatus", &conds); double qr_rows = qr.rows.size(); EXPECT_EQ(simdur, qr_rows); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, TickCoreReplenish) { // Test Reactor specific behaviors of the Tick function here - std::string config = + std::string config = " 300 " " 1.00 " " 6" @@ -160,25 +156,23 @@ TEST_F(ReactorTest, TickCoreReplenish) { int id = sim.Run(); - std::vector conds; conds.push_back(Cond("TritiumCore", "==", std::string("2.121"))); QueryResult qr = sim.db().Query("ReactorInventories", &conds); double qr_rows = qr.rows.size(); - //If the core isn't replenished during tick it will report less than - //startup_inventory during some timestep. This checks that in every - //timestep it's what it should be + // If the core isn't replenished during tick it will report less than + // startup_inventory during some timestep. This checks that in every + // timestep it's what it should be EXPECT_EQ(simdur, qr_rows); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, TickBlanketCycle) { // Test Reactor specific behaviors of the Tick function here - std::string config = + std::string config = " 300 " " 1.00 " " 6" @@ -201,7 +195,6 @@ TEST_F(ReactorTest, TickBlanketCycle) { int id = sim.Run(); - std::vector conds; conds.push_back(Cond("Event", "==", std::string("Blanket Cycled"))); QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); @@ -209,14 +202,13 @@ TEST_F(ReactorTest, TickBlanketCycle) { std::string expected_msg = "30.000000kg of blanket removed"; EXPECT_EQ(expected_msg, msg); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, TickBlanketOverCycle) { // Test Reactor specific behaviors of the Tick function here - std::string config = + std::string config = " 300 " " 1.00 " " 6" @@ -235,19 +227,22 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").capacity(500).recipe("enriched_lithium").Finalize(); + sim.AddSource("Enriched_Lithium") + .capacity(500) + .recipe("enriched_lithium") + .Finalize(); int id = sim.Run(); - std::vector conds; conds.push_back(Cond("Event", "==", std::string("Blanket Not Cycled"))); QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); std::string msg = qr.GetVal("Value"); - std::string expected_msg = "Total blanket material (498.999548) insufficient to extract 650.000000kg!"; + std::string expected_msg = + "Total blanket material (498.999548) insufficient to extract " + "650.000000kg!"; EXPECT_EQ(expected_msg, msg); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -256,7 +251,6 @@ TEST_F(ReactorTest, Tock) { // Note: All specific tock functionality tested in other places. EXPECT_NO_THROW(facility->Tock()); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -844,23 +838,21 @@ TEST_F(ReactorTest, OperateReactorSustainingTBR) { int id = sim.Run(); - std::vector conds_1; conds_1.push_back(Cond("Status", "==", std::string("Online"))); QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); double qr_1_rows = qr_1.rows.size(); - //Reactor always starts offline for initial fuel loading - EXPECT_EQ(simdur-1, qr_1_rows); + // Reactor always starts offline for initial fuel loading + EXPECT_EQ(simdur - 1, qr_1_rows); std::vector conds_2; conds_2.push_back(Cond("Time", "==", std::string("9"))); QueryResult qr_2 = sim.db().Query("ReactorInventories", &conds_2); double storage_quantity = qr_2.GetVal("TritiumStorage"); - //We should have extra Tritium + // We should have extra Tritium EXPECT_LT(0, storage_quantity); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -892,13 +884,12 @@ TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { int id = sim.Run(); - std::vector conds_1; conds_1.push_back(Cond("Status", "==", std::string("Online"))); QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); double qr_1_rows = qr_1.rows.size(); - //Reactor always starts offline for initial fuel loading + // Reactor always starts offline for initial fuel loading EXPECT_EQ(9, qr_1_rows); std::vector conds_2; @@ -906,9 +897,8 @@ TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { QueryResult qr_2 = sim.db().Query("ReactorInventories", &conds_2); double storage_quantity = qr_2.GetVal("TritiumStorage"); - //We should have extra Tritium + // We should have extra Tritium EXPECT_EQ(0, storage_quantity); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -938,7 +928,6 @@ TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { int id = sim.Run(); - std::vector conds; conds.push_back(Cond("Event", "==", std::string("Core Shut-down"))); QueryResult qr = sim.db().Query("ReactorEvents", &conds); @@ -946,7 +935,6 @@ TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { std::string expected_msg = "Not enough tritium to operate"; EXPECT_EQ(expected_msg, msg); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -976,7 +964,6 @@ TEST_F(ReactorTest, OperateReactorCoreSizeTooSmall) { int id = sim.Run(); - std::vector conds_1; conds_1.push_back(Cond("Status", "==", std::string("Shut-down"))); QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); @@ -991,11 +978,12 @@ TEST_F(ReactorTest, OperateReactorCoreSizeTooSmall) { std::string msg = qr_2.GetVal("Value"); std::string expected_event = "Operational Error"; - std::string expected_msg = "core startup_inventory of 0.100000 kg insufficient to support fuel_usage of 1.395980kg/timestep!"; - + std::string expected_msg = + "core startup_inventory of 0.100000 kg insufficient to support " + "fuel_usage of 1.395980kg/timestep!"; + EXPECT_EQ(expected_event, event); EXPECT_EQ(expected_msg, msg); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1025,13 +1013,12 @@ TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { int id = sim.Run(); - std::vector conds_1; conds_1.push_back(Cond("Time", "==", std::string("0"))); conds_1.push_back(Cond("Commodity", "==", std::string("Tritium"))); QueryResult qr_1 = sim.db().Query("Transactions", &conds_1); int resource_id_1 = qr_1.GetVal("ResourceId"); - + std::vector conds_2; conds_2.push_back(Cond("ResourceId", "==", std::to_string(resource_id_1))); QueryResult qr_2 = sim.db().Query("Resources", &conds_2); @@ -1051,7 +1038,6 @@ TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { double quantity_2 = qr_4.GetVal("Quantity"); EXPECT_NEAR(0.0379868, quantity_2, 1e-7); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1084,13 +1070,12 @@ TEST_F(ReactorTest, EnterNotifyScheduleFill) { int id = sim.Run(); - std::vector conds_1; conds_1.push_back(Cond("Time", "==", std::string("0"))); conds_1.push_back(Cond("Commodity", "==", std::string("Tritium"))); QueryResult qr_1 = sim.db().Query("Transactions", &conds_1); int resource_id_1 = qr_1.GetVal("ResourceId"); - + std::vector conds_2; conds_2.push_back(Cond("ResourceId", "==", std::to_string(resource_id_1))); QueryResult qr_2 = sim.db().Query("Resources", &conds_2); @@ -1110,7 +1095,6 @@ TEST_F(ReactorTest, EnterNotifyScheduleFill) { double quantity_2 = qr_4.GetVal("Quantity"); EXPECT_EQ(0.1, quantity_2); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1142,7 +1126,6 @@ TEST_F(ReactorTest, EnterNotifyInvalidFill) { sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); EXPECT_THROW(int id = sim.Run(), cyclus::KeyError); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1173,18 +1156,14 @@ TEST_F(ReactorTest, EnterNotifySellPolicy) { int id = sim.Run(); - std::vector conds; conds.push_back(Cond("TritiumStorage", "==", std::string("0"))); QueryResult qr = sim.db().Query("ReactorInventories", &conds); double qr_rows = qr.rows.size(); - - EXPECT_EQ(simdur, qr_rows); + EXPECT_EQ(simdur, qr_rows); } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Do Not Touch! Below section required for connection with Cyclus cyclus::Agent* ReactorConstructor(cyclus::Context* ctx) { From 4065e4a8dcf1017965c2ed493a5e679faa74dfcb Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 16:23:43 -0500 Subject: [PATCH 08/43] made Li7_contribution a cyclus var, set default to 0.03, delted commented code --- src/reactor.cc | 4 ---- src/reactor.h | 13 +++++++++++-- src/reactor_tests.cc | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 076ced5..51e7bc1 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -92,7 +92,6 @@ void Reactor::Tock() { try { Startup(); fuel_startup_policy.Stop(); - // blanket_startup_policy.Stop(); fuel_refill_policy.Start(); core_loaded = true; } catch (const std::exception& e) { @@ -298,9 +297,6 @@ void Reactor::DepleteBlanket(double bred_tritium_mass) { cyclus::CompMap b = blanket_mat->comp()->mass(); cyclus::compmath::Normalize(&b, blanket_mat->quantity()); - // Percent (as decimal) of T which comes from Li-7 instead of Li-6 - double Li7_contribution = 0.15; - cyclus::CompMap depleted_comp; // This is ALMOST the correct behavior, but "scraping the bottom of the diff --git a/src/reactor.h b/src/reactor.h index 90bf8df..5e6c15d 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -87,8 +87,8 @@ class Reactor : public cyclus::Facility { double reserve_inventory; #pragma cyclus var { \ - "doc": "Tritium core inventory required to start reactor", \ - "tooltip": "Tritium core inventory required to start reactor", \ + "doc": "Tritium required to start reactor, includes a reserve inventory", \ + "tooltip": "Tritium inventory required to start reactor, includes reserve", \ "units": "kg", \ "uilabel": "Start-up Inventory" \ } @@ -134,6 +134,15 @@ class Reactor : public cyclus::Facility { } std::string he3_outcommod; + #pragma cyclus var { \ + "default": 0.03, \ + "doc": "Fraction of tritium that comes from the (n + Li-7 --> T + He + n) reaction", \ + "tooltip": "Fraction of tritium from Li-7 breeding", \ + "units": "dimensionless", \ + "uilabel": "Li-7 Contribution" \ + } + double Li7_contribution; + #pragma cyclus var { \ "default": 1000.0, \ "doc": "Initial mass of full blanket material", \ diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 105482f..3b36550 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -240,7 +240,7 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { std::string msg = qr.GetVal("Value"); std::string expected_msg = - "Total blanket material (498.999548) insufficient to extract " + "Total blanket material (499.055387) insufficient to extract " "650.000000kg!"; EXPECT_EQ(expected_msg, msg); } From a3dbbc5496600ac4216efe79f7b1e6a7abc9e9e1 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:06:57 -0500 Subject: [PATCH 09/43] fixed default language at begining of header --- src/reactor.h | 78 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/src/reactor.h b/src/reactor.h index 5e6c15d..0d9a955 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -10,27 +10,71 @@ namespace tricycle { /// @class Reactor /// -/// This Facility is intended -/// as a skeleton to guide the implementation of new Facility -/// agents. /// The Reactor class inherits from the Facility class and is /// dynamically loaded by the Agent class when requested. /// /// @section intro Introduction -/// Place an introduction to the agent here. +/// This agnet is designed to function as a basic representation of a fusion +/// energy system with respect to tritium flows. This is currently the alpha +/// version of the agent, and as such some simplifying assumptions were made. /// /// @section agentparams Agent Parameters -/// Place a description of the required input parameters which define the -/// agent implementation. +/// Required Inputs: +/// fusion_power - the fusion power of the fusion energy system. Analagous to +/// thermal power. Typical values in the range of 100-5000 MW. +/// TBR - Overall Trituim Breeding Ratio of the fusion energy system. +/// startup_inventory - total inventory of tritium required to start fusion +/// energy system. Includes a reserve inventory. See Abdou 2023 for more +/// details. +/// fuel_incommod - input commodity for fuel. Currently required to be 100% +/// tritium. Future implementations will change this. +/// blanket_incommod - input commodity for tritium breeding blanket. Currently +/// required to be pure enriched lithium. +/// blanket_inrecipe - input recipe for tritium breeding blanket. Currently +/// required to be pure enriched lithium. Enrichment level is not restricted. +/// he-3_outcommod - output commodity for Helium-3 produced by decay of tritium. +/// Required for the agent to offload this supply. /// /// @section optionalparams Optional Parameters -/// Place a description of the optional input parameters to define the -/// agent implementation. -/// +/// refuel_mode - mode of refueling reactor. Two options, "schedule" and "fill" +/// Default is fill, which tries to ensure that tritium_storage is greater than +/// or equal to startup_inventory each timestep. Schedule allows a fixed amount +/// of tritium to be purchased on a fixed schedule. See buy_quantity, and +/// buy_frequency for more details. +/// buy_quantity - quantity of tritium to buy each buy cycle for schedule buy +/// purchase mode (in kg). Default is 0.1 kg. +/// buy_frequency - frequency with which to order tritium in schedule buy mode. +/// Delay (in timesteps) between orders is buy_frequency-1. Purchasing once per +/// year, with 1 month timesteps would correspond to a buy frequency of 12. +/// Default is 1 (buy every time step). +/// Li7_contribution - fraction of tritium which comes from the (n+Li7-->T+He+n) +/// reaction. Default is 0.03 (3%). +/// blanket_size - size of the blanket in kg of enriched lithium. Default is +/// 1000 kg. +/// blanket_turnover_rate - fraction of blanket which gets removed and replaced +/// each timestep. Removed blanket is replaced with the original blanket recipe. +/// Default is 0.05 (5%), but was set arbitrarily. +/// /// @section detailed Detailed Behavior -/// Place a description of the detailed behavior of the agent. Consider -/// describing the behavior at the tick and tock as well as the behavior -/// upon sending and receiving materials and messages. +/// Agent begins by checking if there is sufficient tritium in the system to +/// operate. If there is, it burns tritium to achieve input fusion_power, then +/// replenishes itself by breeding tritium based on TBR. If there is not +/// sufficient tritum in the reactor initially, agent records that it did not +/// produce power that timestep. Next, agent decays all inventories of tritium +/// and extracts He-3 from those inventories. Agent then replaces lost mass +/// from He-3 extraction with tritium from storage, and cycles the blanket. +/// +/// Agent then enters the DRE, where it attempts to purchase more tritium should +/// there be a deficit, or sell excess should there be a surplus, as well as to +/// purchase blanket material required to refill blanket. Finally, excess He-3 +/// is offered to the market. +/// +/// During tock, agent checks again whether there is enough tritium in the system +/// and if not, tries to "startup", which entails loading the core with tritium. +/// If it fails to do so, a note is made in the opearational log. Next, any newly +/// purchased tritium is squashed within its resbuf, and a record is made of all +/// inventory quantities. + class Reactor : public cyclus::Facility { public: /// Constructor for Reactor Class @@ -165,16 +209,6 @@ class Reactor : public cyclus::Facility { } std::string blanket_inrecipe; - #pragma cyclus var { \ - "default": 0.3, \ - "doc": "Li-6 enrichment requirement percent as a decimal", \ - "tooltip": "Defaults to 30% (0.3)", \ - "units": "%", \ - "uilabel": "Minimum Blanket Enrichment" \ - } - double min_blanket_enrichment; - - //WARNING: The default on this is completely arbitrary! #pragma cyclus var { \ "default": 0.05, \ From 0256d9cc5766fec43c0d992e8f98d57f412d41fd Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:12:59 -0500 Subject: [PATCH 10/43] changed default note to describe agent --- src/reactor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reactor.h b/src/reactor.h index 0d9a955..437857a 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -89,8 +89,8 @@ class Reactor : public cyclus::Facility { #pragma cyclus - #pragma cyclus note {"doc": "A stub facility is provided as a skeleton " \ - "for the design of new facility agents."} + #pragma cyclus note {"doc": "A facility to model basic operation of a" \ + "fusion energy system."} /// A verbose printer for the Reactor virtual std::string str(); From dcd1b0127c9c260ef47f7bc822b7cb4f9ed48452 Mon Sep 17 00:00:00 2001 From: Dean Krueger <74223179+dean-krueger@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:14:28 -0500 Subject: [PATCH 11/43] Added UI Type to Fusion Power Co-authored-by: Katie Mummah --- src/reactor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/reactor.h b/src/reactor.h index 437857a..bec432d 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -110,6 +110,8 @@ class Reactor : public cyclus::Facility { "doc": "Nameplate fusion power of the reactor", \ "tooltip": "Nameplate fusion power", \ "units": "MW", \ + "uitype": "range", \ + "range": [0, 1e299], \ "uilabel": "Fusion Power" \ } double fusion_power; From cace768b6e92c2a294138e81021db157f647ea7d Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:31:30 -0500 Subject: [PATCH 12/43] added uitypes to variables, changed buy_frequency from double to int --- src/reactor.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/reactor.h b/src/reactor.h index bec432d..f1ca807 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -120,6 +120,8 @@ class Reactor : public cyclus::Facility { "doc": "Achievable system tritium breeding ratio before decay", \ "tooltip": "Achievable system tritium breeding ratio before decay", \ "units": "non-dimensional", \ + "uitype": "range", \ + "range": [0, 1e299], \ "uilabel": "Tritium Breeding Ratio" \ } double TBR; @@ -153,6 +155,8 @@ class Reactor : public cyclus::Facility { "doc": "Quantity of fuel which reactor tries to purchase", \ "tooltip": "Defaults to 100g/purchase", \ "units": "kg", \ + "uitype": "range", \ + "range": [0, 1e299], \ "uilabel": "Buy quantity" \ } double buy_quantity; @@ -162,9 +166,11 @@ class Reactor : public cyclus::Facility { "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" \ } - double buy_frequency; + int buy_frequency; #pragma cyclus var { \ "doc": "Fresh fuel commodity", \ @@ -185,6 +191,8 @@ class Reactor : public cyclus::Facility { "doc": "Fraction of tritium that comes from the (n + Li-7 --> T + He + n) reaction", \ "tooltip": "Fraction of tritium from Li-7 breeding", \ "units": "dimensionless", \ + "uitype": "range", \ + "range": [0, 1], \ "uilabel": "Li-7 Contribution" \ } double Li7_contribution; @@ -193,6 +201,8 @@ class Reactor : public cyclus::Facility { "default": 1000.0, \ "doc": "Initial mass of full blanket material", \ "tooltip": "Only blanket material mass, not structural mass", \ + "uitype": "range", \ + "range": [0, 10000], \ "uilabel": "Initial Mass of Blanket" \ } double blanket_size; @@ -215,8 +225,10 @@ class Reactor : public cyclus::Facility { #pragma cyclus var { \ "default": 0.05, \ "doc": "Percent of blanket that gets recycled every timestep", \ - "tooltip": "Defaults to 5% (0.05), must be between 0 and 15%", \ - "units": "%", \ + "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_rate; From 534d17148db709ec48197605a4a5e4d5baec1e41 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:37:57 -0500 Subject: [PATCH 13/43] added combobox to refuel_mode as suggested --- src/reactor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/reactor.h b/src/reactor.h index f1ca807..a63dde1 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -146,6 +146,8 @@ class Reactor : public cyclus::Facility { "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; From 530240e2d1c0f87e805a13e6dde9f274597e219a Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:42:41 -0500 Subject: [PATCH 14/43] deleted commented code from reactor.h --- src/reactor.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/reactor.h b/src/reactor.h index a63dde1..7746d4e 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -268,18 +268,11 @@ class Reactor : public cyclus::Facility { cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; - //These two may be redundant (only one may be needed) - //cyclus::toolkit::MatlBuyPolicy blanket_startup_policy; cyclus::toolkit::MatlBuyPolicy blanket_fill_policy; cyclus::toolkit::MatlSellPolicy tritium_sell_policy; cyclus::toolkit::MatlSellPolicy helium_sell_policy; - //For the schedule buy policy - //cyclus::IntDistribution::Ptr active_dist = NULL; - //cyclus::IntDistribution::Ptr dormant_dist = NULL; - //cyclus::IntDistribution::Ptr size_dist = NULL; - void Startup(); void OperateReactor(double TBR, double burn_rate=55.8); void DecayInventory(cyclus::toolkit::ResBuf &inventory); From dc6a0ba1dae732e7cc864a4fee90b9bd2a68ae3c Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:51:04 -0500 Subject: [PATCH 15/43] changed README from default Hello, Cyclus! Still a placeholder --- README.rst | 149 ++++++++++++++--------------------------------------- 1 file changed, 39 insertions(+), 110 deletions(-) diff --git a/README.rst b/README.rst index 1e0467a..ba413a6 100644 --- a/README.rst +++ b/README.rst @@ -1,110 +1,39 @@ -.. _hello_world: - -Hello, Cyclus! -============== -This pages walks you through a very simple hello world example using -|cyclus| agents. First make sure that you have the dependencies installed, -namely |Cyclus|, CMake, and a recent version of Python (2.7 or 3.3+). - -First, you need to get the ``cycstub`` code. Cycstub is a skeleton code base -that you can use to quick-start new |cyclus| module development projects. -You can grab cycstub from |cyclus|. - -Let's put this code in a ``tutorial`` directory and go into it. - -**Getting cycstub via Cyclus:** - -.. code-block:: bash - - $ mkdir tutorial - $ cd tutorial/ - $ cycstub --type facility .:fusion:tutorialfacility - ------------- - -Let's now change the behavior of the TutorialFacility's ``Tick()`` & -``Tock()`` member functions to print "Hello" and "World" respectively. To do -this, please open up the :file:`src/tutorial_facility.cc` file in your -favorite text editor (vim, emacs, gedit, `notepad++ `_). -Change the original functions to look like: - -**Original Tick() and Tock() in src/tutorial_facility.cc:** - -.. code-block:: c++ - - void TutorialFacility::Tick() {} - - void TutorialFacility::Tock() {} - -**New Tick() and Tock() in src/tutorial_facility.cc:** - -.. code-block:: c++ - - void TutorialFacility::Tick() {std::cout << "Hello, ";} - - void TutorialFacility::Tock() {std::cout << "World!\n";} - ------------- - -Now that we have altered the behavior of the TutorialFacility, let's compile and -install the ``tutorial`` project. This done with the install.py script. -The install script puts the project into your cyclus userspace, -``${HOME}/.local/lib/cyclus``. - -.. code-block:: bash - - tutorial $ python install.py - ------------- - -Let's run |cyclus| with the TutorialFacility! In the directory there is -an :file:`example.xml`. Running |cyclus| on this file with the command -``cyclus example.xml`` should produce the following output. - -.. code-block:: bash - - tutorial $ cyclus example.xml - : - .CL:CC CC _Q _Q _Q_Q _Q _Q _Q - CC;CCCCCCCC:C; /_\) /_\)/_/\\) /_\) /_\) /_\) - CCCCCCCCCCCCCl __O|/O___O|/O_OO|/O__O|/O__O|/O____________O|/O__ - CCCCCCf iCCCLCC ///////////////////////////////////////////////// - iCCCt ;;;;;. CCCC - CCCC ;;;;;;;;;. CClL. c - CCCC ,;; ;;: CCCC ; : CCCCi - CCC ;; ;; CC ;;: CCC` `C; - lCCC ;; CCCC ;;;: :CC .;;. C; ; : ; :;; - CCCC ;. CCCC ;;;, CC ; ; Ci ; : ; : ; - iCC :; CC ;;;, ;C ; CC ; : ; . - CCCi ;; CCC ;;;. .C ; tf ; : ; ;. - CCC ;; CCC ;;;;;;; fC : lC ; : ; ;: - iCf ;; CC :;;: tC ; CC ; : ; ; - fCCC :; LCCf ;;;: LC :. ,: C ; ; ; ; ; - CCCC ;; CCCC ;;;: CCi `;;` CC. ;;;; :;.;. ; ,; - CCl ;; CC ;;;; CCC CCL - tCCC ;; ;; CCCL ;;; tCCCCC. - CCCC ;; :;; CCCCf ; ,L - lCCC ;;;;;; CCCL - CCCCCC :;; fCCCCC - . CCCC CCCC . - .CCCCCCCCCCCCCi - iCCCCCLCf - . C. , - : - Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World! - Hello, World! - - Status: Cyclus run successful! - Output location: cyclus.sqlite - Simulation ID: 0ae730e0-a9a8-4576-afaa-d1db6399d5a2 - -If you look in the input file you'll see that the simulation duration was set -to 10. This is why "Hello, World!" is printed ten times. +.................................................................................................... +.................................................................................................... +...........................-@-............%@........................................................ +..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... +...........................@@@..-*==%............................................................... +..................................=*................................................................ +.................................@=#.........................#%..................................... +................................%=*@@@%#=..................#@@%..................................... +................................*=%=======.+%.......@%%%%%@%%@@..................................... +...............................@=%===========:%..........%@%@@...................................... +..............................@@++@============-#.........%%........................................ +.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... +.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... +......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. +....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. +...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ +..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ +.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ +.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. +..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. +..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... +.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ +.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... +...........:@#********************#%%*=:................=##****************************##:.......... +.......#************************************************************************************-....... +..*----------------------------------------------------------------------------------------------*.. +..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. +..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. +..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. +..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. +..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. +..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. +..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. +..*----------------------------------------------------------------------------------------------*.. +.................................................................................................... + +Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is +currently under development at the University of Wisconsin-Madison, and in its alpha stage. +Epect more information to come as development continues! \ No newline at end of file From a64a881342f09ec8304bc0284eb8845ced765d56 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:55:41 -0500 Subject: [PATCH 16/43] Tried to fix readme formatting for website --- README.rst | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/README.rst b/README.rst index ba413a6..91b10c2 100644 --- a/README.rst +++ b/README.rst @@ -1,39 +1,39 @@ -.................................................................................................... -.................................................................................................... -...........................-@-............%@........................................................ -..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... -...........................@@@..-*==%............................................................... -..................................=*................................................................ -.................................@=#.........................#%..................................... -................................%=*@@@%#=..................#@@%..................................... -................................*=%=======.+%.......@%%%%%@%%@@..................................... -...............................@=%===========:%..........%@%@@...................................... -..............................@@++@============-#.........%%........................................ -.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... -.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... -......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. -....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. -...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ -..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ -.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ -.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. -..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. -..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... -.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ -.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... -...........:@#********************#%%*=:................=##****************************##:.......... -.......#************************************************************************************-....... -..*----------------------------------------------------------------------------------------------*.. -..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. -..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. -..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. -..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. -..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. -..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. -..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. -..*----------------------------------------------------------------------------------------------*.. -.................................................................................................... - -Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is -currently under development at the University of Wisconsin-Madison, and in its alpha stage. -Epect more information to come as development continues! \ No newline at end of file +....................................................................................................\n +....................................................................................................\n +...........................-@-............%@........................................................\n +..........................@.@@@-+%.#+=*#%%%%@@@@*...................................................\n +...........................@@@..-*==%...............................................................\n +..................................=*................................................................\n +.................................@=#.........................#%.....................................\n +................................%=*@@@%#=..................#@@%.....................................\n +................................*=%=======.+%.......@%%%%%@%%@@.....................................\n +...............................@=%===========:%..........%@%@@......................................\n +..............................@@++@============-#.........%%........................................\n +.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+......................\n +.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@....................\n +......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@..................\n +....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@.................\n +...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................\n +..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................\n +.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................\n +.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+.............\n +..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#..............\n +..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#..........\n +.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............\n +.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:..........\n +...........:@#********************#%%*=:................=##****************************##:..........\n +.......#************************************************************************************-.......\n +..*----------------------------------------------------------------------------------------------*..\n +..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||..\n +..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||..\n +..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||..\n +..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||..\n +..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||..\n +..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||..\n +..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||..\n +..*----------------------------------------------------------------------------------------------*..\n +....................................................................................................\n +\n +Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is \n +currently under development at the University of Wisconsin-Madison, and in its alpha stage. \n +Epect more information to come as development continues! \n \ No newline at end of file From 5e88457776025c5de055db3378f19f5039c1a107 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 17:59:21 -0500 Subject: [PATCH 17/43] Second attempt at fixing readme file formatting --- README.md | 41 +++++++++++++++++++++++++++- README.rst | 78 +++++++++++++++++++++++++++--------------------------- 2 files changed, 79 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 2e11a2b..c58aa8d 100644 --- a/README.md +++ b/README.md @@ -1 +1,40 @@ -# tricycle \ No newline at end of file +# tricycle +.................................................................................................... +.................................................................................................... +...........................-@-............%@........................................................ +..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... +...........................@@@..-*==%............................................................... +..................................=*................................................................ +.................................@=#.........................#%..................................... +................................%=*@@@%#=..................#@@%..................................... +................................*=%=======.+%.......@%%%%%@%%@@..................................... +...............................@=%===========:%..........%@%@@...................................... +..............................@@++@============-#.........%%........................................ +.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... +.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... +......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. +....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. +...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ +..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ +.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ +.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. +..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. +..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... +.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ +.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... +...........:@#********************#%%*=:................=##****************************##:.......... +.......#************************************************************************************-....... +..*----------------------------------------------------------------------------------------------*.. +..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. +..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. +..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. +..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. +..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. +..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. +..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. +..*----------------------------------------------------------------------------------------------*.. +.................................................................................................... + +Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is +currently under development at the University of Wisconsin-Madison, and in its alpha stage. +Epect more information to come as development continues! \ No newline at end of file diff --git a/README.rst b/README.rst index 91b10c2..0d2dcc1 100644 --- a/README.rst +++ b/README.rst @@ -1,39 +1,39 @@ -....................................................................................................\n -....................................................................................................\n -...........................-@-............%@........................................................\n -..........................@.@@@-+%.#+=*#%%%%@@@@*...................................................\n -...........................@@@..-*==%...............................................................\n -..................................=*................................................................\n -.................................@=#.........................#%.....................................\n -................................%=*@@@%#=..................#@@%.....................................\n -................................*=%=======.+%.......@%%%%%@%%@@.....................................\n -...............................@=%===========:%..........%@%@@......................................\n -..............................@@++@============-#.........%%........................................\n -.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+......................\n -.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@....................\n -......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@..................\n -....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@.................\n -...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................\n -..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................\n -.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................\n -.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+.............\n -..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#..............\n -..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#..........\n -.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............\n -.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:..........\n -...........:@#********************#%%*=:................=##****************************##:..........\n -.......#************************************************************************************-.......\n -..*----------------------------------------------------------------------------------------------*..\n -..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||..\n -..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||..\n -..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||..\n -..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||..\n -..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||..\n -..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||..\n -..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||..\n -..*----------------------------------------------------------------------------------------------*..\n -....................................................................................................\n -\n -Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is \n -currently under development at the University of Wisconsin-Madison, and in its alpha stage. \n -Epect more information to come as development continues! \n \ No newline at end of file +.................................................................................................... +.................................................................................................... +...........................-@-............%@........................................................ +..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... +...........................@@@..-*==%............................................................... +..................................=*................................................................ +.................................@=#.........................#%..................................... +................................%=*@@@%#=..................#@@%..................................... +................................*=%=======.+%.......@%%%%%@%%@@..................................... +...............................@=%===========:%..........%@%@@...................................... +..............................@@++@============-#.........%%........................................ +.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... +.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... +......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. +....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. +...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ +..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ +.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ +.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. +..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. +..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... +.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ +.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... +...........:@#********************#%%*=:................=##****************************##:.......... +.......#************************************************************************************-....... +..*----------------------------------------------------------------------------------------------*.. +..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. +..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. +..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. +..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. +..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. +..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. +..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. +..*----------------------------------------------------------------------------------------------*.. +.................................................................................................... + +Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is +currently under development at the University of Wisconsin-Madison, and in its alpha stage. +Epect more information to come as development continues! \ No newline at end of file From 30ba79683ebb81b4feb4dd4517b007cc49f358a4 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Thu, 14 Mar 2024 18:01:56 -0500 Subject: [PATCH 18/43] removed ascii art from readme --- README.md | 36 ------------------------------------ README.rst | 36 ------------------------------------ 2 files changed, 72 deletions(-) diff --git a/README.md b/README.md index c58aa8d..07a3c44 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,4 @@ # tricycle -.................................................................................................... -.................................................................................................... -...........................-@-............%@........................................................ -..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... -...........................@@@..-*==%............................................................... -..................................=*................................................................ -.................................@=#.........................#%..................................... -................................%=*@@@%#=..................#@@%..................................... -................................*=%=======.+%.......@%%%%%@%%@@..................................... -...............................@=%===========:%..........%@%@@...................................... -..............................@@++@============-#.........%%........................................ -.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... -.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... -......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. -....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. -...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ -..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ -.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ -.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. -..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. -..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... -.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ -.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... -...........:@#********************#%%*=:................=##****************************##:.......... -.......#************************************************************************************-....... -..*----------------------------------------------------------------------------------------------*.. -..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. -..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. -..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. -..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. -..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. -..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. -..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. -..*----------------------------------------------------------------------------------------------*.. -.................................................................................................... - Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is currently under development at the University of Wisconsin-Madison, and in its alpha stage. Epect more information to come as development continues! \ No newline at end of file diff --git a/README.rst b/README.rst index 0d2dcc1..fc702e4 100644 --- a/README.rst +++ b/README.rst @@ -1,39 +1,3 @@ -.................................................................................................... -.................................................................................................... -...........................-@-............%@........................................................ -..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... -...........................@@@..-*==%............................................................... -..................................=*................................................................ -.................................@=#.........................#%..................................... -................................%=*@@@%#=..................#@@%..................................... -................................*=%=======.+%.......@%%%%%@%%@@..................................... -...............................@=%===========:%..........%@%@@...................................... -..............................@@++@============-#.........%%........................................ -.......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... -.........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... -......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. -....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. -...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ -..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ -.................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ -.............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. -..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. -..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... -.............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ -.............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... -...........:@#********************#%%*=:................=##****************************##:.......... -.......#************************************************************************************-....... -..*----------------------------------------------------------------------------------------------*.. -..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. -..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. -..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. -..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. -..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. -..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. -..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. -..*----------------------------------------------------------------------------------------------*.. -.................................................................................................... - Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is currently under development at the University of Wisconsin-Madison, and in its alpha stage. Epect more information to come as development continues! \ No newline at end of file From 97c2dec771b435bccd50161f810f4ff898511405 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 7 Apr 2024 18:39:25 -0500 Subject: [PATCH 19/43] changed internal inventories to better match Abdou 2021, made appropriate changes to unit tests, cleaned up --- src/reactor.cc | 189 ++++++++++++++++-------------- src/reactor.h | 60 +++++++--- src/reactor_tests.cc | 268 ++++++++++--------------------------------- 3 files changed, 208 insertions(+), 309 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 51e7bc1..49a872c 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -6,10 +6,10 @@ namespace tricycle { Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) { // capacities set somewhat arbitrarily - fuel_tracker.Init({&tritium_reserve}, 1000.0); + fuel_tracker.Init({&tritium_storage}, 1000.0); blanket_tracker.Init({&blanket}, 100000.0); - excess_tritium_tracker.Init({&tritium_storage}, 1000.0); - helium_tracker.Init({&helium_storage}, 1000.0); + //excess_tritium_tracker.Init({&tritium_excess}, 1000.0); + //helium_tracker.Init({&helium_storage}, 1000.0); } std::string Reactor::str() { @@ -17,59 +17,69 @@ std::string Reactor::str() { } void Reactor::Tick() { - if (core_loaded) { + if (sufficient_tritium_for_operation) { OperateReactor(TBR); blanket_fill_policy.Start(); - if (operational) { - Reactor::RecordStatus("Online", fusion_power); - } else { - Reactor::RecordStatus("Shut-down", 0); - } + //if (operational) { + Reactor::RecordStatus("Online", fusion_power); + //} else { + // Reactor::RecordStatus("Shut-down", 0); + //} } else { Reactor::RecordStatus("Shut-down", 0); } - DecayInventory(tritium_core); - DecayInventory(tritium_reserve); + //DecayInventory(tritium_core); + //DecayInventory(tritium_reserve); DecayInventory(tritium_storage); + DecayInventory(tritium_excess); - ExtractHelium(tritium_core); - ExtractHelium(tritium_reserve); + //ExtractHelium(tritium_core); + //ExtractHelium(tritium_reserve); ExtractHelium(tritium_storage); + ExtractHelium(tritium_excess); + + +//***************************************************************************** + // This is how we were selling tritium before, but we may need to think + // of a new way to do this // Pull excesss tritium out of reserve and put it into storage // Replenish core from Helium Extraction. - if (!tritium_reserve.empty() && core_loaded) { - double core_deficit = startup_inventory - tritium_core.quantity(); - - // Excess tritium will always be in tritium_reserve. + if (!tritium_storage.empty() && sufficient_tritium_for_operation) { + //double tritium_deficit = startup_inventory - tritium_core.quantity(); double surplus = std::max( - tritium_reserve.quantity() - reserve_inventory - core_deficit, 0.0); + tritium_storage.quantity() - startup_inventory, 0.0); - cyclus::Material::Ptr reserve_fuel = tritium_reserve.Pop(); - cyclus::Material::Ptr core_fuel = tritium_core.Pop(); + cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); + //cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - core_fuel->Absorb(reserve_fuel->ExtractQty(core_deficit)); - tritium_storage.Push(reserve_fuel->ExtractQty(surplus)); + //core_fuel->Absorb(reserve_fuel->ExtractQty(core_deficit)); + tritium_excess.Push(storage_fuel->ExtractQty(surplus)); - RecordOperationalInfo( - "Tritium Moved", - std::to_string(core_deficit) + "kg of T moved from reserve to core"); + //RecordOperationalInfo( + // "Tritium Moved", + // std::to_string(core_deficit) + "kg of T moved from reserve to core"); if (surplus > 0.0) { RecordOperationalInfo( "Tritium Moved", - std::to_string(surplus) + "kg of T moved from reserve to storage"); + std::to_string(surplus) + "kg of T moved from storage to excess"); } - tritium_reserve.Push(reserve_fuel); - tritium_core.Push(core_fuel); + //tritium_reserve.Push(reserve_fuel); + //tritium_core.Push(core_fuel); + tritium_storage.Push(storage_fuel); - CombineInventory(tritium_storage); + CombineInventory(tritium_excess); } +//***************************************************************************** + + // This pulls out some of the blanket each timestep so that fresh blanket can // be added. if (!blanket.empty() && - blanket.quantity() >= blanket_size * blanket_turnover_rate) { + blanket.quantity() >= blanket_size * blanket_turnover_rate && + context()->time() % blanket_turnover_frequency == 0) { cyclus::Material::Ptr blanket_mat = blanket.Pop(); cyclus::Material::Ptr spent_blanket = blanket_mat->ExtractQty(blanket_size * blanket_turnover_rate); @@ -88,34 +98,34 @@ void Reactor::Tick() { } void Reactor::Tock() { - if (!core_loaded) { + if (!sufficient_tritium_for_operation) { try { Startup(); fuel_startup_policy.Stop(); fuel_refill_policy.Start(); - core_loaded = true; } catch (const std::exception& e) { RecordOperationalInfo("Startup Error", e.what()); LOG(cyclus::LEV_INFO2, "Reactor") << e.what(); } } - CombineInventory(tritium_reserve); + CombineInventory(tritium_storage); CombineInventory(blanket); - RecordInventories(tritium_core.quantity(), tritium_reserve.quantity(), - tritium_storage.quantity(), blanket.quantity(), + RecordInventories(tritium_storage.quantity(), tritium_excess.quantity(), blanket.quantity(), helium_storage.quantity()); } void Reactor::EnterNotify() { cyclus::Facility::EnterNotify(); + fuel_usage = burn_rate * (fusion_power / MW_to_GW) / seconds_per_year * context()->dt(); + fuel_startup_policy - .Init(this, &tritium_reserve, std::string("Tritium Storage"), + .Init(this, &tritium_storage, std::string("Tritium Storage"), &fuel_tracker, std::string("ss"), - reserve_inventory + startup_inventory, - reserve_inventory + startup_inventory) + startup_inventory, + startup_inventory) .Set(fuel_incommod) .Start(); blanket_fill_policy @@ -133,12 +143,12 @@ void Reactor::EnterNotify() { cyclus::DoubleDistribution::Ptr size_dist = cyclus::FixedDoubleDist::Ptr(new cyclus::FixedDoubleDist(1)); fuel_refill_policy - .Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, + .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") { fuel_refill_policy - .Init(this, &tritium_reserve, std::string("Input"), &fuel_tracker, + .Init(this, &tritium_storage, std::string("Input"), &fuel_tracker, std::string("ss"), reserve_inventory, reserve_inventory) .Set(fuel_incommod); } else { @@ -150,7 +160,7 @@ void Reactor::EnterNotify() { } tritium_sell_policy - .Init(this, &tritium_storage, std::string("Excess Tritium")) + .Init(this, &tritium_excess, std::string("Excess Tritium")) .Set(fuel_incommod) .Start(); helium_sell_policy.Init(this, &helium_storage, std::string("Helium-3")) @@ -173,33 +183,36 @@ std::string Reactor::GetComp(cyclus::Material::Ptr mat) { } void Reactor::Startup() { - double reserve_qty = tritium_reserve.quantity(); - cyclus::Material::Ptr initial_reserve = tritium_reserve.Pop(); - cyclus::CompMap c = initial_reserve->comp()->atom(); + //double available_tritium = tritium_storage.quantity(); + cyclus::Material::Ptr initial_storage = tritium_storage.Peek(); + cyclus::CompMap c = initial_storage->comp()->atom(); cyclus::compmath::Normalize(&c, 1); - if ((reserve_qty >= (startup_inventory + reserve_inventory)) && - (GetComp(initial_reserve) == "{{10030000,1.000000}}")) { - cyclus::Material::Ptr initial_core = - initial_reserve->ExtractQty(startup_inventory); - tritium_core.Push(initial_core); - tritium_reserve.Push(initial_reserve); - RecordEvent("Startup", "Core Loaded with " + - std::to_string(tritium_core.quantity()) + - " kg of Tritium."); - } else if (GetComp(initial_reserve) != "{{10030000,1.000000}}") { - tritium_reserve.Push(initial_reserve); + if ((tritium_storage.quantity() >= (startup_inventory)) && + (GetComp(initial_storage) == "{{10030000,1.000000}}") && + startup_inventory >= fuel_usage) { + //cyclus::Material::Ptr initial_core = + // initial_reserve->ExtractQty(startup_inventory); + //tritium_core.Push(initial_core); + //tritium_reserve.Push(initial_reserve); + RecordEvent("Startup", "Sufficient tritium in system to begin operation"); + sufficient_tritium_for_operation = true; + } else if (startup_inventory < fuel_usage){ + throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ + std::string("to maintain reactor for full timestep!")); + } else if (GetComp(initial_storage) != "{{10030000,1.000000}}") { + //tritium_reserve.Push(initial_reserve); throw cyclus::ValueError( "Startup Failed: Fuel incommod not as expected. " + std::string("Expected Composition: {{10030000,1.000000}}. ") + std::string("Fuel Incommod Composition: ") + - std::string(GetComp(initial_reserve))); + std::string(GetComp(initial_storage))); } else { - tritium_reserve.Push(initial_reserve); + //tritium_reserve.Push(initial_reserve); throw cyclus::ValueError( - "Startup Failed: " + std::to_string(tritium_reserve.quantity()) + - " kg in reserve is less than required " + - std::to_string(startup_inventory + reserve_inventory) + + "Startup Failed: " + std::to_string(tritium_storage.quantity()) + + " kg in storage is less than required " + + std::to_string(startup_inventory) + " kg to start-up!"); } } @@ -277,15 +290,13 @@ void Reactor::RecordStatus(std::string status, double power) { ->Record(); } -void Reactor::RecordInventories(double core, double reserve, double storage, - double blanket, double helium) { +void Reactor::RecordInventories(double storage, double excess, double blanket, double helium) { context() ->NewDatum("ReactorInventories") ->AddVal("AgentId", id()) ->AddVal("Time", context()->time()) - ->AddVal("TritiumCore", core) - ->AddVal("TritiumReserve", reserve) ->AddVal("TritiumStorage", storage) + ->AddVal("TritiumExcess", excess) ->AddVal("LithiumBlanket", blanket) ->AddVal("HeliumStorage", helium) ->Record(); @@ -350,45 +361,55 @@ cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR) { return bred_fuel; } -void Reactor::OperateReactor(double TBR, double burn_rate) { - int seconds_per_year = 31536000; - double fuel_usage = - burn_rate * (fusion_power / 1000) / seconds_per_year * context()->dt(); +void Reactor::OperateReactor(double TBR) { - cyclus::Material::Ptr reserve_fuel = tritium_reserve.Pop(); - cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - if (core_fuel->quantity() > fuel_usage) { - cyclus::Material::Ptr used_fuel = core_fuel->ExtractQty(fuel_usage); - core_fuel->Absorb(BreedTritium(fuel_usage, TBR)); + cyclus::Material::Ptr fuel = tritium_storage.Pop(); + //cyclus::Material::Ptr core_fuel = tritium_core.Pop(); + + if (fuel->quantity() > fuel_usage) { + cyclus::Material::Ptr used_fuel = fuel->ExtractQty(fuel_usage); + fuel->Absorb(BreedTritium(fuel_usage, TBR)); + tritium_storage.Push(fuel); + //RecordOperationalInfo("Burned Tritium", std::to_string(fuel_usage) + "kg of tritium burned"); - if (((reserve_fuel->quantity() + core_fuel->quantity()) >= - startup_inventory)) { - reserve_fuel->Absorb(core_fuel); - tritium_core.Push(reserve_fuel->ExtractQty(startup_inventory)); - tritium_reserve.Push(reserve_fuel); + + + /* + if (((fuel->quantity()) >= reserve_inventory)) { + //reserve_fuel->Absorb(core_fuel); + //tritium_core.Push(reserve_fuel->ExtractQty(startup_inventory)); + tritium_reserve.Push(reserve_fuel); + } else { RecordOperationalInfo("Tritium Moved", std::to_string(core_fuel->quantity()) + "kg of T moved from core to reserve"); - reserve_fuel->Absorb(core_fuel); - tritium_reserve.Push(reserve_fuel); + //reserve_fuel->Absorb(core_fuel); + //tritium_reserve.Push(reserve_fuel); fuel_refill_policy.Stop(); blanket_fill_policy.Stop(); fuel_startup_policy.Start(); RecordEvent("Core Shut-down", "Not enough tritium to operate"); - core_loaded = false; + sufficient_tritium_for_operation = false; } + */ } else { - operational = false; + fuel_refill_policy.Stop(); + blanket_fill_policy.Stop(); + fuel_startup_policy.Start(); + RecordEvent("Core Shut-down", "Not enough tritium to operate"); + sufficient_tritium_for_operation = false; + /* RecordOperationalInfo("Operational Error", "core startup_inventory of " + std::to_string(startup_inventory) + " kg insufficient to support fuel_usage of " + std::to_string(fuel_usage) + "kg/timestep!"); - tritium_reserve.Push(reserve_fuel); - tritium_core.Push(core_fuel); + */ + tritium_storage.Push(fuel); + //tritium_core.Push(core_fuel); } } diff --git a/src/reactor.h b/src/reactor.h index 7746d4e..8286acd 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -126,22 +126,24 @@ class Reactor : public cyclus::Facility { } double TBR; - #pragma cyclus var { \ - "doc": "Minimum tritium inventory to hold in reserve in case of tritium recovery system failure", \ - "tooltip": "Minimum tritium inventory to hold in reserve (excluding core invneotry)", \ - "units": "kg", \ - "uilabel": "Reserve Inventory" \ - } - double reserve_inventory; - #pragma cyclus var { \ "doc": "Tritium required to start reactor, includes a reserve inventory", \ "tooltip": "Tritium inventory required to start reactor, includes reserve", \ "units": "kg", \ + "uitype": "range", \ + "range": [0, 1e299], \ "uilabel": "Start-up Inventory" \ } double startup_inventory; + #pragma cyclus var { \ + "doc": "Minimum tritium inventory to hold in reserve in case of tritium recovery system failure", \ + "tooltip": "Minimum tritium inventory to hold in reserve (excluding core invneotry)", \ + "units": "kg", \ + "uilabel": "Reserve Inventory" \ + } + double reserve_inventory; + #pragma cyclus var { \ "default": 'fill', \ "doc": "Method of refueling the reactor", \ @@ -226,7 +228,7 @@ class Reactor : public cyclus::Facility { //WARNING: The default on this is completely arbitrary! #pragma cyclus var { \ "default": 0.05, \ - "doc": "Percent of blanket that gets recycled every timestep", \ + "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", \ @@ -235,18 +237,40 @@ class Reactor : public cyclus::Facility { } double blanket_turnover_rate; - bool operational = true; - bool core_loaded = false; + #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; + + //bool operational = true; + bool sufficient_tritium_for_operation = false; + int seconds_per_year = 31536000; + int MW_to_GW = 1000; + double fuel_usage; + + // kg/GW-fusion-power-year (Abdou et al. 2021) + double burn_rate = 55.8; + /* #pragma cyclus var {"tooltip":"Buffer for handling tritium kept in the core"} cyclus::toolkit::ResBuf tritium_core; #pragma cyclus var {"tooltip":"Buffer for handling tritium kept in reserve"} cyclus::toolkit::ResBuf tritium_reserve; + */ - #pragma cyclus var {"tooltip":"Buffer for handling excess tritium material to be sold"} + #pragma cyclus var {"tooltip":"Buffer for handling tritium material to be used in reactor"} cyclus::toolkit::ResBuf tritium_storage; + #pragma cyclus var {"tooltip":"Buffer for handling excess tritium material to be sold"} + cyclus::toolkit::ResBuf tritium_excess; + #pragma cyclus var {"tooltip":"Buffer for handling helium-3 byproduct material"} cyclus::toolkit::ResBuf helium_storage; @@ -259,11 +283,11 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"tooltip":"Tracker to handle blanket material"} cyclus::toolkit::TotalInvTracker blanket_tracker; - #pragma cyclus var {"tooltip":"Tracker to handle excess tritium to be sold"} - cyclus::toolkit::TotalInvTracker excess_tritium_tracker; + //#pragma cyclus var {"tooltip":"Tracker to handle excess tritium to be sold"} + //cyclus::toolkit::TotalInvTracker excess_tritium_tracker; - #pragma cyclus var {"tooltip":"Tracker to handle on-hand helium"} - cyclus::toolkit::TotalInvTracker helium_tracker; + //#pragma cyclus var {"tooltip":"Tracker to handle on-hand helium"} + //cyclus::toolkit::TotalInvTracker helium_tracker; cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; @@ -274,13 +298,13 @@ class Reactor : public cyclus::Facility { cyclus::toolkit::MatlSellPolicy helium_sell_policy; void Startup(); - void OperateReactor(double TBR, double burn_rate=55.8); + void OperateReactor(double TBR); void DecayInventory(cyclus::toolkit::ResBuf &inventory); void CombineInventory(cyclus::toolkit::ResBuf &inventory); void ExtractHelium(cyclus::toolkit::ResBuf &inventory); void RecordEvent(std::string name, std::string val); void RecordStatus(std::string Status, double power); - void RecordInventories(double core, double reserve, double storage, double blanket, double helium); + void RecordInventories(double storage, double excess, double blanket, double helium); void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 3b36550..db1f35d 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -64,13 +64,15 @@ TEST_F(ReactorTest, Print) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(ReactorTest, TickCoreNotLoaded) { - // Test Reactor specific behaviors of the Tick function here +TEST_F(ReactorTest, TickInsufficientTritium) { + // Test that the agent records "shut down" each timestep for which it has + // insufficient tritium to startup. This is achieved by not adding a tritium + // source to the mocksim. std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -96,86 +98,16 @@ TEST_F(ReactorTest, TickCoreNotLoaded) { EXPECT_EQ(simdur, qr_rows); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(ReactorTest, TickNotOperational) { - // Test Reactor specific behaviors of the Tick function here - - std::string config = - " 300 " - " 1.00 " - " 6" - " 0.1" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; - - int simdur = 10; - cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); - - sim.AddRecipe("tritium", tritium()); - sim.AddRecipe("enriched_lithium", enriched_lithium()); - - sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); - - int id = sim.Run(); - - std::vector conds; - conds.push_back(Cond("Status", "==", std::string("Shut-down"))); - QueryResult qr = sim.db().Query("ReactorStatus", &conds); - double qr_rows = qr.rows.size(); - - EXPECT_EQ(simdur, qr_rows); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(ReactorTest, TickCoreReplenish) { - // Test Reactor specific behaviors of the Tick function here - - std::string config = - " 300 " - " 1.00 " - " 6" - " 2.121" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; - - int simdur = 4; - cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); - - sim.AddRecipe("tritium", tritium()); - sim.AddRecipe("enriched_lithium", enriched_lithium()); - - sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); - - int id = sim.Run(); - - std::vector conds; - conds.push_back(Cond("TritiumCore", "==", std::string("2.121"))); - QueryResult qr = sim.db().Query("ReactorInventories", &conds); - double qr_rows = qr.rows.size(); - - // If the core isn't replenished during tick it will report less than - // startup_inventory during some timestep. This checks that in every - // timestep it's what it should be - - EXPECT_EQ(simdur, qr_rows); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, TickBlanketCycle) { - // Test Reactor specific behaviors of the Tick function here + // Test that the agent correctly removes and replaces a portion of the + // blanket every blanket turnover period. The default period is 1 timestep + // so it is left undefined here. std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -206,12 +138,14 @@ TEST_F(ReactorTest, TickBlanketCycle) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, TickBlanketOverCycle) { - // Test Reactor specific behaviors of the Tick function here + // Test the catch for an overcycle of the blanket. The user should be + // notified of this occuring in the ReactorOperationsLog, and the + // simulation should not crash. std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -247,8 +181,8 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, Tock) { - // Test Reactor specific behaviors of the Tock function here - // Note: All specific tock functionality tested in other places. + // Test that the Tock function does not throw an error. More specific + // functionality is tested elsewhere. EXPECT_NO_THROW(facility->Tock()); } @@ -260,7 +194,7 @@ TEST_F(ReactorTest, NormalStartup) { std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -275,7 +209,6 @@ TEST_F(ReactorTest, NormalStartup) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -297,7 +230,7 @@ TEST_F(ReactorTest, FuelConstrainedStartup) { std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -311,15 +244,14 @@ TEST_F(ReactorTest, FuelConstrainedStartup) { sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); - sim.AddSource("Tritium").recipe("tritium").capacity(8.0).Finalize(); - + sim.AddSource("Tritium").recipe("tritium").capacity(2.0).Finalize(); sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); // Under these conditions, we expect the reactor to be able to startup on - // timestep 1 but not before then (buys 8kg of T on each timestep, and - // needs 8.121kg to startup). NOTE: startup occurs after DRE. + // timestep 1 but not before then (buys 2kg of T on each timestep, and + // needs 2.121kg to startup). NOTE: startup occurs after DRE. std::vector conds0; conds0.push_back(Cond("Time", "==", std::string("0"))); QueryResult qr0 = sim.db().Query("ReactorOperationsLog", &conds0); @@ -337,12 +269,14 @@ TEST_F(ReactorTest, FuelConstrainedStartup) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, NoFuelStartup) { - // Test no fuel startup behavior of the Startup function + // Test that the agent can handle never recieving any fuel, and appropriately + // does not start-up under these conditions. This is achieved by not adding + // a source of tritium to the mocksim. std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -372,12 +306,14 @@ TEST_F(ReactorTest, NoFuelStartup) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, WrongFuelStartup) { - // Test wrong fuel startup behavior of the Startup function + // Test that the agent can identify that it has not recieved the correct fuel + // to startup, and will appropriately notify the user, and not start-up under + // these conditions. std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Enriched_Lithium" " Enriched_Lithium" @@ -422,7 +358,7 @@ TEST_F(ReactorTest, WrongFuelStartup) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, DecayInventory) { // Test behaviors of the DecayInventory function here - EXPECT_NO_THROW(facility->DecayInventory(facility->tritium_core)); + EXPECT_NO_THROW(facility->DecayInventory(facility->tritium_storage)); // We use unintuitive values for reserve inventory and startup inventory here // because they were the values we were originally testing with, and we had @@ -430,8 +366,8 @@ TEST_F(ReactorTest, DecayInventory) { std::string config = " 300 " " 1.00 " - " 6" - " 2.121" + " 0" + " 8.121" " Tritium" " Enriched_Lithium" " Lithium" @@ -445,7 +381,6 @@ TEST_F(ReactorTest, DecayInventory) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -506,9 +441,6 @@ TEST_F(ReactorTest, CombineInventory) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, CombineInventoryOneElement) { // Test behaviors of the CombineInventory function here - - // do I need the pragma here? - // #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily cyclus::toolkit::ResBuf test_buf; cyclus::Material::Ptr T1 = cyclus::Material::CreateUntracked(2.5, tritium()); @@ -527,9 +459,6 @@ TEST_F(ReactorTest, CombineInventoryOneElement) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, CombineEmptyInventory) { // Test behaviors of the CombineInventory function here - - // do I need the pragma here? - // #pragma cyclus var {"capacity" : "1000"} //capacity set to 1000 arbitrarily cyclus::toolkit::ResBuf test_buf; EXPECT_NO_THROW(facility->CombineInventory(test_buf)); @@ -583,7 +512,7 @@ TEST_F(ReactorTest, RecordEvent) { std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -598,7 +527,6 @@ TEST_F(ReactorTest, RecordEvent) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -618,7 +546,7 @@ TEST_F(ReactorTest, RecordInventories) { std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -633,7 +561,6 @@ TEST_F(ReactorTest, RecordInventories) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -641,15 +568,14 @@ TEST_F(ReactorTest, RecordInventories) { std::vector conds; conds.push_back(Cond("Time", "==", std::string("0"))); QueryResult qr = sim.db().Query("ReactorInventories", &conds); - double tritium_core = qr.GetVal("TritiumCore"); - double tritium_reserve = qr.GetVal("TritiumReserve"); double tritium_storage = qr.GetVal("TritiumStorage"); + double tritium_excess = qr.GetVal("TritiumExcess"); double blanket = qr.GetVal("LithiumBlanket"); double helium_storage = qr.GetVal("HeliumStorage"); - EXPECT_EQ(2.121, tritium_core); - EXPECT_EQ(6.0, tritium_reserve); - EXPECT_EQ(0.0, tritium_storage); + + EXPECT_EQ(2.121, tritium_storage); + EXPECT_EQ(0.0, tritium_excess); EXPECT_EQ(1000.0, blanket); EXPECT_EQ(0.0, helium_storage); } @@ -661,7 +587,7 @@ TEST_F(ReactorTest, RecordStatus) { std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -676,7 +602,6 @@ TEST_F(ReactorTest, RecordStatus) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -707,7 +632,7 @@ TEST_F(ReactorTest, DepleteBlanket) { std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -722,7 +647,6 @@ TEST_F(ReactorTest, DepleteBlanket) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -742,7 +666,7 @@ TEST_F(ReactorTest, OverDepleteBlanket) { std::string config = " 300 " " 1.50 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -757,7 +681,6 @@ TEST_F(ReactorTest, OverDepleteBlanket) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium") .recipe("enriched_lithium") .capacity(10) @@ -780,7 +703,7 @@ TEST_F(ReactorTest, BreedTritium) { std::string config = " 300 " " 1.05 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -795,7 +718,6 @@ TEST_F(ReactorTest, BreedTritium) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -818,7 +740,7 @@ TEST_F(ReactorTest, OperateReactorSustainingTBR) { std::string config = " 300 " " 1.05 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -833,7 +755,6 @@ TEST_F(ReactorTest, OperateReactorSustainingTBR) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -849,22 +770,22 @@ TEST_F(ReactorTest, OperateReactorSustainingTBR) { std::vector conds_2; conds_2.push_back(Cond("Time", "==", std::string("9"))); QueryResult qr_2 = sim.db().Query("ReactorInventories", &conds_2); - double storage_quantity = qr_2.GetVal("TritiumStorage"); + double excess_quantity = qr_2.GetVal("TritiumExcess"); // We should have extra Tritium - EXPECT_LT(0, storage_quantity); + EXPECT_LT(0, excess_quantity); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { // Test behaviors of the OperateReactor function here // Expect very similar behavior to Sustaining scenario - // except no tritium in storage. + // except no tritium in excess. std::string config = " 300 " " 0.8 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -879,7 +800,6 @@ TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -895,10 +815,10 @@ TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { std::vector conds_2; conds_2.push_back(Cond("Time", "==", std::string("9"))); QueryResult qr_2 = sim.db().Query("ReactorInventories", &conds_2); - double storage_quantity = qr_2.GetVal("TritiumStorage"); + double excess_quantity = qr_2.GetVal("TritiumExcess"); // We should have extra Tritium - EXPECT_EQ(0, storage_quantity); + EXPECT_EQ(0, excess_quantity); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -908,7 +828,7 @@ TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { std::string config = " 300 " " 0.0 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -923,7 +843,6 @@ TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").capacity(1).Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -937,64 +856,16 @@ TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { EXPECT_EQ(expected_msg, msg); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(ReactorTest, OperateReactorCoreSizeTooSmall) { - // Test behaviors of the OperateReactor function here - - std::string config = - " 300 " - " 1.05 " - " 6" - " 0.1" - " Tritium" - " Enriched_Lithium" - " enriched_lithium" - " 1000" - " Helium_3"; - - int simdur = 10; - cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); - - sim.AddRecipe("tritium", tritium()); - sim.AddRecipe("enriched_lithium", enriched_lithium()); - - sim.AddSource("Tritium").recipe("tritium").Finalize(); - - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); - - int id = sim.Run(); - - std::vector conds_1; - conds_1.push_back(Cond("Status", "==", std::string("Shut-down"))); - QueryResult qr_1 = sim.db().Query("ReactorStatus", &conds_1); - double qr_1_rows = qr_1.rows.size(); - - EXPECT_EQ(simdur, qr_1_rows); - - std::vector conds_2; - conds_2.push_back(Cond("Time", "==", std::string("1"))); - QueryResult qr_2 = sim.db().Query("ReactorOperationsLog", &conds_2); - std::string event = qr_2.GetVal("Event"); - std::string msg = qr_2.GetVal("Value"); - - std::string expected_event = "Operational Error"; - std::string expected_msg = - "core startup_inventory of 0.100000 kg insufficient to support " - "fuel_usage of 1.395980kg/timestep!"; - - EXPECT_EQ(expected_event, event); - EXPECT_EQ(expected_msg, msg); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { - // Test behaviors of the OperateReactor function here + // Test default fill behavior of EnterNotify. Specifically look that + // tritium is transacted in the appropriate amounts. std::string config = " 300 " " 1.00 " - " 6" - " 2.121" + " 0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" @@ -1008,7 +879,6 @@ TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -1025,30 +895,17 @@ TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { double quantity = qr_2.GetVal("Quantity"); EXPECT_EQ(8.121, quantity); - - std::vector conds_3; - conds_3.push_back(Cond("Time", "==", std::string("1"))); - conds_3.push_back(Cond("Commodity", "==", std::string("Tritium"))); - QueryResult qr_3 = sim.db().Query("Transactions", &conds_3); - int resource_id_2 = qr_3.GetVal("ResourceId"); - - std::vector conds_4; - conds_4.push_back(Cond("ResourceId", "==", std::to_string(resource_id_2))); - QueryResult qr_4 = sim.db().Query("Resources", &conds_4); - double quantity_2 = qr_4.GetVal("Quantity"); - - EXPECT_NEAR(0.0379868, quantity_2, 1e-7); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, EnterNotifyScheduleFill) { - // Test behaviors of the OperateReactor function here + // Test schedule fill behavior of EnterNotify. std::string config = " 300 " " 1.00 " - " 6" - " 2.121" + " 0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" @@ -1065,7 +922,6 @@ TEST_F(ReactorTest, EnterNotifyScheduleFill) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); @@ -1099,12 +955,12 @@ TEST_F(ReactorTest, EnterNotifyScheduleFill) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, EnterNotifyInvalidFill) { - // Test behaviors of the OperateReactor function here + // Test catch for invalid fill behavior keyword in EnterNotify. std::string config = " 300 " " 1.00 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -1122,7 +978,6 @@ TEST_F(ReactorTest, EnterNotifyInvalidFill) { sim.AddRecipe("enriched_lithium", enriched_lithium()); sim.AddSource("Tritium").recipe("tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); EXPECT_THROW(int id = sim.Run(), cyclus::KeyError); @@ -1130,12 +985,12 @@ TEST_F(ReactorTest, EnterNotifyInvalidFill) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, EnterNotifySellPolicy) { - // Test behaviors of the OperateReactor function here + // Test sell policy behavior of enter notify. std::string config = " 300 " " 1.30 " - " 6" + " 0" " 2.121" " Tritium" " Enriched_Lithium" @@ -1151,13 +1006,12 @@ TEST_F(ReactorTest, EnterNotifySellPolicy) { sim.AddSource("Tritium").capacity(100).recipe("tritium").Finalize(); sim.AddSink("Tritium").Finalize(); - sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); std::vector conds; - conds.push_back(Cond("TritiumStorage", "==", std::string("0"))); + conds.push_back(Cond("TritiumExcess", "==", std::string("0"))); QueryResult qr = sim.db().Query("ReactorInventories", &conds); double qr_rows = qr.rows.size(); From 1aa8ee11231509b9e19bb415eadd1c0ce8697e19 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 7 Apr 2024 19:14:24 -0500 Subject: [PATCH 20/43] added test case for 0% and 100% Li7_contribution, cleaned up some more commented code --- src/reactor.cc | 75 ++------------------------------------------ src/reactor.h | 15 --------- src/reactor_tests.cc | 64 +++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 87 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 49a872c..567c76c 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -8,8 +8,6 @@ Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) { // capacities set somewhat arbitrarily fuel_tracker.Init({&tritium_storage}, 1000.0); blanket_tracker.Init({&blanket}, 100000.0); - //excess_tritium_tracker.Init({&tritium_excess}, 1000.0); - //helium_tracker.Init({&helium_storage}, 1000.0); } std::string Reactor::str() { @@ -20,61 +18,33 @@ void Reactor::Tick() { if (sufficient_tritium_for_operation) { OperateReactor(TBR); blanket_fill_policy.Start(); - //if (operational) { Reactor::RecordStatus("Online", fusion_power); - //} else { - // Reactor::RecordStatus("Shut-down", 0); - //} } else { Reactor::RecordStatus("Shut-down", 0); } - //DecayInventory(tritium_core); - //DecayInventory(tritium_reserve); DecayInventory(tritium_storage); DecayInventory(tritium_excess); - //ExtractHelium(tritium_core); - //ExtractHelium(tritium_reserve); ExtractHelium(tritium_storage); ExtractHelium(tritium_excess); - - -//***************************************************************************** - // This is how we were selling tritium before, but we may need to think - // of a new way to do this - // Pull excesss tritium out of reserve and put it into storage - // Replenish core from Helium Extraction. if (!tritium_storage.empty() && sufficient_tritium_for_operation) { - //double tritium_deficit = startup_inventory - tritium_core.quantity(); double surplus = std::max( - tritium_storage.quantity() - startup_inventory, 0.0); + tritium_storage.quantity() - startup_inventory, 0.0); cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); - //cyclus::Material::Ptr core_fuel = tritium_core.Pop(); - - //core_fuel->Absorb(reserve_fuel->ExtractQty(core_deficit)); tritium_excess.Push(storage_fuel->ExtractQty(surplus)); - //RecordOperationalInfo( - // "Tritium Moved", - // std::to_string(core_deficit) + "kg of T moved from reserve to core"); if (surplus > 0.0) { RecordOperationalInfo( "Tritium Moved", std::to_string(surplus) + "kg of T moved from storage to excess"); } - //tritium_reserve.Push(reserve_fuel); - //tritium_core.Push(core_fuel); tritium_storage.Push(storage_fuel); - CombineInventory(tritium_excess); } -//***************************************************************************** - - // This pulls out some of the blanket each timestep so that fresh blanket can // be added. if (!blanket.empty() && @@ -183,7 +153,6 @@ std::string Reactor::GetComp(cyclus::Material::Ptr mat) { } void Reactor::Startup() { - //double available_tritium = tritium_storage.quantity(); cyclus::Material::Ptr initial_storage = tritium_storage.Peek(); cyclus::CompMap c = initial_storage->comp()->atom(); cyclus::compmath::Normalize(&c, 1); @@ -191,24 +160,18 @@ void Reactor::Startup() { if ((tritium_storage.quantity() >= (startup_inventory)) && (GetComp(initial_storage) == "{{10030000,1.000000}}") && startup_inventory >= fuel_usage) { - //cyclus::Material::Ptr initial_core = - // initial_reserve->ExtractQty(startup_inventory); - //tritium_core.Push(initial_core); - //tritium_reserve.Push(initial_reserve); RecordEvent("Startup", "Sufficient tritium in system to begin operation"); sufficient_tritium_for_operation = true; } else if (startup_inventory < fuel_usage){ throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ std::string("to maintain reactor for full timestep!")); } else if (GetComp(initial_storage) != "{{10030000,1.000000}}") { - //tritium_reserve.Push(initial_reserve); throw cyclus::ValueError( "Startup Failed: Fuel incommod not as expected. " + std::string("Expected Composition: {{10030000,1.000000}}. ") + std::string("Fuel Incommod Composition: ") + std::string(GetComp(initial_storage))); } else { - //tritium_reserve.Push(initial_reserve); throw cyclus::ValueError( "Startup Failed: " + std::to_string(tritium_storage.quantity()) + " kg in storage is less than required " + @@ -363,53 +326,21 @@ cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR) { void Reactor::OperateReactor(double TBR) { - cyclus::Material::Ptr fuel = tritium_storage.Pop(); - //cyclus::Material::Ptr core_fuel = tritium_core.Pop(); if (fuel->quantity() > fuel_usage) { cyclus::Material::Ptr used_fuel = fuel->ExtractQty(fuel_usage); fuel->Absorb(BreedTritium(fuel_usage, TBR)); tritium_storage.Push(fuel); - //RecordOperationalInfo("Burned Tritium", std::to_string(fuel_usage) + "kg of tritium burned"); - - - - - /* - if (((fuel->quantity()) >= reserve_inventory)) { - //reserve_fuel->Absorb(core_fuel); - //tritium_core.Push(reserve_fuel->ExtractQty(startup_inventory)); - tritium_reserve.Push(reserve_fuel); - - } else { - RecordOperationalInfo("Tritium Moved", - std::to_string(core_fuel->quantity()) + - "kg of T moved from core to reserve"); - //reserve_fuel->Absorb(core_fuel); - //tritium_reserve.Push(reserve_fuel); - fuel_refill_policy.Stop(); - blanket_fill_policy.Stop(); - fuel_startup_policy.Start(); - RecordEvent("Core Shut-down", "Not enough tritium to operate"); - sufficient_tritium_for_operation = false; - } - */ + } else { fuel_refill_policy.Stop(); blanket_fill_policy.Stop(); fuel_startup_policy.Start(); RecordEvent("Core Shut-down", "Not enough tritium to operate"); sufficient_tritium_for_operation = false; - /* - RecordOperationalInfo("Operational Error", - "core startup_inventory of " + - std::to_string(startup_inventory) + - " kg insufficient to support fuel_usage of " + - std::to_string(fuel_usage) + "kg/timestep!"); - */ + tritium_storage.Push(fuel); - //tritium_core.Push(core_fuel); } } diff --git a/src/reactor.h b/src/reactor.h index 8286acd..886c99b 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -248,7 +248,6 @@ class Reactor : public cyclus::Facility { } int blanket_turnover_frequency; - //bool operational = true; bool sufficient_tritium_for_operation = false; int seconds_per_year = 31536000; int MW_to_GW = 1000; @@ -257,14 +256,6 @@ class Reactor : public cyclus::Facility { // kg/GW-fusion-power-year (Abdou et al. 2021) double burn_rate = 55.8; - /* - #pragma cyclus var {"tooltip":"Buffer for handling tritium kept in the core"} - cyclus::toolkit::ResBuf tritium_core; - - #pragma cyclus var {"tooltip":"Buffer for handling tritium kept in reserve"} - cyclus::toolkit::ResBuf tritium_reserve; - */ - #pragma cyclus var {"tooltip":"Buffer for handling tritium material to be used in reactor"} cyclus::toolkit::ResBuf tritium_storage; @@ -282,12 +273,6 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"tooltip":"Tracker to handle blanket material"} cyclus::toolkit::TotalInvTracker blanket_tracker; - - //#pragma cyclus var {"tooltip":"Tracker to handle excess tritium to be sold"} - //cyclus::toolkit::TotalInvTracker excess_tritium_tracker; - - //#pragma cyclus var {"tooltip":"Tracker to handle on-hand helium"} - //cyclus::toolkit::TotalInvTracker helium_tracker; cyclus::toolkit::MatlBuyPolicy fuel_startup_policy; cyclus::toolkit::MatlBuyPolicy fuel_refill_policy; diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index db1f35d..26a4e27 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -659,6 +659,70 @@ TEST_F(ReactorTest, DepleteBlanket) { EXPECT_EQ("Blanket Depletion", event); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(ReactorTest, DepleteBlanketLi7EdgeCases) { + // Test behaviors of the DepleteBlanket function here + + std::string config_1 = + " 300 " + " 1.08 " + " 0" + " 8.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3" + " 0.00"; + + std::string config_2 = + " 300 " + " 1.08 " + " 0" + " 8.121" + " Tritium" + " Enriched_Lithium" + " enriched_lithium" + " 1000" + " Helium_3" + " 1.00"; + + int simdur = 2; + cyclus::MockSim sim_1(cyclus::AgentSpec(":tricycle:Reactor"), config_1, simdur); + + sim_1.AddRecipe("tritium", tritium()); + sim_1.AddRecipe("enriched_lithium", enriched_lithium()); + + sim_1.AddSource("Tritium").recipe("tritium").Finalize(); + sim_1.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id_1 = sim_1.Run(); + + + cyclus::MockSim sim_2(cyclus::AgentSpec(":tricycle:Reactor"), config_2, simdur); + + sim_2.AddRecipe("tritium", tritium()); + sim_2.AddRecipe("enriched_lithium", enriched_lithium()); + + sim_2.AddSource("Tritium").recipe("tritium").Finalize(); + sim_2.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); + + int id_2 = sim_2.Run(); + + std::vector conds_1; + conds_1.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr_1 = sim_1.db().Query("ReactorInventories", &conds_1); + double excess_1 = qr_1.GetVal("TritiumExcess"); + + std::vector conds_2; + conds_2.push_back(Cond("Time", "==", std::string("1"))); + QueryResult qr_2 = sim_2.db().Query("ReactorInventories", &conds_2); + double excess_2 = qr_2.GetVal("TritiumExcess"); + + EXPECT_EQ(excess_1, excess_2); +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, OverDepleteBlanket) { // Test behaviors of the DepleteBlanket function here From ddb2bbc3cc08db23cbf228878950a8654815301d Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 7 Apr 2024 19:24:48 -0500 Subject: [PATCH 21/43] simplified the way spent blanket material is popped for disposal --- src/reactor.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 567c76c..4d0e4ff 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -50,13 +50,11 @@ void Reactor::Tick() { if (!blanket.empty() && blanket.quantity() >= blanket_size * blanket_turnover_rate && context()->time() % blanket_turnover_frequency == 0) { - cyclus::Material::Ptr blanket_mat = blanket.Pop(); cyclus::Material::Ptr spent_blanket = - blanket_mat->ExtractQty(blanket_size * blanket_turnover_rate); + blanket.Pop(blanket_size * blanket_turnover_rate); RecordOperationalInfo( "Blanket Cycled", std::to_string(spent_blanket->quantity()) + "kg of blanket removed"); - blanket.Push(blanket_mat); } else if (!blanket.empty() && blanket.quantity() < blanket_size * blanket_turnover_rate) { RecordOperationalInfo( From 30fd9de7f97644871bb29056fab3a4d3bb7d4906 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 7 Apr 2024 19:51:03 -0500 Subject: [PATCH 22/43] added blanket_turnover variable to only calculate that value once --- src/reactor.cc | 13 ++++++++----- src/reactor.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 4d0e4ff..bc4c775 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -47,21 +47,24 @@ void Reactor::Tick() { // This pulls out some of the blanket each timestep so that fresh blanket can // be added. - if (!blanket.empty() && - blanket.quantity() >= blanket_size * blanket_turnover_rate && + // NOTE: currently spent blanket dissapears into the ether. This needs to be + // changed in version 1 for materials tracking. + + double blanket_turnover = blanket_size * blanket_turnover_rate; + if (!blanket.empty() && blanket.quantity() >= blanket_turnover && context()->time() % blanket_turnover_frequency == 0) { cyclus::Material::Ptr spent_blanket = - blanket.Pop(blanket_size * blanket_turnover_rate); + blanket.Pop(blanket_turnover); RecordOperationalInfo( "Blanket Cycled", std::to_string(spent_blanket->quantity()) + "kg of blanket removed"); } else if (!blanket.empty() && - blanket.quantity() < blanket_size * blanket_turnover_rate) { + blanket.quantity() < blanket_turnover) { RecordOperationalInfo( "Blanket Not Cycled", "Total blanket material (" + std::to_string(blanket.quantity()) + ") insufficient to extract " + - std::to_string(blanket_size * blanket_turnover_rate) + "kg!"); + std::to_string(blanket_turnover) + "kg!"); } } diff --git a/src/reactor.h b/src/reactor.h index 886c99b..7f4e609 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -138,7 +138,7 @@ class Reactor : public cyclus::Facility { #pragma cyclus var { \ "doc": "Minimum tritium inventory to hold in reserve in case of tritium recovery system failure", \ - "tooltip": "Minimum tritium inventory to hold in reserve (excluding core invneotry)", \ + "tooltip": "Minimum tritium inventory to hold in reserve", \ "units": "kg", \ "uilabel": "Reserve Inventory" \ } From 8ed0747a3d50d722bbea001c8660fd781865f501 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 7 Apr 2024 20:07:50 -0500 Subject: [PATCH 23/43] new attempt at fixing README. Deleted README.md (redundant) --- README.md | 4 ---- README.rst | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 07a3c44..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# tricycle -Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is -currently under development at the University of Wisconsin-Madison, and in its alpha stage. -Epect more information to come as development continues! \ No newline at end of file diff --git a/README.rst b/README.rst index fc702e4..33cdc40 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,41 @@ +.. code-block:: bash + .................................................................................................... + .................................................................................................... + ...........................-@-............%@........................................................ + ..........................@.@@@-+%.#+=*#%%%%@@@@*................................................... + ...........................@@@..-*==%............................................................... + ..................................=*................................................................ + .................................@=#.........................#%..................................... + ................................%=*@@@%#=..................#@@%..................................... + ................................*=%=======.+%.......@%%%%%@%%@@..................................... + ...............................@=%===========:%..........%@%@@...................................... + ..............................@@++@============-#.........%%........................................ + .......................-%@@%#@@@%-..+@@:.................+@........-%@@@%@@@@+...................... + .........................@@@%%@=+@+..+=%................:=%%....*@@@%*********#@.................... + ......................:@%@@@%%--%*:@..%=%...............*@.-*#.@@@#*************#@.................. + ....................@@@@+..:@#=@%***@+.%=%.............#=...@%%@@****@@@@@@@@@%**=@................. + ...................@%*..@%##@-%@@@***@..@=%............+@..%%@@@***%%@..:%%:..@@#*%%................ + ..................@%..@====@=#%..@@**=@..%=================@%%%%**@@@.======+@.#@#*@................ + .................@%%.%===@@@%@*%-@@#*+@...%===============@@@@@#**@@.:===%*==*#.@@@@................ + .............-...@%*.@===@@@#-=%.@@@#%=...........%%%%%@@@@@@@@#@@@%..===@===*%.@@....+............. + ..............=..%%@.#+=======%:.@@..=.......................@@@@@%@#.:======%.:@@...#.............. + ..........-:#....:%@@..@*===%@..@%-...........................@@@@@@%-%:.:=.::=@@...@.-..#.......... + .............-+@:%*%@@@......:@@@...............................@@@%@@@@....@@%@#%:+@:##............ + .............%@%%@@%##@@%@@@%@%.....................................#@@@@@@@@@%@#*@%*@@..:.......... + ...........:@#********************#%%*=:................=##****************************##:.......... + .......#************************************************************************************-....... + ..*----------------------------------------------------------------------------------------------*.. + ..|| @@@@@@@@@@+ @@@@@@@@@@. @@@ @@@@@@@@@ .@@@ :@@@ .@@@@@@@@@ .@@: .@@@@@@@@@@ ||.. + ..|| .@@+ @@# @@@ @@@ @@@ @@@ @@@ *@@= .@@% .@@@ .@@: .@@. ||.. + ..|| .@@+ @@# -@@@ @@@ %@@ @@@%@@. @@@ .@@: .@@+======. ||.. + ..|| .@@+ @@@@@@@@@ @@@ @@@ #@@@. @@@ .@@: .@@@@@@@@@. ||.. + ..|| .@@+ @@# .@@@ @@@ -@@: @@. @@@ @@@ @# .@@: .@@. ||.. + ..|| .@@+ @@# @@@. @@@ @@@@ .@@@* @@@ @@@: .@@@. .@@: .@@. ||.. + ..|| .@@+ @@# @@@+ @@@ @@@@@@@ @@@ :@@@@@@% .@@@@@@@@@..@@@@@@@@@@ ||.. + ..*----------------------------------------------------------------------------------------------*.. + .................................................................................................... + + Tricycle is a collection of CYCLUS archetypes designed to model the fusion fuel cycle. It is currently under development at the University of Wisconsin-Madison, and in its alpha stage. Epect more information to come as development continues! \ No newline at end of file From 30910bacf99e33d9f1f8d4424fc8277190fc2e1d Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Fri, 12 Apr 2024 16:49:20 -0500 Subject: [PATCH 24/43] removed magic numbers, made tritium breeding calc more precise, updated README, moved some variables to header and made const --- README.rst | 1 + src/reactor.cc | 33 ++++++++++++++------------------- src/reactor.h | 43 +++++++++++++++++++++++++++++++++++-------- src/reactor_tests.cc | 14 +++++++++----- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/README.rst b/README.rst index 33cdc40..4515006 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,5 @@ .. code-block:: bash + .................................................................................................... .................................................................................................... ...........................-@-............%@........................................................ diff --git a/src/reactor.cc b/src/reactor.cc index bc4c775..ee190c8 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -159,14 +159,14 @@ void Reactor::Startup() { cyclus::compmath::Normalize(&c, 1); if ((tritium_storage.quantity() >= (startup_inventory)) && - (GetComp(initial_storage) == "{{10030000,1.000000}}") && + (GetComp(initial_storage) == expected_fuel_comp) && startup_inventory >= fuel_usage) { RecordEvent("Startup", "Sufficient tritium in system to begin operation"); sufficient_tritium_for_operation = true; } else if (startup_inventory < fuel_usage){ throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ std::string("to maintain reactor for full timestep!")); - } else if (GetComp(initial_storage) != "{{10030000,1.000000}}") { + } else if (GetComp(initial_storage) != expected_fuel_comp) { throw cyclus::ValueError( "Startup Failed: Fuel incommod not as expected. " + std::string("Expected Composition: {{10030000,1.000000}}. ") + @@ -211,13 +211,10 @@ void Reactor::ExtractHelium( cyclus::CompMap c = mat->comp()->atom(); cyclus::compmath::Normalize(&c, mat->quantity()); - cyclus::CompMap He3 = {{20030000, 1}}; - // A threshold of 1e-5 was set to allow tritium_reserve inventories up to // 1000kg. A 1 decade lower threshold prevents tritium_reserve inventories // above 33kg. - cyclus::Material::Ptr helium = mat->ExtractComp( - c[20030000], cyclus::Composition::CreateFromAtom(He3), 1e-5); + cyclus::Material::Ptr helium = mat->ExtractComp(c[He3_id], He3_comp, 1e-5); helium_storage.Push(helium); inventory.Push(mat); @@ -274,20 +271,21 @@ void Reactor::DepleteBlanket(double bred_tritium_mass) { cyclus::CompMap depleted_comp; + double bred_tritium_atoms = bred_tritium_mass/tritium_atomic_mass; + // This is ALMOST the correct behavior, but "scraping the bottom of the // barrel" is a little too complex for this implementation. - if ((b[30060000] - (1 - Li7_contribution) * 2 * bred_tritium_mass > 0) && - (b[30070000] - Li7_contribution * 7.0 / 3.0 * bred_tritium_mass > 0)) { - depleted_comp = {{30070000, b[30070000] - Li7_contribution * 7.0 / 3.0 * - bred_tritium_mass}, - {30060000, b[30060000] - (1 - Li7_contribution) * 2 * - bred_tritium_mass}, - {10030000, b[10030000] + bred_tritium_mass}, - {20040000, b[20040000] + 4.0 / 3.0 * bred_tritium_mass}}; + if ((b[Li6_id] - (1 - Li7_contribution) * Li6_atomic_mass * bred_tritium_atoms > 0) && + (b[Li7_id] - Li7_contribution * Li7_atomic_mass * bred_tritium_atoms > 0)) { + depleted_comp = {{Li7_id, b[Li7_id] - Li7_contribution * Li7_atomic_mass * bred_tritium_atoms}, + {Li6_id, b[Li6_id] - (1 - Li7_contribution) * Li6_atomic_mass * bred_tritium_atoms}, + {tritium_id, b[tritium_id] + bred_tritium_mass}, + {He4_id, b[He4_id] + He4_atomic_mass * bred_tritium_atoms}}; // Account for the added mass of the absorbed neutrons double neutron_mass_correction = - 1.0 / 3.0 * bred_tritium_mass * (1 - Li7_contribution); + absorbed_neutron_mass * (bred_tritium_mass/tritium_atomic_mass) + * (1 - Li7_contribution); cyclus::Material::Ptr additional_mass = cyclus::Material::Create( this, neutron_mass_correction, cyclus::Composition::CreateFromMass(depleted_comp)); @@ -313,10 +311,7 @@ cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR) { cyclus::CompMap c = mat->comp()->mass(); cyclus::compmath::Normalize(&c, mat->quantity()); - cyclus::CompMap T = {{10030000, 1}}; - - cyclus::Material::Ptr bred_fuel = - mat->ExtractComp(c[10030000], cyclus::Composition::CreateFromAtom(T)); + cyclus::Material::Ptr bred_fuel = mat->ExtractComp(c[tritium_id], tritium_comp); blanket.Push(mat); RecordOperationalInfo("Bred Tritium", std::to_string(bred_fuel->quantity()) + diff --git a/src/reactor.h b/src/reactor.h index 7f4e609..e3fd951 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -248,14 +248,6 @@ class Reactor : public cyclus::Facility { } int blanket_turnover_frequency; - bool sufficient_tritium_for_operation = false; - int seconds_per_year = 31536000; - int MW_to_GW = 1000; - double fuel_usage; - - // kg/GW-fusion-power-year (Abdou et al. 2021) - double burn_rate = 55.8; - #pragma cyclus var {"tooltip":"Buffer for handling tritium material to be used in reactor"} cyclus::toolkit::ResBuf tritium_storage; @@ -295,6 +287,41 @@ class Reactor : public cyclus::Facility { cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); std::string GetComp(cyclus::Material::Ptr mat); + + private: + bool sufficient_tritium_for_operation = false; + const double seconds_per_year = 31536000.0; + const double MW_to_GW = 1000.0; + double fuel_usage; + std::string expected_fuel_comp = "{{10030000,1.000000}}"; + + //masses in kg/atom + const double Li7_atomic_mass = 1.16503478e-26; + const double Li6_atomic_mass = 9.9883465e-27; + const double tritium_atomic_mass = 5.00826766e-27; + const double He4_atomic_mass = 6.64647907e-27; + const double absorbed_neutron_mass = tritium_atomic_mass + + He4_atomic_mass - Li6_atomic_mass; + + const double Li6_tritium_ratio = Li6_atomic_mass/tritium_atomic_mass; + const double Li7_tritium_ratio = Li6_atomic_mass/tritium_atomic_mass; + const double He4_tritium_ratio = He4_atomic_mass/tritium_atomic_mass; + + //NucIDs for Pyne + const int tritium_id = 10030000; + const int He3_id = 20030000; + const int He4_id = 20040000; + const int Li6_id = 30060000; + const int Li7_id = 30070000; + + // kg/GW-fusion-power-year (Abdou et al. 2021) + double burn_rate = 55.8; + + //Compositions + const cyclus::CompMap He3 = {{He3_id, 1}}; + const cyclus::CompMap T = {{tritium_id, 1}}; + const cyclus::Composition::Ptr He3_comp = cyclus::Composition::CreateFromAtom(He3); + const cyclus::Composition::Ptr tritium_comp = cyclus::Composition::CreateFromAtom(T); // And away we go! }; diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 26a4e27..d88b035 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -174,7 +174,7 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { std::string msg = qr.GetVal("Value"); std::string expected_msg = - "Total blanket material (499.055387) insufficient to extract " + "Total blanket material (499.054570) insufficient to extract " "650.000000kg!"; EXPECT_EQ(expected_msg, msg); } @@ -719,7 +719,7 @@ TEST_F(ReactorTest, DepleteBlanketLi7EdgeCases) { QueryResult qr_2 = sim_2.db().Query("ReactorInventories", &conds_2); double excess_2 = qr_2.GetVal("TritiumExcess"); - EXPECT_EQ(excess_1, excess_2); + EXPECT_NEAR(excess_1, excess_2, 1e-3); } @@ -792,9 +792,13 @@ TEST_F(ReactorTest, BreedTritium) { std::string msg = qr.GetVal("Value"); double val = (55.8 * (300.0 / 1000.0) / 31536000.0 * 2629846.0) * 1.05; - std::string expected_msg = std::to_string(val) + " kg of T bred from blanket"; - - EXPECT_EQ(expected_msg, msg); + + std::stringstream ss(msg); + double bred_tritium; + ss >> bred_tritium; + + //floating point math strikes again + EXPECT_NEAR(val, bred_tritium,1e-6); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 1de3a06c1baff979c533de797b2b42a8790a34d9 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 14 Apr 2024 20:39:58 -0500 Subject: [PATCH 25/43] added tritium sequestration as per a comment Matthew made in our ffh meeting. --- src/reactor.cc | 31 +++++++- src/reactor.h | 14 +++- src/reactor_tests.cc | 166 +++++++++++++++++++++++++------------------ 3 files changed, 136 insertions(+), 75 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index ee190c8..a80b874 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -16,6 +16,7 @@ std::string Reactor::str() { void Reactor::Tick() { if (sufficient_tritium_for_operation) { + SequesterTritium(); OperateReactor(TBR); blanket_fill_policy.Start(); Reactor::RecordStatus("Online", fusion_power); @@ -23,15 +24,17 @@ void Reactor::Tick() { Reactor::RecordStatus("Shut-down", 0); } + DecayInventory(tritium_storage); DecayInventory(tritium_excess); + DecayInventory(tritium_sequestered); ExtractHelium(tritium_storage); ExtractHelium(tritium_excess); if (!tritium_storage.empty() && sufficient_tritium_for_operation) { double surplus = std::max( - tritium_storage.quantity() - startup_inventory, 0.0); + tritium_storage.quantity() - reserve_inventory, 0.0); cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); tritium_excess.Push(storage_fuel->ExtractQty(surplus)); @@ -83,7 +86,8 @@ void Reactor::Tock() { CombineInventory(tritium_storage); CombineInventory(blanket); - RecordInventories(tritium_storage.quantity(), tritium_excess.quantity(), blanket.quantity(), + + RecordInventories(tritium_storage.quantity(), tritium_excess.quantity(), tritium_sequestered.quantity(), blanket.quantity(), helium_storage.quantity()); } @@ -153,6 +157,26 @@ std::string Reactor::GetComp(cyclus::Material::Ptr mat) { return comp; } +void Reactor::SequesterTritium(){ + if (!tritium_sequestered.empty()){ + cyclus::Material::Ptr sequestered_mat = tritium_sequestered.Pop(); + cyclus::CompMap c = sequestered_mat->comp()->atom(); + cyclus::compmath::Normalize(&c, sequestered_mat->quantity()); + + double equilibrium_deficit = sequestered_equilibrium - c[tritium_id]; + + // Another catch might be good here... + sequestered_mat->Absorb(tritium_storage.Pop(equilibrium_deficit)); + + tritium_sequestered.Push(sequestered_mat); + + + } else { + // Should I do a try/catch here, or is "user error" fine? + tritium_sequestered.Push(tritium_storage.Pop(sequestered_equilibrium)); + } +} + void Reactor::Startup() { cyclus::Material::Ptr initial_storage = tritium_storage.Peek(); cyclus::CompMap c = initial_storage->comp()->atom(); @@ -251,13 +275,14 @@ void Reactor::RecordStatus(std::string status, double power) { ->Record(); } -void Reactor::RecordInventories(double storage, double excess, double blanket, double helium) { +void Reactor::RecordInventories(double storage, double excess, double sequestered, double blanket, double helium) { context() ->NewDatum("ReactorInventories") ->AddVal("AgentId", id()) ->AddVal("Time", context()->time()) ->AddVal("TritiumStorage", storage) ->AddVal("TritiumExcess", excess) + ->AddVal("TritiumSequestered", sequestered) ->AddVal("LithiumBlanket", blanket) ->AddVal("HeliumStorage", helium) ->Record(); diff --git a/src/reactor.h b/src/reactor.h index e3fd951..56f3ba7 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -144,6 +144,14 @@ class Reactor : public cyclus::Facility { } double reserve_inventory; + #pragma cyclus var { \ + "doc": "Equilibrium quantity of tritium which is sequestered in the system and no longer accessable", \ + "tooltip": "sequestered tritium equilibrium quantity, should be startup-reserve inventory", \ + "units": "kg", \ + "uilabel": "Equilibrium Quantity of Sequestered Tritium" \ + } + double sequestered_equilibrium; + #pragma cyclus var { \ "default": 'fill', \ "doc": "Method of refueling the reactor", \ @@ -254,6 +262,9 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"tooltip":"Buffer for handling excess tritium material to be sold"} cyclus::toolkit::ResBuf tritium_excess; + #pragma cyclus var {"tooltip":"Buffer for handling tritium sequestered in the system"} + cyclus::toolkit::ResBuf tritium_sequestered; + #pragma cyclus var {"tooltip":"Buffer for handling helium-3 byproduct material"} cyclus::toolkit::ResBuf helium_storage; @@ -276,12 +287,13 @@ class Reactor : public cyclus::Facility { void Startup(); void OperateReactor(double TBR); + void SequesterTritium(); void DecayInventory(cyclus::toolkit::ResBuf &inventory); void CombineInventory(cyclus::toolkit::ResBuf &inventory); void ExtractHelium(cyclus::toolkit::ResBuf &inventory); void RecordEvent(std::string name, std::string val); void RecordStatus(std::string Status, double power); - void RecordInventories(double storage, double excess, double blanket, double helium); + void RecordInventories(double storage, double excess, double sequestered, double blanket, double helium); void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index d88b035..6f5397c 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -72,13 +72,14 @@ TEST_F(ReactorTest, TickInsufficientTritium) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -107,14 +108,15 @@ TEST_F(ReactorTest, TickBlanketCycle) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" " 0.03" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 4; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -145,14 +147,15 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" " 0.65" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -194,13 +197,14 @@ TEST_F(ReactorTest, NormalStartup) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -230,13 +234,14 @@ TEST_F(ReactorTest, FuelConstrainedStartup) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -244,14 +249,14 @@ TEST_F(ReactorTest, FuelConstrainedStartup) { sim.AddRecipe("tritium", tritium()); sim.AddRecipe("enriched_lithium", enriched_lithium()); - sim.AddSource("Tritium").recipe("tritium").capacity(2.0).Finalize(); + sim.AddSource("Tritium").recipe("tritium").capacity(5.0).Finalize(); sim.AddSource("Enriched_Lithium").recipe("enriched_lithium").Finalize(); int id = sim.Run(); // Under these conditions, we expect the reactor to be able to startup on - // timestep 1 but not before then (buys 2kg of T on each timestep, and - // needs 2.121kg to startup). NOTE: startup occurs after DRE. + // timestep 1 but not before then (buys 5kg of T on each timestep, and + // needs 8.121kg to startup). NOTE: startup occurs after DRE. std::vector conds0; conds0.push_back(Cond("Time", "==", std::string("0"))); QueryResult qr0 = sim.db().Query("ReactorOperationsLog", &conds0); @@ -276,13 +281,14 @@ TEST_F(ReactorTest, NoFuelStartup) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -313,13 +319,14 @@ TEST_F(ReactorTest, WrongFuelStartup) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Enriched_Lithium" " Enriched_Lithium" " Lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 3; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -366,13 +373,14 @@ TEST_F(ReactorTest, DecayInventory) { std::string config = " 300 " " 1.00 " - " 0" + " 6.0" " 8.121" " Tritium" " Enriched_Lithium" " Lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -390,9 +398,10 @@ TEST_F(ReactorTest, DecayInventory) { QueryResult qr = sim.db().Query("ReactorInventories", &conds); double he3 = qr.GetVal("HeliumStorage"); - // calculator only gave me 7 decimals, otherwise this should probably - // be 1e-10. - EXPECT_NEAR(0.0379868, he3, 1e-7); + // this is "reserve_inventory - reserve_inventory * 2^(-2.57208504984001213e-09*2629846)" + double expected_decay = 0.028065619; + + EXPECT_NEAR(expected_decay, he3, 1e-7); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -512,13 +521,14 @@ TEST_F(ReactorTest, RecordEvent) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -546,13 +556,14 @@ TEST_F(ReactorTest, RecordInventories) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -574,7 +585,7 @@ TEST_F(ReactorTest, RecordInventories) { double helium_storage = qr.GetVal("HeliumStorage"); - EXPECT_EQ(2.121, tritium_storage); + EXPECT_EQ(8.121, tritium_storage); EXPECT_EQ(0.0, tritium_excess); EXPECT_EQ(1000.0, blanket); EXPECT_EQ(0.0, helium_storage); @@ -587,13 +598,14 @@ TEST_F(ReactorTest, RecordStatus) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -632,13 +644,14 @@ TEST_F(ReactorTest, DepleteBlanket) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -666,26 +679,28 @@ TEST_F(ReactorTest, DepleteBlanketLi7EdgeCases) { std::string config_1 = " 300 " " 1.08 " - " 0" + " 6.0" " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" " Helium_3" - " 0.00"; + " 0.00" + " 2.121"; std::string config_2 = " 300 " " 1.08 " - " 0" + " 6.0" " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" " Helium_3" - " 1.00"; + " 1.00" + " 2.121"; int simdur = 2; cyclus::MockSim sim_1(cyclus::AgentSpec(":tricycle:Reactor"), config_1, simdur); @@ -730,13 +745,14 @@ TEST_F(ReactorTest, OverDepleteBlanket) { std::string config = " 300 " " 1.50 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -767,13 +783,14 @@ TEST_F(ReactorTest, BreedTritium) { std::string config = " 300 " " 1.05 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -808,13 +825,14 @@ TEST_F(ReactorTest, OperateReactorSustainingTBR) { std::string config = " 300 " " 1.05 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -853,13 +871,14 @@ TEST_F(ReactorTest, OperateReactorNonSustainingTBR) { std::string config = " 300 " " 0.8 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -896,13 +915,14 @@ TEST_F(ReactorTest, OperateReactorShutdownLackOfTritium) { std::string config = " 300 " " 0.0 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 25; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -932,13 +952,14 @@ TEST_F(ReactorTest, EnterNotifyInitialFillDefault) { std::string config = " 300 " " 1.00 " - " 0" + " 6.0" " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -972,7 +993,7 @@ TEST_F(ReactorTest, EnterNotifyScheduleFill) { std::string config = " 300 " " 1.00 " - " 0" + " 6.0" " 8.121" " Tritium" " Enriched_Lithium" @@ -981,7 +1002,8 @@ TEST_F(ReactorTest, EnterNotifyScheduleFill) { " 0.1" " 1" " schedule" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -1028,8 +1050,8 @@ TEST_F(ReactorTest, EnterNotifyInvalidFill) { std::string config = " 300 " " 1.00 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" @@ -1037,7 +1059,8 @@ TEST_F(ReactorTest, EnterNotifyInvalidFill) { " 0.1" " 1" " kjnsfdhn" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 2; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); @@ -1058,13 +1081,14 @@ TEST_F(ReactorTest, EnterNotifySellPolicy) { std::string config = " 300 " " 1.30 " - " 0" - " 2.121" + " 6.0" + " 8.121" " Tritium" " Enriched_Lithium" " enriched_lithium" " 1000" - " Helium_3"; + " Helium_3" + " 2.121"; int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":tricycle:Reactor"), config, simdur); From c428ea2db69a2e7bf6bdf9a97a7e257caad4b4bc Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 13:58:28 -0500 Subject: [PATCH 26/43] simplified removal of surplus from storage with pop(qty) --- src/reactor.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index a80b874..38c5659 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -36,16 +36,15 @@ void Reactor::Tick() { double surplus = std::max( tritium_storage.quantity() - reserve_inventory, 0.0); - cyclus::Material::Ptr storage_fuel = tritium_storage.Pop(); - tritium_excess.Push(storage_fuel->ExtractQty(surplus)); - if (surplus > 0.0) { + + tritium_excess.Push(tritium_storage.Pop(surplus)); + CombineInventory(tritium_excess); + RecordOperationalInfo( "Tritium Moved", std::to_string(surplus) + "kg of T moved from storage to excess"); } - tritium_storage.Push(storage_fuel); - CombineInventory(tritium_excess); } // This pulls out some of the blanket each timestep so that fresh blanket can From cfa03de228e60e3bf1bde9a237b3c79a5ae50a61 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 14:44:18 -0500 Subject: [PATCH 27/43] added buffer for spent lithium, and record it in the inventories table --- src/reactor.cc | 18 +++++++++--------- src/reactor.h | 5 ++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 38c5659..0328b19 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -49,17 +49,14 @@ void Reactor::Tick() { // This pulls out some of the blanket each timestep so that fresh blanket can // be added. - // NOTE: currently spent blanket dissapears into the ether. This needs to be - // changed in version 1 for materials tracking. - double blanket_turnover = blanket_size * blanket_turnover_rate; if (!blanket.empty() && blanket.quantity() >= blanket_turnover && context()->time() % blanket_turnover_frequency == 0) { - cyclus::Material::Ptr spent_blanket = - blanket.Pop(blanket_turnover); + blanket_excess.Push(blanket.Pop(blanket_turnover)); + CombineInventory(blanket_excess); RecordOperationalInfo( "Blanket Cycled", - std::to_string(spent_blanket->quantity()) + "kg of blanket removed"); + std::to_string(blanket_turnover) + "kg of blanket removed"); } else if (!blanket.empty() && blanket.quantity() < blanket_turnover) { RecordOperationalInfo( @@ -86,8 +83,9 @@ void Reactor::Tock() { CombineInventory(blanket); - RecordInventories(tritium_storage.quantity(), tritium_excess.quantity(), tritium_sequestered.quantity(), blanket.quantity(), - helium_storage.quantity()); + RecordInventories(tritium_storage.quantity(), tritium_excess.quantity(), + tritium_sequestered.quantity(), blanket.quantity(), + blanket_excess.quantity(), helium_storage.quantity()); } void Reactor::EnterNotify() { @@ -274,7 +272,8 @@ void Reactor::RecordStatus(std::string status, double power) { ->Record(); } -void Reactor::RecordInventories(double storage, double excess, double sequestered, double blanket, double helium) { +void Reactor::RecordInventories(double storage, double excess, double sequestered, + double blanket, double blanket_excess, double helium) { context() ->NewDatum("ReactorInventories") ->AddVal("AgentId", id()) @@ -283,6 +282,7 @@ void Reactor::RecordInventories(double storage, double excess, double sequestere ->AddVal("TritiumExcess", excess) ->AddVal("TritiumSequestered", sequestered) ->AddVal("LithiumBlanket", blanket) + ->AddVal("BlanketExcess", blanket_excess) ->AddVal("HeliumStorage", helium) ->Record(); } diff --git a/src/reactor.h b/src/reactor.h index 56f3ba7..f8faa1d 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -271,6 +271,9 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"tooltip":"Buffer for handling enriched lithium blanket material"} cyclus::toolkit::ResBuf blanket; + #pragma cyclus var {"tooltip":"Buffer for handling enriched lithium blanket material"} + cyclus::toolkit::ResBuf blanket_excess; + #pragma cyclus var {"tooltip":"Tracker to handle on-hand tritium"} cyclus::toolkit::TotalInvTracker fuel_tracker; @@ -293,7 +296,7 @@ class Reactor : public cyclus::Facility { void ExtractHelium(cyclus::toolkit::ResBuf &inventory); void RecordEvent(std::string name, std::string val); void RecordStatus(std::string Status, double power); - void RecordInventories(double storage, double excess, double sequestered, double blanket, double helium); + void RecordInventories(double storage, double excess, double sequestered, double blanket, double blanket_excess, double helium); void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); From 3920d359c4a6024d3f44448ebeb232c4a3127b90 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 15:01:15 -0500 Subject: [PATCH 28/43] changed GetComp to compmath::AlmostEq() with a 1e-7 threshold --- src/reactor.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 0328b19..6f57a4c 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -180,14 +180,14 @@ void Reactor::Startup() { cyclus::compmath::Normalize(&c, 1); if ((tritium_storage.quantity() >= (startup_inventory)) && - (GetComp(initial_storage) == expected_fuel_comp) && + (cyclus::compmath::AlmostEq(c, T, 1e-7)) && startup_inventory >= fuel_usage) { RecordEvent("Startup", "Sufficient tritium in system to begin operation"); sufficient_tritium_for_operation = true; } else if (startup_inventory < fuel_usage){ throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ std::string("to maintain reactor for full timestep!")); - } else if (GetComp(initial_storage) != expected_fuel_comp) { + } else if (!cyclus::compmath::AlmostEq(c, T, 1e-7)) { throw cyclus::ValueError( "Startup Failed: Fuel incommod not as expected. " + std::string("Expected Composition: {{10030000,1.000000}}. ") + From d0e5f3ef678c27fd70a54992bf30cfa92bdc6ac2 Mon Sep 17 00:00:00 2001 From: Dean Krueger <74223179+dean-krueger@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:05:31 -0500 Subject: [PATCH 29/43] remove extra parentheses in if statement Co-authored-by: Paul Wilson --- src/reactor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reactor.cc b/src/reactor.cc index 6f57a4c..2d792c8 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -179,7 +179,7 @@ void Reactor::Startup() { cyclus::CompMap c = initial_storage->comp()->atom(); cyclus::compmath::Normalize(&c, 1); - if ((tritium_storage.quantity() >= (startup_inventory)) && + if ((tritium_storage.quantity() >= startup_inventory) && (cyclus::compmath::AlmostEq(c, T, 1e-7)) && startup_inventory >= fuel_usage) { RecordEvent("Startup", "Sufficient tritium in system to begin operation"); From c536e38bbb6d4c5eacf3d12b003b3e8428a07eea Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 15:34:31 -0500 Subject: [PATCH 30/43] changed the startup if/else block to be more readable --- src/reactor.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 6f57a4c..792ec9e 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -160,7 +160,8 @@ void Reactor::SequesterTritium(){ cyclus::CompMap c = sequestered_mat->comp()->atom(); cyclus::compmath::Normalize(&c, sequestered_mat->quantity()); - double equilibrium_deficit = sequestered_equilibrium - c[tritium_id]; + double equilibrium_deficit = std::max(sequestered_equilibrium - + c[tritium_id],0.0); // Another catch might be good here... sequestered_mat->Absorb(tritium_storage.Pop(equilibrium_deficit)); @@ -179,12 +180,13 @@ void Reactor::Startup() { cyclus::CompMap c = initial_storage->comp()->atom(); cyclus::compmath::Normalize(&c, 1); - if ((tritium_storage.quantity() >= (startup_inventory)) && - (cyclus::compmath::AlmostEq(c, T, 1e-7)) && - startup_inventory >= fuel_usage) { - RecordEvent("Startup", "Sufficient tritium in system to begin operation"); - sufficient_tritium_for_operation = true; - } else if (startup_inventory < fuel_usage){ + if (tritium_storage.quantity() < startup_inventory){ + throw cyclus::ValueError( + "Startup Failed: " + std::to_string(tritium_storage.quantity()) + + " kg in storage is less than required " + + std::to_string(startup_inventory) + + " kg to start-up!"); + } else if (startup_inventory < fuel_usage) { throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ std::string("to maintain reactor for full timestep!")); } else if (!cyclus::compmath::AlmostEq(c, T, 1e-7)) { @@ -194,11 +196,8 @@ void Reactor::Startup() { std::string("Fuel Incommod Composition: ") + std::string(GetComp(initial_storage))); } else { - throw cyclus::ValueError( - "Startup Failed: " + std::to_string(tritium_storage.quantity()) + - " kg in storage is less than required " + - std::to_string(startup_inventory) + - " kg to start-up!"); + RecordEvent("Startup", "Sufficient tritium in system to begin operation"); + sufficient_tritium_for_operation = true; } } From 994096d8dfdeecb1a735bd024bbec73464a7a22d Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 15:39:44 -0500 Subject: [PATCH 31/43] last commit was just the conflicting files bit, this one should fix it --- src/reactor.cc | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index fc08a65..792ec9e 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -180,7 +180,6 @@ void Reactor::Startup() { cyclus::CompMap c = initial_storage->comp()->atom(); cyclus::compmath::Normalize(&c, 1); -<<<<<<< HEAD if (tritium_storage.quantity() < startup_inventory){ throw cyclus::ValueError( "Startup Failed: " + std::to_string(tritium_storage.quantity()) + @@ -188,14 +187,6 @@ void Reactor::Startup() { std::to_string(startup_inventory) + " kg to start-up!"); } else if (startup_inventory < fuel_usage) { -======= - if ((tritium_storage.quantity() >= startup_inventory) && - (cyclus::compmath::AlmostEq(c, T, 1e-7)) && - startup_inventory >= fuel_usage) { - RecordEvent("Startup", "Sufficient tritium in system to begin operation"); - sufficient_tritium_for_operation = true; - } else if (startup_inventory < fuel_usage){ ->>>>>>> d0e5f3ef678c27fd70a54992bf30cfa92bdc6ac2 throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ std::string("to maintain reactor for full timestep!")); } else if (!cyclus::compmath::AlmostEq(c, T, 1e-7)) { From 2e84bc0c5e2ad22dd19794f767a5755d0c655620 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 16:00:57 -0500 Subject: [PATCH 32/43] changed the conditional behavior of blanket cycling --- src/reactor.cc | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 792ec9e..6a9dff5 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -50,20 +50,21 @@ void Reactor::Tick() { // This pulls out some of the blanket each timestep so that fresh blanket can // be added. double blanket_turnover = blanket_size * blanket_turnover_rate; - if (!blanket.empty() && blanket.quantity() >= blanket_turnover && - context()->time() % blanket_turnover_frequency == 0) { - blanket_excess.Push(blanket.Pop(blanket_turnover)); - CombineInventory(blanket_excess); - RecordOperationalInfo( - "Blanket Cycled", - std::to_string(blanket_turnover) + "kg of blanket removed"); - } else if (!blanket.empty() && - blanket.quantity() < blanket_turnover) { - RecordOperationalInfo( - "Blanket Not Cycled", - "Total blanket material (" + std::to_string(blanket.quantity()) + - ") insufficient to extract " + - std::to_string(blanket_turnover) + "kg!"); + if (context()->time() % blanket_turnover_frequency == 0) { + if (!blanket.empty() && blanket.quantity() >= blanket_turnover) { + blanket_excess.Push(blanket.Pop(blanket_turnover)); + CombineInventory(blanket_excess); + RecordOperationalInfo( + "Blanket Cycled", + std::to_string(blanket_turnover) + "kg of blanket removed"); + } else if (!blanket.empty() && + blanket.quantity() < blanket_turnover) { + RecordOperationalInfo( + "Blanket Not Cycled", + "Total blanket material (" + std::to_string(blanket.quantity()) + + ") insufficient to extract " + + std::to_string(blanket_turnover) + "kg!"); + } } } From 032ec4d3399ef1867404809479929f8b65314e1e Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sun, 21 Apr 2024 16:17:11 -0500 Subject: [PATCH 33/43] changed atomic masses source from wolfram to pyne --- src/reactor.cc | 1 - src/reactor.h | 24 +++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 6a9dff5..34f3163 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -24,7 +24,6 @@ void Reactor::Tick() { Reactor::RecordStatus("Shut-down", 0); } - DecayInventory(tritium_storage); DecayInventory(tritium_excess); DecayInventory(tritium_sequestered); diff --git a/src/reactor.h b/src/reactor.h index f8faa1d..78fc600 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -5,6 +5,7 @@ #include "cyclus.h" #include "boost/shared_ptr.hpp" +#include "pyne.h" namespace tricycle { @@ -310,24 +311,25 @@ class Reactor : public cyclus::Facility { double fuel_usage; std::string expected_fuel_comp = "{{10030000,1.000000}}"; + //NucIDs for Pyne + const int tritium_id = 10030000; + const int He3_id = 20030000; + const int He4_id = 20040000; + const int Li6_id = 30060000; + const int Li7_id = 30070000; + //masses in kg/atom - const double Li7_atomic_mass = 1.16503478e-26; - const double Li6_atomic_mass = 9.9883465e-27; - const double tritium_atomic_mass = 5.00826766e-27; - const double He4_atomic_mass = 6.64647907e-27; + const double amu_to_kg = 1.66054e-27; + const double Li7_atomic_mass = pyne::atomic_mass(Li7_id) * amu_to_kg; + const double Li6_atomic_mass = pyne::atomic_mass(Li6_id) * amu_to_kg; + const double tritium_atomic_mass = pyne::atomic_mass(tritium_id) * amu_to_kg; + const double He4_atomic_mass = pyne::atomic_mass(He4_id) * amu_to_kg; const double absorbed_neutron_mass = tritium_atomic_mass + He4_atomic_mass - Li6_atomic_mass; const double Li6_tritium_ratio = Li6_atomic_mass/tritium_atomic_mass; const double Li7_tritium_ratio = Li6_atomic_mass/tritium_atomic_mass; const double He4_tritium_ratio = He4_atomic_mass/tritium_atomic_mass; - - //NucIDs for Pyne - const int tritium_id = 10030000; - const int He3_id = 20030000; - const int He4_id = 20040000; - const int Li6_id = 30060000; - const int Li7_id = 30070000; // kg/GW-fusion-power-year (Abdou et al. 2021) double burn_rate = 55.8; From 14deba40e0f512c60c8659d272dfca03ba9806f5 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Mon, 22 Apr 2024 12:06:04 -0500 Subject: [PATCH 34/43] changed number of seconds in a year to match cyclus --- src/reactor.h | 2 +- src/reactor_tests.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reactor.h b/src/reactor.h index 78fc600..f0c31f1 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -306,7 +306,7 @@ class Reactor : public cyclus::Facility { private: bool sufficient_tritium_for_operation = false; - const double seconds_per_year = 31536000.0; + const double seconds_per_year = 2629846*12; const double MW_to_GW = 1000.0; double fuel_usage; std::string expected_fuel_comp = "{{10030000,1.000000}}"; diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 6f5397c..f545d11 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -177,7 +177,7 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { std::string msg = qr.GetVal("Value"); std::string expected_msg = - "Total blanket material (499.054570) insufficient to extract " + "Total blanket material (499.055234) insufficient to extract " "650.000000kg!"; EXPECT_EQ(expected_msg, msg); } @@ -808,7 +808,7 @@ TEST_F(ReactorTest, BreedTritium) { QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); std::string msg = qr.GetVal("Value"); - double val = (55.8 * (300.0 / 1000.0) / 31536000.0 * 2629846.0) * 1.05; + double val = (55.8 * (300.0 / 1000.0) / (2629846*12) * 2629846.0) * 1.05; std::stringstream ss(msg); double bred_tritium; From fe6dff0e2e7e9147eae3ccdd2efeee7aa697b721 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 10:14:47 -0500 Subject: [PATCH 35/43] removed unused str method, moved conditional in blanket cycle to simplify --- src/reactor.cc | 11 +++-------- src/reactor.h | 3 --- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 34f3163..902c829 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -10,10 +10,6 @@ Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) { blanket_tracker.Init({&blanket}, 100000.0); } -std::string Reactor::str() { - return Facility::str(); -} - void Reactor::Tick() { if (sufficient_tritium_for_operation) { SequesterTritium(); @@ -49,15 +45,14 @@ void Reactor::Tick() { // This pulls out some of the blanket each timestep so that fresh blanket can // be added. double blanket_turnover = blanket_size * blanket_turnover_rate; - if (context()->time() % blanket_turnover_frequency == 0) { - if (!blanket.empty() && blanket.quantity() >= blanket_turnover) { + if (context()->time() % blanket_turnover_frequency == 0 && !blanket.empty()) { + if (blanket.quantity() >= blanket_turnover) { blanket_excess.Push(blanket.Pop(blanket_turnover)); CombineInventory(blanket_excess); RecordOperationalInfo( "Blanket Cycled", std::to_string(blanket_turnover) + "kg of blanket removed"); - } else if (!blanket.empty() && - blanket.quantity() < blanket_turnover) { + } else if (blanket.quantity() < blanket_turnover) { RecordOperationalInfo( "Blanket Not Cycled", "Total blanket material (" + std::to_string(blanket.quantity()) + diff --git a/src/reactor.h b/src/reactor.h index f0c31f1..e41ee3d 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -93,9 +93,6 @@ class Reactor : public cyclus::Facility { #pragma cyclus note {"doc": "A facility to model basic operation of a" \ "fusion energy system."} - /// A verbose printer for the Reactor - virtual std::string str(); - /// Set up policies and buffers: virtual void EnterNotify(); From 34a83f18e28b901cdcaf1ca5444a09f6fc5fe47d Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 12:20:05 -0500 Subject: [PATCH 36/43] changed sequestered_tritium from a resbuf to a materail --- src/reactor.cc | 39 +++++++++++++-------------------------- src/reactor.h | 21 +++++++++++++++------ 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 902c829..f8251fd 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -5,9 +5,8 @@ namespace tricycle { Reactor::Reactor(cyclus::Context* ctx) : cyclus::Facility(ctx) { - // capacities set somewhat arbitrarily - fuel_tracker.Init({&tritium_storage}, 1000.0); - blanket_tracker.Init({&blanket}, 100000.0); + fuel_tracker.Init({&tritium_storage}, fuel_limit); + blanket_tracker.Init({&blanket}, blanket_limit); } void Reactor::Tick() { @@ -22,7 +21,7 @@ void Reactor::Tick() { DecayInventory(tritium_storage); DecayInventory(tritium_excess); - DecayInventory(tritium_sequestered); + sequestered_tritium->Decay(context()->time()); ExtractHelium(tritium_storage); ExtractHelium(tritium_excess); @@ -42,8 +41,6 @@ void Reactor::Tick() { } } - // This pulls out some of the blanket each timestep so that fresh blanket can - // be added. double blanket_turnover = blanket_size * blanket_turnover_rate; if (context()->time() % blanket_turnover_frequency == 0 && !blanket.empty()) { if (blanket.quantity() >= blanket_turnover) { @@ -77,9 +74,8 @@ void Reactor::Tock() { CombineInventory(tritium_storage); CombineInventory(blanket); - RecordInventories(tritium_storage.quantity(), tritium_excess.quantity(), - tritium_sequestered.quantity(), blanket.quantity(), + sequestered_tritium->quantity(), blanket.quantity(), blanket_excess.quantity(), helium_storage.quantity()); } @@ -135,6 +131,7 @@ void Reactor::EnterNotify() { .Start(); } + std::string Reactor::GetComp(cyclus::Material::Ptr mat) { std::string comp = "{"; cyclus::CompMap c = mat->comp()->atom(); @@ -149,24 +146,15 @@ std::string Reactor::GetComp(cyclus::Material::Ptr mat) { return comp; } -void Reactor::SequesterTritium(){ - if (!tritium_sequestered.empty()){ - cyclus::Material::Ptr sequestered_mat = tritium_sequestered.Pop(); - cyclus::CompMap c = sequestered_mat->comp()->atom(); - cyclus::compmath::Normalize(&c, sequestered_mat->quantity()); - - double equilibrium_deficit = std::max(sequestered_equilibrium - - c[tritium_id],0.0); - // Another catch might be good here... - sequestered_mat->Absorb(tritium_storage.Pop(equilibrium_deficit)); - - tritium_sequestered.Push(sequestered_mat); - - +void Reactor::SequesterTritium(){ + if (sequestered_tritium->quantity() == 0.0){ + sequestered_tritium = tritium_storage.Pop(sequestered_equilibrium); } else { - // Should I do a try/catch here, or is "user error" fine? - tritium_sequestered.Push(tritium_storage.Pop(sequestered_equilibrium)); + cyclus::toolkit::MatQuery mq(sequestered_tritium); + double equilibrium_deficit = std::max(sequestered_equilibrium - + mq.mass(tritium_id), 0.0); + sequestered_tritium->Absorb(tritium_storage.Pop(equilibrium_deficit)); } } @@ -188,8 +176,7 @@ void Reactor::Startup() { throw cyclus::ValueError( "Startup Failed: Fuel incommod not as expected. " + std::string("Expected Composition: {{10030000,1.000000}}. ") + - std::string("Fuel Incommod Composition: ") + - std::string(GetComp(initial_storage))); + std::string("Fuel Incommod Composition: ")); } else { RecordEvent("Startup", "Sufficient tritium in system to begin operation"); sufficient_tritium_for_operation = true; diff --git a/src/reactor.h b/src/reactor.h index e41ee3d..0e38691 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -211,6 +211,7 @@ class Reactor : public cyclus::Facility { "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" \ @@ -260,8 +261,9 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"tooltip":"Buffer for handling excess tritium material to be sold"} cyclus::toolkit::ResBuf tritium_excess; - #pragma cyclus var {"tooltip":"Buffer for handling tritium sequestered in the system"} - cyclus::toolkit::ResBuf tritium_sequestered; + //Convert to Material + //#pragma cyclus var {"tooltip":"Buffer for handling tritium sequestered in the system"} + //cyclus::toolkit::ResBuf tritium_sequestered; #pragma cyclus var {"tooltip":"Buffer for handling helium-3 byproduct material"} cyclus::toolkit::ResBuf helium_storage; @@ -294,7 +296,8 @@ class Reactor : public cyclus::Facility { void ExtractHelium(cyclus::toolkit::ResBuf &inventory); void RecordEvent(std::string name, std::string val); void RecordStatus(std::string Status, double power); - void RecordInventories(double storage, double excess, double sequestered, double blanket, double blanket_excess, double helium); + void RecordInventories(double storage, double excess, double sequestered, + double blanket, double blanket_excess, double helium); void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); @@ -306,9 +309,10 @@ class Reactor : public cyclus::Facility { const double seconds_per_year = 2629846*12; const double MW_to_GW = 1000.0; double fuel_usage; - std::string expected_fuel_comp = "{{10030000,1.000000}}"; + double fuel_limit = 1000.0; + double blanket_limit = 100000.0; - //NucIDs for Pyne + //NucIDs for Pyne const int tritium_id = 10030000; const int He3_id = 20030000; const int He4_id = 20040000; @@ -319,7 +323,8 @@ class Reactor : public cyclus::Facility { const double amu_to_kg = 1.66054e-27; const double Li7_atomic_mass = pyne::atomic_mass(Li7_id) * amu_to_kg; const double Li6_atomic_mass = pyne::atomic_mass(Li6_id) * amu_to_kg; - const double tritium_atomic_mass = pyne::atomic_mass(tritium_id) * amu_to_kg; + const double tritium_atomic_mass = pyne::atomic_mass(tritium_id) + * amu_to_kg; const double He4_atomic_mass = pyne::atomic_mass(He4_id) * amu_to_kg; const double absorbed_neutron_mass = tritium_atomic_mass + He4_atomic_mass - Li6_atomic_mass; @@ -336,6 +341,10 @@ class Reactor : public cyclus::Facility { const cyclus::CompMap T = {{tritium_id, 1}}; const cyclus::Composition::Ptr He3_comp = cyclus::Composition::CreateFromAtom(He3); const cyclus::Composition::Ptr tritium_comp = cyclus::Composition::CreateFromAtom(T); + + //Materials + cyclus::Material::Ptr sequestered_tritium = cyclus::Material::CreateUntracked(0.0, tritium_comp); + // And away we go! }; From 5b8e2a45897bf6e36616385d0a924b085149d271 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 12:43:27 -0500 Subject: [PATCH 37/43] removed several instances of compmap c --> normalize and replaced with matquery --- src/reactor.cc | 20 ++++++-------------- src/reactor_tests.cc | 6 ++---- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index f8251fd..d44fcea 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -174,9 +174,7 @@ void Reactor::Startup() { std::string("to maintain reactor for full timestep!")); } else if (!cyclus::compmath::AlmostEq(c, T, 1e-7)) { throw cyclus::ValueError( - "Startup Failed: Fuel incommod not as expected. " + - std::string("Expected Composition: {{10030000,1.000000}}. ") + - std::string("Fuel Incommod Composition: ")); + "Startup Failed: Fuel incommod not as expected. "); } else { RecordEvent("Startup", "Sufficient tritium in system to begin operation"); sufficient_tritium_for_operation = true; @@ -210,13 +208,9 @@ void Reactor::ExtractHelium( cyclus::toolkit::ResBuf& inventory) { if (!inventory.empty()) { cyclus::Material::Ptr mat = inventory.Pop(); - cyclus::CompMap c = mat->comp()->atom(); - cyclus::compmath::Normalize(&c, mat->quantity()); - - // A threshold of 1e-5 was set to allow tritium_reserve inventories up to - // 1000kg. A 1 decade lower threshold prevents tritium_reserve inventories - // above 33kg. - cyclus::Material::Ptr helium = mat->ExtractComp(c[He3_id], He3_comp, 1e-5); + cyclus::toolkit::MatQuery mq(mat); + + cyclus::Material::Ptr helium = mat->ExtractComp(mq.mass(He3_id), He3_comp); helium_storage.Push(helium); inventory.Push(mat); @@ -312,11 +306,9 @@ void Reactor::DepleteBlanket(double bred_tritium_mass) { cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR) { DepleteBlanket(fuel_usage * TBR); cyclus::Material::Ptr mat = blanket.Pop(); + cyclus::toolkit::MatQuery mq(mat); - cyclus::CompMap c = mat->comp()->mass(); - cyclus::compmath::Normalize(&c, mat->quantity()); - - cyclus::Material::Ptr bred_fuel = mat->ExtractComp(c[tritium_id], tritium_comp); + cyclus::Material::Ptr bred_fuel = mat->ExtractComp(mq.mass(tritium_id), tritium_comp); blanket.Push(mat); RecordOperationalInfo("Bred Tritium", std::to_string(bred_fuel->quantity()) + diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index f545d11..8aada69 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -356,9 +356,7 @@ TEST_F(ReactorTest, WrongFuelStartup) { std::string value = qr2.GetVal("Value"); std::string expected_message = - "Startup Failed: Fuel incommod not as expected. " - "Expected Composition: {{10030000,1.000000}}. Fuel Incommod " - "Composition: {{30060000,0.300000},{30070000,0.700000}}"; + "Startup Failed: Fuel incommod not as expected. "; EXPECT_EQ(value, expected_message); } @@ -401,7 +399,7 @@ TEST_F(ReactorTest, DecayInventory) { // this is "reserve_inventory - reserve_inventory * 2^(-2.57208504984001213e-09*2629846)" double expected_decay = 0.028065619; - EXPECT_NEAR(expected_decay, he3, 1e-7); + EXPECT_NEAR(expected_decay, he3, 1e-6); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From beb87c2ad4fdecdf2b6f323b25b3924994782015 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 13:07:34 -0500 Subject: [PATCH 38/43] removed GetComp() function and modified relevant unit tests --- src/reactor.cc | 16 ---------------- src/reactor.h | 2 -- src/reactor_tests.cc | 30 ++++-------------------------- 3 files changed, 4 insertions(+), 44 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index d44fcea..dd59758 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -131,22 +131,6 @@ void Reactor::EnterNotify() { .Start(); } - -std::string Reactor::GetComp(cyclus::Material::Ptr mat) { - std::string comp = "{"; - cyclus::CompMap c = mat->comp()->atom(); - cyclus::compmath::Normalize(&c, 1); - for (std::map::const_iterator it = c.begin(); - it != c.end(); ++it) { - comp = comp + std::string("{") + std::to_string(it->first) + - std::string(",") + std::to_string(it->second) + std::string("},"); - } - comp.pop_back(); - comp = comp + std::string("}"); - return comp; -} - - void Reactor::SequesterTritium(){ if (sequestered_tritium->quantity() == 0.0){ sequestered_tritium = tritium_storage.Pop(sequestered_equilibrium); diff --git a/src/reactor.h b/src/reactor.h index 0e38691..163ea24 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -301,8 +301,6 @@ class Reactor : public cyclus::Facility { void RecordOperationalInfo(std::string name, std::string val); void DepleteBlanket(double bred_tritium_mass); cyclus::Material::Ptr BreedTritium(double fuel_usage, double TBR); - std::string GetComp(cyclus::Material::Ptr mat); - private: bool sufficient_tritium_for_operation = false; diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 8aada69..8bebe97 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -402,20 +402,6 @@ TEST_F(ReactorTest, DecayInventory) { EXPECT_NEAR(expected_decay, he3, 1e-6); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(ReactorTest, GetComp) { - // Test behaviors of the GetComp function here - - cyclus::Material::Ptr Li = - cyclus::Material::CreateUntracked(1, enriched_lithium()); - cyclus::Material::Ptr T = cyclus::Material::CreateUntracked(1, tritium()); - std::string comp_Li = facility->GetComp(Li); - std::string comp_T = facility->GetComp(T); - - EXPECT_EQ("{{30060000,0.300000},{30070000,0.700000}}", comp_Li); - EXPECT_EQ("{{10030000,1.000000}}", comp_T); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(ReactorTest, CombineInventory) { // Test behaviors of the CombineInventory function here @@ -479,16 +465,12 @@ TEST_F(ReactorTest, ExtractHelium) { cyclus::Material::Ptr test_mat = cyclus::Material::CreateUntracked(1.0, decayed_tritium()); - std::string comp_original = facility->GetComp(test_mat); - - EXPECT_EQ("{{10030000,0.900000},{20030000,0.100000}}", comp_original); - test_buf.Push(test_mat); facility->ExtractHelium(test_buf); cyclus::Material::Ptr extracted_mat = test_buf.Pop(); - std::string comp_extracted = facility->GetComp(extracted_mat); - EXPECT_EQ("{{10030000,1.000000}}", comp_extracted); + double qty_after_extraction = extracted_mat->quantity(); + EXPECT_NEAR(0.9, qty_after_extraction, 1e-5); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -499,16 +481,12 @@ TEST_F(ReactorTest, ExtractNoHelium) { cyclus::Material::Ptr test_mat = cyclus::Material::CreateUntracked(1.0, tritium()); - std::string comp_original = facility->GetComp(test_mat); - - EXPECT_EQ("{{10030000,1.000000}}", comp_original); - test_buf.Push(test_mat); facility->ExtractHelium(test_buf); cyclus::Material::Ptr extracted_mat = test_buf.Pop(); - std::string comp_extracted = facility->GetComp(extracted_mat); - EXPECT_EQ("{{10030000,1.000000}}", comp_extracted); + double qty_after_extraction = extracted_mat->quantity() ; + EXPECT_EQ(1.0, qty_after_extraction); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 71564a05710e28371df956c98154d470697a471e Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 17:54:18 -0500 Subject: [PATCH 39/43] changed DepleteBlanket from mass to atom basis, simplified greatly, fixed Li7 bug --- src/reactor.cc | 69 ++++++++++++++++++++++---------------------- src/reactor.h | 11 +++---- src/reactor_tests.cc | 4 +-- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index dd59758..c2bf02d 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -81,8 +81,9 @@ void Reactor::Tock() { void Reactor::EnterNotify() { cyclus::Facility::EnterNotify(); - - fuel_usage = burn_rate * (fusion_power / MW_to_GW) / seconds_per_year * context()->dt(); + + fuel_usage_mass = (burn_rate * (fusion_power / MW_to_GW) / seconds_per_year * context()->dt()); + fuel_usage_atoms = fuel_usage_mass / tritium_atomic_mass; fuel_startup_policy .Init(this, &tritium_storage, std::string("Tritium Storage"), @@ -153,7 +154,7 @@ void Reactor::Startup() { " kg in storage is less than required " + std::to_string(startup_inventory) + " kg to start-up!"); - } else if (startup_inventory < fuel_usage) { + } else if (startup_inventory < fuel_usage_mass) { throw cyclus::ValueError("Startup Failed: Startup Inventory insufficient "+ std::string("to maintain reactor for full timestep!")); } else if (!cyclus::compmath::AlmostEq(c, T, 1e-7)) { @@ -246,35 +247,36 @@ void Reactor::RecordInventories(double storage, double excess, double sequestere ->Record(); } -void Reactor::DepleteBlanket(double bred_tritium_mass) { +void Reactor::DepleteBlanket(double bred_tritium_atoms) { cyclus::Material::Ptr blanket_mat = blanket.Pop(); - - cyclus::CompMap b = blanket_mat->comp()->mass(); - cyclus::compmath::Normalize(&b, blanket_mat->quantity()); - + cyclus::toolkit::MatQuery b(blanket_mat); cyclus::CompMap depleted_comp; - double bred_tritium_atoms = bred_tritium_mass/tritium_atomic_mass; + double converted_Li6 = Li6_contribution * bred_tritium_atoms; + double converted_Li7 = Li7_contribution * bred_tritium_atoms; + double bred_He4 = bred_tritium_atoms; + double blanket_Li6 = b.moles(Li6_id)*avagadros_number; + double blanket_Li7 = b.moles(Li7_id)*avagadros_number; + double blanket_tritium = b.moles(tritium_id)*avagadros_number; + double blanket_He4 = b.moles(He4_id)*avagadros_number; - // This is ALMOST the correct behavior, but "scraping the bottom of the - // barrel" is a little too complex for this implementation. - if ((b[Li6_id] - (1 - Li7_contribution) * Li6_atomic_mass * bred_tritium_atoms > 0) && - (b[Li7_id] - Li7_contribution * Li7_atomic_mass * bred_tritium_atoms > 0)) { - depleted_comp = {{Li7_id, b[Li7_id] - Li7_contribution * Li7_atomic_mass * bred_tritium_atoms}, - {Li6_id, b[Li6_id] - (1 - Li7_contribution) * Li6_atomic_mass * bred_tritium_atoms}, - {tritium_id, b[tritium_id] + bred_tritium_mass}, - {He4_id, b[He4_id] + He4_atomic_mass * bred_tritium_atoms}}; - - // Account for the added mass of the absorbed neutrons - double neutron_mass_correction = - absorbed_neutron_mass * (bred_tritium_mass/tritium_atomic_mass) - * (1 - Li7_contribution); - cyclus::Material::Ptr additional_mass = cyclus::Material::Create( - this, neutron_mass_correction, - cyclus::Composition::CreateFromMass(depleted_comp)); - - blanket_mat->Transmute(cyclus::Composition::CreateFromMass(depleted_comp)); - blanket_mat->Absorb(additional_mass); + // This is ALMOST the right behavior, not "scraping the bottom of the barrel + if ((blanket_Li6 - converted_Li6 > 0) && (blanket_Li7 - converted_Li7 > 0)) { + depleted_comp = {{Li7_id, blanket_Li7 - converted_Li7}, + {Li6_id, blanket_Li6 - converted_Li6}, + {tritium_id, blanket_tritium + bred_tritium_atoms}, + {He4_id, blanket_He4 + bred_He4}}; + + cyclus::compmath::Normalize(&depleted_comp, 1); + + // Because there's a mass difference between T+He and Li we need a new mass + double new_mass = (blanket_Li7 - converted_Li7) * Li7_atomic_mass + + (blanket_Li6 - converted_Li6) * Li6_atomic_mass + + (blanket_tritium + bred_tritium_atoms) * tritium_atomic_mass + + (blanket_He4 + bred_He4) * He4_atomic_mass; + + blanket_mat = cyclus::Material::Create(this, new_mass, + cyclus::Composition::CreateFromAtom(depleted_comp)); RecordOperationalInfo("Blanket Depletion", "Tritium bred at perscribed rate"); @@ -287,11 +289,10 @@ void Reactor::DepleteBlanket(double bred_tritium_mass) { blanket.Push(blanket_mat); } -cyclus::Material::Ptr Reactor::BreedTritium(double fuel_usage, double TBR) { - DepleteBlanket(fuel_usage * TBR); +cyclus::Material::Ptr Reactor::BreedTritium(double atoms_burned, double TBR) { + DepleteBlanket(atoms_burned * TBR); cyclus::Material::Ptr mat = blanket.Pop(); cyclus::toolkit::MatQuery mq(mat); - cyclus::Material::Ptr bred_fuel = mat->ExtractComp(mq.mass(tritium_id), tritium_comp); blanket.Push(mat); @@ -305,9 +306,9 @@ void Reactor::OperateReactor(double TBR) { cyclus::Material::Ptr fuel = tritium_storage.Pop(); - if (fuel->quantity() > fuel_usage) { - cyclus::Material::Ptr used_fuel = fuel->ExtractQty(fuel_usage); - fuel->Absorb(BreedTritium(fuel_usage, TBR)); + if (fuel->quantity() > fuel_usage_mass) { + cyclus::Material::Ptr used_fuel = fuel->ExtractQty(fuel_usage_mass); + fuel->Absorb(BreedTritium(fuel_usage_atoms, TBR)); tritium_storage.Push(fuel); } else { diff --git a/src/reactor.h b/src/reactor.h index 163ea24..9617eac 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -306,9 +306,12 @@ class Reactor : public cyclus::Facility { bool sufficient_tritium_for_operation = false; const double seconds_per_year = 2629846*12; const double MW_to_GW = 1000.0; - double fuel_usage; + double fuel_usage_atoms; + double fuel_usage_mass; + double avagadros_number = 6.022e23; double fuel_limit = 1000.0; double blanket_limit = 100000.0; + double Li6_contribution = 1.0-Li7_contribution; //NucIDs for Pyne const int tritium_id = 10030000; @@ -324,12 +327,6 @@ class Reactor : public cyclus::Facility { const double tritium_atomic_mass = pyne::atomic_mass(tritium_id) * amu_to_kg; const double He4_atomic_mass = pyne::atomic_mass(He4_id) * amu_to_kg; - const double absorbed_neutron_mass = tritium_atomic_mass - + He4_atomic_mass - Li6_atomic_mass; - - const double Li6_tritium_ratio = Li6_atomic_mass/tritium_atomic_mass; - const double Li7_tritium_ratio = Li6_atomic_mass/tritium_atomic_mass; - const double He4_tritium_ratio = He4_atomic_mass/tritium_atomic_mass; // kg/GW-fusion-power-year (Abdou et al. 2021) double burn_rate = 55.8; diff --git a/src/reactor_tests.cc b/src/reactor_tests.cc index 8bebe97..fba2a6f 100644 --- a/src/reactor_tests.cc +++ b/src/reactor_tests.cc @@ -177,7 +177,7 @@ TEST_F(ReactorTest, TickBlanketOverCycle) { std::string msg = qr.GetVal("Value"); std::string expected_msg = - "Total blanket material (499.055234) insufficient to extract " + "Total blanket material (498.960400) insufficient to extract " "650.000000kg!"; EXPECT_EQ(expected_msg, msg); } @@ -784,7 +784,7 @@ TEST_F(ReactorTest, BreedTritium) { QueryResult qr = sim.db().Query("ReactorOperationsLog", &conds); std::string msg = qr.GetVal("Value"); - double val = (55.8 * (300.0 / 1000.0) / (2629846*12) * 2629846.0) * 1.05; + double val = (55.8 * (300.0 / 1000.0) / 12.0) * 1.05; std::stringstream ss(msg); double bred_tritium; From 3f7bcc9440f1c0f670b7e41eae326b254d230d9f Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 18:26:58 -0500 Subject: [PATCH 40/43] cleaned up comments and commented code --- src/reactor.cc | 2 +- src/reactor.h | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index c2bf02d..8c95fef 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -81,7 +81,7 @@ void Reactor::Tock() { void Reactor::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; diff --git a/src/reactor.h b/src/reactor.h index 9617eac..7b0c7ff 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -232,7 +232,7 @@ class Reactor : public cyclus::Facility { } std::string blanket_inrecipe; - //WARNING: The default on this is completely arbitrary! + //WARNING: The default on this is arbitrary! #pragma cyclus var { \ "default": 0.05, \ "doc": "Percent of blanket that gets recycled every blanket turnover period", \ @@ -261,10 +261,6 @@ class Reactor : public cyclus::Facility { #pragma cyclus var {"tooltip":"Buffer for handling excess tritium material to be sold"} cyclus::toolkit::ResBuf tritium_excess; - //Convert to Material - //#pragma cyclus var {"tooltip":"Buffer for handling tritium sequestered in the system"} - //cyclus::toolkit::ResBuf tritium_sequestered; - #pragma cyclus var {"tooltip":"Buffer for handling helium-3 byproduct material"} cyclus::toolkit::ResBuf helium_storage; From a887c777427a5206872d82e1deaaf10f563f711a Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Sat, 27 Apr 2024 19:46:18 -0500 Subject: [PATCH 41/43] changed atom to mole basis in depleteblanket, cleaned up code some more --- src/reactor.cc | 41 +++++++++++++++++++++-------------------- src/reactor.h | 1 + 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 8c95fef..943b6e9 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -41,7 +41,6 @@ void Reactor::Tick() { } } - double blanket_turnover = blanket_size * blanket_turnover_rate; if (context()->time() % blanket_turnover_frequency == 0 && !blanket.empty()) { if (blanket.quantity() >= blanket_turnover) { blanket_excess.Push(blanket.Pop(blanket_turnover)); @@ -49,7 +48,7 @@ void Reactor::Tick() { RecordOperationalInfo( "Blanket Cycled", std::to_string(blanket_turnover) + "kg of blanket removed"); - } else if (blanket.quantity() < blanket_turnover) { + } else { RecordOperationalInfo( "Blanket Not Cycled", "Total blanket material (" + std::to_string(blanket.quantity()) + @@ -84,6 +83,7 @@ void Reactor::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; fuel_startup_policy .Init(this, &tritium_storage, std::string("Tritium Storage"), @@ -247,33 +247,34 @@ void Reactor::RecordInventories(double storage, double excess, double sequestere ->Record(); } -void Reactor::DepleteBlanket(double bred_tritium_atoms) { +void Reactor::DepleteBlanket(double bred_tritium_moles) { cyclus::Material::Ptr blanket_mat = blanket.Pop(); cyclus::toolkit::MatQuery b(blanket_mat); cyclus::CompMap depleted_comp; - double converted_Li6 = Li6_contribution * bred_tritium_atoms; - double converted_Li7 = Li7_contribution * bred_tritium_atoms; - double bred_He4 = bred_tritium_atoms; - double blanket_Li6 = b.moles(Li6_id)*avagadros_number; - double blanket_Li7 = b.moles(Li7_id)*avagadros_number; - double blanket_tritium = b.moles(tritium_id)*avagadros_number; - double blanket_He4 = b.moles(He4_id)*avagadros_number; - + + double bred_He4 = bred_tritium_moles; + double blanket_tritium = b.moles(tritium_id); + double blanket_He4 = b.moles(He4_id); + double remaining_Li6 = b.moles(Li6_id) - Li6_contribution + * bred_tritium_moles; + double remaining_Li7 = b.moles(Li7_id) - Li7_contribution + * bred_tritium_moles; + // This is ALMOST the right behavior, not "scraping the bottom of the barrel - if ((blanket_Li6 - converted_Li6 > 0) && (blanket_Li7 - converted_Li7 > 0)) { - depleted_comp = {{Li7_id, blanket_Li7 - converted_Li7}, - {Li6_id, blanket_Li6 - converted_Li6}, - {tritium_id, blanket_tritium + bred_tritium_atoms}, + if ((remaining_Li6 > 0) && (remaining_Li7 > 0)) { + depleted_comp = {{Li7_id, remaining_Li7}, + {Li6_id, remaining_Li6}, + {tritium_id, blanket_tritium + bred_tritium_moles}, {He4_id, blanket_He4 + bred_He4}}; cyclus::compmath::Normalize(&depleted_comp, 1); // Because there's a mass difference between T+He and Li we need a new mass - double new_mass = (blanket_Li7 - converted_Li7) * Li7_atomic_mass - + (blanket_Li6 - converted_Li6) * Li6_atomic_mass - + (blanket_tritium + bred_tritium_atoms) * tritium_atomic_mass - + (blanket_He4 + bred_He4) * He4_atomic_mass; + double new_mass = ((remaining_Li7) * Li7_atomic_mass + + (remaining_Li6) * Li6_atomic_mass + + (blanket_tritium + bred_tritium_moles) * tritium_atomic_mass + + (blanket_He4 + bred_He4) * He4_atomic_mass)*avagadros_number; blanket_mat = cyclus::Material::Create(this, new_mass, cyclus::Composition::CreateFromAtom(depleted_comp)); @@ -290,7 +291,7 @@ void Reactor::DepleteBlanket(double bred_tritium_atoms) { } cyclus::Material::Ptr Reactor::BreedTritium(double atoms_burned, double TBR) { - DepleteBlanket(atoms_burned * TBR); + DepleteBlanket(atoms_burned/avagadros_number * TBR); cyclus::Material::Ptr mat = blanket.Pop(); cyclus::toolkit::MatQuery mq(mat); cyclus::Material::Ptr bred_fuel = mat->ExtractComp(mq.mass(tritium_id), tritium_comp); diff --git a/src/reactor.h b/src/reactor.h index 7b0c7ff..3963fbb 100644 --- a/src/reactor.h +++ b/src/reactor.h @@ -308,6 +308,7 @@ class Reactor : public cyclus::Facility { double fuel_limit = 1000.0; double blanket_limit = 100000.0; double Li6_contribution = 1.0-Li7_contribution; + double blanket_turnover; //NucIDs for Pyne const int tritium_id = 10030000; From 431b3d407cd7d26b61a1266e19bfd468c33bfe32 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Tue, 30 Apr 2024 13:50:41 -0500 Subject: [PATCH 42/43] fixed cyclus-dangerous method of depleting blanket --- src/reactor.cc | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/reactor.cc b/src/reactor.cc index 943b6e9..f020f6c 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -270,15 +270,26 @@ void Reactor::DepleteBlanket(double bred_tritium_moles) { cyclus::compmath::Normalize(&depleted_comp, 1); - // Because there's a mass difference between T+He and Li we need a new mass - double new_mass = ((remaining_Li7) * Li7_atomic_mass - + (remaining_Li6) * Li6_atomic_mass - + (blanket_tritium + bred_tritium_moles) * tritium_atomic_mass - + (blanket_He4 + bred_He4) * He4_atomic_mass)*avagadros_number; - - blanket_mat = cyclus::Material::Create(this, new_mass, - cyclus::Composition::CreateFromAtom(depleted_comp)); - + // There's a mass difference between T+He and Li, blanket will change mass + double mass_difference = ((remaining_Li7) * Li7_atomic_mass + + (remaining_Li6) * Li6_atomic_mass + + (blanket_tritium + bred_tritium_moles) * tritium_atomic_mass + + (blanket_He4 + bred_He4) * He4_atomic_mass)*avagadros_number + -blanket_mat->quantity(); + + // Account for the mass difference after depletion, then transmute to new comp + if (mass_difference > 0){ + blanket_mat->Absorb(cyclus::Material::Create(this, mass_difference, + cyclus::Composition::CreateFromAtom(blanket_mat->comp()->mass()))); + blanket_mat->Transmute(cyclus::Composition::CreateFromAtom(depleted_comp)); + } else if (mass_difference < 0){ + std::cout<ExtractQty(std::abs(mass_difference)); + blanket_mat->Transmute(cyclus::Composition::CreateFromAtom(depleted_comp)); + } else { + blanket_mat->Transmute(cyclus::Composition::CreateFromAtom(depleted_comp)); + } + RecordOperationalInfo("Blanket Depletion", "Tritium bred at perscribed rate"); } else { From 75ad3d0281e7b35c22f4fe1d54da0772710d3349 Mon Sep 17 00:00:00 2001 From: Dean Krueger Date: Tue, 30 Apr 2024 13:55:49 -0500 Subject: [PATCH 43/43] removed uncaught std::cout statement --- src/reactor.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/reactor.cc b/src/reactor.cc index f020f6c..0123c45 100644 --- a/src/reactor.cc +++ b/src/reactor.cc @@ -283,7 +283,6 @@ void Reactor::DepleteBlanket(double bred_tritium_moles) { cyclus::Composition::CreateFromAtom(blanket_mat->comp()->mass()))); blanket_mat->Transmute(cyclus::Composition::CreateFromAtom(depleted_comp)); } else if (mass_difference < 0){ - std::cout<ExtractQty(std::abs(mass_difference)); blanket_mat->Transmute(cyclus::Composition::CreateFromAtom(depleted_comp)); } else {