From 7a142ac42ea89b213dec01da1cf3f20752e2f484 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 15:20:08 -0500 Subject: [PATCH 001/116] first add of stageconfig --- src/StageConfig.cc | 129 +++++++++++++++++++++++++++++++++++++++ src/StageConfig.h | 69 +++++++++++++++++++++ src/StageConfig_tests.cc | 118 +++++++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 src/StageConfig.cc create mode 100644 src/StageConfig.h create mode 100644 src/StageConfig_tests.cc diff --git a/src/StageConfig.cc b/src/StageConfig.cc new file mode 100644 index 0000000..402982d --- /dev/null +++ b/src/StageConfig.cc @@ -0,0 +1,129 @@ +// Implements the CascadeEnrich class +#include "StageConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbmore { + +StageConfig::StageConfig(double f_assay, double feed_, double precision_, + double cut_, double DU_, double alpha_) + : feed_assay(f_assay), + feed_flow(feed_), + precision(precision_), + DU(DU_), + alpha(alpha_), + cut(cut_) { + if (cut == -1) { + BuildIdealStg(feed_assay, precision); + } + + if (DU == -1) { + DU = centrifuge.ComputeDeltaU(cut); + } + + if (alpha == -1) { + AlphaByDU(); + } + + BetaByAlphaAndCut(); + ProductAssay(); + TailAssay(); +} + +double StageConfig::CutForIdealStg(double f_assay, double precision) { + feed_assay = f_assay; + double p_cut = cut = 0.1; + (*this).DU = centrifuge.ComputeDeltaU(cut); + double p_alpha = AlphaByDU(); + double p_beta = BetaByAlphaAndCut(); + double p_alpha_m_beta = p_alpha - p_beta; + cut = 0.9; + (*this).DU = centrifuge.ComputeDeltaU(cut); + AlphaByDU(); + BetaByAlphaAndCut(); + while (std::abs(alpha - beta) > precision) { + // a*cut +b =y + double alpha_m_beta = alpha - beta; + double a = (p_alpha_m_beta - alpha_m_beta) / (p_cut - cut); + double b = alpha_m_beta - cut * a; + // old = new + p_alpha_m_beta = alpha_m_beta; + p_cut = cut; + // targeting alpha_m_beta = 0 + cut = -b / a; + DU = centrifuge.ComputeDeltaU(cut); + alpha = AlphaByDU(); + beta = BetaByAlphaAndCut(); + } + return cut; +} + +double StageConfig::ProductAssay() { + double ratio = alpha * feed_assay / (1.0 - feed_assay); + product_assay = ratio / (1. + ratio); + return product_assay; +} + +double StageConfig::TailAssay() { + double A = (feed_assay / (1. - feed_assay)) / beta; + tail_assay = A / (1. + A); + return tail_assay; +} + +double StageConfig::AlphaByDU() { + double feed = centrifuge.feed; + double M = centrifuge.M; + alpha = 1 + std::sqrt((2 * (DU / M) * (1 - cut) / (cut * feed))); + return alpha; +} + +double StageConfig::BetaByAlphaAndCut() { + double product_assay = ProductAssay(); + double waste_assay = (feed_assay - cut * product_assay) / (1. - cut); + + beta = feed_assay / (1. - feed_assay) * (1. - waste_assay) / waste_assay; + return beta; +} + +double StageConfig::CutByAlphaBeta() { + double product_assay = ProductAssay(); + double tail_assay = TailAssay(); + + cut = (feed_assay - tail_assay) / (product_assay - tail_assay); + return cut; +} + +void StageConfig::BuildIdealStg(double f_assay, double precision) { + feed_assay = f_assay; + if (DU == -1 || alpha == -1) { + cut = CutForIdealStg(feed_assay, precision); + DU = centrifuge.ComputeDeltaU(cut); + alpha = AlphaByDU(); + beta = alpha; + cut = CutByAlphaBeta(); + } else { + beta = alpha; + cut = CutByAlphaBeta(); + } + product_assay = ProductAssay(); + tail_assay = TailAssay(); +} + +double StageConfig::MachinesPerStage() { + n_machines = feed_flow / (2.0 * DU / (pow((alpha - 1.0), 2))); + return n_machines; +} + +double StageConfig::ProductPerEnrStage() { + return feed_flow * (alpha - 1.0) * feed_assay * (1 - feed_assay) / + (2 * (product_assay - feed_assay)); +} + +} // namespace mbmore diff --git a/src/StageConfig.h b/src/StageConfig.h new file mode 100644 index 0000000..0c5957e --- /dev/null +++ b/src/StageConfig.h @@ -0,0 +1,69 @@ +#ifndef MBMORE_SRC_STAGE_H_ +#define MBMORE_SRC_STAGE_H_ + +#include +#include "CentrifugeConfig.h" + +namespace mbmore { +class CascadeConfig; + +class StageConfig { + friend CascadeConfig; + + public: + StageConfig() {;} + StageConfig(double f_assay, double feed_flow, double precision, double cut = -1, double DU = -1, double alpha = -1); + + // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) + void BuildIdealStg(double f_assay, double precision = 1e-8); + // Compute the cut to ensure alpha = beta (from dU) + double CutForIdealStg(double f_assay, double precision = 1e-8); + + // calculate Alpha value using the dU, Cut and the centrifuge feed flow value + double AlphaByDU(); + + // Compute Beta value from alpha value, cut and feed assay + double BetaByAlphaAndCut(); + // recompute Cut value assuming Alpha and Beta fixed + double CutByAlphaBeta(); + + // COmpute Product assay from feed assay and alpha + double ProductAssay(); + // Compute Waste assy from feed assay and beta + double TailAssay(); + + // Return the minimum number of centrifudes required to meed the feed flow + double MachinesPerStage(); + // Compute the Product feed + double ProductPerEnrStage(); + + // Configuration of all the centrifuges in the stage + CentrifugeConfig centrifuge; + // Precision used for the cut calculation defautl 1e-8 + double precision; + + // cut value of the stage + double cut; + // dU value of the stage (calculted form the centrifuges config with the cut) + double DU; + // Feed to Product enrichment ratio + double alpha; + // Feed to Tail enrichment ratio + double beta; + // Feed flow (g/s) + double feed_flow; + + // number of centriges in the stage + double n_machines; + + // Feed assay + double feed_assay; + // Product assay + double product_assay; + // Tail assay + double tail_assay; +}; + +} // namespace mbmore + +#endif // MBMORE_SRC_STAGE_H_ diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc new file mode 100644 index 0000000..a61ccdc --- /dev/null +++ b/src/StageConfig_tests.cc @@ -0,0 +1,118 @@ +#include + +#include "StageConfig.h" + +#include "agent_tests.h" +#include "context.h" +#include "facility_tests.h" + +namespace mbmore { + +// Benchmarked against mbmore_enrich_compare.ipynb +// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +namespace stageconfig_test { +// Fixed for a cascade separating out U235 from U238 in UF6 gas +// Fixed for a cascade separating out U235 from U238 in UF6 gas +double M = 0.352; // kg/mol UF6 +double dM = 0.003; // kg/mol U238 - U235 +double x = 1000; // Pressure ratio (Glaser) + +// General cascade assumptions +double flow_internal = 2.0; +double eff = 1.0; +double cut = 0.5; + +// Centrifuge params used in Python test code +// (based on Glaser SGS 2009 paper) +double v_a = 485; // m/s +double height = 0.5; // meters +double diameter = 0.15; // meters +double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec +double temp = 320.0; // Kelvin + +// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +const double feed_assay = 0.0071; +const double product_assay = 0.035; +const double waste_assay = 0.001; +const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, + flow_internal); +// del U=7.0323281e-08 alpha=1.16321 +double delU = centrifuge.ComputeDeltaU(cut); + +const double tol_assay = 1e-5; +const double tol_qty = 1e-6; +const double tol_num = 1e-2; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Find product assay from separation factor alpha +TEST(StageConfig_Test, TestAssays) { + double cur_alpha = 1.4; + double cur_f_assay = 0.007; + + StageConfig stage(cur_f_assay, feed_m, 1e-16, cut, delU, cur_alpha); + double cal_prod_assay = stage.ProductAssay(); + + // N_prime = alpha*R / ( 1+alpha*R) + double th_prod_assay = 0.009773; + double tol = 1e-6; + + EXPECT_NEAR(cal_prod_assay, th_prod_assay, tol); + + double n_stages = 5; + double th_w_assay = 0.004227; + double cur_beta = stage.BetaByAlphaAndCut(); + double cal_w_assay = stage.TailAssay(); + + EXPECT_NEAR(cal_w_assay, th_w_assay, tol); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate ideal SWU params of single machine (separation potential delU +// and separation factor alpha) +TEST(StageConfig_Test, TestSWU) { + double pycode_U = 7.03232816847e-08; + double tol = 1e-9; + + StageConfig stage(feed_assay, feed_m, 1e-16, cut, delU, -1); + + double pycode_alpha = 1.16321; + double tol_alpha = 1e-2; + EXPECT_NEAR(stage.alpha, pycode_alpha, tol_alpha); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Determine the output of the first enrich/strip stage of a cascade +// based on the design params for the cascade +TEST(StageConfig_Test, TestStages) { + StageConfig stage(feed_assay, feed_c, 1e-16, cut, delU, -1); + + double product_assay_s = stage.ProductAssay(); + double n_mach_e = stage.MachinesPerStage(); + double product_s = stage.ProductPerEnrStage(); + + double enrich_waste = feed_c - product_s; + double enrich_waste_assay = + (feed_c * feed_assay - product_s * product_assay_s) / enrich_waste; + + double pycode_product_assay_s = 0.0082492; + double pycode_n_mach_e = 53.287; + double pycode_product_s = 0.0001408; + + EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); + EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); + EXPECT_NEAR(product_s, pycode_product_s, tol_qty); + + stage = StageConfig(feed_assay, enrich_waste, 1e-16, cut, delU, -1); + double n_mach_w = stage.MachinesPerStage(); + double strip_waste_assay = stage.TailAssay(); + + double pycode_n_mach_w = 26.6127; + double th_waste_assay_s = 0.005951; + + EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); + EXPECT_NEAR(strip_waste_assay, th_waste_assay_s, tol_assay); +} + +} // namespace enrichfunctiontests +} // namespace mbmore From 636d033896660e989eed8e555ba48d02da9b2748 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 15:20:42 -0500 Subject: [PATCH 002/116] add StageConfig to CmakeFile --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23ea67f..0ae6747 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ USE_CYCLUS("mbmore" "mytest") USE_CYCLUS("mbmore" "behavior_functions") USE_CYCLUS("mbmore" "RandomEnrich") USE_CYCLUS("mbmore" "CentrifugeConfig") +USE_CYCLUS("mbmore" "StageConfig") USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") USE_CYCLUS("mbmore" "InteractRegion") From 01bd5308a2d98322c9d3cf6f7c83957006dcc74b Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 15:40:15 -0500 Subject: [PATCH 003/116] some improvement --- src/StageConfig.cc | 42 +++++++++++++++++++++--------------------- src/StageConfig.h | 2 ++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 402982d..3122cea 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -20,23 +20,23 @@ StageConfig::StageConfig(double f_assay, double feed_, double precision_, DU(DU_), alpha(alpha_), cut(cut_) { + // if the cut is not provided guess it such as Alpha = Beta if (cut == -1) { BuildIdealStg(feed_assay, precision); + } else { + if (DU == -1) { + DU = centrifuge.ComputeDeltaU(cut); + } + // if alpha is not provided, compute it from the dU + if (alpha == -1) { + AlphaByDU(); + } + + BetaByAlphaAndCut(); + ProductAssay(); + TailAssay(); } - - if (DU == -1) { - DU = centrifuge.ComputeDeltaU(cut); - } - - if (alpha == -1) { - AlphaByDU(); - } - - BetaByAlphaAndCut(); - ProductAssay(); - TailAssay(); } - double StageConfig::CutForIdealStg(double f_assay, double precision) { feed_assay = f_assay; double p_cut = cut = 0.1; @@ -59,8 +59,8 @@ double StageConfig::CutForIdealStg(double f_assay, double precision) { // targeting alpha_m_beta = 0 cut = -b / a; DU = centrifuge.ComputeDeltaU(cut); - alpha = AlphaByDU(); - beta = BetaByAlphaAndCut(); + AlphaByDU(); + BetaByAlphaAndCut(); } return cut; } @@ -103,17 +103,17 @@ double StageConfig::CutByAlphaBeta() { void StageConfig::BuildIdealStg(double f_assay, double precision) { feed_assay = f_assay; if (DU == -1 || alpha == -1) { - cut = CutForIdealStg(feed_assay, precision); + CutForIdealStg(feed_assay, precision); DU = centrifuge.ComputeDeltaU(cut); - alpha = AlphaByDU(); + AlphaByDU(); beta = alpha; - cut = CutByAlphaBeta(); + CutByAlphaBeta(); } else { beta = alpha; - cut = CutByAlphaBeta(); + CutByAlphaBeta(); } - product_assay = ProductAssay(); - tail_assay = TailAssay(); + ProductAssay(); + TailAssay(); } double StageConfig::MachinesPerStage() { diff --git a/src/StageConfig.h b/src/StageConfig.h index 0c5957e..0c4b141 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -11,7 +11,9 @@ class StageConfig { friend CascadeConfig; public: + // Setup a empty stage StageConfig() {;} + // Design a ideal stage for a specific feed assay and feed flow StageConfig(double f_assay, double feed_flow, double precision, double cut = -1, double DU = -1, double alpha = -1); // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) From 46e2c998c02b00a4f6a6736b908372e42df978f9 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 16:08:49 -0500 Subject: [PATCH 004/116] some improvement in StageConfig, with a constructor without centrifuges some options are not possible... --- src/StageConfig.cc | 38 +++++++++++++++++++------------------- src/StageConfig.h | 4 +++- src/StageConfig_tests.cc | 8 ++++---- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 3122cea..e457627 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -12,30 +12,30 @@ namespace mbmore { -StageConfig::StageConfig(double f_assay, double feed_, double precision_, - double cut_, double DU_, double alpha_) +StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, double feed_, + double precision_) + : centrifuge(cent), + feed_assay(f_assay), + feed_flow(feed_), + precision(precision_) { + BuildIdealStg(feed_assay, precision); +} +StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, + double alpha_, double precision_) : feed_assay(f_assay), feed_flow(feed_), precision(precision_), + cut(cut_), DU(DU_), - alpha(alpha_), - cut(cut_) { - // if the cut is not provided guess it such as Alpha = Beta - if (cut == -1) { - BuildIdealStg(feed_assay, precision); - } else { - if (DU == -1) { - DU = centrifuge.ComputeDeltaU(cut); - } - // if alpha is not provided, compute it from the dU - if (alpha == -1) { - AlphaByDU(); - } - - BetaByAlphaAndCut(); - ProductAssay(); - TailAssay(); + alpha(alpha_) { + // if alpha is not provided, compute it from the dU + if (alpha == -1) { + AlphaByDU(); } + + BetaByAlphaAndCut(); + ProductAssay(); + TailAssay(); } double StageConfig::CutForIdealStg(double f_assay, double precision) { feed_assay = f_assay; diff --git a/src/StageConfig.h b/src/StageConfig.h index 0c4b141..ab43c9f 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -14,7 +14,9 @@ class StageConfig { // Setup a empty stage StageConfig() {;} // Design a ideal stage for a specific feed assay and feed flow - StageConfig(double f_assay, double feed_flow, double precision, double cut = -1, double DU = -1, double alpha = -1); + StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, double precision = 1e-8); + // Design a ideal stage for a specific feed assay and feed flow + StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8 ); // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) void BuildIdealStg(double f_assay, double precision = 1e-8); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index a61ccdc..7274081 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -51,7 +51,7 @@ TEST(StageConfig_Test, TestAssays) { double cur_alpha = 1.4; double cur_f_assay = 0.007; - StageConfig stage(cur_f_assay, feed_m, 1e-16, cut, delU, cur_alpha); + StageConfig stage(cur_f_assay, feed_m, cut, delU, cur_alpha, 1e-16); double cal_prod_assay = stage.ProductAssay(); // N_prime = alpha*R / ( 1+alpha*R) @@ -74,7 +74,7 @@ TEST(StageConfig_Test, TestSWU) { double pycode_U = 7.03232816847e-08; double tol = 1e-9; - StageConfig stage(feed_assay, feed_m, 1e-16, cut, delU, -1); + StageConfig stage(feed_assay, feed_m, cut, delU, -1, 1e-16); double pycode_alpha = 1.16321; double tol_alpha = 1e-2; @@ -85,7 +85,7 @@ TEST(StageConfig_Test, TestSWU) { // Determine the output of the first enrich/strip stage of a cascade // based on the design params for the cascade TEST(StageConfig_Test, TestStages) { - StageConfig stage(feed_assay, feed_c, 1e-16, cut, delU, -1); + StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); double product_assay_s = stage.ProductAssay(); double n_mach_e = stage.MachinesPerStage(); @@ -103,7 +103,7 @@ TEST(StageConfig_Test, TestStages) { EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); EXPECT_NEAR(product_s, pycode_product_s, tol_qty); - stage = StageConfig(feed_assay, enrich_waste, 1e-16, cut, delU, -1); + stage = StageConfig(feed_assay, enrich_waste, cut, delU, -1, 1e-16); double n_mach_w = stage.MachinesPerStage(); double strip_waste_assay = stage.TailAssay(); From da8501b2850b1ece4df061ae002719a5d0b05639 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 16:13:11 -0500 Subject: [PATCH 005/116] autoformat --- src/StageConfig.cc | 4 ++-- src/StageConfig.h | 18 +++++++++++------- src/StageConfig_tests.cc | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index e457627..ac6cbac 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -4,11 +4,11 @@ #include #include #include +#include +#include #include #include #include -#include -#include namespace mbmore { diff --git a/src/StageConfig.h b/src/StageConfig.h index ab43c9f..23683bc 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -12,13 +12,17 @@ class StageConfig { public: // Setup a empty stage - StageConfig() {;} + StageConfig() { ; } // Design a ideal stage for a specific feed assay and feed flow - StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, double precision = 1e-8); + StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, + double precision = 1e-8); // Design a ideal stage for a specific feed assay and feed flow - StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8 ); + StageConfig(double f_assay, double feed_flow, double cut_, double DU_, + double alpha_ = -1, double precision = 1e-8); - // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) + // Build a stage assumming alpha = beta (if cut is not defined, compute the + // cut + // to make it so) void BuildIdealStg(double f_assay, double precision = 1e-8); // Compute the cut to ensure alpha = beta (from dU) double CutForIdealStg(double f_assay, double precision = 1e-8); @@ -38,7 +42,7 @@ class StageConfig { // Return the minimum number of centrifudes required to meed the feed flow double MachinesPerStage(); - // Compute the Product feed + // Compute the Product feed double ProductPerEnrStage(); // Configuration of all the centrifuges in the stage @@ -56,10 +60,10 @@ class StageConfig { double beta; // Feed flow (g/s) double feed_flow; - + // number of centriges in the stage double n_machines; - + // Feed assay double feed_assay; // Product assay diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 7274081..e517758 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -54,7 +54,7 @@ TEST(StageConfig_Test, TestAssays) { StageConfig stage(cur_f_assay, feed_m, cut, delU, cur_alpha, 1e-16); double cal_prod_assay = stage.ProductAssay(); - // N_prime = alpha*R / ( 1+alpha*R) + // N_prime = alpha*R / ( 1+alpha*R) double th_prod_assay = 0.009773; double tol = 1e-6; From 3eb90591e08b1114be9332feeebc5f3fb9ba5403 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:05:55 -0500 Subject: [PATCH 006/116] removing methods reimplemented in StageConfig --- src/enrich_functions.cc | 19 ------------------- src/enrich_functions.h | 15 --------------- 2 files changed, 34 deletions(-) diff --git a/src/enrich_functions.cc b/src/enrich_functions.cc index 29a5471..16c8f31 100644 --- a/src/enrich_functions.cc +++ b/src/enrich_functions.cc @@ -15,25 +15,6 @@ double gas_const = 8.314; // J/K/mol double M_238 = 0.238; // kg/mol -double AlphaBySwu(double del_U, double feed, double cut, double M) { - double alpha = 1 + std::sqrt((2 * (del_U / M) * (1 - cut) / (cut * feed))); - return alpha; -} - -// per machine -double ProductAssayByAlpha(double alpha, double feed_assay) { - // Possibly incorrect is commented out ? - // double ratio = (1.0 - feed_assay) / (alpha * feed_assay); - // return 1.0 / (ratio + 1.0); - double ratio = alpha * feed_assay / (1.0 - feed_assay); - return ratio / (1 + ratio); -} - -double WasteAssayByAlpha(double alpha, double feed_assay) { - double A = (feed_assay / (1 - feed_assay)) / alpha; - return A / (1 + A); -} - // This equation can only be used in the limit where the separation factor // (alpha) is very close to one, which is not true for modern gas centrifuges // DO NOT USE THIS EQUATION!!! diff --git a/src/enrich_functions.h b/src/enrich_functions.h index db6e707..9916b70 100644 --- a/src/enrich_functions.h +++ b/src/enrich_functions.h @@ -15,21 +15,6 @@ extern "C" { } - // Calculates the separations factor given the ideal separation energy of a - // single machine (del_U has units of moles/sec) - // Avery p 18 - double AlphaBySwu(double del_U, double feed, double cut, double M); - - // Calculates the assay of the product given the assay - // of the feed and the theoretical separation factor of the machine - // Avery p 57 - double ProductAssayByAlpha(double alpha, double feed_assay); - - // Calculates the assay of the waste given the assay - // of the feed and the theoretical separation factor of the machine - // Avery p 59 (per machine) - double WasteAssayByAlpha(double alpha, double feed_assay); - // Calculates the number of stages needed in a cascade given the separation // potential of a single centrifuge and the material assays std::pair From 563199105645cafa33766847000da857e35a50d0 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:10:34 -0500 Subject: [PATCH 007/116] cleaning enrich_functions_tests --- src/enrich_functions_tests.cc | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/enrich_functions_tests.cc b/src/enrich_functions_tests.cc index 6421450..ca2473d 100644 --- a/src/enrich_functions_tests.cc +++ b/src/enrich_functions_tests.cc @@ -46,27 +46,6 @@ namespace mbmore { const double tol_num = 1e-2; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Find product assay from separation factor alpha -TEST(Enrich_Functions_Test, TestAssays) { - - double cur_alpha = 1.4; - double cur_f_assay = 0.007; - - double cpp_assay = ProductAssayByAlpha(cur_alpha, cur_f_assay); - - double pycode_assay = 0.009772636; - double tol = 1e-6; - - EXPECT_NEAR(cpp_assay, pycode_assay, tol); - - double n_stages = 5; - double pycode_w_assay = 0.00095311 ; - - double cpp_w_assay = WasteAssayFromNStages(cur_alpha, cur_f_assay, n_stages); - - EXPECT_NEAR(cpp_w_assay, pycode_w_assay, tol); - -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Ideal cascade design, and then using away from ideal design From 6ce16e764c2a5f1cbc49b983979953602af69712 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 008/116] initial import --- src/CMakeLists.txt | 3 + src/CascadeConfig.cc | 384 +++++++++++++++++++++++++++++++++++++ src/CascadeConfig.h | 76 ++++++++ src/CascadeConfig_tests.cc | 196 +++++++++++++++++++ src/CascadeEnrich_tests.h | 1 + 5 files changed, 660 insertions(+) create mode 100644 src/CascadeConfig.cc create mode 100644 src/CascadeConfig.h create mode 100644 src/CascadeConfig_tests.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ae6747..b8e3464 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,8 +3,11 @@ USE_CYCLUS("mbmore" "mytest") USE_CYCLUS("mbmore" "behavior_functions") USE_CYCLUS("mbmore" "RandomEnrich") + USE_CYCLUS("mbmore" "CentrifugeConfig") USE_CYCLUS("mbmore" "StageConfig") +USE_CYCLUS("mbmore" "CascadeConfig") + USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") USE_CYCLUS("mbmore" "InteractRegion") diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc new file mode 100644 index 0000000..c5d02e6 --- /dev/null +++ b/src/CascadeConfig.cc @@ -0,0 +1,384 @@ +// Implements the CascadeEnrich class +#include "CascadeConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbmore { + +CascadeConfig::CascadeConfig() + : n_enrich(0), + n_strip(0), + n_machines(0), + feed_flow(0), + feed_assay(0), + design_product_assay(0), + design_tail_assay(0) {} + +CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, + double p_assay, double t_assay, + double max_feed_flow, int max_centrifuge, + double precision) { + centrifuge = centrifuge_; + feed_assay = f_assay; + design_product_assay = p_assay; + design_tail_assay = t_assay; + + feed_flow = max_feed_flow; + n_machines = max_centrifuge; + BuildIdealCascade(f_assay, p_assay, t_assay, precision); + DesignCascade(max_feed_flow, max_centrifuge); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate steady-state flow rates into each stage +// Linear system of equations in form AX = B, where A is nxn square matrix +// of linear equations for the flow rates of each stage and B are the external +// feeds for the stage. External feed is zero for all stages accept cascade +// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] +// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html +// +void CascadeConfig::CalcFeedFlows() { + // This is the Max # of stages in It cannot be passed in due to + // how memory is allocated and so must be hardcoded. It's been chosen + // to be much larger than it should ever need to be + + // total number of stages + int n_stages = n_enrich + n_strip; + int max_stages = n_stages; + if (n_stages > max_stages) { + std::cout << "To many stages in the can't calculated the " + "thoerritical flows..." + << std::endl; + exit(1); + } + + // Build Array with pointers + double flow_eqns[max_stages][max_stages]; + double flows[1][max_stages]; + + // build matrix of equations in this pattern + // [[ -1, 1-cut, 0, 0, 0] [[0] + // [cut, -1, 1-cut, 0, 0] [0] + // [ 0, cut, -1, 1-cut, 0] * X = [-1*feed] + // [ 0, 0, cut, -1, 1-cut] [0] + // [ 0, 0, 0, cut, -1]] [0]] + // + for (int row_idx = 0; row_idx < max_stages; row_idx++) { + // fill the array with zeros, then update individual elements as nonzero + flows[0][row_idx] = 0; + for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { + flow_eqns[fill_idx][row_idx] = 0; + } + // Required do to the artificial 'Max Stages' defn. Only calculate + // non-zero matrix elements where stages really exist. + if (row_idx < n_stages) { + int stg_i = row_idx - n_strip; + int col_idx = n_strip + stg_i; + flow_eqns[col_idx][row_idx] = -1.; + if (row_idx != 0) { + std::map::iterator it = stgs_config.find(stg_i - 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx - 1][row_idx] = it->second.cut; + } + } + if (row_idx != n_stages - 1) { + std::map::iterator it = stgs_config.find(stg_i + 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut); + } + } + // Add the external feed for the cascade + if (stg_i == 0) { + flows[0][row_idx] = -1. * feed_flow; + } + } + } + + // LAPACK solver variables + int nrhs = 1; // 1 column solution + int lda = max_stages; // must be >= MAX(1,N) + int ldb = max_stages; // must be >= MAX(1,N) + int ipiv[max_stages]; + int info; + + // Solve the linear system + dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, + &info); + + // Check for success + if (info != 0) { + std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; + } + + int i = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + it->second.feed_flow = flows[0][i]; + i++; + } +} + +void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, + double waste_assay, double precision) { + std::map ideal_stgs; + int ideal_enrich_stage = 0; + int ideal_strip_stage = 0; + + // Initialisation of Feeding stage (I == 0) + StageConfig stg; + stg.alpha = -1; + stg.DU = -1; + stg.centrifuge = centrifuge; + stg.BuildIdealStg(f_assay, precision); + int stg_i = 0; + ideal_stgs[stg_i] = stg; + double ref_alpha = ideal_stgs[0].alpha; + double ref_du = ideal_stgs[0].DU; + // Calculate number of enriching stages + while (stg.product_assay < product_assay) { + stg.BuildIdealStg(stg.product_assay, precision); + stg_i++; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_enrich = stg_i + 1; + // reset + stg_i = 0; + stg = ideal_stgs[stg_i]; + // Calculate number of stripping stages + while (stg.tail_assay > waste_assay) { + stg.BuildIdealStg(stg.tail_assay, precision); + stg_i--; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_strip = -stg_i; + stgs_config = ideal_stgs; +} + + +void CascadeConfig::CalcStageFeatures() { + double machine_tol = 0.01; + int n_stages = n_enrich + n_strip; + + for (int i = 0; i < n_stages; i++) { + int curr_stage = i - n_strip; + std::map::iterator it = stgs_config.find(curr_stage); + if (it == stgs_config.end()) { + std::cout << "Bad Stage number" << std::endl; + exit(1); + } + double n_mach_exact = it->second.MachinesPerStage(); + // unless the ideal number of machines is Very close to an integer value, + // round up to next integer to preserve steady-state flow balance + int n_mach = (int)n_mach_exact; + if (std::abs(n_mach_exact - n_mach) > machine_tol) { + n_mach = int(n_mach_exact) + 1; + } + it->second.n_machines = n_mach; + } +} + + +int CascadeConfig::FindTotalMachines() { + int machines = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + machines += it->second.n_machines; + } + return machines; +} + +void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { + // Determine the ideal steady-state feed flows for this cascade design given + // the maximum potential design feed rate + feed_flow = max_feed; + CalcFeedFlows(); + CalcStageFeatures(); + + // Do design parameters require more centrifuges than what is available? + int machines_needed = FindTotalMachines(); + double max_feed_from_machine = max_feed; + while (machines_needed > max_centrifuges) { + double scaling_ratio = (double)machines_needed / (double)max_centrifuges; + max_feed_from_machine = max_feed_from_machine / scaling_ratio; + feed_flow = max_feed_from_machine; + CalcFeedFlows(); + CalcStageFeatures(); + machines_needed = FindTotalMachines(); + } + n_machines = machines_needed; +} + +CascadeConfig CascadeConfig::Compute_Assay(double f_assay, double precision, + bool u_cut) { + CascadeConfig actual_cascade = (*this); + + // Initialiase Feeding stage + std::map::iterator it = actual_cascade.stgs_config.find(0); + it->second.feed_assay = f_assay; + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + + // Propagate initialisation to all stages + for (int i = 0; i < actual_cascade.n_enrich; i++){ + it = actual_cascade.stgs_config.find(i); + std::map::iterator it_feed; + + // Enrich stage -> feed = Product from Previous Stage + it_feed = actual_cascade.stgs_config.find(it->first - 1); + if (it->first > 0 && it_feed != actual_cascade.stgs_config.end()) { + it->second.feed_assay = it_feed->second.product_assay; + } + + // Update Product and Tail assay from feed assay + if (it->first != 0) { + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + for (int i = 1; i <= actual_cascade.n_strip; i++){ + it = actual_cascade.stgs_config.find(-i); + std::map::iterator it_feed; + + // Striping stage -> feed = tails from Next Stage + it_feed = actual_cascade.stgs_config.find(it->first + 1); + if (it->first < 0 && it_feed != actual_cascade.stgs_config.end()) { + it->second.feed_assay = it_feed->second.tail_assay; + } + + // Update Product and Tail assay from feed assay + if (it->first != 0) { + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + if(u_cut){ + actual_cascade.CalcFeedFlows(); + double ratio = 1; + for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ + std::map::iterator it_real = (*this).stgs_config.find(it->first); + double max_stg_flow = it_real->second.n_machines *it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + if (ratio < stg_flow_ratio){ + ratio = stg_flow_ratio; + } + } + for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ + it->second.feed_flow *= 1./ratio; + } + actual_cascade.feed_flow *= 1./ratio; + return actual_cascade; + } + // Looping to get the equilibrium + CascadeConfig previous_cascade; + while (Diff_enrichment(actual_cascade, previous_cascade) > precision) { + previous_cascade = actual_cascade; + actual_cascade.stgs_config = Update_enrichment(actual_cascade, f_assay, u_cut); + } + return actual_cascade; +} + +double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, + CascadeConfig p_enrichments) { + if (p_enrichments.n_enrich == 0) { + return 100.; + } + double square_feed_diff = 0; + double square_product_diff = 0; + double square_waste_diff = 0; + std::map::iterator it; + for (it = a_enrichments.stgs_config.begin(); + it != a_enrichments.stgs_config.end(); it++) { + int i = it->first; + std::map::iterator it2 = + p_enrichments.stgs_config.find(it->first); + if (it2 != p_enrichments.stgs_config.end()) { + square_feed_diff += + pow(it->second.feed_assay - it2->second.feed_assay, 2); + square_product_diff += + pow(it->second.product_assay - it2->second.product_assay, 2); + square_waste_diff += + pow(it->second.tail_assay - it2->second.tail_assay, 2); + } + } + return square_feed_diff + square_product_diff + square_waste_diff; +} + +std::map CascadeConfig::Update_enrichment( + CascadeConfig cascade, double f_assay, bool u_cut) { + CascadeConfig updated_enrichment = cascade; + + // mixing variables + double down_assay = 0; + double up_assay = 0; + double down_flow = 0; + double up_flow = 0; + double stg_feed_flow = 0; + std::map::iterator it; + + // Get the Flow and Assay quantity + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); + it++) { + int i = it->first; + std::map::iterator it_up = + cascade.stgs_config.find(i + 1); + std::map::iterator it_down = + cascade.stgs_config.find(i - 1); + down_assay = 0; + up_assay = 0; + down_flow = 0; + up_flow = 0; + + if (it_down != cascade.stgs_config.end()) { + down_assay = it_down->second.product_assay; + down_flow = it_down->second.feed_flow * it_down->second.cut; + } + if (it_up != cascade.stgs_config.end()) { + up_assay = it_up->second.tail_assay; + up_flow = it_up->second.feed_flow * (1 - it_up->second.cut); + } + + // Mix the Product and the Tail to have the correct Feed Assay + double stg_f_assay = + (down_assay * down_flow + up_assay * up_flow) / (down_flow + up_flow); + if (i == 0) { // add Feed flow in the entry stage + stg_f_assay = (down_assay * down_flow + up_assay * up_flow + + f_assay * cascade.feed_flow) / + (down_flow + up_flow + cascade.feed_flow); + stg_feed_flow = down_flow + up_flow + cascade.feed_flow; + } + + std::map::iterator it_new = + updated_enrichment.stgs_config.find(i); + + // Update Stage feed assay + it_new->second.feed_assay = stg_f_assay; + // Update Beta values (from feed) -- Alpha & Cut are cte + if(u_cut){ + it_new->second.CutByAlphaBeta(); + } else{ + it_new->second.BetaByAlphaAndCut(); + } + // Recompute Product Assay and Tail Assay + it_new->second.ProductAssay(); + it_new->second.TailAssay(); + } + + return updated_enrichment.stgs_config; +} +} // namespace mbmore diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h new file mode 100644 index 0000000..cb2735b --- /dev/null +++ b/src/CascadeConfig.h @@ -0,0 +1,76 @@ +#ifndef MBMORE_SRC_CASCADE_H_ +#define MBMORE_SRC_CASCADE_H_ + +#include +#include + +#include "CentrifugeConfig.h" +#include "StageConfig.h" + +namespace mbmore { +// LAPACK solver for system of linear equations +extern "C" { +void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipivot, double *b, + int *ldb, int *info); +} + +class CascadeConfig { + public: + CascadeConfig() ; + CascadeConfig(CentrifugeConfig centrifuge, double f_assay, double p_assay, + double t_assay, double max_feed_flow, int max_centrifuge, + double precision = 1e-8); + // Build a full cascade such as all stage follow alpha = beta = const. Get + // alpha/beta value from feeding stage. From the design feed/product/assay + void BuildIdealCascade(double f_assay, double p_assay, double w_assay, + double precision = 1e-8); + // Get the total number of machine in the Cascade + int FindTotalMachines(); + + // Solve the flow matrix from the stages cuts + void CalcFeedFlows(); + // DO something ?! + void CalcStageFeatures(); + // Scale the Casacde to meet the limitation in max feed or max centrifuges + void DesignCascade(double max_feed, int max_centrifuges); + + // Compute the response of the cascade to a non ideal feed assay + CascadeConfig Compute_Assay(double feed_assay, double precision, bool u_cut = false); + + double FeedFlow() { return feed_flow; } + // Configuration of the centrifuges in the stages + CentrifugeConfig centrifuge; + // Map of all the stage configuration + std::map stgs_config; + // number of enrich stages + int n_enrich; + // number of stripping stages + int n_strip; + + private: + // total number of machine in the Cascade + int n_machines; + // real feed flow (constrained by the cascade design/total number of + // machine/max feed flow + double feed_flow; + + //design feed assay + double feed_assay; + //design product assay + double design_product_assay; + //design tail assay + double design_tail_assay; + + // Method to check the assays different between 2 cascades + double Diff_enrichment(CascadeConfig actual_enrichments, + CascadeConfig previous_enrichement); + + // method computing one iteration, of the algorithm used to get the response + // to non ideal feed assay + std::map Update_enrichment(CascadeConfig cascade, + double feed_assay, bool u_cut = false); +}; + +} // namespace mbmore + +#endif // MBMORE_SRC_CASCADE_H_ diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc new file mode 100644 index 0000000..4a64971 --- /dev/null +++ b/src/CascadeConfig_tests.cc @@ -0,0 +1,196 @@ +#include + +#include "CascadeConfig.h" + +#include "agent_tests.h" +#include "context.h" +#include "facility_tests.h" + +namespace mbmore { + +// Benchmarked against mbmore_enrich_compare.ipynb +// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +namespace cascadeconfig_tests { +// Fixed for a cascade separating out U235 from U238 in UF6 gas +const double M = 0.352; // kg/mol UF6 +const double dM = 0.003; // kg/mol U238 - U235 +const double x = 1000; // Pressure ratio (Glaser) + +// General cascade assumptions +const double flow_internal = 2.0; +const double eff = 1.0; +const double cut = 0.5; + +// Centrifuge params used in Python test code +// (based on Glaser SGS 2009 paper) +const double v_a = 485; // m/s +const double height = 0.5; // meters +const double diameter = 0.15; // meters +const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec +const double temp = 320.0; // Kelvin + +// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +const double feed_assay = 0.0071; +const double product_assay = 0.035; +const double waste_assay = 0.001; +const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, + flow_internal); +// del U=7.0323281e-08 alpha=1.16321 +double delU = centrifuge.ComputeDeltaU(cut); + +const double tol_assay = 1e-5; +const double tol_qty = 1e-6; +const double tol_num = 1e-2; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Ideal cascade design, and then using away from ideal design + +TEST(CascadeStage_Test, TestCascade) { + CascadeConfig cascade; + cascade.centrifuge = centrifuge; + cascade.BuildIdealCascade(feed_assay, product_assay, waste_assay, 1e-8); + int pycode_n_enrich_stage = 11; + int pycode_n_strip_stage = 12; + // integer + int n_stage_enrich = cascade.n_enrich; + int n_stage_waste = cascade.n_strip; + + EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); + EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); + + // Now test assays when cascade is modified away from ideal design + // (cascade optimized for natural uranium feed, now use 20% enriched + double feed_assay_mod = 0.20; + cascade.DesignCascade(feed_c, 1000000); + CascadeConfig cascade_non_ideal = + cascade.Compute_Assay(feed_assay_mod, 1e-31); + + double mod_product_assay = + cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; + double mod_waste_assay = + cascade_non_ideal.stgs_config[-n_stage_waste].product_assay; + + double pycode_mod_product_assay = 0.8189; + EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); + + double pycode_mod_waste_assay = 0.11198; + EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// tests the steady state flow rates for a cascade +// +TEST(CascadeStage_Test, TestCascadeDesign) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + std::vector pycode_flows = { + 0.00030693, 0.00061387, 0.0009208, 0.00122774, 0.00153467, + 0.00127889, 0.00102311, 0.00076734, 0.00051156, 0.00025578}; + + std::vector pycode_machines = {80, 149, 210, 264, 312, + 241, 180, 127, 80, 38}; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); + + for (int i = 0; i < pycode_flows.size(); i++) { + EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow, + pycode_flows[i], tol_num); + int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines; + EXPECT_EQ(nmach, pycode_machines[i]); + } + + // not enough machines + int max_centrifuges = 80; + cascade.DesignCascade(feed_c, max_centrifuges); + int py_tot_mach = 80; + double py_opt_feed = 1.30116169899e-05; + + EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + + // more machines than requested capacity + max_centrifuges = 1000; + cascade.DesignCascade(feed_c, max_centrifuges); + py_tot_mach = 999; + py_opt_feed = 0.0001667; + + EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); +} + +TEST(CascadeStage_Test, TestUpdateAssay) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); + double product_assay = + cascade.stgs_config[cascade.n_enrich - 1].product_assay; + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + + double feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + double tail_from_assay = + product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); + + fa = 0.2; + cascade = cascade.Compute_Assay(fa, 1e-17); + product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; + tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + tail_from_assay = product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); +} + +TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); + double product_assay = + cascade.stgs_config[cascade.n_enrich - 1].product_assay; + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + + double feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + double tail_from_assay = + product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); + + fa = 0.2; + cascade = cascade.Compute_Assay(fa, 1e-17, true); + double alpha_ref = cascade.stgs_config[0].alpha; + std::map::iterator it; + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ + EXPECT_EQ(alpha_ref, it->second.alpha); + EXPECT_EQ(alpha_ref, it->second.beta); + } +} + +} // namespace cascadeconfig_tests +} // namespace mbmore diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From 13df6fdf529a9f1e7e22bec8f0c007af666ee171 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 17:28:59 -0500 Subject: [PATCH 009/116] some reshape on the cascade config --- src/CascadeConfig.cc | 147 ++++++++++++++++++++----------------- src/CascadeConfig.h | 20 +++-- src/CascadeConfig_tests.cc | 12 +-- 3 files changed, 100 insertions(+), 79 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index c5d02e6..9ae97db 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -33,7 +33,7 @@ CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, feed_flow = max_feed_flow; n_machines = max_centrifuge; BuildIdealCascade(f_assay, p_assay, t_assay, precision); - DesignCascade(max_feed_flow, max_centrifuge); + ScaleCascade(max_feed_flow, max_centrifuge); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -161,8 +161,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stgs_config = ideal_stgs; } - -void CascadeConfig::CalcStageFeatures() { +void CascadeConfig::PopulateStages() { double machine_tol = 0.01; int n_stages = n_enrich + n_strip; @@ -184,7 +183,6 @@ void CascadeConfig::CalcStageFeatures() { } } - int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; @@ -194,12 +192,12 @@ int CascadeConfig::FindTotalMachines() { return machines; } -void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { +void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { // Determine the ideal steady-state feed flows for this cascade design given // the maximum potential design feed rate feed_flow = max_feed; CalcFeedFlows(); - CalcStageFeatures(); + PopulateStages(); // Do design parameters require more centrifuges than what is available? int machines_needed = FindTotalMachines(); @@ -209,91 +207,112 @@ void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { max_feed_from_machine = max_feed_from_machine / scaling_ratio; feed_flow = max_feed_from_machine; CalcFeedFlows(); - CalcStageFeatures(); + PopulateStages(); machines_needed = FindTotalMachines(); } n_machines = machines_needed; } -CascadeConfig CascadeConfig::Compute_Assay(double f_assay, double precision, - bool u_cut) { - CascadeConfig actual_cascade = (*this); +CascadeConfig CascadeConfig::ModelMissUsedCascade(double f_assay, + int modeling_opt, + double precision) { + CascadeConfig miss_used_cascade = (*this); + miss_used_cascade.PropagateAssay(f_assay); + + switch (modeling_opt) { + default: + miss_used_cascade.ComputeAssay(f_assay, precision); + break; + + case 1: + miss_used_cascade.UpdateCut(); + miss_used_cascade.UpdateFlow(); + break; + } + return miss_used_cascade; +} - // Initialiase Feeding stage - std::map::iterator it = actual_cascade.stgs_config.find(0); - it->second.feed_assay = f_assay; - if (u_cut) { +void CascadeConfig::UpdateFlow() { + // recompute the flow according to the new cuts + (*this).CalcFeedFlows(); + + double ratio = 1; + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + std::map::iterator it_real = + (*this).stgs_config.find(it->first); + double max_stg_flow = + it_real->second.n_machines * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + if (ratio < stg_flow_ratio) { + ratio = stg_flow_ratio; + } + } + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + it->second.feed_flow *= 1. / ratio; + } + (*this).feed_flow *= 1. / ratio; +} + +void CascadeConfig::UpdateCut() { + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { it->second.CutByAlphaBeta(); } +} + +void CascadeConfig::PropagateAssay(double f_assay) { + // Initialiase Feeding stage + std::map::iterator it = (*this).stgs_config.find(0); + it->second.feed_assay = f_assay; it->second.ProductAssay(); it->second.TailAssay(); // Propagate initialisation to all stages - for (int i = 0; i < actual_cascade.n_enrich; i++){ - it = actual_cascade.stgs_config.find(i); + for (int i = 0; i < (*this).n_enrich; i++) { + it = (*this).stgs_config.find(i); std::map::iterator it_feed; // Enrich stage -> feed = Product from Previous Stage - it_feed = actual_cascade.stgs_config.find(it->first - 1); - if (it->first > 0 && it_feed != actual_cascade.stgs_config.end()) { - it->second.feed_assay = it_feed->second.product_assay; - } - - // Update Product and Tail assay from feed assay - if (it->first != 0) { - if (u_cut) { - it->second.CutByAlphaBeta(); + it_feed = (*this).stgs_config.find(it->first - 1); + if (it->first > 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay = it_feed->second.product_assay; } + // Update Product and Tail assay from feed assay it->second.ProductAssay(); it->second.TailAssay(); } } - for (int i = 1; i <= actual_cascade.n_strip; i++){ - it = actual_cascade.stgs_config.find(-i); + for (int i = 1; i <= (*this).n_strip; i++) { + it = (*this).stgs_config.find(-i); std::map::iterator it_feed; // Striping stage -> feed = tails from Next Stage - it_feed = actual_cascade.stgs_config.find(it->first + 1); - if (it->first < 0 && it_feed != actual_cascade.stgs_config.end()) { - it->second.feed_assay = it_feed->second.tail_assay; - } - - // Update Product and Tail assay from feed assay - if (it->first != 0) { - if (u_cut) { - it->second.CutByAlphaBeta(); + it_feed = (*this).stgs_config.find(it->first + 1); + if (it->first < 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay = it_feed->second.tail_assay; } + // Update Product and Tail assay from feed assay it->second.ProductAssay(); it->second.TailAssay(); } } - if(u_cut){ - actual_cascade.CalcFeedFlows(); - double ratio = 1; - for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ - std::map::iterator it_real = (*this).stgs_config.find(it->first); - double max_stg_flow = it_real->second.n_machines *it_real->second.centrifuge.feed; - double stg_flow_ratio = it->second.feed_flow / max_stg_flow; - if (ratio < stg_flow_ratio){ - ratio = stg_flow_ratio; - } - } - for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ - it->second.feed_flow *= 1./ratio; - } - actual_cascade.feed_flow *= 1./ratio; - return actual_cascade; - } - // Looping to get the equilibrium +} + +void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (Diff_enrichment(actual_cascade, previous_cascade) > precision) { - previous_cascade = actual_cascade; - actual_cascade.stgs_config = Update_enrichment(actual_cascade, f_assay, u_cut); + while (DeltaEnrichment((*this), previous_cascade) > precision) { + previous_cascade = (*this); + (*this).stgs_config = IterrateEnrichment((*this), f_assay); } - return actual_cascade; } -double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, +double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, CascadeConfig p_enrichments) { if (p_enrichments.n_enrich == 0) { return 100.; @@ -319,8 +338,8 @@ double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::Update_enrichment( - CascadeConfig cascade, double f_assay, bool u_cut) { +std::map CascadeConfig::IterrateEnrichment( + CascadeConfig cascade, double f_assay) { CascadeConfig updated_enrichment = cascade; // mixing variables @@ -369,11 +388,7 @@ std::map CascadeConfig::Update_enrichment( // Update Stage feed assay it_new->second.feed_assay = stg_f_assay; // Update Beta values (from feed) -- Alpha & Cut are cte - if(u_cut){ - it_new->second.CutByAlphaBeta(); - } else{ - it_new->second.BetaByAlphaAndCut(); - } + it_new->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay it_new->second.ProductAssay(); it_new->second.TailAssay(); diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index cb2735b..e4bce3e 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -30,12 +30,18 @@ class CascadeConfig { // Solve the flow matrix from the stages cuts void CalcFeedFlows(); // DO something ?! - void CalcStageFeatures(); + void PopulateStages(); + // Scale the Casacde to meet the limitation in max feed or max centrifuges - void DesignCascade(double max_feed, int max_centrifuges); + void ScaleCascade(double max_feed, int max_centrifuges); + + CascadeConfig ModelMissUsedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay - CascadeConfig Compute_Assay(double feed_assay, double precision, bool u_cut = false); + void PropagateAssay(double f_assay); + void ComputeAssay(double f_assay, double precision = 1e-8); + void UpdateCut(); + void UpdateFlow(); double FeedFlow() { return feed_flow; } // Configuration of the centrifuges in the stages @@ -62,13 +68,13 @@ class CascadeConfig { double design_tail_assay; // Method to check the assays different between 2 cascades - double Diff_enrichment(CascadeConfig actual_enrichments, - CascadeConfig previous_enrichement); + double DeltaEnrichment(CascadeConfig actual_enrichments, + CascadeConfig previous_enrichment); // method computing one iteration, of the algorithm used to get the response // to non ideal feed assay - std::map Update_enrichment(CascadeConfig cascade, - double feed_assay, bool u_cut = false); + std::map IterrateEnrichment(CascadeConfig cascade, + double feed_assay); }; } // namespace mbmore diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 4a64971..32940c0 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -63,9 +63,9 @@ TEST(CascadeStage_Test, TestCascade) { // Now test assays when cascade is modified away from ideal design // (cascade optimized for natural uranium feed, now use 20% enriched double feed_assay_mod = 0.20; - cascade.DesignCascade(feed_c, 1000000); + cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.Compute_Assay(feed_assay_mod, 1e-31); + cascade.ModelMissUsedCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; @@ -105,7 +105,7 @@ TEST(CascadeStage_Test, TestCascadeDesign) { // not enough machines int max_centrifuges = 80; - cascade.DesignCascade(feed_c, max_centrifuges); + cascade.ScaleCascade(feed_c, max_centrifuges); int py_tot_mach = 80; double py_opt_feed = 1.30116169899e-05; @@ -114,7 +114,7 @@ TEST(CascadeStage_Test, TestCascadeDesign) { // more machines than requested capacity max_centrifuges = 1000; - cascade.DesignCascade(feed_c, max_centrifuges); + cascade.ScaleCascade(feed_c, max_centrifuges); py_tot_mach = 999; py_opt_feed = 0.0001667; @@ -145,7 +145,7 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.Compute_Assay(fa, 1e-17); + cascade = cascade.ModelMissUsedCascade(fa, 0, 1e-17); product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * @@ -183,7 +183,7 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.Compute_Assay(fa, 1e-17, true); + cascade = cascade.ModelMissUsedCascade(fa, 1, 1e-17); double alpha_ref = cascade.stgs_config[0].alpha; std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ From f1acffe0f0c727b33c6cc54a2ec5789079036b77 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:19:11 -0500 Subject: [PATCH 010/116] Removing some file not suppose to be there yet --- src/CascadeEnrich_tests.h | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h deleted file mode 100644 index 025911b..0000000 --- a/src/CascadeEnrich_tests.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ -#define MBMORE_SRC_CASCADEENRICH_TESTS_ - -#include - -#include - -#include "test_context.h" -#include "env.h" -#include "exchange_context.h" -#include "material.h" - -#include "CascadeEnrich.h" -#include "CascadeConfig.h" - -namespace mbmore { - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class CascadeEnrichTest : public ::testing::Test { - protected: - cyclus::TestContext tc_; - CascadeEnrich* src_facility; - std::string feed_commod, product_commod, feed_recipe, tails_commod; - cyclus::Composition::Ptr recipe; - TestFacility* trader; - - double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; - - bool order_prefs; - - double reserves; - - virtual void SetUp(); - virtual void TearDown(); - void InitParameters(); - void SetUpSource(); - cyclus::Material::Ptr GetMat(double qty); - /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 - cyclus::Material::Ptr GetReqMat(double qty, double enr); - void DoAddMat(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoRequest(); - cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); - /// @param nreqs the total number of requests - /// @param nvalid the number of requests that are valid - boost::shared_ptr< cyclus::ExchangeContext > - GetContext(int nreqs, int nvalid); -}; - -} // namespace cycamore -#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From ed100fa4fb2b6574aabcbaac1dbfacbe2d459c8c Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:14:46 -0500 Subject: [PATCH 011/116] removing methods reimplemented in CascadeConfig --- src/enrich_functions.cc | 122 ---------------------- src/enrich_functions_tests.cc | 187 ---------------------------------- 2 files changed, 309 deletions(-) delete mode 100644 src/enrich_functions_tests.cc diff --git a/src/enrich_functions.cc b/src/enrich_functions.cc index 16c8f31..c0c593b 100644 --- a/src/enrich_functions.cc +++ b/src/enrich_functions.cc @@ -44,38 +44,6 @@ std::pair StagesPerCascade(double alpha, double feed_assay, // Determine number of stages required to reach ideal cascade product assay // (requires integer number of stages, so output may exceed target assay) -std::pair FindNStages(double alpha, double feed_assay, - double product_assay, double waste_assay) { - using std::pair; - - int ideal_enrich_stage = 0; - int ideal_strip_stage = 0; - double stage_feed_assay = feed_assay; - double stage_product_assay = feed_assay; - double stage_waste_assay = feed_assay; // start w/waste of 1st enrich stage - - // Calculate number of enriching stages - while (stage_product_assay < product_assay) { - stage_product_assay = ProductAssayByAlpha(alpha, stage_feed_assay); - if (ideal_enrich_stage == 0) { - stage_waste_assay = WasteAssayByAlpha(alpha, stage_feed_assay); - } - ideal_enrich_stage += 1; - stage_feed_assay = stage_product_assay; - } - // Calculate number of stripping stages - stage_feed_assay = stage_waste_assay; - while (stage_waste_assay > waste_assay) { - stage_waste_assay = WasteAssayByAlpha(alpha, stage_feed_assay); - ideal_strip_stage += 1; - stage_feed_assay = stage_waste_assay; - } - - std::pair stages = - std::make_pair(ideal_enrich_stage, ideal_strip_stage); - return stages; -} - double ProductAssayFromNStages(double alpha, double feed_assay, double enrich_stages) { double A = @@ -135,86 +103,6 @@ double DelUByCascadeConfig(double product_assay, double waste_assay, return U_cascade / feed_assay; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Calculate steady-state flow rates into each cascade stage -// Linear system of equations in form AX = B, where A is nxn square matrix -// of linear equations for the flow rates of each stage and B are the external -// feeds for the stage. External feed is zero for all stages accept cascade -// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] -// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html -// -std::vector CalcFeedFlows(std::pair n_st, double cascade_feed, - double cut) { - // This is the Max # of stages in cascade. It cannot be passed in due to - // how memory is allocated and so must be hardcoded. It's been chosen - // to be much larger than it should ever need to be - int max_stages = 100; - - int n_enrich = n_st.first; - int n_strip = n_st.second; - int n_stages = n_st.first + n_st.second; - - // LAPACK takes the external flow feeds as B, and then returns a modified - // version of the same array now representing the solution flow rates. - - // Build Array with pointers - double flow_eqns[max_stages][max_stages]; - double flows[1][max_stages]; - - // build matrix of equations in this pattern - // [[ -1, 1-cut, 0, 0, 0] [[0] - // [cut, -1, 1-cut, 0, 0] [0] - // [ 0, cut, -1, 1-cut, 0] * X = [-1*cascade_feed] - // [ 0, 0, cut, -1, 1-cut] [0] - // [ 0, 0, 0, cut, -1]] [0]] - // - for (int row_idx = 0; row_idx < max_stages; row_idx++) { - // fill the array with zeros, then update individual elements as nonzero - flows[0][row_idx] = 0; - for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { - flow_eqns[fill_idx][row_idx] = 0; - } - // Required do to the artificial 'Max Stages' defn. Only calculate - // non-zero matrix elements where stages really exist. - if (row_idx < n_stages) { - int i = row_idx - n_strip; - int col_idx = n_strip + i; - flow_eqns[col_idx][row_idx] = -1; - if (col_idx != 0) { - flow_eqns[col_idx - 1][row_idx] = cut; - } - if (col_idx != n_stages - 1) { - flow_eqns[col_idx + 1][row_idx] = (1 - cut); - } - // Add the external feed for the cascade - if (i == 0) { - flows[0][row_idx] = -1 * cascade_feed; - } - } - } - - // LAPACK solver variables - int nrhs = 1; // 1 column solution - int lda = max_stages; // must be >= MAX(1,N) - int ldb = max_stages; // must be >= MAX(1,N) - int ipiv[max_stages]; - int info; - - // Solve the linear system - dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, - &info); - - // Check for success - if (info != 0) { - std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; - } - - std::vector final_flows; - for (int i = 0; i < n_stages; i++) { - final_flows.push_back(flows[0][i]); - } - return final_flows; -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine number of machines in each stage of the cascade, and total // output flow from each stage @@ -279,16 +167,6 @@ std::vector> CalcStageFeatures( return stage_info; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Determine total number of machines in the cascade from machines per stage -int FindTotalMachines(std::vector> stage_info) { - int machines_needed = 0; - std::vector>::const_iterator it; - for (it = stage_info.begin(); it != stage_info.end(); it++) { - machines_needed += it->first; - } - return machines_needed; -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::pair DesignCascade(double design_feed, diff --git a/src/enrich_functions_tests.cc b/src/enrich_functions_tests.cc deleted file mode 100644 index ca2473d..0000000 --- a/src/enrich_functions_tests.cc +++ /dev/null @@ -1,187 +0,0 @@ -#include - -#include "enrich_functions.h" - -#include "agent_tests.h" -#include "context.h" -#include "facility_tests.h" - -namespace mbmore { - - // Benchmarked against mbmore_enrich_compare.ipynb - // https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs - namespace enrichfunctiontests { - // Fixed for a cascade separating out U235 from U238 in UF6 gas - const double M = 0.352; // kg/mol UF6 - const double dM = 0.003; // kg/mol U238 - U235 - const double x = 1000; // Pressure ratio (Glaser) - - // General cascade assumptions - const double flow_internal = 2.0 ; - const double eff = 1.0; - const double cut = 0.5; - - // Centrifuge params used in Python test code - // (based on Glaser SGS 2009 paper) - const double v_a = 485; // m/s - const double height = 0.5; // meters - const double diameter = 0.15; // meters - const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec - const double temp = 320.0 ; //Kelvin - - // Cascade params used in Python test code (Enrichment_Calculations.ipynb) - const double feed_assay = 0.0071; - const double product_assay = 0.035; - const double waste_assay = 0.001; - const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec - const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec - - //del U=7.0323281e-08 alpha=1.16321 - double delU = CalcDelU(v_a, height, diameter, feed_m, temp, cut, eff, - M, dM, x, flow_internal); - - double alpha = AlphaBySwu(delU, feed_m, cut, M); - const double tol_assay = 1e-5; - const double tol_qty = 1e-6; - const double tol_num = 1e-2; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Ideal cascade design, and then using away from ideal design - -TEST(Enrich_Functions_Test, TestCascade) { - double n_machines = MachinesPerCascade(delU, product_assay, - waste_assay, feed_c, product_c); - - double pycode_n_mach = 25990.392; - EXPECT_NEAR(n_machines, pycode_n_mach, tol_num); - - std::pair n_stages = FindNStages(alpha, feed_assay, - product_assay, - waste_assay); - int pycode_n_enrich_stage = 11; - int pycode_n_strip_stage = 13; - - - // int n_stage_enrich = (int) n_stages.first + 1; // Round up to next integer - // int n_stage_waste = (int) n_stages.second + 1; // Round up to next integer - int n_stage_enrich = n_stages.first; - int n_stage_waste = n_stages.second; - - EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); - EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); - - // Now test assays when cascade is modified away from ideal design - // (cascade optimized for natural uranium feed, now use 20% enriched - double feed_assay_mod = 0.20; - - double mod_product_assay = ProductAssayFromNStages(alpha, feed_assay_mod, - n_stage_enrich); - double mod_waste_assay = WasteAssayFromNStages(alpha, feed_assay_mod, - n_stage_waste); - - std::cout << "alpha " << alpha << " feed " << feed_assay_mod << " nstage " << n_stage_enrich << " unrounded stages " << n_stages.first << std::endl; - double pycode_mod_product_assay = 0.60085; - double pycode_mod_waste_assay = 0.0290846; - EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); - EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine the output of the first enrich/strip stage of a cascade - // based on the design params for the cascade - TEST(Enrich_Functions_Test, TestStages) { - double product_assay_s = ProductAssayByAlpha(alpha, feed_assay); - double n_mach_e = MachinesPerStage(alpha, delU, feed_c); - double product_s = ProductPerEnrStage(alpha, feed_assay, - product_assay_s, feed_c); - - double enrich_waste = feed_c - product_s; - double enrich_waste_assay = (feed_c * feed_assay - product_s * - product_assay_s)/enrich_waste; - - double pycode_product_assay_s = 0.0082492; - double pycode_n_mach_e = 53.287; - double pycode_product_s = 0.0001408; - - EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); - EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); - EXPECT_NEAR(product_s, pycode_product_s, tol_qty); - - double n_mach_w = MachinesPerStage(alpha, delU, enrich_waste); - double strip_waste_assay = WasteAssayByAlpha(alpha, enrich_waste_assay); - - // This AVERY EQN doesn't work for some reason - // double strip_waste = WastePerStripStage(alpha, enrich_waste_assay, - // strip_waste_assay, enrich_waste); - - double pycode_n_mach_w = 26.6127; - double pycode_waste_assay_s = 0.005117; - // double pycode_waste_s = 8.60660553717e-05; - - EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); - EXPECT_NEAR(strip_waste_assay, pycode_waste_assay_s, tol_assay); - // EXPECT_NEAR(strip_waste, pycode_waste_s, tol_qty); - - } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// tests the steady state flow rates for a cascade -// -TEST(Enrich_Functions_Test, TestCascadeDesign) { - double fa = 0.10; - double pa = 0.20; - double wa = 0.05; - - std::vector pycode_flows = {0.00030693, 0.00061387, 0.0009208 , - 0.00122774, 0.00153467, 0.00127889, - 0.00102311, 0.00076734, 0.00051156, - 0.00025578}; - - - std::vector pycode_machines={59, 117, 175, 233, 291, 243, 194, - 146, 97, 49}; - - std::pair n_stages = FindNStages(alpha, fa, pa, wa); - std::vector flows = CalcFeedFlows(n_stages, feed_c, cut); - - // if # Machines for the stage is within tol_num of an integer - // then round down. Otherwise round up to the next integer machine to - // preserve steady-state flow calculations. - std::vector> stage_info = - CalcStageFeatures(fa, alpha, delU, cut, n_stages, flows); - - for (int i = 0; i < pycode_flows.size(); i++){ - EXPECT_NEAR(flows[i], pycode_flows[i], tol_num); - int nmach = stage_info[i].first; - EXPECT_EQ(nmach, pycode_machines[i]); - } - - // not enough machines - int max_centrifuges = 80; - std::pair design_params = DesignCascade(feed_c, alpha, delU, - cut, max_centrifuges, - n_stages); - int py_tot_mach = 79; - double py_opt_feed = 1.30116169899e-05; - - EXPECT_EQ(py_tot_mach, design_params.first); - EXPECT_NEAR(py_opt_feed, design_params.second, tol_qty); - - // more machines than requested capacity - max_centrifuges = 1000; - design_params = DesignCascade(feed_c, alpha, delU, - cut, max_centrifuges, - n_stages); - py_tot_mach = 986; - py_opt_feed = 0.000172728; - - EXPECT_EQ(py_tot_mach, design_params.first); - EXPECT_NEAR(py_opt_feed, design_params.second, tol_qty); - -} - - - } // namespace enrichfunctiontests -} // namespace mbmore From b948dd58ec5ce1be7d473f9db12e2104bfc2a02d Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:20:06 -0500 Subject: [PATCH 012/116] removing methods reimplemented in CascadeConfig --- src/enrich_functions.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/enrich_functions.h b/src/enrich_functions.h index 9916b70..cba6f99 100644 --- a/src/enrich_functions.h +++ b/src/enrich_functions.h @@ -15,11 +15,6 @@ extern "C" { } - // Calculates the number of stages needed in a cascade given the separation - // potential of a single centrifuge and the material assays - std::pair - FindNStages(double alpha, double feed_assay, double product_assay, - double Nwc); // Calculates the product assay after N enriching stages double ProductAssayFromNStages(double alpha, double feed_assay, @@ -68,10 +63,6 @@ extern "C" { double product_flow, double waste_flow, double feed_assay); - // Solves system of linear eqns to determine steady state flow rates - // in each stage of cascade - std::vector CalcFeedFlows(std::pair n_st, - double cascade_feed, double cut); // Determines the number of machines and product in each stage based // on the steady-state flows defined for the cascade. @@ -81,8 +72,6 @@ extern "C" { std::pair n_st, std::vector feed_flow); - // Determine total number of machines in the cascade from machines per stage - int FindTotalMachines(std::vector> stage_info); std::pair DesignCascade( double design_feed, double design_alpha, double design_delU, double cut, From f248bc82813bf74f8ea1ffba2658287dacb4a941 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:23:35 -0500 Subject: [PATCH 013/116] readd missing file --- src/CascadeEnrich_tests.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h new file mode 100644 index 0000000..22a650d --- /dev/null +++ b/src/CascadeEnrich_tests.h @@ -0,0 +1,51 @@ +#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ +#define MBMORE_SRC_CASCADEENRICH_TESTS_ + +#include + +#include + +#include "test_context.h" +#include "env.h" +#include "exchange_context.h" +#include "material.h" + +#include "CascadeEnrich.h" + +namespace mbmore { + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class CascadeEnrichTest : public ::testing::Test { + protected: + cyclus::TestContext tc_; + CascadeEnrich* src_facility; + std::string feed_commod, product_commod, feed_recipe, tails_commod; + cyclus::Composition::Ptr recipe; + TestFacility* trader; + + double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; + + bool order_prefs; + + double reserves; + + virtual void SetUp(); + virtual void TearDown(); + void InitParameters(); + void SetUpSource(); + cyclus::Material::Ptr GetMat(double qty); + /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 + cyclus::Material::Ptr GetReqMat(double qty, double enr); + void DoAddMat(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoRequest(); + cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); + /// @param nreqs the total number of requests + /// @param nvalid the number of requests that are valid + boost::shared_ptr< cyclus::ExchangeContext > + GetContext(int nreqs, int nvalid); +}; + +} // namespace cycamore +#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From 9a0a83da9dbf704204497d0042d6cfab82031452 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:21:00 -0500 Subject: [PATCH 014/116] initial addition --- src/CascadeEnrich.cc | 317 ++++++++++++++++++++----------------- src/CascadeEnrich.h | 210 ++++++++++-------------- src/CascadeEnrich_tests.cc | 248 +++-------------------------- 3 files changed, 281 insertions(+), 494 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index 64dc116..cbc7ac5 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -1,48 +1,46 @@ // Implements the CascadeEnrich class #include "CascadeEnrich.h" #include "behavior_functions.h" -#include "enrich_functions.h" #include "sim_init.h" #include +#include #include #include #include #include -#include - namespace mbmore { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) +CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) : cyclus::Facility(ctx), - feed_recipe(""), - max_centrifuges(), - design_feed_assay(), - design_product_assay(), - design_tails_assay(), - centrifuge_velocity(485.0), - temp(320.0), - height(0.5), - diameter(0.15), - machine_feed(15), - max_enrich(1), - design_feed_flow(0), - feed_commod(""), - product_commod(""), - tails_commod(""), - order_prefs(true) {} + feed_recipe(""), + max_centrifuges(), + design_feed_assay(), + design_product_assay(), + design_tails_assay(), + centrifuge_velocity(485.0), + temp(320.0), + height(0.5), + diameter(0.15), + machine_feed(15), + max_enrich(1), + design_feed_flow(100), + L_over_F(2), + feed_commod(""), + product_commod(""), + tails_commod(""), + miss_use_model(0), + order_prefs(true) {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CascadeEnrich::~CascadeEnrich() {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::string CascadeEnrich::str() { std::stringstream ss; - ss << cyclus::Facility::str() - << " with enrichment facility parameters:" - << " * SWU capacity: " << SwuCapacity() - << " * Tails assay: " << tails_assay << " * Feed assay: " << FeedAssay() + ss << cyclus::Facility::str() << " with enrichment facility parameters:" + << " * Tails assay: " << design_tails_assay << " * Feed assay: " << design_feed_assay << " * Input cyclus::Commodity: " << feed_commod << " * Output cyclus::Commodity: " << product_commod << " * Tails cyclus::Commodity: " << tails_commod; @@ -50,72 +48,59 @@ std::string CascadeEnrich::str() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CascadeEnrich::Build(cyclus::Agent* parent) { +void CascadeEnrich::EnterNotify() { using cyclus::Material; - - tails_assay = design_tails_assay; - - // Calculate ideal machine performance - double design_delU = CalcDelU(centrifuge_velocity, height, diameter, - Mg2kgPerSec(machine_feed), temp, - cut, eff, M, dM, x, flow_internal); - double design_alpha = AlphaBySwu(design_delU, Mg2kgPerSec(machine_feed), - cut, M); - - // Design ideal cascade based on target feed flow and product assay - std::pair n_stages = - FindNStages(design_alpha, design_feed_assay, design_product_assay, - design_tails_assay); - - // TODO DELETE THIS, STAGES ARE ALREADY INTS - // set as internal state variables - // int truncates but we need # of stages to assure target values, - // so if the number is 5.1 we need 6. - // n_enrich_stages = int(n_stages.first) + 1; - // n_strip_stages = int(n_stages.second) + 1; - n_enrich_stages = n_stages.first; - n_strip_stages = n_stages.second; - - std::pair cascade_info = DesignCascade(FlowPerSec(design_feed_flow), - design_alpha, - design_delU, - cut, max_centrifuges, - n_stages); - - max_feed_inventory = FlowPerMon(cascade_info.second); - // Number of machines times swu per machine - SwuCapacity(cascade_info.first * FlowPerMon(design_delU)); - - Facility::Build(parent); + cyclus::Facility::EnterNotify(); + centrifuge = CentrifugeConfig(); + // Update Centrifuge paramter from the user input: + centrifuge.v_a = centrifuge_velocity; + centrifuge.height = height; + centrifuge.diameter = diameter; + centrifuge.feed = machine_feed / 1000 / 1000; + centrifuge.temp = temp; + centrifuge.flow_internal = L_over_F; + + cascade = CascadeConfig(centrifuge, design_feed_assay, design_product_assay, + design_tails_assay, FlowPerSec(design_feed_flow), + max_centrifuges, precision); + + std::map::iterator it; + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); + it++) { + std::cout << "stg " << it->first; + std::cout << " FA: " << it->second.feed_assay; + std::cout << " PA: " << it->second.product_assay; + std::cout << " TA: " << it->second.tail_assay; + std::cout << " feed_flow: " << it->second.feed_flow; + std::cout << " cut: " << it->second.cut; + std::cout << " alpha: " << it->second.alpha; + std::cout << " beta: " << it->second.beta; + std::cout << " machine: " << it->second.n_machines; + std::cout << std::endl; + } + std::cout << "Dsign Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; + if (max_feed_inventory > 0) { + inventory.capacity(max_feed_inventory); + } if (initial_feed > 0) { - inventory.Push( - Material::Create( - this, initial_feed, context()->GetRecipe(feed_recipe))); + inventory.Push(Material::Create(this, initial_feed, + context()->GetRecipe(feed_recipe))); } - LOG(cyclus::LEV_DEBUG2, "EnrFac") << "CascadeEnrich " - << " entering the simuluation: "; + << " entering the simuluation: "; LOG(cyclus::LEV_DEBUG2, "EnrFac") << str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CascadeEnrich::Tick() { - - current_swu_capacity = SwuCapacity(); - - } +void CascadeEnrich::Tick() {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::Tock() { using cyclus::toolkit::RecordTimeSeries; - LOG(cyclus::LEV_INFO4, "EnrFac") << prototype() << " used " - << intra_timestep_swu_ << " SWU"; - RecordTimeSeries(this, intra_timestep_swu_); LOG(cyclus::LEV_INFO4, "EnrFac") << prototype() << " used " << intra_timestep_feed_ << " feed"; RecordTimeSeries(this, intra_timestep_feed_); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -149,7 +134,6 @@ void CascadeEnrich::AdjustMatlPrefs( if (order_prefs == false) { return; } - cyclus::PrefMap::type::iterator reqit; // Loop over all requests @@ -168,7 +152,7 @@ void CascadeEnrich::AdjustMatlPrefs( bool u235_mass = 0; for (int bidit = 0; bidit < bids_vector.size(); bidit++) { - int new_pref = bidit + 1; + int new_pref = bidit + 10; // For any bids with U-235 qty=0, set pref to zero. if (!u235_mass) { @@ -188,11 +172,11 @@ void CascadeEnrich::AdjustMatlPrefs( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::AcceptMatlTrades( const std::vector, - cyclus::Material::Ptr> >& responses) { + cyclus::Material::Ptr>>& responses) { // see // http://stackoverflow.com/questions/5181183/boostshared-ptr-and-inheritance std::vector, - cyclus::Material::Ptr> >::const_iterator it; + cyclus::Material::Ptr>>::const_iterator it; for (it = responses.begin(); it != responses.end(); ++it) { AddMat_(it->second); } @@ -241,7 +225,8 @@ void CascadeEnrich::AddMat_(cyclus::Material::Ptr mat) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::set::Ptr> -CascadeEnrich::GetMatlBids(cyclus::CommodMap::type& out_requests) { +CascadeEnrich::GetMatlBids( + cyclus::CommodMap::type& out_requests) { using cyclus::Bid; using cyclus::BidPortfolio; using cyclus::CapacityConstraint; @@ -287,27 +272,34 @@ CascadeEnrich::GetMatlBids(cyclus::CommodMap::type& out_reques std::vector*>::iterator it; for (it = commod_requests.begin(); it != commod_requests.end(); ++it) { Request* req = *it; - Material::Ptr mat = req->target(); - double request_enrich = cyclus::toolkit::UraniumAssay(mat); - if (ValidReq(req->target()) && - ((request_enrich < max_enrich) || - (cyclus::AlmostEq(request_enrich, max_enrich)))) { - Material::Ptr offer = Offer_(req->target()); - commod_port->AddBid(req, offer, this); - } + Material::Ptr offer = Offer_(req->target()); + // The offer might not match the required enrichment ! it just produce + // what it can according to the cascade configuration and the feed asays + commod_port->AddBid(req, offer, this); } - Converter::Ptr sc(new SWUConverter(FeedAssay(), tails_assay)); - Converter::Ptr nc(new NatUConverter(FeedAssay(), tails_assay)); - CapacityConstraint swu(swu_capacity, sc); - CapacityConstraint natu(inventory.quantity(), nc); - commod_port->AddConstraint(swu); - commod_port->AddConstraint(natu); - - LOG(cyclus::LEV_INFO5, "EnrFac") - << prototype() << " adding a swu constraint of " << swu.capacity(); + // overbidding (bidding on every offer) + // add an overall production capacity constraint + + // correct the actual inventory quantity by the amount of Uranium in it... + double feed_qty = inventory.quantity(); + Material::Ptr natu_matl = inventory.Pop(feed_qty, cyclus::eps_rsrc()); + inventory.Push(natu_matl); + cyclus::toolkit::MatQuery mq(natu_matl); + std::set nucs; + nucs.insert(922350000); + nucs.insert(922380000); + double u_frac = mq.mass_frac(nucs); + double cor_feed_qty = feed_qty * u_frac; + double production_capacity = + ProductFlow(std::min(cor_feed_qty, MaxFeedFlow(FeedAssay(feed_qty)))); + cyclus::CapacityConstraint production_contraint( + production_capacity); + commod_port->AddConstraint(production_contraint); LOG(cyclus::LEV_INFO5, "EnrFac") - << prototype() << " adding a natu constraint of " << natu.capacity(); + << prototype() << " adding production capacity constraint of " + << production_capacity; + ports.insert(commod_port); } return ports; @@ -315,21 +307,18 @@ CascadeEnrich::GetMatlBids(cyclus::CommodMap::type& out_reques // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::GetMatlTrades( - const std::vector >& trades, + const std::vector>& trades, std::vector, - cyclus::Material::Ptr> >& responses) { + cyclus::Material::Ptr>>& responses) { using cyclus::Material; using cyclus::Trade; - intra_timestep_swu_ = 0; intra_timestep_feed_ = 0; - - std::vector >::const_iterator it; + std::vector>::const_iterator it; for (it = trades.begin(); it != trades.end(); ++it) { double qty = it->amt; std::string commod_type = it->bid->request()->commodity(); Material::Ptr response; - // Figure out whether material is tails or enriched, // if tails then make transfer of material if (commod_type == tails_commod) { @@ -352,29 +341,26 @@ void CascadeEnrich::GetMatlTrades( ss << "is being asked to provide more than its current inventory."; throw cyclus::ValueError(Agent::InformErrorMsg(ss.str())); } - if (cyclus::IsNegative(current_swu_capacity)) { - throw cyclus::ValueError("EnrFac " + prototype() + - " is being asked to provide more than" + - " its SWU capacity."); - } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, - double qty) { + double qty) { using cyclus::Material; using cyclus::ResCast; using cyclus::toolkit::Assays; using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; using cyclus::toolkit::FeedQty; using cyclus::toolkit::TailsQty; - // get enrichment parameters - Assays assays(FeedAssay(), UraniumAssay(mat), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); + double feed_qty = FeedRequired(qty); + + double feed_assay = FeedAssay(feed_qty); + double product_assay = ProductAssay(feed_assay); + + double tails_assay = TailsAssay(FeedAssay(feed_qty)); + double tails_mass = TailsFlow(feed_qty); // Determine the composition of the natural uranium // (ie. U-235+U-238/TotalMass) double pop_qty = inventory.quantity(); @@ -386,8 +372,7 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, nucs.insert(922350000); nucs.insert(922380000); double natu_frac = mq.mass_frac(nucs); - double feed_req = natu_req / natu_frac; - + double feed_req = feed_qty / natu_frac; // pop amount from inventory and blob it into one material Material::Ptr r; try { @@ -398,12 +383,9 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, r = inventory.Pop(feed_req, cyclus::eps_rsrc()); } } catch (cyclus::Error& e) { - NatUConverter nc(FeedAssay(), tails_assay); std::stringstream ss; ss << " tried to remove " << feed_req << " from its inventory of size " - << inventory.quantity() - << " and the conversion of the material into natu is " - << nc.convert(mat); + << inventory.quantity(); throw cyclus::ValueError(Agent::InformErrorMsg(ss.str())); } @@ -413,46 +395,34 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, Material::Ptr response = r->ExtractComp(qty, comp); tails.Push(r); - current_swu_capacity -= swu_req; - - intra_timestep_swu_ += swu_req; - intra_timestep_feed_ += feed_req; - RecordEnrichment_(feed_req, swu_req); + RecordEnrichment_(feed_req); LOG(cyclus::LEV_INFO5, "EnrFac") << prototype() << " has performed an enrichment: "; LOG(cyclus::LEV_INFO5, "EnrFac") << " * Feed Qty: " << feed_req; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Feed Assay: " - << assays.Feed() * 100; + LOG(cyclus::LEV_INFO5, "EnrFac") << " * Feed Assay: " << feed_assay * 100; LOG(cyclus::LEV_INFO5, "EnrFac") << " * Product Qty: " << qty; LOG(cyclus::LEV_INFO5, "EnrFac") << " * Product Assay: " - << assays.Product() * 100; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Qty: " - << TailsQty(qty, assays); - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Assay: " - << assays.Tails() * 100; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * SWU: " << swu_req; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Current SWU capacity: " - << current_swu_capacity; + << product_assay * 100; + LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Qty: " << tails_mass; + LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Assay: " << tails_assay * 100; return response; } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CascadeEnrich::RecordEnrichment_(double natural_u, double swu) { +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CascadeEnrich::RecordEnrichment_(double natural_u) { using cyclus::Context; using cyclus::Agent; LOG(cyclus::LEV_DEBUG1, "EnrFac") << prototype() << " has enriched a material:"; LOG(cyclus::LEV_DEBUG1, "EnrFac") << " * Amount: " << natural_u; - LOG(cyclus::LEV_DEBUG1, "EnrFac") << " * SWU: " << swu; Context* ctx = Agent::context(); ctx->NewDatum("Enrichments") ->AddVal("ID", id()) ->AddVal("Time", ctx->time()) ->AddVal("Natural_Uranium", natural_u) - ->AddVal("SWU", swu) ->Record(); } @@ -464,10 +434,13 @@ cyclus::Material::Ptr CascadeEnrich::Request_() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cyclus::Material::Ptr CascadeEnrich::Offer_(cyclus::Material::Ptr mat) { - cyclus::toolkit::MatQuery q(mat); + double feed_assay = FeedAssay(mat->quantity()); + double product_assay = ProductAssay(feed_assay); + cyclus::CompMap comp; - comp[922350000] = q.atom_frac(922350000); - comp[922380000] = q.atom_frac(922380000); + comp[922350000] = product_assay; + comp[922380000] = 1 - product_assay; + return cyclus::Material::CreateUntracked( mat->quantity(), cyclus::Composition::CreateFromAtom(comp)); } @@ -479,22 +452,76 @@ bool CascadeEnrich::ValidReq(const cyclus::Material::Ptr mat) { return (u238 > 0 && u235 / (u235 + u238) > tails_assay); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double CascadeEnrich::FeedAssay() { +double CascadeEnrich::FeedAssay(double quantity) { using cyclus::Material; if (inventory.empty()) { return 0; } - double pop_qty = inventory.quantity(); + double pop_qty = std::min(inventory.quantity(), quantity); cyclus::Material::Ptr fission_matl = inventory.Pop(pop_qty, cyclus::eps_rsrc()); inventory.Push(fission_matl); return cyclus::toolkit::UraniumAssay(fission_matl); } +double CascadeEnrich::ProductAssay(double feed_assay) { + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.rbegin()->second.product_assay; +} +double CascadeEnrich::TailsAssay(double feed_assay) { + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.begin()->second.tail_assay; +} + +double CascadeEnrich::MaxFeedFlow(double feed_assay){ + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + + return FlowPerMon(cascade_tmp.FeedFlow()); + +} + +double CascadeEnrich::FeedRequired(double prod_qty) { + double max_feed_flow = MaxFeedFlow(FeedAssay(inventory.quantity())); + double max_product_flow = ProductFlow(max_feed_flow); + double feed_required = max_feed_flow / max_product_flow * prod_qty; + + max_feed_flow = MaxFeedFlow(FeedAssay(feed_required)); + max_product_flow = ProductFlow(max_feed_flow); + double corrected_feed_required = max_feed_flow / max_product_flow * prod_qty; + double diff_feed = std::abs(feed_required - corrected_feed_required); + + while (diff_feed > precision) { + // reset feed_required + feed_required = corrected_feed_required; + + max_feed_flow = MaxFeedFlow(FeedAssay(feed_required)); + max_product_flow = ProductFlow(max_feed_flow); + corrected_feed_required = max_feed_flow / max_product_flow * prod_qty; + diff_feed = std::abs(feed_required - corrected_feed_required); + } + + return corrected_feed_required; +} + +double CascadeEnrich::ProductFlow(double feed_flow) { + double feed_assay = FeedAssay(feed_flow); + double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; + double product_flow = last_stg.feed_flow * last_stg.cut; + return feed_ratio * FlowPerMon(product_flow); +} + +double CascadeEnrich::TailsFlow(double feed_flow) { + // this assume mass flow conservation + return feed_flow - ProductFlow(feed_flow); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - extern "C" cyclus::Agent* ConstructCascadeEnrich(cyclus::Context* ctx) { return new CascadeEnrich(ctx); } - + } // namespace mbmore diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index eceb46a..56837c5 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -5,6 +5,8 @@ #include "cyclus.h" #include "sim_init.h" +#include "CascadeConfig.h" +#include "CentrifugeConfig.h" /* Working with cycamore Develop build: 3ada148442de636d @@ -37,77 +39,6 @@ B) Change cascade feed assay */ namespace mbmore { -/// @class SWUConverter -/// -/// @brief The SWUConverter is a simple Converter class for material to -/// determine the amount of SWU required for their proposed enrichment -class SWUConverter : public cyclus::Converter { - public: - SWUConverter(double feed_commod, double tails) - : feed_(feed_commod), tails_(tails) {} - virtual ~SWUConverter() {} - - /// @brief provides a conversion for the SWU required - virtual double convert( - cyclus::Material::Ptr m, cyclus::Arc const* a = NULL, - cyclus::ExchangeTranslationContext const* ctx = - NULL) const { - cyclus::toolkit::Assays assays(feed_, cyclus::toolkit::UraniumAssay(m), - tails_); - return cyclus::toolkit::SwuRequired(m->quantity(), assays); - } - - /// @returns true if Converter is a SWUConverter and feed and tails equal - virtual bool operator==(Converter& other) const { - SWUConverter* cast = dynamic_cast(&other); - return cast != NULL && feed_ == cast->feed_ && tails_ == cast->tails_; - } - - private: - double feed_, tails_; -}; - - -/// @class NatUConverter -/// -/// @brief The NatUConverter is a simple Converter class for material to -/// determine the amount of natural uranium required for their proposed -/// enrichment -class NatUConverter : public cyclus::Converter { - public: - NatUConverter(double feed_commod, double tails) - : feed_(feed_commod), tails_(tails) {} - virtual ~NatUConverter() {} - - // virtual std::string version() { return CYCAMORE_VERSION; } - - /// @brief provides a conversion for the amount of natural Uranium required - virtual double convert( - cyclus::Material::Ptr m, cyclus::Arc const* a = NULL, - cyclus::ExchangeTranslationContext const* ctx = - NULL) const { - cyclus::toolkit::Assays assays(feed_, cyclus::toolkit::UraniumAssay(m), - tails_); - cyclus::toolkit::MatQuery mq(m); - std::set nucs; - nucs.insert(922350000); - nucs.insert(922380000); - - double natu_frac = mq.mass_frac(nucs); - double natu_req = cyclus::toolkit::FeedQty(m->quantity(), assays); - return natu_req / natu_frac; - } - - /// @returns true if Converter is a NatUConverter and feed and tails equal - virtual bool operator==(Converter& other) const { - NatUConverter* cast = dynamic_cast(&other); - return cast != NULL && feed_ == cast->feed_ && tails_ == cast->tails_; - } - - private: - double feed_, tails_; -}; - class CascadeEnrich : public cyclus::Facility { #pragma cyclus note { \ @@ -134,13 +65,13 @@ class CascadeEnrich : public cyclus::Facility { // --- Facility Members --- /// perform module-specific tasks when entering the simulation - virtual void Build(cyclus::Agent* parent); + //virtual void Build(cyclus::Agent* parent); // --- // --- Agent Members --- /// Each facility is prompted to do its beginning-of-time-step /// stuff at the tick of the timer. - + virtual void EnterNotify(); /// @param time is the time to perform the tick virtual void Tick(); @@ -188,13 +119,6 @@ class CascadeEnrich : public cyclus::Facility { inventory.capacity(size); } - inline void SwuCapacity(double capacity) { - swu_capacity = capacity; - current_swu_capacity = swu_capacity; - } - - inline double SwuCapacity() const { return swu_capacity; } - // TODO: MAKE THESE CONVERSIONS TOOLKIT FNS and have them explicitly check // timestep duration @@ -208,9 +132,9 @@ class CascadeEnrich : public cyclus::Facility { } inline double Mg2kgPerSec(double feed_mg_per_sec) { - return feed_mg_per_sec / (1e6); + return feed_mg_per_sec / (1e6); } - + /// @brief Determines if a particular material is a valid request to respond /// to. Valid requests must contain U235 and U238 and must have a relative /// U235-to-U238 ratio less than this facility's tails_assay(). @@ -223,7 +147,7 @@ class CascadeEnrich : public cyclus::Facility { private: /// @brief calculates the feed assay based on the unenriched inventory - double FeedAssay(); + double FeedAssay(double quantity); /// @brief adds a material into the natural uranium inventory @@ -245,55 +169,64 @@ class CascadeEnrich : public cyclus::Facility { cyclus::Material::Ptr Enrich_(cyclus::Material::Ptr mat, double qty); /// @brief records and enrichment with the cyclus::Recorder - void RecordEnrichment_(double natural_u, double swu); + void RecordEnrichment_(double natural_u); + + + // Not physical constants but fixed assumptions for a cascade separating + // out U235 from U238 in UF6 gas +//group all the characteristic of a centrifuges + CentrifugeConfig centrifuge; + CascadeConfig cascade; + double precision = 1e-15; + + + const double secpermonth = 60.*60.*24.*(365.25/12.); // Set to design_tails at beginning of simulation. Gets reset if // facility is used off-design - double tails_assay; + double tails_assay; - // These state variables are constrained by the design input params at - // the start of the simulation: - // Set by max feed for an individual machine - double design_delU; - double design_alpha; - // Set by design assays (feed, product, tails) int n_enrich_stages; int n_strip_stages; // Set by maximum allowable centrifuges - double max_feed_inventory; - double swu_capacity; - - // Not physical constants but fixed assumptions for a cascade separating - // out U235 from U238 in UF6 gas - const double M = 0.352; // kg/mol UF6 - const double dM = 0.003; // kg/mol U238 - U235 - const double x = 1000; // Pressure ratio (Glaser) - - const double flow_internal = 2.0; // can vary from 2-4 - const double eff = 1.0; // typical efficiencies <0.6 - const double cut = 0.5; // target for ideal cascade + double ProductAssay(double feed_assay); + double ProductFlow(double feed_flow); + double TailsAssay(double feed_assay); + double TailsFlow(double feed_flow); + double FeedRequired(double prod_qty); + double MaxFeedFlow(double feed_assay); - const double secpermonth = 60*60*24*(365.25/12); - - private: #pragma cyclus var { \ "tooltip" : "feed recipe", \ "doc" : "recipe for enrichment facility feed commodity", \ - "uilabel" : "Feed Recipe", "uitype" : "recipe" } + "uilabel" : "Feed Recipe", \ + "uitype" : "recipe" } std::string feed_recipe; #pragma cyclus var { \ - "default": 0, "tooltip": "initial uranium reserves (kg)", \ + "default": 0, \ + "tooltip": "initial uranium reserves (kg)", \ "uilabel": "Initial Feed Inventory", \ "doc": "amount of natural uranium stored at the enrichment " \ "facility at the beginning of the simulation (kg)" } double initial_feed; + + #pragma cyclus var { \ + "default": 1e299, "tooltip": "max inventory of feed material (kg)", \ + "uilabel": "Maximum Feed Inventory", \ + "uitype": "range", \ + "range": [0.0, 1e299], \ + "doc": "maximum total inventory of natural uranium in " \ + "the enrichment facility (kg)" \ + } + double max_feed_inventory; #pragma cyclus var { \ - "default": 0, "tooltip": "design feed flow (kg/mon)", \ + "default": 100, \ + "tooltip": "design feed flow (kg/mon)", \ "uilabel": "Design Feed Flow", \ "doc": "Target amount of feed material to be processed by the" \ " facility (kg/mon). Either this or max_centrifuges is used to constrain" \ @@ -301,63 +234,90 @@ class CascadeEnrich : public cyclus::Facility { double design_feed_flow; #pragma cyclus var { \ - "default" : 0, "tooltip" : "number of centrifuges available ", \ + "default" : 1000, \ + "tooltip" : "number of centrifuges available ", \ "uilabel" : "Number of Centrifuges", \ "doc" : "number of centrifuges available to make the cascade" } int max_centrifuges; // TODO: USE FEED RECIPE TO DETERMINE FEED ASSAY!!! #pragma cyclus var { \ - "default": 0.0071, "tooltip": "initial uranium reserves (kg)", \ + "default": 0.0071, \ + "tooltip": "initial uranium reserves (kg)", \ "uilabel": "Initial feed assay", \ "doc": "desired fraction of U235 in feed material (should be consistent "\ "with feed recipe" } double design_feed_assay; #pragma cyclus var { \ - "default" : 0.035, "tooltip" : "Initial target product assay", \ + "default" : 0.035, \ + "tooltip" : "Initial target product assay", \ "uilabel" : "Target product assay", \ "doc" : "desired fraction of U235 in product" } double design_product_assay; #pragma cyclus var { \ - "default" : 0.003, "tooltip" : "Initial target tails assay", \ + "default" : 0.003, \ + "tooltip" : "Initial target tails assay", \ "uilabel" : "Target tails assay", \ "doc" : "desired fraction of U235 in tails" } double design_tails_assay; #pragma cyclus var { \ - "default" : 320.0, "tooltip" : "Centrifuge temperature (Kelvin)", \ + "default" : 320.0, \ + "tooltip" : "Centrifuge temperature (Kelvin)", \ "uilabel" : "Centrifuge temperature (Kelvin)", \ "doc" : "temperature at which centrifuges are operated (Kelvin)" } double temp; #pragma cyclus var { \ - "default" : 485.0, "tooltip" : "Centrifuge velocity (m/s)", \ + "default" : 485.0, \ + "tooltip" : "Centrifuge velocity (m/s)", \ "uilabel" : "Centrifuge velocity (m/s)", \ "doc" : "operational centrifuge velocity (m/s) at the outer radius (a)"} double centrifuge_velocity; #pragma cyclus var { \ - "default" : 0.5, "tooltip" : "Centrifuge height (m)", \ + "default" : 0.5, \ + "tooltip" : "Centrifuge height (m)", \ "uilabel" : "Centrifuge height (m)", \ "doc" : "height of centrifuge (m)"} double height; #pragma cyclus var { \ - "default" : 0.15, "tooltip" : "Centrifuge diameter (m)", \ + "default" : 0.15, \ + "tooltip" : "Centrifuge diameter (m)", \ "uilabel" : "Centrifuge diameter (m)", \ "doc" : "diameter of centrifuge (m)"} double diameter; #pragma cyclus var { \ - "default" : 15.0, "tooltip" : "Centrifuge feed rate (mg/sec)", \ + "default" : 2, \ + "tooltip" : "Centrifuge L/F* ", \ + "uilabel" : "Centrifuge Countercurrent to feed ratio", \ + "doc" : "Countercurrent to feed ratio"} + double L_over_F; + +#pragma cyclus var { \ + "default" : 15.0, \ + "tooltip" : "Centrifuge feed rate (mg/sec)", \ "uilabel" : "Max feed rate for single centrifuge (mg/sec)", \ "doc" : "maximum feed rate for a single centrifuge (mg/sec)"} double machine_feed; + + #pragma cyclus var { \ + "default": 0, \ + "userlevel": 10, \ + "tooltip": "Modeling option for miss-use calculation", \ + "uilabel": "Miss-use Modeling", \ + "doc": "Miss-use modeling option: " \ + " - 0: alpha-theta fix -- beta varies, " \ + " - 1: alpha=beta fix -- theta varies, " \ + " - 2: alpha*beta fix "} + int miss_use_model; + - // Input params from cycamore::Enrichment #pragma cyclus var { \ "default": 1, \ @@ -386,34 +346,34 @@ class CascadeEnrich : public cyclus::Facility { #pragma cyclus var { \ "tooltip" : "feed commodity", \ "doc" : "feed commodity that the enrichment facility accepts", \ - "uilabel" : "Feed Commodity", "uitype" : "incommodity" } + "uilabel" : "Feed Commodity", \ + "uitype" : "incommodity" } std::string feed_commod; #pragma cyclus var { \ "tooltip" : "product commodity", \ "doc" : "product commodity that the enrichment facility generates", \ - "uilabel" : "Product Commodity", "uitype" : "outcommodity" } + "uilabel" : "Product Commodity", \ + "uitype" : "outcommodity" } std::string product_commod; #pragma cyclus var { \ "tooltip" : "tails commodity", \ "doc" : "tails commodity supplied by enrichment facility", \ - "uilabel" : "Tails Commodity", "uitype" : "outcommodity" } + "uilabel" : "Tails Commodity", \ + "uitype" : "outcommodity" } std::string tails_commod; - double current_swu_capacity; #pragma cyclus var {} cyclus::toolkit::ResBuf tails; // depleted u // used to total intra-timestep swu and natu usage for meeting requests - // these help enable time series generation. - double intra_timestep_swu_; double intra_timestep_feed_; // END LEGACY -#pragma cyclus var { 'capacity' : 'max_feed_inventory' } cyclus::toolkit::ResBuf inventory; // natural u friend class CascadeEnrichTest; diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index cbcf745..87e83b9 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -20,9 +20,9 @@ using cyclus::Material; namespace mbmore { -namespace cascadenrichtest{ +namespace cascadenrichtest { - Composition::Ptr c_nou235() { +Composition::Ptr c_nou235() { cyclus::CompMap m; m[922380000] = 1.0; return Composition::CreateFromMass(m); @@ -62,10 +62,10 @@ TEST_F(CascadeEnrichTest, RequestQty) { " natu1 " " enr_u " " tails " - " 1.0 " - " 0.003 "; + " 0.003 " + " 1000 "; - int simdur = 10; + int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); @@ -80,14 +80,14 @@ TEST_F(CascadeEnrichTest, RequestQty) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); // Should be only one transaction into the EF, - // and it should be exactly 1kg of natu - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 1e-10) + // and it should be exactly 207.8928179411368kg of natu + EXPECT_EQ(1, qr.rows.size()); + EXPECT_NEAR(1000, m->quantity(), 1e-3) << "matched trade provides the wrong quantity of material"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, CheckSWUConstraint) { +TEST_F(CascadeEnrichTest, CheckFlowConstraint) { // Tests that request for enrichment that exceeds the SWU constraint // fulfilled only up to the available SWU. // Also confirms that initial_feed flag works. @@ -99,8 +99,7 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { " enr_u " " tails " " 0.003 " - " 1000 " - " 195 "; + " 1000 "; int simdur = 1; @@ -120,8 +119,8 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.1) - << "traded quantity exceeds SWU constraint"; + EXPECT_NEAR(10, m->quantity(), 0.1) + << "traded quantity differ from flow contraints"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -135,7 +134,8 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { " enr_u " " tails " " 0.003 " - " 243 "; + " 200 " + " 50 "; int simdur = 1; @@ -155,59 +155,10 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.01) + EXPECT_NEAR(5.831, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, RequestEnrich) { - // this tests verifies that requests for output material exceeding - // the maximum allowed enrichment are not fulfilled. - - std::string config = - " natu " - " natu1 " - " enr_u " - " tails " - " 0.003 " - " 0.20 "; - - int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, - simdur); - sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); - sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddRecipe("heu", cascadenrichtest::c_heu()); - - sim.AddSource("natu").recipe("natu1").Finalize(); - sim.AddSink("enr_u").recipe("leu").capacity(1.0).Finalize(); - sim.AddSink("enr_u").recipe("heu").Finalize(); - - int id = sim.Run(); - - std::vector conds; - conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); - QueryResult qr = sim.db().Query("Transactions", &conds); - Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - - // Should be only one transaction out of the EF, - // and it should be 1kg of LEU - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 0.01) - << "Not providing the requested quantity"; - - CompMap got = m->comp()->mass(); - CompMap want = cascadenrichtest::c_leu()->mass(); - cyclus::compmath::Normalize(&got); - cyclus::compmath::Normalize(&want); - - CompMap::iterator it; - for (it = want.begin(); it != want.end(); ++it) { - EXPECT_DOUBLE_EQ(it->second, got[it->first]) - << "nuclide qty off: " << pyne::nucname::name(it->first); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. @@ -226,7 +177,7 @@ TEST_F(CascadeEnrichTest, TradeTails) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").Finalize(); sim.AddSink("tails").Finalize(); @@ -258,7 +209,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("tails").Finalize(); @@ -270,7 +221,8 @@ TEST_F(CascadeEnrichTest, TailsQty) { QueryResult qr = sim.db().Query("Transactions", &conds); Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - // Should be 2 tails transactions, one from each LEU sink, each 4.084kg. + // Should be 2 tails transactions, one from each LEU sink, each 3.787453kg. + // (1* (0.0403193-0.00271456) / (0.0071-0.00271456) -1)/2. = 3.787453 EXPECT_EQ(2, qr.rows.size()); cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare( @@ -280,7 +232,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(8.168, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } @@ -291,7 +243,7 @@ TEST_F(CascadeEnrichTest, BidPrefs) { std::string config = " natu " - " natu1 " + " natu2 " " enr_u " " tails " " 0.003 " @@ -303,9 +255,10 @@ TEST_F(CascadeEnrichTest, BidPrefs) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("natu2", cascadenrichtest::c_natu2()); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSource("natu").recipe("natu1").capacity(1).Finalize(); - sim.AddSource("natu").recipe("natu2").capacity(1).Finalize(); + sim.AddSource("natu").recipe("natu2").capacity(2).Finalize(); int id = sim.Run(); @@ -422,7 +375,7 @@ void CascadeEnrichTest::InitParameters() { tails_assay = 0.002; swu_capacity = 100; //** - inv_size = 5; + inv_size = 105.5; reserves = 105.5; } @@ -436,7 +389,6 @@ void CascadeEnrichTest::SetUpSource() { src_facility->tails_assay = tails_assay; src_facility->max_enrich = max_enrich; src_facility->SetMaxInventorySize(inv_size); - src_facility->SwuCapacity(swu_capacity); src_facility->initial_feed = reserves; } @@ -521,158 +473,6 @@ TEST_F(CascadeEnrichTest, ValidReq) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, ConstraintConverters) { - // Tests the SWU and NatU converters to make sure that amount of - // feed and SWU required are correct to fulfill the enrichment request. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::MatQuery; - using mbmore::SWUConverter; - cyclus::Env::SetNucDataPath(); - - double qty = 5; // 5 kg - double product_assay = 0.05; // of 5 w/o enriched U - CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - v[94239] = 0.5; // 94239 shouldn't be taken into account - Material::Ptr target = - Material::CreateUntracked(qty, Composition::CreateFromMass(v)); - - std::set nucs; - nucs.insert(922350000); - nucs.insert(922380000); - - MatQuery mq(target); - double mass_frac = mq.mass_frac(nucs); - - SWUConverter swuc(feed_assay, tails_assay); - NatUConverter natuc(feed_assay, tails_assay); - - Material::Ptr offer = DoOffer(target); - - EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001); - EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Enrich) { - // this test asks the facility to enrich a material that results in an amount - // of natural uranium required that is exactly its inventory level. that - // inventory will be comprised of two materials to test the manifest/absorb - // strategy employed in Enrich_. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - - double qty = 5; // kg - double product_assay = 0.05; // of 5 w/o enriched U - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - double tails_qty = TailsQty(qty, assays); - - double swu_cap = swu_req * 5; - src_facility->SwuCapacity(swu_cap); - src_facility->SetMaxInventorySize(natu_req); - DoAddMat(GetMat(natu_req / 2)); - DoAddMat(GetMat(natu_req / 2)); - - Material::Ptr response; - EXPECT_NO_THROW(response = DoEnrich(target, qty)); - EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty); - - MatQuery q(response); - EXPECT_EQ(response->quantity(), qty); - EXPECT_EQ(q.mass_frac(922350000), product_assay); - EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay); - - // test too much natu request - DoAddMat(GetMat(natu_req - 1)); - EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Response) { - // this test asks the facility to respond to multiple requests for enriched - // uranium. two requests are provided, whose total equals the swu capacity of - // the facility while not exceeding its inventory capacity (that's taken care - // of in the Enrich tests). - // - // note that response quantity and quality need not be tested, because they - // are covered by the Enrich and RequestEnrich tests - using cyclus::Bid; - using cyclus::CompMap; - using cyclus::Material; - using cyclus::Request; - using cyclus::Trade; - using cyclus::toolkit::Assays; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::UraniumAssay; - - // problem set up - std::vector > trades; - std::vector< - std::pair, cyclus::Material::Ptr> > - responses; - - double qty = 5; // kg - double trade_qty = qty / 3; - double product_assay = 0.05; // of 5 w/o enriched U - - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - - src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat - src_facility->SwuCapacity(swu_req); // swu capacitated - - src_facility->GetMatlTrades(trades, responses); - - // set up state - DoAddMat(GetMat(natu_req * 2)); - - src_facility->GetMatlTrades(trades, responses); - - Request* req = - Request::Create(target, trader, product_commod); - Bid* bid = Bid::Create(req, target, src_facility); - Trade trade(req, bid, trade_qty); - trades.push_back(trade); - - // 2 trades, SWU = SWU cap - ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3, -1 * cyclus::eps()); - trades.push_back(trade); - responses.clear(); - EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses)); - EXPECT_EQ(responses.size(), 2); -} } // namespace cycamore From feb52dedefb60e1fc73444fe137a55cc36e74fdd Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:50:03 -0500 Subject: [PATCH 015/116] working version --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b8e3464..29c1b60 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,7 @@ USE_CYCLUS("mbmore" "RandomEnrich") USE_CYCLUS("mbmore" "CentrifugeConfig") USE_CYCLUS("mbmore" "StageConfig") USE_CYCLUS("mbmore" "CascadeConfig") +USE_CYCLUS("mbmore" "CascadeEnrich") USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") From c8fd1d8c6c77eb5ccba1ad56815969230b4805d3 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:21:46 -0500 Subject: [PATCH 016/116] readd missing file --- src/CascadeEnrich_tests.cc | 248 +++++++++++++++++++++++++++++++++---- 1 file changed, 224 insertions(+), 24 deletions(-) diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index 87e83b9..cbcf745 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -20,9 +20,9 @@ using cyclus::Material; namespace mbmore { -namespace cascadenrichtest { +namespace cascadenrichtest{ -Composition::Ptr c_nou235() { + Composition::Ptr c_nou235() { cyclus::CompMap m; m[922380000] = 1.0; return Composition::CreateFromMass(m); @@ -62,10 +62,10 @@ TEST_F(CascadeEnrichTest, RequestQty) { " natu1 " " enr_u " " tails " - " 0.003 " - " 1000 "; + " 1.0 " + " 0.003 "; - int simdur = 1; + int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); @@ -80,14 +80,14 @@ TEST_F(CascadeEnrichTest, RequestQty) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); // Should be only one transaction into the EF, - // and it should be exactly 207.8928179411368kg of natu - EXPECT_EQ(1, qr.rows.size()); - EXPECT_NEAR(1000, m->quantity(), 1e-3) + // and it should be exactly 1kg of natu + EXPECT_EQ(1.0, qr.rows.size()); + EXPECT_NEAR(1.0, m->quantity(), 1e-10) << "matched trade provides the wrong quantity of material"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, CheckFlowConstraint) { +TEST_F(CascadeEnrichTest, CheckSWUConstraint) { // Tests that request for enrichment that exceeds the SWU constraint // fulfilled only up to the available SWU. // Also confirms that initial_feed flag works. @@ -99,7 +99,8 @@ TEST_F(CascadeEnrichTest, CheckFlowConstraint) { " enr_u " " tails " " 0.003 " - " 1000 "; + " 1000 " + " 195 "; int simdur = 1; @@ -119,8 +120,8 @@ TEST_F(CascadeEnrichTest, CheckFlowConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(10, m->quantity(), 0.1) - << "traded quantity differ from flow contraints"; + EXPECT_NEAR(5.0, m->quantity(), 0.1) + << "traded quantity exceeds SWU constraint"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -134,8 +135,7 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { " enr_u " " tails " " 0.003 " - " 200 " - " 50 "; + " 243 "; int simdur = 1; @@ -155,10 +155,59 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.831, m->quantity(), 0.01) + EXPECT_NEAR(5.0, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, RequestEnrich) { + // this tests verifies that requests for output material exceeding + // the maximum allowed enrichment are not fulfilled. + + std::string config = + " natu " + " natu1 " + " enr_u " + " tails " + " 0.003 " + " 0.20 "; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, + simdur); + sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); + sim.AddRecipe("leu", cascadenrichtest::c_leu()); + sim.AddRecipe("heu", cascadenrichtest::c_heu()); + + sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSink("enr_u").recipe("leu").capacity(1.0).Finalize(); + sim.AddSink("enr_u").recipe("heu").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); + QueryResult qr = sim.db().Query("Transactions", &conds); + Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); + + // Should be only one transaction out of the EF, + // and it should be 1kg of LEU + EXPECT_EQ(1.0, qr.rows.size()); + EXPECT_NEAR(1.0, m->quantity(), 0.01) + << "Not providing the requested quantity"; + + CompMap got = m->comp()->mass(); + CompMap want = cascadenrichtest::c_leu()->mass(); + cyclus::compmath::Normalize(&got); + cyclus::compmath::Normalize(&want); + + CompMap::iterator it; + for (it = want.begin(); it != want.end(); ++it) { + EXPECT_DOUBLE_EQ(it->second, got[it->first]) + << "nuclide qty off: " << pyne::nucname::name(it->first); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. @@ -177,7 +226,7 @@ TEST_F(CascadeEnrichTest, TradeTails) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); + sim.AddSource("natu").recipe("natu1").Finalize(); sim.AddSink("enr_u").recipe("leu").Finalize(); sim.AddSink("tails").Finalize(); @@ -209,7 +258,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); + sim.AddSource("natu").recipe("natu1").Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("tails").Finalize(); @@ -221,8 +270,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { QueryResult qr = sim.db().Query("Transactions", &conds); Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - // Should be 2 tails transactions, one from each LEU sink, each 3.787453kg. - // (1* (0.0403193-0.00271456) / (0.0071-0.00271456) -1)/2. = 3.787453 + // Should be 2 tails transactions, one from each LEU sink, each 4.084kg. EXPECT_EQ(2, qr.rows.size()); cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare( @@ -232,7 +280,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(8.168, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } @@ -243,7 +291,7 @@ TEST_F(CascadeEnrichTest, BidPrefs) { std::string config = " natu " - " natu2 " + " natu1 " " enr_u " " tails " " 0.003 " @@ -255,10 +303,9 @@ TEST_F(CascadeEnrichTest, BidPrefs) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("natu2", cascadenrichtest::c_natu2()); - sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSource("natu").recipe("natu1").capacity(1).Finalize(); - sim.AddSource("natu").recipe("natu2").capacity(2).Finalize(); + sim.AddSource("natu").recipe("natu2").capacity(1).Finalize(); int id = sim.Run(); @@ -375,7 +422,7 @@ void CascadeEnrichTest::InitParameters() { tails_assay = 0.002; swu_capacity = 100; //** - inv_size = 105.5; + inv_size = 5; reserves = 105.5; } @@ -389,6 +436,7 @@ void CascadeEnrichTest::SetUpSource() { src_facility->tails_assay = tails_assay; src_facility->max_enrich = max_enrich; src_facility->SetMaxInventorySize(inv_size); + src_facility->SwuCapacity(swu_capacity); src_facility->initial_feed = reserves; } @@ -473,6 +521,158 @@ TEST_F(CascadeEnrichTest, ValidReq) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, ConstraintConverters) { + // Tests the SWU and NatU converters to make sure that amount of + // feed and SWU required are correct to fulfill the enrichment request. + using cyclus::CompMap; + using cyclus::Material; + using cyclus::toolkit::MatQuery; + using cyclus::Composition; + using cyclus::toolkit::Assays; + using cyclus::toolkit::UraniumAssay; + using cyclus::toolkit::SwuRequired; + using cyclus::toolkit::FeedQty; + using cyclus::toolkit::MatQuery; + using mbmore::SWUConverter; + cyclus::Env::SetNucDataPath(); + + double qty = 5; // 5 kg + double product_assay = 0.05; // of 5 w/o enriched U + CompMap v; + v[922350000] = product_assay; + v[922380000] = 1 - product_assay; + v[94239] = 0.5; // 94239 shouldn't be taken into account + Material::Ptr target = + Material::CreateUntracked(qty, Composition::CreateFromMass(v)); + + std::set nucs; + nucs.insert(922350000); + nucs.insert(922380000); + + MatQuery mq(target); + double mass_frac = mq.mass_frac(nucs); + + SWUConverter swuc(feed_assay, tails_assay); + NatUConverter natuc(feed_assay, tails_assay); + + Material::Ptr offer = DoOffer(target); + + EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001); + EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, Enrich) { + // this test asks the facility to enrich a material that results in an amount + // of natural uranium required that is exactly its inventory level. that + // inventory will be comprised of two materials to test the manifest/absorb + // strategy employed in Enrich_. + using cyclus::CompMap; + using cyclus::Material; + using cyclus::toolkit::MatQuery; + using cyclus::Composition; + using cyclus::toolkit::Assays; + using cyclus::toolkit::UraniumAssay; + using cyclus::toolkit::SwuRequired; + using cyclus::toolkit::FeedQty; + + double qty = 5; // kg + double product_assay = 0.05; // of 5 w/o enriched U + cyclus::CompMap v; + v[922350000] = product_assay; + v[922380000] = 1 - product_assay; + // target qty need not be = to request qty + Material::Ptr target = cyclus::Material::CreateUntracked( + qty + 10, cyclus::Composition::CreateFromMass(v)); + + Assays assays(feed_assay, UraniumAssay(target), tails_assay); + double swu_req = SwuRequired(qty, assays); + double natu_req = FeedQty(qty, assays); + double tails_qty = TailsQty(qty, assays); + + double swu_cap = swu_req * 5; + src_facility->SwuCapacity(swu_cap); + src_facility->SetMaxInventorySize(natu_req); + DoAddMat(GetMat(natu_req / 2)); + DoAddMat(GetMat(natu_req / 2)); + + Material::Ptr response; + EXPECT_NO_THROW(response = DoEnrich(target, qty)); + EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty); + + MatQuery q(response); + EXPECT_EQ(response->quantity(), qty); + EXPECT_EQ(q.mass_frac(922350000), product_assay); + EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay); + + // test too much natu request + DoAddMat(GetMat(natu_req - 1)); + EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, Response) { + // this test asks the facility to respond to multiple requests for enriched + // uranium. two requests are provided, whose total equals the swu capacity of + // the facility while not exceeding its inventory capacity (that's taken care + // of in the Enrich tests). + // + // note that response quantity and quality need not be tested, because they + // are covered by the Enrich and RequestEnrich tests + using cyclus::Bid; + using cyclus::CompMap; + using cyclus::Material; + using cyclus::Request; + using cyclus::Trade; + using cyclus::toolkit::Assays; + using cyclus::toolkit::FeedQty; + using cyclus::toolkit::SwuRequired; + using cyclus::toolkit::UraniumAssay; + + // problem set up + std::vector > trades; + std::vector< + std::pair, cyclus::Material::Ptr> > + responses; + + double qty = 5; // kg + double trade_qty = qty / 3; + double product_assay = 0.05; // of 5 w/o enriched U + + cyclus::CompMap v; + v[922350000] = product_assay; + v[922380000] = 1 - product_assay; + // target qty need not be = to request qty + Material::Ptr target = cyclus::Material::CreateUntracked( + qty + 10, cyclus::Composition::CreateFromMass(v)); + + Assays assays(feed_assay, UraniumAssay(target), tails_assay); + double swu_req = SwuRequired(qty, assays); + double natu_req = FeedQty(qty, assays); + + src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat + src_facility->SwuCapacity(swu_req); // swu capacitated + + src_facility->GetMatlTrades(trades, responses); + + // set up state + DoAddMat(GetMat(natu_req * 2)); + + src_facility->GetMatlTrades(trades, responses); + + Request* req = + Request::Create(target, trader, product_commod); + Bid* bid = Bid::Create(req, target, src_facility); + Trade trade(req, bid, trade_qty); + trades.push_back(trade); + + // 2 trades, SWU = SWU cap + ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3, -1 * cyclus::eps()); + trades.push_back(trade); + responses.clear(); + EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses)); + EXPECT_EQ(responses.size(), 2); +} } // namespace cycamore From 70df9298f7e4eec8cc13a8bc4b9a0358fbc93d71 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:27:04 -0500 Subject: [PATCH 017/116] fix test header --- src/CascadeEnrich_tests.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From b3288e9c58131f7a17faa16f596faf99c27a20f7 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:51:55 -0500 Subject: [PATCH 018/116] fix unit_test --- src/CascadeEnrich_tests.cc | 248 ++++--------------------------------- 1 file changed, 24 insertions(+), 224 deletions(-) diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index cbcf745..87e83b9 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -20,9 +20,9 @@ using cyclus::Material; namespace mbmore { -namespace cascadenrichtest{ +namespace cascadenrichtest { - Composition::Ptr c_nou235() { +Composition::Ptr c_nou235() { cyclus::CompMap m; m[922380000] = 1.0; return Composition::CreateFromMass(m); @@ -62,10 +62,10 @@ TEST_F(CascadeEnrichTest, RequestQty) { " natu1 " " enr_u " " tails " - " 1.0 " - " 0.003 "; + " 0.003 " + " 1000 "; - int simdur = 10; + int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); @@ -80,14 +80,14 @@ TEST_F(CascadeEnrichTest, RequestQty) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); // Should be only one transaction into the EF, - // and it should be exactly 1kg of natu - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 1e-10) + // and it should be exactly 207.8928179411368kg of natu + EXPECT_EQ(1, qr.rows.size()); + EXPECT_NEAR(1000, m->quantity(), 1e-3) << "matched trade provides the wrong quantity of material"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, CheckSWUConstraint) { +TEST_F(CascadeEnrichTest, CheckFlowConstraint) { // Tests that request for enrichment that exceeds the SWU constraint // fulfilled only up to the available SWU. // Also confirms that initial_feed flag works. @@ -99,8 +99,7 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { " enr_u " " tails " " 0.003 " - " 1000 " - " 195 "; + " 1000 "; int simdur = 1; @@ -120,8 +119,8 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.1) - << "traded quantity exceeds SWU constraint"; + EXPECT_NEAR(10, m->quantity(), 0.1) + << "traded quantity differ from flow contraints"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -135,7 +134,8 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { " enr_u " " tails " " 0.003 " - " 243 "; + " 200 " + " 50 "; int simdur = 1; @@ -155,59 +155,10 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.01) + EXPECT_NEAR(5.831, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, RequestEnrich) { - // this tests verifies that requests for output material exceeding - // the maximum allowed enrichment are not fulfilled. - - std::string config = - " natu " - " natu1 " - " enr_u " - " tails " - " 0.003 " - " 0.20 "; - - int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, - simdur); - sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); - sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddRecipe("heu", cascadenrichtest::c_heu()); - - sim.AddSource("natu").recipe("natu1").Finalize(); - sim.AddSink("enr_u").recipe("leu").capacity(1.0).Finalize(); - sim.AddSink("enr_u").recipe("heu").Finalize(); - - int id = sim.Run(); - - std::vector conds; - conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); - QueryResult qr = sim.db().Query("Transactions", &conds); - Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - - // Should be only one transaction out of the EF, - // and it should be 1kg of LEU - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 0.01) - << "Not providing the requested quantity"; - - CompMap got = m->comp()->mass(); - CompMap want = cascadenrichtest::c_leu()->mass(); - cyclus::compmath::Normalize(&got); - cyclus::compmath::Normalize(&want); - - CompMap::iterator it; - for (it = want.begin(); it != want.end(); ++it) { - EXPECT_DOUBLE_EQ(it->second, got[it->first]) - << "nuclide qty off: " << pyne::nucname::name(it->first); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. @@ -226,7 +177,7 @@ TEST_F(CascadeEnrichTest, TradeTails) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").Finalize(); sim.AddSink("tails").Finalize(); @@ -258,7 +209,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("tails").Finalize(); @@ -270,7 +221,8 @@ TEST_F(CascadeEnrichTest, TailsQty) { QueryResult qr = sim.db().Query("Transactions", &conds); Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - // Should be 2 tails transactions, one from each LEU sink, each 4.084kg. + // Should be 2 tails transactions, one from each LEU sink, each 3.787453kg. + // (1* (0.0403193-0.00271456) / (0.0071-0.00271456) -1)/2. = 3.787453 EXPECT_EQ(2, qr.rows.size()); cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare( @@ -280,7 +232,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(8.168, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } @@ -291,7 +243,7 @@ TEST_F(CascadeEnrichTest, BidPrefs) { std::string config = " natu " - " natu1 " + " natu2 " " enr_u " " tails " " 0.003 " @@ -303,9 +255,10 @@ TEST_F(CascadeEnrichTest, BidPrefs) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("natu2", cascadenrichtest::c_natu2()); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSource("natu").recipe("natu1").capacity(1).Finalize(); - sim.AddSource("natu").recipe("natu2").capacity(1).Finalize(); + sim.AddSource("natu").recipe("natu2").capacity(2).Finalize(); int id = sim.Run(); @@ -422,7 +375,7 @@ void CascadeEnrichTest::InitParameters() { tails_assay = 0.002; swu_capacity = 100; //** - inv_size = 5; + inv_size = 105.5; reserves = 105.5; } @@ -436,7 +389,6 @@ void CascadeEnrichTest::SetUpSource() { src_facility->tails_assay = tails_assay; src_facility->max_enrich = max_enrich; src_facility->SetMaxInventorySize(inv_size); - src_facility->SwuCapacity(swu_capacity); src_facility->initial_feed = reserves; } @@ -521,158 +473,6 @@ TEST_F(CascadeEnrichTest, ValidReq) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, ConstraintConverters) { - // Tests the SWU and NatU converters to make sure that amount of - // feed and SWU required are correct to fulfill the enrichment request. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::MatQuery; - using mbmore::SWUConverter; - cyclus::Env::SetNucDataPath(); - - double qty = 5; // 5 kg - double product_assay = 0.05; // of 5 w/o enriched U - CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - v[94239] = 0.5; // 94239 shouldn't be taken into account - Material::Ptr target = - Material::CreateUntracked(qty, Composition::CreateFromMass(v)); - - std::set nucs; - nucs.insert(922350000); - nucs.insert(922380000); - - MatQuery mq(target); - double mass_frac = mq.mass_frac(nucs); - - SWUConverter swuc(feed_assay, tails_assay); - NatUConverter natuc(feed_assay, tails_assay); - - Material::Ptr offer = DoOffer(target); - - EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001); - EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Enrich) { - // this test asks the facility to enrich a material that results in an amount - // of natural uranium required that is exactly its inventory level. that - // inventory will be comprised of two materials to test the manifest/absorb - // strategy employed in Enrich_. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - - double qty = 5; // kg - double product_assay = 0.05; // of 5 w/o enriched U - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - double tails_qty = TailsQty(qty, assays); - - double swu_cap = swu_req * 5; - src_facility->SwuCapacity(swu_cap); - src_facility->SetMaxInventorySize(natu_req); - DoAddMat(GetMat(natu_req / 2)); - DoAddMat(GetMat(natu_req / 2)); - - Material::Ptr response; - EXPECT_NO_THROW(response = DoEnrich(target, qty)); - EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty); - - MatQuery q(response); - EXPECT_EQ(response->quantity(), qty); - EXPECT_EQ(q.mass_frac(922350000), product_assay); - EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay); - - // test too much natu request - DoAddMat(GetMat(natu_req - 1)); - EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Response) { - // this test asks the facility to respond to multiple requests for enriched - // uranium. two requests are provided, whose total equals the swu capacity of - // the facility while not exceeding its inventory capacity (that's taken care - // of in the Enrich tests). - // - // note that response quantity and quality need not be tested, because they - // are covered by the Enrich and RequestEnrich tests - using cyclus::Bid; - using cyclus::CompMap; - using cyclus::Material; - using cyclus::Request; - using cyclus::Trade; - using cyclus::toolkit::Assays; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::UraniumAssay; - - // problem set up - std::vector > trades; - std::vector< - std::pair, cyclus::Material::Ptr> > - responses; - - double qty = 5; // kg - double trade_qty = qty / 3; - double product_assay = 0.05; // of 5 w/o enriched U - - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - - src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat - src_facility->SwuCapacity(swu_req); // swu capacitated - - src_facility->GetMatlTrades(trades, responses); - - // set up state - DoAddMat(GetMat(natu_req * 2)); - - src_facility->GetMatlTrades(trades, responses); - - Request* req = - Request::Create(target, trader, product_commod); - Bid* bid = Bid::Create(req, target, src_facility); - Trade trade(req, bid, trade_qty); - trades.push_back(trade); - - // 2 trades, SWU = SWU cap - ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3, -1 * cyclus::eps()); - trades.push_back(trade); - responses.clear(); - EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses)); - EXPECT_EQ(responses.size(), 2); -} } // namespace cycamore From 8bb5efaffd7967bb97432add8f6d3d508fa2b21a Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 15:20:08 -0500 Subject: [PATCH 019/116] first add of stageconfig --- src/StageConfig.cc | 129 +++++++++++++++++++++++++++++++++++++++ src/StageConfig.h | 69 +++++++++++++++++++++ src/StageConfig_tests.cc | 118 +++++++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+) create mode 100644 src/StageConfig.cc create mode 100644 src/StageConfig.h create mode 100644 src/StageConfig_tests.cc diff --git a/src/StageConfig.cc b/src/StageConfig.cc new file mode 100644 index 0000000..402982d --- /dev/null +++ b/src/StageConfig.cc @@ -0,0 +1,129 @@ +// Implements the CascadeEnrich class +#include "StageConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbmore { + +StageConfig::StageConfig(double f_assay, double feed_, double precision_, + double cut_, double DU_, double alpha_) + : feed_assay(f_assay), + feed_flow(feed_), + precision(precision_), + DU(DU_), + alpha(alpha_), + cut(cut_) { + if (cut == -1) { + BuildIdealStg(feed_assay, precision); + } + + if (DU == -1) { + DU = centrifuge.ComputeDeltaU(cut); + } + + if (alpha == -1) { + AlphaByDU(); + } + + BetaByAlphaAndCut(); + ProductAssay(); + TailAssay(); +} + +double StageConfig::CutForIdealStg(double f_assay, double precision) { + feed_assay = f_assay; + double p_cut = cut = 0.1; + (*this).DU = centrifuge.ComputeDeltaU(cut); + double p_alpha = AlphaByDU(); + double p_beta = BetaByAlphaAndCut(); + double p_alpha_m_beta = p_alpha - p_beta; + cut = 0.9; + (*this).DU = centrifuge.ComputeDeltaU(cut); + AlphaByDU(); + BetaByAlphaAndCut(); + while (std::abs(alpha - beta) > precision) { + // a*cut +b =y + double alpha_m_beta = alpha - beta; + double a = (p_alpha_m_beta - alpha_m_beta) / (p_cut - cut); + double b = alpha_m_beta - cut * a; + // old = new + p_alpha_m_beta = alpha_m_beta; + p_cut = cut; + // targeting alpha_m_beta = 0 + cut = -b / a; + DU = centrifuge.ComputeDeltaU(cut); + alpha = AlphaByDU(); + beta = BetaByAlphaAndCut(); + } + return cut; +} + +double StageConfig::ProductAssay() { + double ratio = alpha * feed_assay / (1.0 - feed_assay); + product_assay = ratio / (1. + ratio); + return product_assay; +} + +double StageConfig::TailAssay() { + double A = (feed_assay / (1. - feed_assay)) / beta; + tail_assay = A / (1. + A); + return tail_assay; +} + +double StageConfig::AlphaByDU() { + double feed = centrifuge.feed; + double M = centrifuge.M; + alpha = 1 + std::sqrt((2 * (DU / M) * (1 - cut) / (cut * feed))); + return alpha; +} + +double StageConfig::BetaByAlphaAndCut() { + double product_assay = ProductAssay(); + double waste_assay = (feed_assay - cut * product_assay) / (1. - cut); + + beta = feed_assay / (1. - feed_assay) * (1. - waste_assay) / waste_assay; + return beta; +} + +double StageConfig::CutByAlphaBeta() { + double product_assay = ProductAssay(); + double tail_assay = TailAssay(); + + cut = (feed_assay - tail_assay) / (product_assay - tail_assay); + return cut; +} + +void StageConfig::BuildIdealStg(double f_assay, double precision) { + feed_assay = f_assay; + if (DU == -1 || alpha == -1) { + cut = CutForIdealStg(feed_assay, precision); + DU = centrifuge.ComputeDeltaU(cut); + alpha = AlphaByDU(); + beta = alpha; + cut = CutByAlphaBeta(); + } else { + beta = alpha; + cut = CutByAlphaBeta(); + } + product_assay = ProductAssay(); + tail_assay = TailAssay(); +} + +double StageConfig::MachinesPerStage() { + n_machines = feed_flow / (2.0 * DU / (pow((alpha - 1.0), 2))); + return n_machines; +} + +double StageConfig::ProductPerEnrStage() { + return feed_flow * (alpha - 1.0) * feed_assay * (1 - feed_assay) / + (2 * (product_assay - feed_assay)); +} + +} // namespace mbmore diff --git a/src/StageConfig.h b/src/StageConfig.h new file mode 100644 index 0000000..0c5957e --- /dev/null +++ b/src/StageConfig.h @@ -0,0 +1,69 @@ +#ifndef MBMORE_SRC_STAGE_H_ +#define MBMORE_SRC_STAGE_H_ + +#include +#include "CentrifugeConfig.h" + +namespace mbmore { +class CascadeConfig; + +class StageConfig { + friend CascadeConfig; + + public: + StageConfig() {;} + StageConfig(double f_assay, double feed_flow, double precision, double cut = -1, double DU = -1, double alpha = -1); + + // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) + void BuildIdealStg(double f_assay, double precision = 1e-8); + // Compute the cut to ensure alpha = beta (from dU) + double CutForIdealStg(double f_assay, double precision = 1e-8); + + // calculate Alpha value using the dU, Cut and the centrifuge feed flow value + double AlphaByDU(); + + // Compute Beta value from alpha value, cut and feed assay + double BetaByAlphaAndCut(); + // recompute Cut value assuming Alpha and Beta fixed + double CutByAlphaBeta(); + + // COmpute Product assay from feed assay and alpha + double ProductAssay(); + // Compute Waste assy from feed assay and beta + double TailAssay(); + + // Return the minimum number of centrifudes required to meed the feed flow + double MachinesPerStage(); + // Compute the Product feed + double ProductPerEnrStage(); + + // Configuration of all the centrifuges in the stage + CentrifugeConfig centrifuge; + // Precision used for the cut calculation defautl 1e-8 + double precision; + + // cut value of the stage + double cut; + // dU value of the stage (calculted form the centrifuges config with the cut) + double DU; + // Feed to Product enrichment ratio + double alpha; + // Feed to Tail enrichment ratio + double beta; + // Feed flow (g/s) + double feed_flow; + + // number of centriges in the stage + double n_machines; + + // Feed assay + double feed_assay; + // Product assay + double product_assay; + // Tail assay + double tail_assay; +}; + +} // namespace mbmore + +#endif // MBMORE_SRC_STAGE_H_ diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc new file mode 100644 index 0000000..a61ccdc --- /dev/null +++ b/src/StageConfig_tests.cc @@ -0,0 +1,118 @@ +#include + +#include "StageConfig.h" + +#include "agent_tests.h" +#include "context.h" +#include "facility_tests.h" + +namespace mbmore { + +// Benchmarked against mbmore_enrich_compare.ipynb +// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +namespace stageconfig_test { +// Fixed for a cascade separating out U235 from U238 in UF6 gas +// Fixed for a cascade separating out U235 from U238 in UF6 gas +double M = 0.352; // kg/mol UF6 +double dM = 0.003; // kg/mol U238 - U235 +double x = 1000; // Pressure ratio (Glaser) + +// General cascade assumptions +double flow_internal = 2.0; +double eff = 1.0; +double cut = 0.5; + +// Centrifuge params used in Python test code +// (based on Glaser SGS 2009 paper) +double v_a = 485; // m/s +double height = 0.5; // meters +double diameter = 0.15; // meters +double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec +double temp = 320.0; // Kelvin + +// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +const double feed_assay = 0.0071; +const double product_assay = 0.035; +const double waste_assay = 0.001; +const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, + flow_internal); +// del U=7.0323281e-08 alpha=1.16321 +double delU = centrifuge.ComputeDeltaU(cut); + +const double tol_assay = 1e-5; +const double tol_qty = 1e-6; +const double tol_num = 1e-2; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Find product assay from separation factor alpha +TEST(StageConfig_Test, TestAssays) { + double cur_alpha = 1.4; + double cur_f_assay = 0.007; + + StageConfig stage(cur_f_assay, feed_m, 1e-16, cut, delU, cur_alpha); + double cal_prod_assay = stage.ProductAssay(); + + // N_prime = alpha*R / ( 1+alpha*R) + double th_prod_assay = 0.009773; + double tol = 1e-6; + + EXPECT_NEAR(cal_prod_assay, th_prod_assay, tol); + + double n_stages = 5; + double th_w_assay = 0.004227; + double cur_beta = stage.BetaByAlphaAndCut(); + double cal_w_assay = stage.TailAssay(); + + EXPECT_NEAR(cal_w_assay, th_w_assay, tol); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate ideal SWU params of single machine (separation potential delU +// and separation factor alpha) +TEST(StageConfig_Test, TestSWU) { + double pycode_U = 7.03232816847e-08; + double tol = 1e-9; + + StageConfig stage(feed_assay, feed_m, 1e-16, cut, delU, -1); + + double pycode_alpha = 1.16321; + double tol_alpha = 1e-2; + EXPECT_NEAR(stage.alpha, pycode_alpha, tol_alpha); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Determine the output of the first enrich/strip stage of a cascade +// based on the design params for the cascade +TEST(StageConfig_Test, TestStages) { + StageConfig stage(feed_assay, feed_c, 1e-16, cut, delU, -1); + + double product_assay_s = stage.ProductAssay(); + double n_mach_e = stage.MachinesPerStage(); + double product_s = stage.ProductPerEnrStage(); + + double enrich_waste = feed_c - product_s; + double enrich_waste_assay = + (feed_c * feed_assay - product_s * product_assay_s) / enrich_waste; + + double pycode_product_assay_s = 0.0082492; + double pycode_n_mach_e = 53.287; + double pycode_product_s = 0.0001408; + + EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); + EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); + EXPECT_NEAR(product_s, pycode_product_s, tol_qty); + + stage = StageConfig(feed_assay, enrich_waste, 1e-16, cut, delU, -1); + double n_mach_w = stage.MachinesPerStage(); + double strip_waste_assay = stage.TailAssay(); + + double pycode_n_mach_w = 26.6127; + double th_waste_assay_s = 0.005951; + + EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); + EXPECT_NEAR(strip_waste_assay, th_waste_assay_s, tol_assay); +} + +} // namespace enrichfunctiontests +} // namespace mbmore From 1e53ec3dbe6c8d054177c43a0bfd1cdc938154fc Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 15:20:42 -0500 Subject: [PATCH 020/116] add StageConfig to CmakeFile --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23ea67f..0ae6747 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ USE_CYCLUS("mbmore" "mytest") USE_CYCLUS("mbmore" "behavior_functions") USE_CYCLUS("mbmore" "RandomEnrich") USE_CYCLUS("mbmore" "CentrifugeConfig") +USE_CYCLUS("mbmore" "StageConfig") USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") USE_CYCLUS("mbmore" "InteractRegion") From 3bf10bf12bde241743aa34e8e3735110937b4223 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 15:40:15 -0500 Subject: [PATCH 021/116] some improvement --- src/StageConfig.cc | 42 +++++++++++++++++++++--------------------- src/StageConfig.h | 2 ++ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 402982d..3122cea 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -20,23 +20,23 @@ StageConfig::StageConfig(double f_assay, double feed_, double precision_, DU(DU_), alpha(alpha_), cut(cut_) { + // if the cut is not provided guess it such as Alpha = Beta if (cut == -1) { BuildIdealStg(feed_assay, precision); + } else { + if (DU == -1) { + DU = centrifuge.ComputeDeltaU(cut); + } + // if alpha is not provided, compute it from the dU + if (alpha == -1) { + AlphaByDU(); + } + + BetaByAlphaAndCut(); + ProductAssay(); + TailAssay(); } - - if (DU == -1) { - DU = centrifuge.ComputeDeltaU(cut); - } - - if (alpha == -1) { - AlphaByDU(); - } - - BetaByAlphaAndCut(); - ProductAssay(); - TailAssay(); } - double StageConfig::CutForIdealStg(double f_assay, double precision) { feed_assay = f_assay; double p_cut = cut = 0.1; @@ -59,8 +59,8 @@ double StageConfig::CutForIdealStg(double f_assay, double precision) { // targeting alpha_m_beta = 0 cut = -b / a; DU = centrifuge.ComputeDeltaU(cut); - alpha = AlphaByDU(); - beta = BetaByAlphaAndCut(); + AlphaByDU(); + BetaByAlphaAndCut(); } return cut; } @@ -103,17 +103,17 @@ double StageConfig::CutByAlphaBeta() { void StageConfig::BuildIdealStg(double f_assay, double precision) { feed_assay = f_assay; if (DU == -1 || alpha == -1) { - cut = CutForIdealStg(feed_assay, precision); + CutForIdealStg(feed_assay, precision); DU = centrifuge.ComputeDeltaU(cut); - alpha = AlphaByDU(); + AlphaByDU(); beta = alpha; - cut = CutByAlphaBeta(); + CutByAlphaBeta(); } else { beta = alpha; - cut = CutByAlphaBeta(); + CutByAlphaBeta(); } - product_assay = ProductAssay(); - tail_assay = TailAssay(); + ProductAssay(); + TailAssay(); } double StageConfig::MachinesPerStage() { diff --git a/src/StageConfig.h b/src/StageConfig.h index 0c5957e..0c4b141 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -11,7 +11,9 @@ class StageConfig { friend CascadeConfig; public: + // Setup a empty stage StageConfig() {;} + // Design a ideal stage for a specific feed assay and feed flow StageConfig(double f_assay, double feed_flow, double precision, double cut = -1, double DU = -1, double alpha = -1); // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) From ffcc12249f45148dca3f44b9440954facd2bbddb Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 16:08:49 -0500 Subject: [PATCH 022/116] some improvement in StageConfig, with a constructor without centrifuges some options are not possible... --- src/StageConfig.cc | 38 +++++++++++++++++++------------------- src/StageConfig.h | 4 +++- src/StageConfig_tests.cc | 8 ++++---- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 3122cea..e457627 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -12,30 +12,30 @@ namespace mbmore { -StageConfig::StageConfig(double f_assay, double feed_, double precision_, - double cut_, double DU_, double alpha_) +StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, double feed_, + double precision_) + : centrifuge(cent), + feed_assay(f_assay), + feed_flow(feed_), + precision(precision_) { + BuildIdealStg(feed_assay, precision); +} +StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, + double alpha_, double precision_) : feed_assay(f_assay), feed_flow(feed_), precision(precision_), + cut(cut_), DU(DU_), - alpha(alpha_), - cut(cut_) { - // if the cut is not provided guess it such as Alpha = Beta - if (cut == -1) { - BuildIdealStg(feed_assay, precision); - } else { - if (DU == -1) { - DU = centrifuge.ComputeDeltaU(cut); - } - // if alpha is not provided, compute it from the dU - if (alpha == -1) { - AlphaByDU(); - } - - BetaByAlphaAndCut(); - ProductAssay(); - TailAssay(); + alpha(alpha_) { + // if alpha is not provided, compute it from the dU + if (alpha == -1) { + AlphaByDU(); } + + BetaByAlphaAndCut(); + ProductAssay(); + TailAssay(); } double StageConfig::CutForIdealStg(double f_assay, double precision) { feed_assay = f_assay; diff --git a/src/StageConfig.h b/src/StageConfig.h index 0c4b141..ab43c9f 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -14,7 +14,9 @@ class StageConfig { // Setup a empty stage StageConfig() {;} // Design a ideal stage for a specific feed assay and feed flow - StageConfig(double f_assay, double feed_flow, double precision, double cut = -1, double DU = -1, double alpha = -1); + StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, double precision = 1e-8); + // Design a ideal stage for a specific feed assay and feed flow + StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8 ); // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) void BuildIdealStg(double f_assay, double precision = 1e-8); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index a61ccdc..7274081 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -51,7 +51,7 @@ TEST(StageConfig_Test, TestAssays) { double cur_alpha = 1.4; double cur_f_assay = 0.007; - StageConfig stage(cur_f_assay, feed_m, 1e-16, cut, delU, cur_alpha); + StageConfig stage(cur_f_assay, feed_m, cut, delU, cur_alpha, 1e-16); double cal_prod_assay = stage.ProductAssay(); // N_prime = alpha*R / ( 1+alpha*R) @@ -74,7 +74,7 @@ TEST(StageConfig_Test, TestSWU) { double pycode_U = 7.03232816847e-08; double tol = 1e-9; - StageConfig stage(feed_assay, feed_m, 1e-16, cut, delU, -1); + StageConfig stage(feed_assay, feed_m, cut, delU, -1, 1e-16); double pycode_alpha = 1.16321; double tol_alpha = 1e-2; @@ -85,7 +85,7 @@ TEST(StageConfig_Test, TestSWU) { // Determine the output of the first enrich/strip stage of a cascade // based on the design params for the cascade TEST(StageConfig_Test, TestStages) { - StageConfig stage(feed_assay, feed_c, 1e-16, cut, delU, -1); + StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); double product_assay_s = stage.ProductAssay(); double n_mach_e = stage.MachinesPerStage(); @@ -103,7 +103,7 @@ TEST(StageConfig_Test, TestStages) { EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); EXPECT_NEAR(product_s, pycode_product_s, tol_qty); - stage = StageConfig(feed_assay, enrich_waste, 1e-16, cut, delU, -1); + stage = StageConfig(feed_assay, enrich_waste, cut, delU, -1, 1e-16); double n_mach_w = stage.MachinesPerStage(); double strip_waste_assay = stage.TailAssay(); From 2081794b03eae1adcbdb9be8c8c9742934ec8947 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Tue, 24 Apr 2018 16:13:11 -0500 Subject: [PATCH 023/116] autoformat --- src/StageConfig.cc | 4 ++-- src/StageConfig.h | 18 +++++++++++------- src/StageConfig_tests.cc | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index e457627..ac6cbac 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -4,11 +4,11 @@ #include #include #include +#include +#include #include #include #include -#include -#include namespace mbmore { diff --git a/src/StageConfig.h b/src/StageConfig.h index ab43c9f..23683bc 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -12,13 +12,17 @@ class StageConfig { public: // Setup a empty stage - StageConfig() {;} + StageConfig() { ; } // Design a ideal stage for a specific feed assay and feed flow - StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, double precision = 1e-8); + StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, + double precision = 1e-8); // Design a ideal stage for a specific feed assay and feed flow - StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8 ); + StageConfig(double f_assay, double feed_flow, double cut_, double DU_, + double alpha_ = -1, double precision = 1e-8); - // Build a stage assumming alpha = beta (if cut is not defined, compute the cut to make it so) + // Build a stage assumming alpha = beta (if cut is not defined, compute the + // cut + // to make it so) void BuildIdealStg(double f_assay, double precision = 1e-8); // Compute the cut to ensure alpha = beta (from dU) double CutForIdealStg(double f_assay, double precision = 1e-8); @@ -38,7 +42,7 @@ class StageConfig { // Return the minimum number of centrifudes required to meed the feed flow double MachinesPerStage(); - // Compute the Product feed + // Compute the Product feed double ProductPerEnrStage(); // Configuration of all the centrifuges in the stage @@ -56,10 +60,10 @@ class StageConfig { double beta; // Feed flow (g/s) double feed_flow; - + // number of centriges in the stage double n_machines; - + // Feed assay double feed_assay; // Product assay diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 7274081..e517758 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -54,7 +54,7 @@ TEST(StageConfig_Test, TestAssays) { StageConfig stage(cur_f_assay, feed_m, cut, delU, cur_alpha, 1e-16); double cal_prod_assay = stage.ProductAssay(); - // N_prime = alpha*R / ( 1+alpha*R) + // N_prime = alpha*R / ( 1+alpha*R) double th_prod_assay = 0.009773; double tol = 1e-6; From 7c2e62817a57823fa0bb68f3eba0a0c0cf9b3bf1 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:05:55 -0500 Subject: [PATCH 024/116] removing methods reimplemented in StageConfig --- src/enrich_functions.cc | 19 ------------------- src/enrich_functions.h | 15 --------------- 2 files changed, 34 deletions(-) diff --git a/src/enrich_functions.cc b/src/enrich_functions.cc index 29a5471..16c8f31 100644 --- a/src/enrich_functions.cc +++ b/src/enrich_functions.cc @@ -15,25 +15,6 @@ double gas_const = 8.314; // J/K/mol double M_238 = 0.238; // kg/mol -double AlphaBySwu(double del_U, double feed, double cut, double M) { - double alpha = 1 + std::sqrt((2 * (del_U / M) * (1 - cut) / (cut * feed))); - return alpha; -} - -// per machine -double ProductAssayByAlpha(double alpha, double feed_assay) { - // Possibly incorrect is commented out ? - // double ratio = (1.0 - feed_assay) / (alpha * feed_assay); - // return 1.0 / (ratio + 1.0); - double ratio = alpha * feed_assay / (1.0 - feed_assay); - return ratio / (1 + ratio); -} - -double WasteAssayByAlpha(double alpha, double feed_assay) { - double A = (feed_assay / (1 - feed_assay)) / alpha; - return A / (1 + A); -} - // This equation can only be used in the limit where the separation factor // (alpha) is very close to one, which is not true for modern gas centrifuges // DO NOT USE THIS EQUATION!!! diff --git a/src/enrich_functions.h b/src/enrich_functions.h index db6e707..9916b70 100644 --- a/src/enrich_functions.h +++ b/src/enrich_functions.h @@ -15,21 +15,6 @@ extern "C" { } - // Calculates the separations factor given the ideal separation energy of a - // single machine (del_U has units of moles/sec) - // Avery p 18 - double AlphaBySwu(double del_U, double feed, double cut, double M); - - // Calculates the assay of the product given the assay - // of the feed and the theoretical separation factor of the machine - // Avery p 57 - double ProductAssayByAlpha(double alpha, double feed_assay); - - // Calculates the assay of the waste given the assay - // of the feed and the theoretical separation factor of the machine - // Avery p 59 (per machine) - double WasteAssayByAlpha(double alpha, double feed_assay); - // Calculates the number of stages needed in a cascade given the separation // potential of a single centrifuge and the material assays std::pair From 5da42b1ba6cb94beb561663d7e373d3a8e050c18 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:10:34 -0500 Subject: [PATCH 025/116] cleaning enrich_functions_tests --- src/enrich_functions_tests.cc | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/enrich_functions_tests.cc b/src/enrich_functions_tests.cc index 6421450..ca2473d 100644 --- a/src/enrich_functions_tests.cc +++ b/src/enrich_functions_tests.cc @@ -46,27 +46,6 @@ namespace mbmore { const double tol_num = 1e-2; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Find product assay from separation factor alpha -TEST(Enrich_Functions_Test, TestAssays) { - - double cur_alpha = 1.4; - double cur_f_assay = 0.007; - - double cpp_assay = ProductAssayByAlpha(cur_alpha, cur_f_assay); - - double pycode_assay = 0.009772636; - double tol = 1e-6; - - EXPECT_NEAR(cpp_assay, pycode_assay, tol); - - double n_stages = 5; - double pycode_w_assay = 0.00095311 ; - - double cpp_w_assay = WasteAssayFromNStages(cur_alpha, cur_f_assay, n_stages); - - EXPECT_NEAR(cpp_w_assay, pycode_w_assay, tol); - -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Ideal cascade design, and then using away from ideal design From b3db7084d8d222a5c9895ea73775937d381d82c7 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 23 Sep 2019 15:16:07 -0500 Subject: [PATCH 026/116] Edited Comments in StageConfig.h --- src/StageConfig.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/StageConfig.h b/src/StageConfig.h index 23683bc..085adb6 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -13,14 +13,14 @@ class StageConfig { public: // Setup a empty stage StageConfig() { ; } - // Design a ideal stage for a specific feed assay and feed flow + // Design an ideal stage for a specific feed assay and feed flow StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, double precision = 1e-8); - // Design a ideal stage for a specific feed assay and feed flow + // Design an ideal stage for a specific feed assay and feed flow StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8); - // Build a stage assumming alpha = beta (if cut is not defined, compute the + // Build a stage assuming alpha = beta (if cut is not defined, compute the // cut // to make it so) void BuildIdealStg(double f_assay, double precision = 1e-8); @@ -35,12 +35,12 @@ class StageConfig { // recompute Cut value assuming Alpha and Beta fixed double CutByAlphaBeta(); - // COmpute Product assay from feed assay and alpha + // Compute Product assay from feed assay and alpha double ProductAssay(); - // Compute Waste assy from feed assay and beta + // Compute Waste assay from feed assay and beta double TailAssay(); - // Return the minimum number of centrifudes required to meed the feed flow + // Return the minimum number of centrifuges required to meet the feed flow double MachinesPerStage(); // Compute the Product feed double ProductPerEnrStage(); @@ -52,7 +52,7 @@ class StageConfig { // cut value of the stage double cut; - // dU value of the stage (calculted form the centrifuges config with the cut) + // dU value of the stage (calculated form the centrifuges config with the cut) double DU; // Feed to Product enrichment ratio double alpha; @@ -61,7 +61,7 @@ class StageConfig { // Feed flow (g/s) double feed_flow; - // number of centriges in the stage + // number of centrifuges in the stage double n_machines; // Feed assay From 962e56f1663e9de1f9470440eb7981607636649a Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 23 Sep 2019 15:54:13 -0500 Subject: [PATCH 027/116] Changing th prefix to theory. --- src/StageConfig_tests.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index e517758..e2e8c68 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -55,17 +55,17 @@ TEST(StageConfig_Test, TestAssays) { double cal_prod_assay = stage.ProductAssay(); // N_prime = alpha*R / ( 1+alpha*R) - double th_prod_assay = 0.009773; + double theory_prod_assay = 0.009773; double tol = 1e-6; - EXPECT_NEAR(cal_prod_assay, th_prod_assay, tol); + EXPECT_NEAR(cal_prod_assay, theory_prod_assay, tol); double n_stages = 5; - double th_w_assay = 0.004227; + double theory_w_assay = 0.004227; double cur_beta = stage.BetaByAlphaAndCut(); double cal_w_assay = stage.TailAssay(); - EXPECT_NEAR(cal_w_assay, th_w_assay, tol); + EXPECT_NEAR(cal_w_assay, theory_w_assay, tol); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Calculate ideal SWU params of single machine (separation potential delU @@ -108,10 +108,10 @@ TEST(StageConfig_Test, TestStages) { double strip_waste_assay = stage.TailAssay(); double pycode_n_mach_w = 26.6127; - double th_waste_assay_s = 0.005951; + double theory_waste_assay_s = 0.005951; EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); - EXPECT_NEAR(strip_waste_assay, th_waste_assay_s, tol_assay); + EXPECT_NEAR(strip_waste_assay, theory_waste_assay_s, tol_assay); } } // namespace enrichfunctiontests From 40dca2214b173f645868e5a062e8f59eaba56ee3 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot Date: Tue, 24 Sep 2019 09:16:34 -0500 Subject: [PATCH 028/116] Apply suggestions from code review Co-Authored-By: Jordan Stomps --- src/StageConfig.cc | 22 +++++++++++----------- src/StageConfig_tests.cc | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index ac6cbac..5b2cd67 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -43,20 +43,20 @@ double StageConfig::CutForIdealStg(double f_assay, double precision) { (*this).DU = centrifuge.ComputeDeltaU(cut); double p_alpha = AlphaByDU(); double p_beta = BetaByAlphaAndCut(); - double p_alpha_m_beta = p_alpha - p_beta; + double p_alpha_minus_beta = p_alpha - p_beta; cut = 0.9; (*this).DU = centrifuge.ComputeDeltaU(cut); AlphaByDU(); BetaByAlphaAndCut(); while (std::abs(alpha - beta) > precision) { // a*cut +b =y - double alpha_m_beta = alpha - beta; - double a = (p_alpha_m_beta - alpha_m_beta) / (p_cut - cut); - double b = alpha_m_beta - cut * a; + double alpha_minus_beta = alpha - beta; + double a = (p_alpha_minus_beta - alpha_minus_beta) / (p_cut - cut); + double b = alpha_minus_beta - cut * a; // old = new - p_alpha_m_beta = alpha_m_beta; + p_alpha_minus_beta = alpha_minus_beta; p_cut = cut; - // targeting alpha_m_beta = 0 + // targeting alpha_minus_beta = 0 cut = -b / a; DU = centrifuge.ComputeDeltaU(cut); AlphaByDU(); @@ -66,7 +66,7 @@ double StageConfig::CutForIdealStg(double f_assay, double precision) { } double StageConfig::ProductAssay() { - double ratio = alpha * feed_assay / (1.0 - feed_assay); + double ratio = alpha * feed_assay / (1. - feed_assay); product_assay = ratio / (1. + ratio); return product_assay; } @@ -80,7 +80,7 @@ double StageConfig::TailAssay() { double StageConfig::AlphaByDU() { double feed = centrifuge.feed; double M = centrifuge.M; - alpha = 1 + std::sqrt((2 * (DU / M) * (1 - cut) / (cut * feed))); + alpha = 1. + std::sqrt((2. * (DU / M) * (1. - cut) / (cut * feed))); return alpha; } @@ -117,13 +117,13 @@ void StageConfig::BuildIdealStg(double f_assay, double precision) { } double StageConfig::MachinesPerStage() { - n_machines = feed_flow / (2.0 * DU / (pow((alpha - 1.0), 2))); + n_machines = feed_flow / (2. * DU / (pow((alpha - 1.), 2.))); return n_machines; } double StageConfig::ProductPerEnrStage() { - return feed_flow * (alpha - 1.0) * feed_assay * (1 - feed_assay) / - (2 * (product_assay - feed_assay)); + return feed_flow * (alpha - 1.) * feed_assay * (1. - feed_assay) / + (2. * (product_assay - feed_assay)); } } // namespace mbmore diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index e2e8c68..e452de1 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -31,6 +31,7 @@ double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec double temp = 320.0; // Kelvin // Cascade params used in Python test code (Enrichment_Calculations.ipynb) +// found in enrich_calcs repo listed above. const double feed_assay = 0.0071; const double product_assay = 0.035; const double waste_assay = 0.001; From 0f874f61a4a2c0f9105aa68a2314804f13c888a1 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 24 Sep 2019 15:28:43 -0500 Subject: [PATCH 029/116] Added Comment to CutForIdealStg Method --- src/StageConfig.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 5b2cd67..a72d4be 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -37,6 +37,9 @@ StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, ProductAssay(); TailAssay(); } + +// alpha = beta occurs approx. in the region 0.1 < cut < 0.9 +// so bounds are calculated for ideal cut double StageConfig::CutForIdealStg(double f_assay, double precision) { feed_assay = f_assay; double p_cut = cut = 0.1; From 9f7c750918fc1cb9ce713ae005dac4cb079d0285 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 26 Sep 2019 16:49:13 -0500 Subject: [PATCH 030/116] Removing ProductPerEnrStage & Fixing Test Cases --- src/StageConfig.cc | 12 +++++------- src/StageConfig.h | 2 +- src/StageConfig_tests.cc | 35 ++++++++++++----------------------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index a72d4be..c73b6de 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -37,7 +37,7 @@ StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, ProductAssay(); TailAssay(); } - + // alpha = beta occurs approx. in the region 0.1 < cut < 0.9 // so bounds are calculated for ideal cut double StageConfig::CutForIdealStg(double f_assay, double precision) { @@ -119,14 +119,12 @@ void StageConfig::BuildIdealStg(double f_assay, double precision) { TailAssay(); } -double StageConfig::MachinesPerStage() { +double StageConfig::MachinesNeededPerStage() { + // This equation was replaced because the per-machine feed-flow + // is already calculated inside the centrifuge object. n_machines = feed_flow / (2. * DU / (pow((alpha - 1.), 2.))); + //n_machines = feed_flow / centrifuge.feed; return n_machines; } -double StageConfig::ProductPerEnrStage() { - return feed_flow * (alpha - 1.) * feed_assay * (1. - feed_assay) / - (2. * (product_assay - feed_assay)); -} - } // namespace mbmore diff --git a/src/StageConfig.h b/src/StageConfig.h index 085adb6..4078ab7 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -41,7 +41,7 @@ class StageConfig { double TailAssay(); // Return the minimum number of centrifuges required to meet the feed flow - double MachinesPerStage(); + double MachinesNeededPerStage(); // Compute the Product feed double ProductPerEnrStage(); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index e452de1..d92d7ce 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -56,20 +56,20 @@ TEST(StageConfig_Test, TestAssays) { double cal_prod_assay = stage.ProductAssay(); // N_prime = alpha*R / ( 1+alpha*R) - double theory_prod_assay = 0.009773; + double target_prod_assay = 0.009773; double tol = 1e-6; - EXPECT_NEAR(cal_prod_assay, theory_prod_assay, tol); + EXPECT_NEAR(cal_prod_assay, target_prod_assay, tol); double n_stages = 5; - double theory_w_assay = 0.004227; + double target_w_assay = 0.004227; double cur_beta = stage.BetaByAlphaAndCut(); double cal_w_assay = stage.TailAssay(); - EXPECT_NEAR(cal_w_assay, theory_w_assay, tol); + EXPECT_NEAR(cal_w_assay, target_w_assay, tol); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Calculate ideal SWU params of single machine (separation potential delU +// Calculate ideal SWU params of single machinefeed_assay (separation potential delU // and separation factor alpha) TEST(StageConfig_Test, TestSWU) { double pycode_U = 7.03232816847e-08; @@ -82,6 +82,12 @@ TEST(StageConfig_Test, TestSWU) { EXPECT_NEAR(stage.alpha, pycode_alpha, tol_alpha); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate the product assay for an ideal stage configuration. +//TEST(StageConfig_Test, TestAssays) { +// +//} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine the output of the first enrich/strip stage of a cascade // based on the design params for the cascade @@ -89,30 +95,13 @@ TEST(StageConfig_Test, TestStages) { StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); double product_assay_s = stage.ProductAssay(); - double n_mach_e = stage.MachinesPerStage(); - double product_s = stage.ProductPerEnrStage(); - - double enrich_waste = feed_c - product_s; - double enrich_waste_assay = - (feed_c * feed_assay - product_s * product_assay_s) / enrich_waste; + double n_mach_e = stage.MachinesNeededPerStage(); double pycode_product_assay_s = 0.0082492; double pycode_n_mach_e = 53.287; - double pycode_product_s = 0.0001408; EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); - EXPECT_NEAR(product_s, pycode_product_s, tol_qty); - - stage = StageConfig(feed_assay, enrich_waste, cut, delU, -1, 1e-16); - double n_mach_w = stage.MachinesPerStage(); - double strip_waste_assay = stage.TailAssay(); - - double pycode_n_mach_w = 26.6127; - double theory_waste_assay_s = 0.005951; - - EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); - EXPECT_NEAR(strip_waste_assay, theory_waste_assay_s, tol_assay); } } // namespace enrichfunctiontests From 2097e5c5a54e04df57538a54c073a20b16963828 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 27 Sep 2019 14:47:10 -0500 Subject: [PATCH 031/116] Failure of TestStages due to centrifuge declaration --- src/StageConfig_tests.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index d92d7ce..c59503f 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -84,7 +84,7 @@ TEST(StageConfig_Test, TestSWU) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Calculate the product assay for an ideal stage configuration. -//TEST(StageConfig_Test, TestAssays) { +//TEST(StageConfig_Test, TestIdealStage) { // //} @@ -92,7 +92,10 @@ TEST(StageConfig_Test, TestSWU) { // Determine the output of the first enrich/strip stage of a cascade // based on the design params for the cascade TEST(StageConfig_Test, TestStages) { - StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); + //StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); + StageConfig stage(centrifuge, feed_assay, feed_c, 1e-16); + + stage.AlphaByDU(); double product_assay_s = stage.ProductAssay(); double n_mach_e = stage.MachinesNeededPerStage(); From 3f85bb4eee3da29bbcc2793a77d67b14c7f435ce Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 1 Oct 2019 14:52:18 -0500 Subject: [PATCH 032/116] Added test for building ideal stage --- src/StageConfig.cc | 4 ++-- src/StageConfig_tests.cc | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index c73b6de..1079ca6 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -122,8 +122,8 @@ void StageConfig::BuildIdealStg(double f_assay, double precision) { double StageConfig::MachinesNeededPerStage() { // This equation was replaced because the per-machine feed-flow // is already calculated inside the centrifuge object. - n_machines = feed_flow / (2. * DU / (pow((alpha - 1.), 2.))); - //n_machines = feed_flow / centrifuge.feed; + //n_machines = feed_flow / (2. * DU / (pow((alpha - 1.), 2.))); + n_machines = feed_flow / centrifuge.feed; return n_machines; } diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index c59503f..329c066 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -84,9 +84,24 @@ TEST(StageConfig_Test, TestSWU) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Calculate the product assay for an ideal stage configuration. -//TEST(StageConfig_Test, TestIdealStage) { -// -//} +TEST(StageConfig_Test, TestIdealStage) { + StageConfig stage_ideal(feed_assay, feed_m, cut, -1, -1, 1e-16); + + stage_ideal.BuildIdealStg(feed_assay,1e-3); + + double pycode_alpha = 1.16321; + double tol_alpha = 1e-2; + + double pycode_cut = 0.5; + double tol_cut = 1e-3; + + double pycode_U = 7.03232816847e-08; + double tol_DU = 1e-9; + + EXPECT_NEAR(stage_ideal.alpha, pycode_alpha, tol_alpha); + EXPECT_NEAR(stage_ideal.cut, pycode_cut, tol_cut); + EXPECT_NEAR(stage_ideal.DU, pycode_U, tol_DU); +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine the output of the first enrich/strip stage of a cascade @@ -94,7 +109,7 @@ TEST(StageConfig_Test, TestSWU) { TEST(StageConfig_Test, TestStages) { //StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); StageConfig stage(centrifuge, feed_assay, feed_c, 1e-16); - + stage.AlphaByDU(); double product_assay_s = stage.ProductAssay(); From 4acf4a9cae9b4e03b3a7983b0945e78fc8a4fa67 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 3 Oct 2019 14:42:38 -0500 Subject: [PATCH 033/116] Completed corrections to TestIdeal, TestStages, and MachinesNeededPerStage --- src/StageConfig.cc | 8 ++++---- src/StageConfig_tests.cc | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 1079ca6..9e70111 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -120,10 +120,10 @@ void StageConfig::BuildIdealStg(double f_assay, double precision) { } double StageConfig::MachinesNeededPerStage() { - // This equation was replaced because the per-machine feed-flow - // is already calculated inside the centrifuge object. - //n_machines = feed_flow / (2. * DU / (pow((alpha - 1.), 2.))); - n_machines = feed_flow / centrifuge.feed; + // n_machines: the denominator should be equal to the + // centrifuge feed flow (centrifuge.feed). + + n_machines = feed_flow / ((2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.)); return n_machines; } diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 329c066..bf25c37 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -84,18 +84,20 @@ TEST(StageConfig_Test, TestSWU) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Calculate the product assay for an ideal stage configuration. -TEST(StageConfig_Test, TestIdealStage) { +TEST(StageConfig_Test, TestIdeal) { StageConfig stage_ideal(feed_assay, feed_m, cut, -1, -1, 1e-16); stage_ideal.BuildIdealStg(feed_assay,1e-3); - double pycode_alpha = 1.16321; + // All expected numbers were calculated using the methods used + // and are trusted to be correct (regression test). + double pycode_alpha = 1.18181; double tol_alpha = 1e-2; - double pycode_cut = 0.5; + double pycode_cut = 0.4589269; double tol_cut = 1e-3; - double pycode_U = 7.03232816847e-08; + double pycode_U = 7.4221362040947e-08; double tol_DU = 1e-9; EXPECT_NEAR(stage_ideal.alpha, pycode_alpha, tol_alpha); @@ -107,16 +109,17 @@ TEST(StageConfig_Test, TestIdealStage) { // Determine the output of the first enrich/strip stage of a cascade // based on the design params for the cascade TEST(StageConfig_Test, TestStages) { - //StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); - StageConfig stage(centrifuge, feed_assay, feed_c, 1e-16); - - stage.AlphaByDU(); + StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); double product_assay_s = stage.ProductAssay(); double n_mach_e = stage.MachinesNeededPerStage(); double pycode_product_assay_s = 0.0082492; - double pycode_n_mach_e = 53.287; + + // cent_feed_flow = (2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.) + // N_machines = feed_flow / cent_feed_flow + // centrifuge feed flow should be equal to feed_m (from Glaser) + double pycode_n_mach_e = 18.7571; EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); From d4c883cbd0f9c510c8ece63ad067490b87e5f6c8 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 8 Oct 2019 15:03:38 -0500 Subject: [PATCH 034/116] Adding selection algorithm for CutForIdealStage() --- src/StageConfig.cc | 51 +++++++++++++++++++++++++++++----------- src/StageConfig.h | 9 +++---- src/StageConfig_tests.cc | 3 ++- 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 9e70111..673642e 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -38,19 +38,40 @@ StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, TailAssay(); } -// alpha = beta occurs approx. in the region 0.1 < cut < 0.9 -// so bounds are calculated for ideal cut +// Search for cut where alpha = beta by starting at cut = 0.1, 0.9 double StageConfig::CutForIdealStg(double f_assay, double precision) { feed_assay = f_assay; + + // Calculating high and low parameters double p_cut = cut = 0.1; (*this).DU = centrifuge.ComputeDeltaU(cut); - double p_alpha = AlphaByDU(); - double p_beta = BetaByAlphaAndCut(); - double p_alpha_minus_beta = p_alpha - p_beta; - cut = 0.9; + double low_alpha = AlphaByDU(); + double low_beta = BetaByAlphaAndCut(); + double high_cut = cut = 0.9; (*this).DU = centrifuge.ComputeDeltaU(cut); - AlphaByDU(); - BetaByAlphaAndCut(); + double high_alpha = AlphaByDU(); + double high_beta = BetaByAlphaAndCut(); + + // Set initial guess to closer cut values + if (std::abs(low_alpha - low_beta) < std::abs(high_alpha - high_beta)) { + alpha = low_alpha; + beta = low_beta; + cut = low_cut; + + double p_alpha = high_alpha; + double p_beta = high_beta; + double p_cut = high_cut; + } else { + alpha = high_alpha; + beta = high_beta; + cut = high_cut; + + double p_alpha = low_alpha; + double p_beta = low_beta; + double p_cut = low_cut; + } + + double p_alpha_minus_beta = p_alpha - p_beta; while (std::abs(alpha - beta) > precision) { // a*cut +b =y double alpha_minus_beta = alpha - beta; @@ -83,6 +104,7 @@ double StageConfig::TailAssay() { double StageConfig::AlphaByDU() { double feed = centrifuge.feed; double M = centrifuge.M; + // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 alpha = 1. + std::sqrt((2. * (DU / M) * (1. - cut) / (cut * feed))); return alpha; } @@ -109,12 +131,10 @@ void StageConfig::BuildIdealStg(double f_assay, double precision) { CutForIdealStg(feed_assay, precision); DU = centrifuge.ComputeDeltaU(cut); AlphaByDU(); - beta = alpha; - CutByAlphaBeta(); - } else { - beta = alpha; - CutByAlphaBeta(); } + + beta = alpha; + CutByAlphaBeta(); ProductAssay(); TailAssay(); } @@ -123,7 +143,10 @@ double StageConfig::MachinesNeededPerStage() { // n_machines: the denominator should be equal to the // centrifuge feed flow (centrifuge.feed). - n_machines = feed_flow / ((2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.)); + // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 + cfeed_flow = (2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.); + //n_machines = (feed_flow / ((2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.))); + n_machines = std::round(feed_flow / cfeed_flow); return n_machines; } diff --git a/src/StageConfig.h b/src/StageConfig.h index 4078ab7..1167606 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -8,7 +8,7 @@ namespace mbmore { class CascadeConfig; class StageConfig { - friend CascadeConfig; + //friend CascadeConfig; public: // Setup a empty stage @@ -20,9 +20,8 @@ class StageConfig { StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8); - // Build a stage assuming alpha = beta (if cut is not defined, compute the - // cut - // to make it so) + // Build a stage assuming alpha = beta + // (if cut is not defined, compute the cut to make it so) void BuildIdealStg(double f_assay, double precision = 1e-8); // Compute the cut to ensure alpha = beta (from dU) double CutForIdealStg(double f_assay, double precision = 1e-8); @@ -42,8 +41,6 @@ class StageConfig { // Return the minimum number of centrifuges required to meet the feed flow double MachinesNeededPerStage(); - // Compute the Product feed - double ProductPerEnrStage(); // Configuration of all the centrifuges in the stage CentrifugeConfig centrifuge; diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index bf25c37..4a1640f 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -119,7 +119,8 @@ TEST(StageConfig_Test, TestStages) { // cent_feed_flow = (2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.) // N_machines = feed_flow / cent_feed_flow // centrifuge feed flow should be equal to feed_m (from Glaser) - double pycode_n_mach_e = 18.7571; + //double pycode_n_mach_e = 18.7571; + double pycode_n_mach_e = 10; EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); From a80780e885278401378fb80c124a4369378d86e8 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 9 Oct 2019 14:44:43 -0500 Subject: [PATCH 035/116] Implementing getter/setter methods and making variables private. --- src/StageConfig.cc | 151 +++++++++++++++++++-------------------- src/StageConfig.h | 138 ++++++++++++++++++++--------------- src/StageConfig_tests.cc | 36 +++++----- 3 files changed, 173 insertions(+), 152 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 673642e..2eecd0e 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -12,24 +12,25 @@ namespace mbmore { -StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, double feed_, - double precision_) +StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, double feed__, + double precision__) : centrifuge(cent), - feed_assay(f_assay), - feed_flow(feed_), - precision(precision_) { - BuildIdealStg(feed_assay, precision); + feed_assay_(f_assay), + feed_flow_(feed__), + precision_(precision__) { + BuildIdealStg(); } -StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, - double alpha_, double precision_) - : feed_assay(f_assay), - feed_flow(feed_), - precision(precision_), - cut(cut_), - DU(DU_), - alpha(alpha_) { +StageConfig::StageConfig(double f_assay, double feed__, double cut__, double DU__, + double alpha__, double precision__) + : centrifuge(), + feed_assay_(f_assay), + feed_flow_(feed__), + precision_(precision__), + cut_(cut__), + DU_(DU__), + alpha_(alpha__) { // if alpha is not provided, compute it from the dU - if (alpha == -1) { + if (alpha_ == -1) { AlphaByDU(); } @@ -39,115 +40,109 @@ StageConfig::StageConfig(double f_assay, double feed_, double cut_, double DU_, } // Search for cut where alpha = beta by starting at cut = 0.1, 0.9 -double StageConfig::CutForIdealStg(double f_assay, double precision) { - feed_assay = f_assay; - +void StageConfig::CutForIdealStg() { // Calculating high and low parameters - double p_cut = cut = 0.1; - (*this).DU = centrifuge.ComputeDeltaU(cut); - double low_alpha = AlphaByDU(); - double low_beta = BetaByAlphaAndCut(); - double high_cut = cut = 0.9; - (*this).DU = centrifuge.ComputeDeltaU(cut); - double high_alpha = AlphaByDU(); - double high_beta = BetaByAlphaAndCut(); + double low_cut = cut_ = 0.1; + DU_ = centrifuge.ComputeDeltaU(cut_); + AlphaByDU(); + BetaByAlphaAndCut(); + double low_alpha = alpha_; + double low_beta = beta_; + double high_cut = cut_ = 0.9; + DU_ = centrifuge.ComputeDeltaU(cut_); + AlphaByDU(); + BetaByAlphaAndCut(); + double high_alpha = alpha_; + double high_beta = beta_; + double p_alpha, p_beta, p_cut; // Set initial guess to closer cut values if (std::abs(low_alpha - low_beta) < std::abs(high_alpha - high_beta)) { - alpha = low_alpha; - beta = low_beta; - cut = low_cut; + alpha_ = low_alpha; + beta_ = low_beta; + cut_ = low_cut; - double p_alpha = high_alpha; - double p_beta = high_beta; - double p_cut = high_cut; + p_alpha = high_alpha; + p_beta = high_beta; + p_cut = high_cut; } else { - alpha = high_alpha; - beta = high_beta; - cut = high_cut; + alpha_ = high_alpha; + beta_ = high_beta; + cut_ = high_cut; - double p_alpha = low_alpha; - double p_beta = low_beta; - double p_cut = low_cut; + p_alpha = low_alpha; + p_beta = low_beta; + p_cut = low_cut; } double p_alpha_minus_beta = p_alpha - p_beta; - while (std::abs(alpha - beta) > precision) { + while (std::abs(alpha_ - beta_) > precision_) { // a*cut +b =y - double alpha_minus_beta = alpha - beta; - double a = (p_alpha_minus_beta - alpha_minus_beta) / (p_cut - cut); - double b = alpha_minus_beta - cut * a; + double alpha_minus_beta = alpha_ - beta_; + double a = (p_alpha_minus_beta - alpha_minus_beta) / (p_cut - cut_); + double b = alpha_minus_beta - cut_ * a; // old = new p_alpha_minus_beta = alpha_minus_beta; - p_cut = cut; + p_cut = cut_; // targeting alpha_minus_beta = 0 - cut = -b / a; - DU = centrifuge.ComputeDeltaU(cut); + cut_ = -b / a; + DU_ = centrifuge.ComputeDeltaU(cut_); AlphaByDU(); BetaByAlphaAndCut(); } - return cut; } -double StageConfig::ProductAssay() { - double ratio = alpha * feed_assay / (1. - feed_assay); - product_assay = ratio / (1. + ratio); - return product_assay; +void StageConfig::ProductAssay() { + double ratio = alpha_ * feed_assay_ / (1. - feed_assay_); + product_assay_ = ratio / (1. + ratio); } -double StageConfig::TailAssay() { - double A = (feed_assay / (1. - feed_assay)) / beta; - tail_assay = A / (1. + A); - return tail_assay; +void StageConfig::TailAssay() { + double A = (feed_assay_ / (1. - feed_assay_)) / beta_; + tail_assay_ = A / (1. + A); } -double StageConfig::AlphaByDU() { +void StageConfig::AlphaByDU() { double feed = centrifuge.feed; double M = centrifuge.M; // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - alpha = 1. + std::sqrt((2. * (DU / M) * (1. - cut) / (cut * feed))); - return alpha; + alpha_ = 1. + std::sqrt((2. * (DU_ / M) * (1. - cut_) / (cut_ * feed))); } -double StageConfig::BetaByAlphaAndCut() { - double product_assay = ProductAssay(); - double waste_assay = (feed_assay - cut * product_assay) / (1. - cut); +void StageConfig::BetaByAlphaAndCut() { + ProductAssay(); + double waste_assay = (feed_assay_ - cut_ * product_assay_) / (1. - cut_); - beta = feed_assay / (1. - feed_assay) * (1. - waste_assay) / waste_assay; - return beta; + beta_ = feed_assay_ / (1. - feed_assay_) * (1. - waste_assay) / waste_assay; } -double StageConfig::CutByAlphaBeta() { - double product_assay = ProductAssay(); - double tail_assay = TailAssay(); +void StageConfig::CutByAlphaBeta() { + ProductAssay(); + TailAssay(); - cut = (feed_assay - tail_assay) / (product_assay - tail_assay); - return cut; + cut_ = (feed_assay_ - tail_assay_) / (product_assay_ - tail_assay_); } -void StageConfig::BuildIdealStg(double f_assay, double precision) { - feed_assay = f_assay; - if (DU == -1 || alpha == -1) { - CutForIdealStg(feed_assay, precision); - DU = centrifuge.ComputeDeltaU(cut); +void StageConfig::BuildIdealStg() { + if (DU_ == -1 || alpha_ == -1) { + CutForIdealStg(); + DU_ = centrifuge.ComputeDeltaU(cut_); AlphaByDU(); } - beta = alpha; + beta_ = alpha_; CutByAlphaBeta(); ProductAssay(); TailAssay(); } -double StageConfig::MachinesNeededPerStage() { +void StageConfig::MachinesNeededPerStage() { // n_machines: the denominator should be equal to the // centrifuge feed flow (centrifuge.feed). // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - cfeed_flow = (2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.); - //n_machines = (feed_flow / ((2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.))); - n_machines = std::round(feed_flow / cfeed_flow); - return n_machines; + double cfeed_flow = (2 * DU_ / centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); + n_machines_ = std::ceil(feed_flow_ / cfeed_flow); } } // namespace mbmore diff --git a/src/StageConfig.h b/src/StageConfig.h index 1167606..4a0a954 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -10,63 +10,87 @@ class CascadeConfig; class StageConfig { //friend CascadeConfig; - public: - // Setup a empty stage - StageConfig() { ; } - // Design an ideal stage for a specific feed assay and feed flow - StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, - double precision = 1e-8); - // Design an ideal stage for a specific feed assay and feed flow - StageConfig(double f_assay, double feed_flow, double cut_, double DU_, - double alpha_ = -1, double precision = 1e-8); - - // Build a stage assuming alpha = beta - // (if cut is not defined, compute the cut to make it so) - void BuildIdealStg(double f_assay, double precision = 1e-8); - // Compute the cut to ensure alpha = beta (from dU) - double CutForIdealStg(double f_assay, double precision = 1e-8); - - // calculate Alpha value using the dU, Cut and the centrifuge feed flow value - double AlphaByDU(); - - // Compute Beta value from alpha value, cut and feed assay - double BetaByAlphaAndCut(); - // recompute Cut value assuming Alpha and Beta fixed - double CutByAlphaBeta(); - - // Compute Product assay from feed assay and alpha - double ProductAssay(); - // Compute Waste assay from feed assay and beta - double TailAssay(); - - // Return the minimum number of centrifuges required to meet the feed flow - double MachinesNeededPerStage(); - - // Configuration of all the centrifuges in the stage - CentrifugeConfig centrifuge; - // Precision used for the cut calculation defautl 1e-8 - double precision; - - // cut value of the stage - double cut; - // dU value of the stage (calculated form the centrifuges config with the cut) - double DU; - // Feed to Product enrichment ratio - double alpha; - // Feed to Tail enrichment ratio - double beta; - // Feed flow (g/s) - double feed_flow; - - // number of centrifuges in the stage - double n_machines; - - // Feed assay - double feed_assay; - // Product assay - double product_assay; - // Tail assay - double tail_assay; + private: + + // Compute the cut to ensure alpha = beta (from dU) + void CutForIdealStg(); + + // Configuration of all the centrifuges in the stage + CentrifugeConfig centrifuge; + // Precision used for the cut calculation defautl 1e-8 + double precision_ = 1e-8; + + // cut value of the stage + double cut_; + // dU value of the stage (calculated form the centrifuges config with the cut) + double DU_; + // Feed to Product enrichment ratio + double alpha_; + // Feed to Tail enrichment ratio + double beta_; + // Feed flow (g/s) + double feed_flow_; + + // number of centrifuges in the stage + int n_machines_; + + // Feed assay + double feed_assay_; + // Product assay + double product_assay_; + // Tail assay + double tail_assay_; + + public: + // Setup a empty stage + StageConfig() { ; } + // Design an ideal stage for a specific feed assay and feed flow + StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, + double precision = 1e-8); + // Design an ideal stage for a specific feed assay and feed flow + StageConfig(double f_assay, double feed_flow, double cut_, double DU_, + double alpha_ = -1, double precision = 1e-8); + + // Build a stage assuming alpha = beta + // (if cut is not defined, compute the cut to make it so) + void BuildIdealStg(); + + // calculate Alpha value using the dU, Cut and the centrifuge feed flow value + void AlphaByDU(); + + // Compute Beta value from alpha value, cut and feed assay + void BetaByAlphaAndCut(); + // recompute Cut value assuming Alpha and Beta fixed + void CutByAlphaBeta(); + + // Compute Product assay from feed assay and alpha + void ProductAssay(); + // Compute Waste assay from feed assay and beta + void TailAssay(); + + // Return the minimum number of centrifuges required to meet the feed flow + void MachinesNeededPerStage(); + + // Setter methods + void precision(double p) {precision_ = p;} + void cut(double c) {cut_ = c;} + void DU(double du) {DU_ = du;} + void alpha(double a) {alpha_ = a;} + void beta(double b) {beta_ = b;} + void feed_flow(double f) {feed_flow_ = f;} + void feed_assay(double fa) {feed_assay_ = fa;} + + // Getter methods + double precision() {return precision_;} + double cut() {return cut_;} + double DU() {return DU_;} + double alpha() {return alpha_;} + double beta() {return beta_;} + double feed_flow() {return feed_flow_;} + int n_machines() {return n_machines_;} + double feed_assay() {return feed_assay_;} + double product_assay() {return product_assay_;} + double tail_assay() {return tail_assay_;} }; } // namespace mbmore diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 4a1640f..f3b1830 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -33,7 +33,7 @@ double temp = 320.0; // Kelvin // Cascade params used in Python test code (Enrichment_Calculations.ipynb) // found in enrich_calcs repo listed above. const double feed_assay = 0.0071; -const double product_assay = 0.035; +const double prod_assay = 0.035; const double waste_assay = 0.001; const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec @@ -53,20 +53,20 @@ TEST(StageConfig_Test, TestAssays) { double cur_f_assay = 0.007; StageConfig stage(cur_f_assay, feed_m, cut, delU, cur_alpha, 1e-16); - double cal_prod_assay = stage.ProductAssay(); + stage.ProductAssay(); // N_prime = alpha*R / ( 1+alpha*R) double target_prod_assay = 0.009773; double tol = 1e-6; - EXPECT_NEAR(cal_prod_assay, target_prod_assay, tol); + EXPECT_NEAR(stage.product_assay(), target_prod_assay, tol); double n_stages = 5; double target_w_assay = 0.004227; - double cur_beta = stage.BetaByAlphaAndCut(); - double cal_w_assay = stage.TailAssay(); + stage.BetaByAlphaAndCut(); + stage.TailAssay(); - EXPECT_NEAR(cal_w_assay, target_w_assay, tol); + EXPECT_NEAR(stage.tail_assay(), target_w_assay, tol); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Calculate ideal SWU params of single machinefeed_assay (separation potential delU @@ -79,7 +79,7 @@ TEST(StageConfig_Test, TestSWU) { double pycode_alpha = 1.16321; double tol_alpha = 1e-2; - EXPECT_NEAR(stage.alpha, pycode_alpha, tol_alpha); + EXPECT_NEAR(stage.alpha(), pycode_alpha, tol_alpha); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -87,7 +87,10 @@ TEST(StageConfig_Test, TestSWU) { TEST(StageConfig_Test, TestIdeal) { StageConfig stage_ideal(feed_assay, feed_m, cut, -1, -1, 1e-16); - stage_ideal.BuildIdealStg(feed_assay,1e-3); + // Only setting precision for building ideal stage + stage_ideal.precision(1e-3); + stage_ideal.BuildIdealStg(); + stage_ideal.precision(1e-16); // All expected numbers were calculated using the methods used // and are trusted to be correct (regression test). @@ -100,9 +103,9 @@ TEST(StageConfig_Test, TestIdeal) { double pycode_U = 7.4221362040947e-08; double tol_DU = 1e-9; - EXPECT_NEAR(stage_ideal.alpha, pycode_alpha, tol_alpha); - EXPECT_NEAR(stage_ideal.cut, pycode_cut, tol_cut); - EXPECT_NEAR(stage_ideal.DU, pycode_U, tol_DU); + EXPECT_NEAR(stage_ideal.alpha(), pycode_alpha, tol_alpha); + EXPECT_NEAR(stage_ideal.cut(), pycode_cut, tol_cut); + EXPECT_NEAR(stage_ideal.DU(), pycode_U, tol_DU); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -111,19 +114,18 @@ TEST(StageConfig_Test, TestIdeal) { TEST(StageConfig_Test, TestStages) { StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); - double product_assay_s = stage.ProductAssay(); - double n_mach_e = stage.MachinesNeededPerStage(); + stage.ProductAssay(); + stage.MachinesNeededPerStage(); double pycode_product_assay_s = 0.0082492; // cent_feed_flow = (2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.) // N_machines = feed_flow / cent_feed_flow // centrifuge feed flow should be equal to feed_m (from Glaser) - //double pycode_n_mach_e = 18.7571; - double pycode_n_mach_e = 10; + int pycode_n_mach_e = 19; - EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); - EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); + EXPECT_NEAR(stage.n_machines(), pycode_n_mach_e, tol_num); + EXPECT_NEAR(stage.product_assay(), pycode_product_assay_s, tol_assay); } } // namespace enrichfunctiontests From c0d98089d7b27d54fb2028fb322bb3c11f8c78bf Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 17 Oct 2019 12:00:33 -0500 Subject: [PATCH 036/116] Making centrifuge variable public The cascade object references a stage's centrifuge to change its variables. --- src/StageConfig.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/StageConfig.h b/src/StageConfig.h index 4a0a954..f6b225e 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -15,8 +15,6 @@ class StageConfig { // Compute the cut to ensure alpha = beta (from dU) void CutForIdealStg(); - // Configuration of all the centrifuges in the stage - CentrifugeConfig centrifuge; // Precision used for the cut calculation defautl 1e-8 double precision_ = 1e-8; @@ -70,6 +68,10 @@ class StageConfig { // Return the minimum number of centrifuges required to meet the feed flow void MachinesNeededPerStage(); + + // Configuration of all the centrifuges in the stage + // Default centrifuge initialized + CentrifugeConfig centrifuge; // Setter methods void precision(double p) {precision_ = p;} From 6de7db0b84f5a167d86278540dfe726acf6ee3ec Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 18 Oct 2019 09:30:29 -0500 Subject: [PATCH 037/116] Updating calls to StageConfig w/ Getters/Setters --- src/CascadeConfig.cc | 82 +++++++++++++++++++------------------- src/CascadeConfig.h | 14 +++---- src/CascadeConfig_tests.cc | 6 +-- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 9ae97db..53256c1 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -53,8 +53,8 @@ void CascadeConfig::CalcFeedFlows() { int n_stages = n_enrich + n_strip; int max_stages = n_stages; if (n_stages > max_stages) { - std::cout << "To many stages in the can't calculated the " - "thoerritical flows..." + std::cout << "Too many stages in the cascade." + "Can't calculate the theoretical flows..." << std::endl; exit(1); } @@ -76,7 +76,7 @@ void CascadeConfig::CalcFeedFlows() { for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { flow_eqns[fill_idx][row_idx] = 0; } - // Required do to the artificial 'Max Stages' defn. Only calculate + // Required to do the artificial 'Max Stages' defn. Only calculate // non-zero matrix elements where stages really exist. if (row_idx < n_stages) { int stg_i = row_idx - n_strip; @@ -85,13 +85,13 @@ void CascadeConfig::CalcFeedFlows() { if (row_idx != 0) { std::map::iterator it = stgs_config.find(stg_i - 1); if (it != stgs_config.end()) { - flow_eqns[col_idx - 1][row_idx] = it->second.cut; + flow_eqns[col_idx - 1][row_idx] = it->second.cut(); } } if (row_idx != n_stages - 1) { std::map::iterator it = stgs_config.find(stg_i + 1); if (it != stgs_config.end()) { - flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut); + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut()); } } // Add the external feed for the cascade @@ -120,7 +120,7 @@ void CascadeConfig::CalcFeedFlows() { int i = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { - it->second.feed_flow = flows[0][i]; + it->second.feed_flow(flows[0][i]); i++; } } @@ -133,17 +133,17 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, // Initialisation of Feeding stage (I == 0) StageConfig stg; - stg.alpha = -1; - stg.DU = -1; + stg.alpha(-1); + stg.DU(-1); stg.centrifuge = centrifuge; stg.BuildIdealStg(f_assay, precision); int stg_i = 0; ideal_stgs[stg_i] = stg; - double ref_alpha = ideal_stgs[0].alpha; - double ref_du = ideal_stgs[0].DU; + double ref_alpha = ideal_stgs[0].alpha(); + double ref_du = ideal_stgs[0].DU(); // Calculate number of enriching stages - while (stg.product_assay < product_assay) { - stg.BuildIdealStg(stg.product_assay, precision); + while (stg.product_assay() < product_assay) { + stg.BuildIdealStg(); stg_i++; ideal_stgs.insert(std::make_pair(stg_i, stg)); } @@ -152,8 +152,9 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg_i = 0; stg = ideal_stgs[stg_i]; // Calculate number of stripping stages - while (stg.tail_assay > waste_assay) { - stg.BuildIdealStg(stg.tail_assay, precision); + while (stg.tail_assay() > waste_assay) { + stg.product_assay(stg.tail_assay()) + stg.BuildIdealStg(); stg_i--; ideal_stgs.insert(std::make_pair(stg_i, stg)); } @@ -172,14 +173,15 @@ void CascadeConfig::PopulateStages() { std::cout << "Bad Stage number" << std::endl; exit(1); } - double n_mach_exact = it->second.MachinesPerStage(); + it->second.MachinesNeededPerStage(); + double n_mach_exact = it->second.n_machines(); // unless the ideal number of machines is Very close to an integer value, // round up to next integer to preserve steady-state flow balance int n_mach = (int)n_mach_exact; if (std::abs(n_mach_exact - n_mach) > machine_tol) { n_mach = int(n_mach_exact) + 1; } - it->second.n_machines = n_mach; + it->second.n_machines(n_mach); } } @@ -187,7 +189,7 @@ int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { - machines += it->second.n_machines; + machines += it->second.n_machines(); } return machines; } @@ -213,29 +215,29 @@ void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { n_machines = machines_needed; } -CascadeConfig CascadeConfig::ModelMissUsedCascade(double f_assay, +CascadeConfig CascadeConfig::ModelMisusedCascade(double f_assay, int modeling_opt, double precision) { - CascadeConfig miss_used_cascade = (*this); - miss_used_cascade.PropagateAssay(f_assay); + CascadeConfig misused_cascade = (*this); + misused_cascade.PropagateAssay(f_assay); switch (modeling_opt) { default: - miss_used_cascade.ComputeAssay(f_assay, precision); + misused_cascade.ComputeAssay(f_assay, precision); break; case 1: - miss_used_cascade.UpdateCut(); - miss_used_cascade.UpdateFlow(); + misused_cascade.UpdateCut(); + misused_cascade.UpdateFlow(); break; } - return miss_used_cascade; + return misused_cascade; } void CascadeConfig::UpdateFlow() { - // recompute the flow according to the new cuts + // recompute the flow according to the new cuts (*this).CalcFeedFlows(); - + double ratio = 1; std::map::iterator it; for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); @@ -243,15 +245,15 @@ void CascadeConfig::UpdateFlow() { std::map::iterator it_real = (*this).stgs_config.find(it->first); double max_stg_flow = - it_real->second.n_machines * it_real->second.centrifuge.feed; - double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + it_real->second.n_machines() * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow() / max_stg_flow; if (ratio < stg_flow_ratio) { ratio = stg_flow_ratio; } } for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { - it->second.feed_flow *= 1. / ratio; + it->second.feed_flow(second.feed_flow() * (1. / ratio)); } (*this).feed_flow *= 1. / ratio; } @@ -267,7 +269,7 @@ void CascadeConfig::UpdateCut() { void CascadeConfig::PropagateAssay(double f_assay) { // Initialiase Feeding stage std::map::iterator it = (*this).stgs_config.find(0); - it->second.feed_assay = f_assay; + it->second.feed_assay(f_assay); it->second.ProductAssay(); it->second.TailAssay(); @@ -280,7 +282,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { it_feed = (*this).stgs_config.find(it->first - 1); if (it->first > 0) { if (it_feed != (*this).stgs_config.end()) { - it->second.feed_assay = it_feed->second.product_assay; + it->second.feed_assay(it_feed->second.product_assay()); } // Update Product and Tail assay from feed assay it->second.ProductAssay(); @@ -295,7 +297,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { it_feed = (*this).stgs_config.find(it->first + 1); if (it->first < 0) { if (it_feed != (*this).stgs_config.end()) { - it->second.feed_assay = it_feed->second.tail_assay; + it->second.feed_assay(it_feed->second.tail_assay()); } // Update Product and Tail assay from feed assay it->second.ProductAssay(); @@ -328,11 +330,11 @@ double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, p_enrichments.stgs_config.find(it->first); if (it2 != p_enrichments.stgs_config.end()) { square_feed_diff += - pow(it->second.feed_assay - it2->second.feed_assay, 2); + pow(it->second.feed_assay() - it2->second.feed_assay(), 2); square_product_diff += - pow(it->second.product_assay - it2->second.product_assay, 2); + pow(it->second.product_assay() - it2->second.product_assay(), 2); square_waste_diff += - pow(it->second.tail_assay - it2->second.tail_assay, 2); + pow(it->second.tail_assay() - it2->second.tail_assay(), 2); } } return square_feed_diff + square_product_diff + square_waste_diff; @@ -364,12 +366,12 @@ std::map CascadeConfig::IterrateEnrichment( up_flow = 0; if (it_down != cascade.stgs_config.end()) { - down_assay = it_down->second.product_assay; - down_flow = it_down->second.feed_flow * it_down->second.cut; + down_assay = it_down->second.product_assay(); + down_flow = it_down->second.feed_flow() * it_down->second.cut(); } if (it_up != cascade.stgs_config.end()) { - up_assay = it_up->second.tail_assay; - up_flow = it_up->second.feed_flow * (1 - it_up->second.cut); + up_assay = it_up->second.tail_assay(); + up_flow = it_up->second.feed_flow() * (1 - it_up->second.cut()); } // Mix the Product and the Tail to have the correct Feed Assay @@ -386,7 +388,7 @@ std::map CascadeConfig::IterrateEnrichment( updated_enrichment.stgs_config.find(i); // Update Stage feed assay - it_new->second.feed_assay = stg_f_assay; + it_new->second.feed_assay(stg_f_assay); // Update Beta values (from feed) -- Alpha & Cut are cte it_new->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index e4bce3e..ae4ec5e 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -29,13 +29,13 @@ class CascadeConfig { // Solve the flow matrix from the stages cuts void CalcFeedFlows(); - // DO something ?! + // Establish machines needed in each stage void PopulateStages(); - - // Scale the Casacde to meet the limitation in max feed or max centrifuges + + // Scale the Cascade to meet the limitation in max feed or max centrifuges void ScaleCascade(double max_feed, int max_centrifuges); - CascadeConfig ModelMissUsedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); + CascadeConfig ModelMisusedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay void PropagateAssay(double f_assay); @@ -57,7 +57,7 @@ class CascadeConfig { // total number of machine in the Cascade int n_machines; // real feed flow (constrained by the cascade design/total number of - // machine/max feed flow + // machine/max feed flow) double feed_flow; //design feed assay @@ -71,8 +71,8 @@ class CascadeConfig { double DeltaEnrichment(CascadeConfig actual_enrichments, CascadeConfig previous_enrichment); - // method computing one iteration, of the algorithm used to get the response - // to non ideal feed assay + // method computing one iteration of the algorithm used to get the response + // to non ideal feed assay std::map IterrateEnrichment(CascadeConfig cascade, double feed_assay); }; diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 32940c0..9d4dc6e 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -65,7 +65,7 @@ TEST(CascadeStage_Test, TestCascade) { double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.ModelMissUsedCascade(feed_assay_mod, 0, 1e-31); + cascade.ModelMisusedCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; @@ -145,7 +145,7 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMissUsedCascade(fa, 0, 1e-17); + cascade = cascade.ModelMisusedCascade(fa, 0, 1e-17); product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * @@ -183,7 +183,7 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMissUsedCascade(fa, 1, 1e-17); + cascade = cascade.ModelMisusedCascade(fa, 1, 1e-17); double alpha_ref = cascade.stgs_config[0].alpha; std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ From d0eb79313d398729172c0535bbf281827515a630 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 28 Oct 2019 14:12:41 -0500 Subject: [PATCH 038/116] Updating BuildIdealStg calls by first updating ProductAssay --- src/CascadeConfig.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 53256c1..2701ad4 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -136,13 +136,16 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg.alpha(-1); stg.DU(-1); stg.centrifuge = centrifuge; - stg.BuildIdealStg(f_assay, precision); + stg.feed_assay(f_assay); + stg.precision(precision); + stg.BuildIdealStg(); int stg_i = 0; ideal_stgs[stg_i] = stg; double ref_alpha = ideal_stgs[0].alpha(); double ref_du = ideal_stgs[0].DU(); // Calculate number of enriching stages while (stg.product_assay() < product_assay) { + stg.feed_assay(stg.product_assay()); stg.BuildIdealStg(); stg_i++; ideal_stgs.insert(std::make_pair(stg_i, stg)); @@ -153,7 +156,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg = ideal_stgs[stg_i]; // Calculate number of stripping stages while (stg.tail_assay() > waste_assay) { - stg.product_assay(stg.tail_assay()) + stg.feed_assay(stg.tail_assay()) stg.BuildIdealStg(); stg_i--; ideal_stgs.insert(std::make_pair(stg_i, stg)); From 8a1854197e47f2c1290a37cbeb979fdf4ddc7f1f Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 29 Oct 2019 14:43:40 -0500 Subject: [PATCH 039/116] Minor grammar changes. --- src/CascadeConfig.cc | 8 ++++---- src/CascadeConfig.h | 4 ++-- src/CascadeConfig_tests.cc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 2701ad4..6a7b7d4 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -256,7 +256,7 @@ void CascadeConfig::UpdateFlow() { } for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { - it->second.feed_flow(second.feed_flow() * (1. / ratio)); + it->second.feed_flow(second.feed_flow() / ratio); } (*this).feed_flow *= 1. / ratio; } @@ -270,7 +270,7 @@ void CascadeConfig::UpdateCut() { } void CascadeConfig::PropagateAssay(double f_assay) { - // Initialiase Feeding stage + // Initialise Feeding stage std::map::iterator it = (*this).stgs_config.find(0); it->second.feed_assay(f_assay); it->second.ProductAssay(); @@ -313,7 +313,7 @@ void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; while (DeltaEnrichment((*this), previous_cascade) > precision) { previous_cascade = (*this); - (*this).stgs_config = IterrateEnrichment((*this), f_assay); + (*this).stgs_config = IterateEnrichment((*this), f_assay); } } @@ -343,7 +343,7 @@ double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::IterrateEnrichment( +std::map CascadeConfig::IterateEnrichment( CascadeConfig cascade, double f_assay) { CascadeConfig updated_enrichment = cascade; diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index ae4ec5e..982d3fa 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -66,14 +66,14 @@ class CascadeConfig { double design_product_assay; //design tail assay double design_tail_assay; - + // Method to check the assays different between 2 cascades double DeltaEnrichment(CascadeConfig actual_enrichments, CascadeConfig previous_enrichment); // method computing one iteration of the algorithm used to get the response // to non ideal feed assay - std::map IterrateEnrichment(CascadeConfig cascade, + std::map IterateEnrichment(CascadeConfig cascade, double feed_assay); }; diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 9d4dc6e..fbd9a0d 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -61,7 +61,7 @@ TEST(CascadeStage_Test, TestCascade) { EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); // Now test assays when cascade is modified away from ideal design - // (cascade optimized for natural uranium feed, now use 20% enriched + // (cascade optimized for natural uranium feed, now use 20% enriched) double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = From e013214f84354c0599655831c3c0ec67e4490fc9 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 30 Oct 2019 15:15:29 -0500 Subject: [PATCH 040/116] Adding Stages functionality to test cases --- src/CascadeConfig.cc | 14 +++++----- src/CascadeConfig.h | 2 +- src/CascadeConfig_tests.cc | 56 +++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 6a7b7d4..7abaa6d 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -218,23 +218,23 @@ void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { n_machines = machines_needed; } -CascadeConfig CascadeConfig::ModelMisusedCascade(double f_assay, +CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, int modeling_opt, double precision) { - CascadeConfig misused_cascade = (*this); - misused_cascade.PropagateAssay(f_assay); + CascadeConfig misuse_cascade = (*this); + misuse_cascade.PropagateAssay(f_assay); switch (modeling_opt) { default: - misused_cascade.ComputeAssay(f_assay, precision); + misuse_cascade.ComputeAssay(f_assay, precision); break; case 1: - misused_cascade.UpdateCut(); - misused_cascade.UpdateFlow(); + misuse_cascade.UpdateCut(); + misuse_cascade.UpdateFlow(); break; } - return misused_cascade; + return misuse_cascade; } void CascadeConfig::UpdateFlow() { diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index 982d3fa..4590299 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -35,7 +35,7 @@ class CascadeConfig { // Scale the Cascade to meet the limitation in max feed or max centrifuges void ScaleCascade(double max_feed, int max_centrifuges); - CascadeConfig ModelMisusedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); + CascadeConfig ModelMisuseCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay void PropagateAssay(double f_assay); diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index fbd9a0d..37dfa21 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -65,12 +65,12 @@ TEST(CascadeStage_Test, TestCascade) { double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.ModelMisusedCascade(feed_assay_mod, 0, 1e-31); + cascade.ModelMisuseCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = - cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; + cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay(); double mod_waste_assay = - cascade_non_ideal.stgs_config[-n_stage_waste].product_assay; + cascade_non_ideal.stgs_config[-n_stage_waste].product_assay(); double pycode_mod_product_assay = 0.8189; EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); @@ -97,9 +97,9 @@ TEST(CascadeStage_Test, TestCascadeDesign) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); for (int i = 0; i < pycode_flows.size(); i++) { - EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow, + EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow(), pycode_flows[i], tol_num); - int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines; + int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines(); EXPECT_EQ(nmach, pycode_machines[i]); } @@ -129,12 +129,12 @@ TEST(CascadeStage_Test, TestUpdateAssay) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); double product_assay = - cascade.stgs_config[cascade.n_enrich - 1].product_assay; - double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); double feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); @@ -145,13 +145,13 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMisusedCascade(fa, 0, 1e-17); - product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; - tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade = cascade.ModelMisuseCascade(fa, 0, 1e-17); + product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); tail_from_assay = product_flow * (product_assay - fa) / (fa - tail_assay); @@ -167,12 +167,12 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); double product_assay = - cascade.stgs_config[cascade.n_enrich - 1].product_assay; - double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); double feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); @@ -183,12 +183,12 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMisusedCascade(fa, 1, 1e-17); - double alpha_ref = cascade.stgs_config[0].alpha; + cascade = cascade.ModelMisuseCascade(fa, 1, 1e-17); + double alpha_ref = cascade.stgs_config[0].alpha(); std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ - EXPECT_EQ(alpha_ref, it->second.alpha); - EXPECT_EQ(alpha_ref, it->second.beta); + EXPECT_EQ(alpha_ref, it->second.alpha()); + EXPECT_EQ(alpha_ref, it->second.beta()); } } From 4f0751851365ade271cca739862578665e242d99 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 30 Oct 2019 15:21:22 -0500 Subject: [PATCH 041/116] Remove unnecessary comment --- src/StageConfig.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/StageConfig.h b/src/StageConfig.h index f6b225e..3e64b39 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -8,7 +8,6 @@ namespace mbmore { class CascadeConfig; class StageConfig { - //friend CascadeConfig; private: From 6b1331b41ce25ce65c7012799d34d0fb34570317 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 4 Nov 2019 15:20:27 -0600 Subject: [PATCH 042/116] Added tolerance input to MachinesNeededPerStage() --- src/StageConfig.cc | 11 +++++++++-- src/StageConfig.h | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 2eecd0e..c543f31 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -136,13 +136,20 @@ void StageConfig::BuildIdealStg() { TailAssay(); } -void StageConfig::MachinesNeededPerStage() { +void StageConfig::MachinesNeededPerStage(double tolerance) { // n_machines: the denominator should be equal to the // centrifuge feed flow (centrifuge.feed). // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 double cfeed_flow = (2 * DU_ / centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); - n_machines_ = std::ceil(feed_flow_ / cfeed_flow); + double n_exact = feed_flow_ / cfeed_flow; + + // Adds a machine if fractional amount is needed + n_machines_ = int(n_exact); + if (std::abs(n_exact - n_machines_) > tolerance) { + n_machines_ = int(n_exact) + 1; + } + } } // namespace mbmore diff --git a/src/StageConfig.h b/src/StageConfig.h index 3e64b39..b5f9759 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -66,8 +66,8 @@ class StageConfig { void TailAssay(); // Return the minimum number of centrifuges required to meet the feed flow - void MachinesNeededPerStage(); - + void MachinesNeededPerStage(double tolerance = 0.01); + // Configuration of all the centrifuges in the stage // Default centrifuge initialized CentrifugeConfig centrifuge; From 13168eb5775c8173e8ba076796659be1caa19dcc Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 043/116] initial import --- src/CMakeLists.txt | 3 + src/CascadeConfig.cc | 384 +++++++++++++++++++++++++++++++++++++ src/CascadeConfig.h | 76 ++++++++ src/CascadeConfig_tests.cc | 196 +++++++++++++++++++ src/CascadeEnrich_tests.h | 1 + 5 files changed, 660 insertions(+) create mode 100644 src/CascadeConfig.cc create mode 100644 src/CascadeConfig.h create mode 100644 src/CascadeConfig_tests.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ae6747..b8e3464 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,8 +3,11 @@ USE_CYCLUS("mbmore" "mytest") USE_CYCLUS("mbmore" "behavior_functions") USE_CYCLUS("mbmore" "RandomEnrich") + USE_CYCLUS("mbmore" "CentrifugeConfig") USE_CYCLUS("mbmore" "StageConfig") +USE_CYCLUS("mbmore" "CascadeConfig") + USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") USE_CYCLUS("mbmore" "InteractRegion") diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc new file mode 100644 index 0000000..c5d02e6 --- /dev/null +++ b/src/CascadeConfig.cc @@ -0,0 +1,384 @@ +// Implements the CascadeEnrich class +#include "CascadeConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbmore { + +CascadeConfig::CascadeConfig() + : n_enrich(0), + n_strip(0), + n_machines(0), + feed_flow(0), + feed_assay(0), + design_product_assay(0), + design_tail_assay(0) {} + +CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, + double p_assay, double t_assay, + double max_feed_flow, int max_centrifuge, + double precision) { + centrifuge = centrifuge_; + feed_assay = f_assay; + design_product_assay = p_assay; + design_tail_assay = t_assay; + + feed_flow = max_feed_flow; + n_machines = max_centrifuge; + BuildIdealCascade(f_assay, p_assay, t_assay, precision); + DesignCascade(max_feed_flow, max_centrifuge); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate steady-state flow rates into each stage +// Linear system of equations in form AX = B, where A is nxn square matrix +// of linear equations for the flow rates of each stage and B are the external +// feeds for the stage. External feed is zero for all stages accept cascade +// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] +// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html +// +void CascadeConfig::CalcFeedFlows() { + // This is the Max # of stages in It cannot be passed in due to + // how memory is allocated and so must be hardcoded. It's been chosen + // to be much larger than it should ever need to be + + // total number of stages + int n_stages = n_enrich + n_strip; + int max_stages = n_stages; + if (n_stages > max_stages) { + std::cout << "To many stages in the can't calculated the " + "thoerritical flows..." + << std::endl; + exit(1); + } + + // Build Array with pointers + double flow_eqns[max_stages][max_stages]; + double flows[1][max_stages]; + + // build matrix of equations in this pattern + // [[ -1, 1-cut, 0, 0, 0] [[0] + // [cut, -1, 1-cut, 0, 0] [0] + // [ 0, cut, -1, 1-cut, 0] * X = [-1*feed] + // [ 0, 0, cut, -1, 1-cut] [0] + // [ 0, 0, 0, cut, -1]] [0]] + // + for (int row_idx = 0; row_idx < max_stages; row_idx++) { + // fill the array with zeros, then update individual elements as nonzero + flows[0][row_idx] = 0; + for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { + flow_eqns[fill_idx][row_idx] = 0; + } + // Required do to the artificial 'Max Stages' defn. Only calculate + // non-zero matrix elements where stages really exist. + if (row_idx < n_stages) { + int stg_i = row_idx - n_strip; + int col_idx = n_strip + stg_i; + flow_eqns[col_idx][row_idx] = -1.; + if (row_idx != 0) { + std::map::iterator it = stgs_config.find(stg_i - 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx - 1][row_idx] = it->second.cut; + } + } + if (row_idx != n_stages - 1) { + std::map::iterator it = stgs_config.find(stg_i + 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut); + } + } + // Add the external feed for the cascade + if (stg_i == 0) { + flows[0][row_idx] = -1. * feed_flow; + } + } + } + + // LAPACK solver variables + int nrhs = 1; // 1 column solution + int lda = max_stages; // must be >= MAX(1,N) + int ldb = max_stages; // must be >= MAX(1,N) + int ipiv[max_stages]; + int info; + + // Solve the linear system + dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, + &info); + + // Check for success + if (info != 0) { + std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; + } + + int i = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + it->second.feed_flow = flows[0][i]; + i++; + } +} + +void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, + double waste_assay, double precision) { + std::map ideal_stgs; + int ideal_enrich_stage = 0; + int ideal_strip_stage = 0; + + // Initialisation of Feeding stage (I == 0) + StageConfig stg; + stg.alpha = -1; + stg.DU = -1; + stg.centrifuge = centrifuge; + stg.BuildIdealStg(f_assay, precision); + int stg_i = 0; + ideal_stgs[stg_i] = stg; + double ref_alpha = ideal_stgs[0].alpha; + double ref_du = ideal_stgs[0].DU; + // Calculate number of enriching stages + while (stg.product_assay < product_assay) { + stg.BuildIdealStg(stg.product_assay, precision); + stg_i++; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_enrich = stg_i + 1; + // reset + stg_i = 0; + stg = ideal_stgs[stg_i]; + // Calculate number of stripping stages + while (stg.tail_assay > waste_assay) { + stg.BuildIdealStg(stg.tail_assay, precision); + stg_i--; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_strip = -stg_i; + stgs_config = ideal_stgs; +} + + +void CascadeConfig::CalcStageFeatures() { + double machine_tol = 0.01; + int n_stages = n_enrich + n_strip; + + for (int i = 0; i < n_stages; i++) { + int curr_stage = i - n_strip; + std::map::iterator it = stgs_config.find(curr_stage); + if (it == stgs_config.end()) { + std::cout << "Bad Stage number" << std::endl; + exit(1); + } + double n_mach_exact = it->second.MachinesPerStage(); + // unless the ideal number of machines is Very close to an integer value, + // round up to next integer to preserve steady-state flow balance + int n_mach = (int)n_mach_exact; + if (std::abs(n_mach_exact - n_mach) > machine_tol) { + n_mach = int(n_mach_exact) + 1; + } + it->second.n_machines = n_mach; + } +} + + +int CascadeConfig::FindTotalMachines() { + int machines = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + machines += it->second.n_machines; + } + return machines; +} + +void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { + // Determine the ideal steady-state feed flows for this cascade design given + // the maximum potential design feed rate + feed_flow = max_feed; + CalcFeedFlows(); + CalcStageFeatures(); + + // Do design parameters require more centrifuges than what is available? + int machines_needed = FindTotalMachines(); + double max_feed_from_machine = max_feed; + while (machines_needed > max_centrifuges) { + double scaling_ratio = (double)machines_needed / (double)max_centrifuges; + max_feed_from_machine = max_feed_from_machine / scaling_ratio; + feed_flow = max_feed_from_machine; + CalcFeedFlows(); + CalcStageFeatures(); + machines_needed = FindTotalMachines(); + } + n_machines = machines_needed; +} + +CascadeConfig CascadeConfig::Compute_Assay(double f_assay, double precision, + bool u_cut) { + CascadeConfig actual_cascade = (*this); + + // Initialiase Feeding stage + std::map::iterator it = actual_cascade.stgs_config.find(0); + it->second.feed_assay = f_assay; + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + + // Propagate initialisation to all stages + for (int i = 0; i < actual_cascade.n_enrich; i++){ + it = actual_cascade.stgs_config.find(i); + std::map::iterator it_feed; + + // Enrich stage -> feed = Product from Previous Stage + it_feed = actual_cascade.stgs_config.find(it->first - 1); + if (it->first > 0 && it_feed != actual_cascade.stgs_config.end()) { + it->second.feed_assay = it_feed->second.product_assay; + } + + // Update Product and Tail assay from feed assay + if (it->first != 0) { + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + for (int i = 1; i <= actual_cascade.n_strip; i++){ + it = actual_cascade.stgs_config.find(-i); + std::map::iterator it_feed; + + // Striping stage -> feed = tails from Next Stage + it_feed = actual_cascade.stgs_config.find(it->first + 1); + if (it->first < 0 && it_feed != actual_cascade.stgs_config.end()) { + it->second.feed_assay = it_feed->second.tail_assay; + } + + // Update Product and Tail assay from feed assay + if (it->first != 0) { + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + if(u_cut){ + actual_cascade.CalcFeedFlows(); + double ratio = 1; + for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ + std::map::iterator it_real = (*this).stgs_config.find(it->first); + double max_stg_flow = it_real->second.n_machines *it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + if (ratio < stg_flow_ratio){ + ratio = stg_flow_ratio; + } + } + for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ + it->second.feed_flow *= 1./ratio; + } + actual_cascade.feed_flow *= 1./ratio; + return actual_cascade; + } + // Looping to get the equilibrium + CascadeConfig previous_cascade; + while (Diff_enrichment(actual_cascade, previous_cascade) > precision) { + previous_cascade = actual_cascade; + actual_cascade.stgs_config = Update_enrichment(actual_cascade, f_assay, u_cut); + } + return actual_cascade; +} + +double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, + CascadeConfig p_enrichments) { + if (p_enrichments.n_enrich == 0) { + return 100.; + } + double square_feed_diff = 0; + double square_product_diff = 0; + double square_waste_diff = 0; + std::map::iterator it; + for (it = a_enrichments.stgs_config.begin(); + it != a_enrichments.stgs_config.end(); it++) { + int i = it->first; + std::map::iterator it2 = + p_enrichments.stgs_config.find(it->first); + if (it2 != p_enrichments.stgs_config.end()) { + square_feed_diff += + pow(it->second.feed_assay - it2->second.feed_assay, 2); + square_product_diff += + pow(it->second.product_assay - it2->second.product_assay, 2); + square_waste_diff += + pow(it->second.tail_assay - it2->second.tail_assay, 2); + } + } + return square_feed_diff + square_product_diff + square_waste_diff; +} + +std::map CascadeConfig::Update_enrichment( + CascadeConfig cascade, double f_assay, bool u_cut) { + CascadeConfig updated_enrichment = cascade; + + // mixing variables + double down_assay = 0; + double up_assay = 0; + double down_flow = 0; + double up_flow = 0; + double stg_feed_flow = 0; + std::map::iterator it; + + // Get the Flow and Assay quantity + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); + it++) { + int i = it->first; + std::map::iterator it_up = + cascade.stgs_config.find(i + 1); + std::map::iterator it_down = + cascade.stgs_config.find(i - 1); + down_assay = 0; + up_assay = 0; + down_flow = 0; + up_flow = 0; + + if (it_down != cascade.stgs_config.end()) { + down_assay = it_down->second.product_assay; + down_flow = it_down->second.feed_flow * it_down->second.cut; + } + if (it_up != cascade.stgs_config.end()) { + up_assay = it_up->second.tail_assay; + up_flow = it_up->second.feed_flow * (1 - it_up->second.cut); + } + + // Mix the Product and the Tail to have the correct Feed Assay + double stg_f_assay = + (down_assay * down_flow + up_assay * up_flow) / (down_flow + up_flow); + if (i == 0) { // add Feed flow in the entry stage + stg_f_assay = (down_assay * down_flow + up_assay * up_flow + + f_assay * cascade.feed_flow) / + (down_flow + up_flow + cascade.feed_flow); + stg_feed_flow = down_flow + up_flow + cascade.feed_flow; + } + + std::map::iterator it_new = + updated_enrichment.stgs_config.find(i); + + // Update Stage feed assay + it_new->second.feed_assay = stg_f_assay; + // Update Beta values (from feed) -- Alpha & Cut are cte + if(u_cut){ + it_new->second.CutByAlphaBeta(); + } else{ + it_new->second.BetaByAlphaAndCut(); + } + // Recompute Product Assay and Tail Assay + it_new->second.ProductAssay(); + it_new->second.TailAssay(); + } + + return updated_enrichment.stgs_config; +} +} // namespace mbmore diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h new file mode 100644 index 0000000..cb2735b --- /dev/null +++ b/src/CascadeConfig.h @@ -0,0 +1,76 @@ +#ifndef MBMORE_SRC_CASCADE_H_ +#define MBMORE_SRC_CASCADE_H_ + +#include +#include + +#include "CentrifugeConfig.h" +#include "StageConfig.h" + +namespace mbmore { +// LAPACK solver for system of linear equations +extern "C" { +void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipivot, double *b, + int *ldb, int *info); +} + +class CascadeConfig { + public: + CascadeConfig() ; + CascadeConfig(CentrifugeConfig centrifuge, double f_assay, double p_assay, + double t_assay, double max_feed_flow, int max_centrifuge, + double precision = 1e-8); + // Build a full cascade such as all stage follow alpha = beta = const. Get + // alpha/beta value from feeding stage. From the design feed/product/assay + void BuildIdealCascade(double f_assay, double p_assay, double w_assay, + double precision = 1e-8); + // Get the total number of machine in the Cascade + int FindTotalMachines(); + + // Solve the flow matrix from the stages cuts + void CalcFeedFlows(); + // DO something ?! + void CalcStageFeatures(); + // Scale the Casacde to meet the limitation in max feed or max centrifuges + void DesignCascade(double max_feed, int max_centrifuges); + + // Compute the response of the cascade to a non ideal feed assay + CascadeConfig Compute_Assay(double feed_assay, double precision, bool u_cut = false); + + double FeedFlow() { return feed_flow; } + // Configuration of the centrifuges in the stages + CentrifugeConfig centrifuge; + // Map of all the stage configuration + std::map stgs_config; + // number of enrich stages + int n_enrich; + // number of stripping stages + int n_strip; + + private: + // total number of machine in the Cascade + int n_machines; + // real feed flow (constrained by the cascade design/total number of + // machine/max feed flow + double feed_flow; + + //design feed assay + double feed_assay; + //design product assay + double design_product_assay; + //design tail assay + double design_tail_assay; + + // Method to check the assays different between 2 cascades + double Diff_enrichment(CascadeConfig actual_enrichments, + CascadeConfig previous_enrichement); + + // method computing one iteration, of the algorithm used to get the response + // to non ideal feed assay + std::map Update_enrichment(CascadeConfig cascade, + double feed_assay, bool u_cut = false); +}; + +} // namespace mbmore + +#endif // MBMORE_SRC_CASCADE_H_ diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc new file mode 100644 index 0000000..4a64971 --- /dev/null +++ b/src/CascadeConfig_tests.cc @@ -0,0 +1,196 @@ +#include + +#include "CascadeConfig.h" + +#include "agent_tests.h" +#include "context.h" +#include "facility_tests.h" + +namespace mbmore { + +// Benchmarked against mbmore_enrich_compare.ipynb +// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +namespace cascadeconfig_tests { +// Fixed for a cascade separating out U235 from U238 in UF6 gas +const double M = 0.352; // kg/mol UF6 +const double dM = 0.003; // kg/mol U238 - U235 +const double x = 1000; // Pressure ratio (Glaser) + +// General cascade assumptions +const double flow_internal = 2.0; +const double eff = 1.0; +const double cut = 0.5; + +// Centrifuge params used in Python test code +// (based on Glaser SGS 2009 paper) +const double v_a = 485; // m/s +const double height = 0.5; // meters +const double diameter = 0.15; // meters +const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec +const double temp = 320.0; // Kelvin + +// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +const double feed_assay = 0.0071; +const double product_assay = 0.035; +const double waste_assay = 0.001; +const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, + flow_internal); +// del U=7.0323281e-08 alpha=1.16321 +double delU = centrifuge.ComputeDeltaU(cut); + +const double tol_assay = 1e-5; +const double tol_qty = 1e-6; +const double tol_num = 1e-2; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Ideal cascade design, and then using away from ideal design + +TEST(CascadeStage_Test, TestCascade) { + CascadeConfig cascade; + cascade.centrifuge = centrifuge; + cascade.BuildIdealCascade(feed_assay, product_assay, waste_assay, 1e-8); + int pycode_n_enrich_stage = 11; + int pycode_n_strip_stage = 12; + // integer + int n_stage_enrich = cascade.n_enrich; + int n_stage_waste = cascade.n_strip; + + EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); + EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); + + // Now test assays when cascade is modified away from ideal design + // (cascade optimized for natural uranium feed, now use 20% enriched + double feed_assay_mod = 0.20; + cascade.DesignCascade(feed_c, 1000000); + CascadeConfig cascade_non_ideal = + cascade.Compute_Assay(feed_assay_mod, 1e-31); + + double mod_product_assay = + cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; + double mod_waste_assay = + cascade_non_ideal.stgs_config[-n_stage_waste].product_assay; + + double pycode_mod_product_assay = 0.8189; + EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); + + double pycode_mod_waste_assay = 0.11198; + EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// tests the steady state flow rates for a cascade +// +TEST(CascadeStage_Test, TestCascadeDesign) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + std::vector pycode_flows = { + 0.00030693, 0.00061387, 0.0009208, 0.00122774, 0.00153467, + 0.00127889, 0.00102311, 0.00076734, 0.00051156, 0.00025578}; + + std::vector pycode_machines = {80, 149, 210, 264, 312, + 241, 180, 127, 80, 38}; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); + + for (int i = 0; i < pycode_flows.size(); i++) { + EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow, + pycode_flows[i], tol_num); + int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines; + EXPECT_EQ(nmach, pycode_machines[i]); + } + + // not enough machines + int max_centrifuges = 80; + cascade.DesignCascade(feed_c, max_centrifuges); + int py_tot_mach = 80; + double py_opt_feed = 1.30116169899e-05; + + EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + + // more machines than requested capacity + max_centrifuges = 1000; + cascade.DesignCascade(feed_c, max_centrifuges); + py_tot_mach = 999; + py_opt_feed = 0.0001667; + + EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); +} + +TEST(CascadeStage_Test, TestUpdateAssay) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); + double product_assay = + cascade.stgs_config[cascade.n_enrich - 1].product_assay; + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + + double feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + double tail_from_assay = + product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); + + fa = 0.2; + cascade = cascade.Compute_Assay(fa, 1e-17); + product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; + tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + tail_from_assay = product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); +} + +TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); + double product_assay = + cascade.stgs_config[cascade.n_enrich - 1].product_assay; + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + + double feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + double tail_from_assay = + product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); + + fa = 0.2; + cascade = cascade.Compute_Assay(fa, 1e-17, true); + double alpha_ref = cascade.stgs_config[0].alpha; + std::map::iterator it; + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ + EXPECT_EQ(alpha_ref, it->second.alpha); + EXPECT_EQ(alpha_ref, it->second.beta); + } +} + +} // namespace cascadeconfig_tests +} // namespace mbmore diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From ef75e6793311e4d72de56141b64ed652d07fbb57 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 17:28:59 -0500 Subject: [PATCH 044/116] some reshape on the cascade config --- src/CascadeConfig.cc | 147 ++++++++++++++++++++----------------- src/CascadeConfig.h | 20 +++-- src/CascadeConfig_tests.cc | 12 +-- 3 files changed, 100 insertions(+), 79 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index c5d02e6..9ae97db 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -33,7 +33,7 @@ CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, feed_flow = max_feed_flow; n_machines = max_centrifuge; BuildIdealCascade(f_assay, p_assay, t_assay, precision); - DesignCascade(max_feed_flow, max_centrifuge); + ScaleCascade(max_feed_flow, max_centrifuge); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -161,8 +161,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stgs_config = ideal_stgs; } - -void CascadeConfig::CalcStageFeatures() { +void CascadeConfig::PopulateStages() { double machine_tol = 0.01; int n_stages = n_enrich + n_strip; @@ -184,7 +183,6 @@ void CascadeConfig::CalcStageFeatures() { } } - int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; @@ -194,12 +192,12 @@ int CascadeConfig::FindTotalMachines() { return machines; } -void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { +void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { // Determine the ideal steady-state feed flows for this cascade design given // the maximum potential design feed rate feed_flow = max_feed; CalcFeedFlows(); - CalcStageFeatures(); + PopulateStages(); // Do design parameters require more centrifuges than what is available? int machines_needed = FindTotalMachines(); @@ -209,91 +207,112 @@ void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { max_feed_from_machine = max_feed_from_machine / scaling_ratio; feed_flow = max_feed_from_machine; CalcFeedFlows(); - CalcStageFeatures(); + PopulateStages(); machines_needed = FindTotalMachines(); } n_machines = machines_needed; } -CascadeConfig CascadeConfig::Compute_Assay(double f_assay, double precision, - bool u_cut) { - CascadeConfig actual_cascade = (*this); +CascadeConfig CascadeConfig::ModelMissUsedCascade(double f_assay, + int modeling_opt, + double precision) { + CascadeConfig miss_used_cascade = (*this); + miss_used_cascade.PropagateAssay(f_assay); + + switch (modeling_opt) { + default: + miss_used_cascade.ComputeAssay(f_assay, precision); + break; + + case 1: + miss_used_cascade.UpdateCut(); + miss_used_cascade.UpdateFlow(); + break; + } + return miss_used_cascade; +} - // Initialiase Feeding stage - std::map::iterator it = actual_cascade.stgs_config.find(0); - it->second.feed_assay = f_assay; - if (u_cut) { +void CascadeConfig::UpdateFlow() { + // recompute the flow according to the new cuts + (*this).CalcFeedFlows(); + + double ratio = 1; + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + std::map::iterator it_real = + (*this).stgs_config.find(it->first); + double max_stg_flow = + it_real->second.n_machines * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + if (ratio < stg_flow_ratio) { + ratio = stg_flow_ratio; + } + } + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + it->second.feed_flow *= 1. / ratio; + } + (*this).feed_flow *= 1. / ratio; +} + +void CascadeConfig::UpdateCut() { + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { it->second.CutByAlphaBeta(); } +} + +void CascadeConfig::PropagateAssay(double f_assay) { + // Initialiase Feeding stage + std::map::iterator it = (*this).stgs_config.find(0); + it->second.feed_assay = f_assay; it->second.ProductAssay(); it->second.TailAssay(); // Propagate initialisation to all stages - for (int i = 0; i < actual_cascade.n_enrich; i++){ - it = actual_cascade.stgs_config.find(i); + for (int i = 0; i < (*this).n_enrich; i++) { + it = (*this).stgs_config.find(i); std::map::iterator it_feed; // Enrich stage -> feed = Product from Previous Stage - it_feed = actual_cascade.stgs_config.find(it->first - 1); - if (it->first > 0 && it_feed != actual_cascade.stgs_config.end()) { - it->second.feed_assay = it_feed->second.product_assay; - } - - // Update Product and Tail assay from feed assay - if (it->first != 0) { - if (u_cut) { - it->second.CutByAlphaBeta(); + it_feed = (*this).stgs_config.find(it->first - 1); + if (it->first > 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay = it_feed->second.product_assay; } + // Update Product and Tail assay from feed assay it->second.ProductAssay(); it->second.TailAssay(); } } - for (int i = 1; i <= actual_cascade.n_strip; i++){ - it = actual_cascade.stgs_config.find(-i); + for (int i = 1; i <= (*this).n_strip; i++) { + it = (*this).stgs_config.find(-i); std::map::iterator it_feed; // Striping stage -> feed = tails from Next Stage - it_feed = actual_cascade.stgs_config.find(it->first + 1); - if (it->first < 0 && it_feed != actual_cascade.stgs_config.end()) { - it->second.feed_assay = it_feed->second.tail_assay; - } - - // Update Product and Tail assay from feed assay - if (it->first != 0) { - if (u_cut) { - it->second.CutByAlphaBeta(); + it_feed = (*this).stgs_config.find(it->first + 1); + if (it->first < 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay = it_feed->second.tail_assay; } + // Update Product and Tail assay from feed assay it->second.ProductAssay(); it->second.TailAssay(); } } - if(u_cut){ - actual_cascade.CalcFeedFlows(); - double ratio = 1; - for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ - std::map::iterator it_real = (*this).stgs_config.find(it->first); - double max_stg_flow = it_real->second.n_machines *it_real->second.centrifuge.feed; - double stg_flow_ratio = it->second.feed_flow / max_stg_flow; - if (ratio < stg_flow_ratio){ - ratio = stg_flow_ratio; - } - } - for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ - it->second.feed_flow *= 1./ratio; - } - actual_cascade.feed_flow *= 1./ratio; - return actual_cascade; - } - // Looping to get the equilibrium +} + +void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (Diff_enrichment(actual_cascade, previous_cascade) > precision) { - previous_cascade = actual_cascade; - actual_cascade.stgs_config = Update_enrichment(actual_cascade, f_assay, u_cut); + while (DeltaEnrichment((*this), previous_cascade) > precision) { + previous_cascade = (*this); + (*this).stgs_config = IterrateEnrichment((*this), f_assay); } - return actual_cascade; } -double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, +double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, CascadeConfig p_enrichments) { if (p_enrichments.n_enrich == 0) { return 100.; @@ -319,8 +338,8 @@ double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::Update_enrichment( - CascadeConfig cascade, double f_assay, bool u_cut) { +std::map CascadeConfig::IterrateEnrichment( + CascadeConfig cascade, double f_assay) { CascadeConfig updated_enrichment = cascade; // mixing variables @@ -369,11 +388,7 @@ std::map CascadeConfig::Update_enrichment( // Update Stage feed assay it_new->second.feed_assay = stg_f_assay; // Update Beta values (from feed) -- Alpha & Cut are cte - if(u_cut){ - it_new->second.CutByAlphaBeta(); - } else{ - it_new->second.BetaByAlphaAndCut(); - } + it_new->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay it_new->second.ProductAssay(); it_new->second.TailAssay(); diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index cb2735b..e4bce3e 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -30,12 +30,18 @@ class CascadeConfig { // Solve the flow matrix from the stages cuts void CalcFeedFlows(); // DO something ?! - void CalcStageFeatures(); + void PopulateStages(); + // Scale the Casacde to meet the limitation in max feed or max centrifuges - void DesignCascade(double max_feed, int max_centrifuges); + void ScaleCascade(double max_feed, int max_centrifuges); + + CascadeConfig ModelMissUsedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay - CascadeConfig Compute_Assay(double feed_assay, double precision, bool u_cut = false); + void PropagateAssay(double f_assay); + void ComputeAssay(double f_assay, double precision = 1e-8); + void UpdateCut(); + void UpdateFlow(); double FeedFlow() { return feed_flow; } // Configuration of the centrifuges in the stages @@ -62,13 +68,13 @@ class CascadeConfig { double design_tail_assay; // Method to check the assays different between 2 cascades - double Diff_enrichment(CascadeConfig actual_enrichments, - CascadeConfig previous_enrichement); + double DeltaEnrichment(CascadeConfig actual_enrichments, + CascadeConfig previous_enrichment); // method computing one iteration, of the algorithm used to get the response // to non ideal feed assay - std::map Update_enrichment(CascadeConfig cascade, - double feed_assay, bool u_cut = false); + std::map IterrateEnrichment(CascadeConfig cascade, + double feed_assay); }; } // namespace mbmore diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 4a64971..32940c0 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -63,9 +63,9 @@ TEST(CascadeStage_Test, TestCascade) { // Now test assays when cascade is modified away from ideal design // (cascade optimized for natural uranium feed, now use 20% enriched double feed_assay_mod = 0.20; - cascade.DesignCascade(feed_c, 1000000); + cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.Compute_Assay(feed_assay_mod, 1e-31); + cascade.ModelMissUsedCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; @@ -105,7 +105,7 @@ TEST(CascadeStage_Test, TestCascadeDesign) { // not enough machines int max_centrifuges = 80; - cascade.DesignCascade(feed_c, max_centrifuges); + cascade.ScaleCascade(feed_c, max_centrifuges); int py_tot_mach = 80; double py_opt_feed = 1.30116169899e-05; @@ -114,7 +114,7 @@ TEST(CascadeStage_Test, TestCascadeDesign) { // more machines than requested capacity max_centrifuges = 1000; - cascade.DesignCascade(feed_c, max_centrifuges); + cascade.ScaleCascade(feed_c, max_centrifuges); py_tot_mach = 999; py_opt_feed = 0.0001667; @@ -145,7 +145,7 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.Compute_Assay(fa, 1e-17); + cascade = cascade.ModelMissUsedCascade(fa, 0, 1e-17); product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * @@ -183,7 +183,7 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.Compute_Assay(fa, 1e-17, true); + cascade = cascade.ModelMissUsedCascade(fa, 1, 1e-17); double alpha_ref = cascade.stgs_config[0].alpha; std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ From aece4c6bd9a32f50abad56772428093da3e18c61 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:19:11 -0500 Subject: [PATCH 045/116] Removing some file not suppose to be there yet --- src/CascadeEnrich_tests.h | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h deleted file mode 100644 index 025911b..0000000 --- a/src/CascadeEnrich_tests.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ -#define MBMORE_SRC_CASCADEENRICH_TESTS_ - -#include - -#include - -#include "test_context.h" -#include "env.h" -#include "exchange_context.h" -#include "material.h" - -#include "CascadeEnrich.h" -#include "CascadeConfig.h" - -namespace mbmore { - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class CascadeEnrichTest : public ::testing::Test { - protected: - cyclus::TestContext tc_; - CascadeEnrich* src_facility; - std::string feed_commod, product_commod, feed_recipe, tails_commod; - cyclus::Composition::Ptr recipe; - TestFacility* trader; - - double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; - - bool order_prefs; - - double reserves; - - virtual void SetUp(); - virtual void TearDown(); - void InitParameters(); - void SetUpSource(); - cyclus::Material::Ptr GetMat(double qty); - /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 - cyclus::Material::Ptr GetReqMat(double qty, double enr); - void DoAddMat(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoRequest(); - cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); - /// @param nreqs the total number of requests - /// @param nvalid the number of requests that are valid - boost::shared_ptr< cyclus::ExchangeContext > - GetContext(int nreqs, int nvalid); -}; - -} // namespace cycamore -#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From 88a8979517fb424d54b952a0b1bc0dca809e6f73 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:14:46 -0500 Subject: [PATCH 046/116] removing methods reimplemented in CascadeConfig --- src/enrich_functions.cc | 122 ---------------------- src/enrich_functions_tests.cc | 187 ---------------------------------- 2 files changed, 309 deletions(-) delete mode 100644 src/enrich_functions_tests.cc diff --git a/src/enrich_functions.cc b/src/enrich_functions.cc index 16c8f31..c0c593b 100644 --- a/src/enrich_functions.cc +++ b/src/enrich_functions.cc @@ -44,38 +44,6 @@ std::pair StagesPerCascade(double alpha, double feed_assay, // Determine number of stages required to reach ideal cascade product assay // (requires integer number of stages, so output may exceed target assay) -std::pair FindNStages(double alpha, double feed_assay, - double product_assay, double waste_assay) { - using std::pair; - - int ideal_enrich_stage = 0; - int ideal_strip_stage = 0; - double stage_feed_assay = feed_assay; - double stage_product_assay = feed_assay; - double stage_waste_assay = feed_assay; // start w/waste of 1st enrich stage - - // Calculate number of enriching stages - while (stage_product_assay < product_assay) { - stage_product_assay = ProductAssayByAlpha(alpha, stage_feed_assay); - if (ideal_enrich_stage == 0) { - stage_waste_assay = WasteAssayByAlpha(alpha, stage_feed_assay); - } - ideal_enrich_stage += 1; - stage_feed_assay = stage_product_assay; - } - // Calculate number of stripping stages - stage_feed_assay = stage_waste_assay; - while (stage_waste_assay > waste_assay) { - stage_waste_assay = WasteAssayByAlpha(alpha, stage_feed_assay); - ideal_strip_stage += 1; - stage_feed_assay = stage_waste_assay; - } - - std::pair stages = - std::make_pair(ideal_enrich_stage, ideal_strip_stage); - return stages; -} - double ProductAssayFromNStages(double alpha, double feed_assay, double enrich_stages) { double A = @@ -135,86 +103,6 @@ double DelUByCascadeConfig(double product_assay, double waste_assay, return U_cascade / feed_assay; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Calculate steady-state flow rates into each cascade stage -// Linear system of equations in form AX = B, where A is nxn square matrix -// of linear equations for the flow rates of each stage and B are the external -// feeds for the stage. External feed is zero for all stages accept cascade -// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] -// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html -// -std::vector CalcFeedFlows(std::pair n_st, double cascade_feed, - double cut) { - // This is the Max # of stages in cascade. It cannot be passed in due to - // how memory is allocated and so must be hardcoded. It's been chosen - // to be much larger than it should ever need to be - int max_stages = 100; - - int n_enrich = n_st.first; - int n_strip = n_st.second; - int n_stages = n_st.first + n_st.second; - - // LAPACK takes the external flow feeds as B, and then returns a modified - // version of the same array now representing the solution flow rates. - - // Build Array with pointers - double flow_eqns[max_stages][max_stages]; - double flows[1][max_stages]; - - // build matrix of equations in this pattern - // [[ -1, 1-cut, 0, 0, 0] [[0] - // [cut, -1, 1-cut, 0, 0] [0] - // [ 0, cut, -1, 1-cut, 0] * X = [-1*cascade_feed] - // [ 0, 0, cut, -1, 1-cut] [0] - // [ 0, 0, 0, cut, -1]] [0]] - // - for (int row_idx = 0; row_idx < max_stages; row_idx++) { - // fill the array with zeros, then update individual elements as nonzero - flows[0][row_idx] = 0; - for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { - flow_eqns[fill_idx][row_idx] = 0; - } - // Required do to the artificial 'Max Stages' defn. Only calculate - // non-zero matrix elements where stages really exist. - if (row_idx < n_stages) { - int i = row_idx - n_strip; - int col_idx = n_strip + i; - flow_eqns[col_idx][row_idx] = -1; - if (col_idx != 0) { - flow_eqns[col_idx - 1][row_idx] = cut; - } - if (col_idx != n_stages - 1) { - flow_eqns[col_idx + 1][row_idx] = (1 - cut); - } - // Add the external feed for the cascade - if (i == 0) { - flows[0][row_idx] = -1 * cascade_feed; - } - } - } - - // LAPACK solver variables - int nrhs = 1; // 1 column solution - int lda = max_stages; // must be >= MAX(1,N) - int ldb = max_stages; // must be >= MAX(1,N) - int ipiv[max_stages]; - int info; - - // Solve the linear system - dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, - &info); - - // Check for success - if (info != 0) { - std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; - } - - std::vector final_flows; - for (int i = 0; i < n_stages; i++) { - final_flows.push_back(flows[0][i]); - } - return final_flows; -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine number of machines in each stage of the cascade, and total // output flow from each stage @@ -279,16 +167,6 @@ std::vector> CalcStageFeatures( return stage_info; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Determine total number of machines in the cascade from machines per stage -int FindTotalMachines(std::vector> stage_info) { - int machines_needed = 0; - std::vector>::const_iterator it; - for (it = stage_info.begin(); it != stage_info.end(); it++) { - machines_needed += it->first; - } - return machines_needed; -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::pair DesignCascade(double design_feed, diff --git a/src/enrich_functions_tests.cc b/src/enrich_functions_tests.cc deleted file mode 100644 index ca2473d..0000000 --- a/src/enrich_functions_tests.cc +++ /dev/null @@ -1,187 +0,0 @@ -#include - -#include "enrich_functions.h" - -#include "agent_tests.h" -#include "context.h" -#include "facility_tests.h" - -namespace mbmore { - - // Benchmarked against mbmore_enrich_compare.ipynb - // https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs - namespace enrichfunctiontests { - // Fixed for a cascade separating out U235 from U238 in UF6 gas - const double M = 0.352; // kg/mol UF6 - const double dM = 0.003; // kg/mol U238 - U235 - const double x = 1000; // Pressure ratio (Glaser) - - // General cascade assumptions - const double flow_internal = 2.0 ; - const double eff = 1.0; - const double cut = 0.5; - - // Centrifuge params used in Python test code - // (based on Glaser SGS 2009 paper) - const double v_a = 485; // m/s - const double height = 0.5; // meters - const double diameter = 0.15; // meters - const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec - const double temp = 320.0 ; //Kelvin - - // Cascade params used in Python test code (Enrichment_Calculations.ipynb) - const double feed_assay = 0.0071; - const double product_assay = 0.035; - const double waste_assay = 0.001; - const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec - const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec - - //del U=7.0323281e-08 alpha=1.16321 - double delU = CalcDelU(v_a, height, diameter, feed_m, temp, cut, eff, - M, dM, x, flow_internal); - - double alpha = AlphaBySwu(delU, feed_m, cut, M); - const double tol_assay = 1e-5; - const double tol_qty = 1e-6; - const double tol_num = 1e-2; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Ideal cascade design, and then using away from ideal design - -TEST(Enrich_Functions_Test, TestCascade) { - double n_machines = MachinesPerCascade(delU, product_assay, - waste_assay, feed_c, product_c); - - double pycode_n_mach = 25990.392; - EXPECT_NEAR(n_machines, pycode_n_mach, tol_num); - - std::pair n_stages = FindNStages(alpha, feed_assay, - product_assay, - waste_assay); - int pycode_n_enrich_stage = 11; - int pycode_n_strip_stage = 13; - - - // int n_stage_enrich = (int) n_stages.first + 1; // Round up to next integer - // int n_stage_waste = (int) n_stages.second + 1; // Round up to next integer - int n_stage_enrich = n_stages.first; - int n_stage_waste = n_stages.second; - - EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); - EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); - - // Now test assays when cascade is modified away from ideal design - // (cascade optimized for natural uranium feed, now use 20% enriched - double feed_assay_mod = 0.20; - - double mod_product_assay = ProductAssayFromNStages(alpha, feed_assay_mod, - n_stage_enrich); - double mod_waste_assay = WasteAssayFromNStages(alpha, feed_assay_mod, - n_stage_waste); - - std::cout << "alpha " << alpha << " feed " << feed_assay_mod << " nstage " << n_stage_enrich << " unrounded stages " << n_stages.first << std::endl; - double pycode_mod_product_assay = 0.60085; - double pycode_mod_waste_assay = 0.0290846; - EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); - EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine the output of the first enrich/strip stage of a cascade - // based on the design params for the cascade - TEST(Enrich_Functions_Test, TestStages) { - double product_assay_s = ProductAssayByAlpha(alpha, feed_assay); - double n_mach_e = MachinesPerStage(alpha, delU, feed_c); - double product_s = ProductPerEnrStage(alpha, feed_assay, - product_assay_s, feed_c); - - double enrich_waste = feed_c - product_s; - double enrich_waste_assay = (feed_c * feed_assay - product_s * - product_assay_s)/enrich_waste; - - double pycode_product_assay_s = 0.0082492; - double pycode_n_mach_e = 53.287; - double pycode_product_s = 0.0001408; - - EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); - EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); - EXPECT_NEAR(product_s, pycode_product_s, tol_qty); - - double n_mach_w = MachinesPerStage(alpha, delU, enrich_waste); - double strip_waste_assay = WasteAssayByAlpha(alpha, enrich_waste_assay); - - // This AVERY EQN doesn't work for some reason - // double strip_waste = WastePerStripStage(alpha, enrich_waste_assay, - // strip_waste_assay, enrich_waste); - - double pycode_n_mach_w = 26.6127; - double pycode_waste_assay_s = 0.005117; - // double pycode_waste_s = 8.60660553717e-05; - - EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); - EXPECT_NEAR(strip_waste_assay, pycode_waste_assay_s, tol_assay); - // EXPECT_NEAR(strip_waste, pycode_waste_s, tol_qty); - - } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// tests the steady state flow rates for a cascade -// -TEST(Enrich_Functions_Test, TestCascadeDesign) { - double fa = 0.10; - double pa = 0.20; - double wa = 0.05; - - std::vector pycode_flows = {0.00030693, 0.00061387, 0.0009208 , - 0.00122774, 0.00153467, 0.00127889, - 0.00102311, 0.00076734, 0.00051156, - 0.00025578}; - - - std::vector pycode_machines={59, 117, 175, 233, 291, 243, 194, - 146, 97, 49}; - - std::pair n_stages = FindNStages(alpha, fa, pa, wa); - std::vector flows = CalcFeedFlows(n_stages, feed_c, cut); - - // if # Machines for the stage is within tol_num of an integer - // then round down. Otherwise round up to the next integer machine to - // preserve steady-state flow calculations. - std::vector> stage_info = - CalcStageFeatures(fa, alpha, delU, cut, n_stages, flows); - - for (int i = 0; i < pycode_flows.size(); i++){ - EXPECT_NEAR(flows[i], pycode_flows[i], tol_num); - int nmach = stage_info[i].first; - EXPECT_EQ(nmach, pycode_machines[i]); - } - - // not enough machines - int max_centrifuges = 80; - std::pair design_params = DesignCascade(feed_c, alpha, delU, - cut, max_centrifuges, - n_stages); - int py_tot_mach = 79; - double py_opt_feed = 1.30116169899e-05; - - EXPECT_EQ(py_tot_mach, design_params.first); - EXPECT_NEAR(py_opt_feed, design_params.second, tol_qty); - - // more machines than requested capacity - max_centrifuges = 1000; - design_params = DesignCascade(feed_c, alpha, delU, - cut, max_centrifuges, - n_stages); - py_tot_mach = 986; - py_opt_feed = 0.000172728; - - EXPECT_EQ(py_tot_mach, design_params.first); - EXPECT_NEAR(py_opt_feed, design_params.second, tol_qty); - -} - - - } // namespace enrichfunctiontests -} // namespace mbmore From 284624748f7d0fe48c698161a808e31a72470354 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:20:06 -0500 Subject: [PATCH 047/116] removing methods reimplemented in CascadeConfig --- src/enrich_functions.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/enrich_functions.h b/src/enrich_functions.h index 9916b70..cba6f99 100644 --- a/src/enrich_functions.h +++ b/src/enrich_functions.h @@ -15,11 +15,6 @@ extern "C" { } - // Calculates the number of stages needed in a cascade given the separation - // potential of a single centrifuge and the material assays - std::pair - FindNStages(double alpha, double feed_assay, double product_assay, - double Nwc); // Calculates the product assay after N enriching stages double ProductAssayFromNStages(double alpha, double feed_assay, @@ -68,10 +63,6 @@ extern "C" { double product_flow, double waste_flow, double feed_assay); - // Solves system of linear eqns to determine steady state flow rates - // in each stage of cascade - std::vector CalcFeedFlows(std::pair n_st, - double cascade_feed, double cut); // Determines the number of machines and product in each stage based // on the steady-state flows defined for the cascade. @@ -81,8 +72,6 @@ extern "C" { std::pair n_st, std::vector feed_flow); - // Determine total number of machines in the cascade from machines per stage - int FindTotalMachines(std::vector> stage_info); std::pair DesignCascade( double design_feed, double design_alpha, double design_delU, double cut, From c2d0dbfcdbc5190ee106f1b385f1307897c47a59 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:23:35 -0500 Subject: [PATCH 048/116] readd missing file --- src/CascadeEnrich_tests.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h new file mode 100644 index 0000000..22a650d --- /dev/null +++ b/src/CascadeEnrich_tests.h @@ -0,0 +1,51 @@ +#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ +#define MBMORE_SRC_CASCADEENRICH_TESTS_ + +#include + +#include + +#include "test_context.h" +#include "env.h" +#include "exchange_context.h" +#include "material.h" + +#include "CascadeEnrich.h" + +namespace mbmore { + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class CascadeEnrichTest : public ::testing::Test { + protected: + cyclus::TestContext tc_; + CascadeEnrich* src_facility; + std::string feed_commod, product_commod, feed_recipe, tails_commod; + cyclus::Composition::Ptr recipe; + TestFacility* trader; + + double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; + + bool order_prefs; + + double reserves; + + virtual void SetUp(); + virtual void TearDown(); + void InitParameters(); + void SetUpSource(); + cyclus::Material::Ptr GetMat(double qty); + /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 + cyclus::Material::Ptr GetReqMat(double qty, double enr); + void DoAddMat(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoRequest(); + cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); + /// @param nreqs the total number of requests + /// @param nvalid the number of requests that are valid + boost::shared_ptr< cyclus::ExchangeContext > + GetContext(int nreqs, int nvalid); +}; + +} // namespace cycamore +#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From 3ee262c9e515069d7e247816f5ac2bc435d60f93 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 049/116] initial import --- src/CascadeConfig.cc | 108 ++++++++++++++++--------------------- src/CascadeConfig.h | 18 +++---- src/CascadeConfig_tests.cc | 58 ++++++++++---------- src/CascadeEnrich_tests.h | 1 + 4 files changed, 86 insertions(+), 99 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 9ae97db..64c7815 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -45,19 +45,9 @@ CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, // http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html // void CascadeConfig::CalcFeedFlows() { - // This is the Max # of stages in It cannot be passed in due to - // how memory is allocated and so must be hardcoded. It's been chosen - // to be much larger than it should ever need to be - // total number of stages int n_stages = n_enrich + n_strip; int max_stages = n_stages; - if (n_stages > max_stages) { - std::cout << "To many stages in the can't calculated the " - "thoerritical flows..." - << std::endl; - exit(1); - } // Build Array with pointers double flow_eqns[max_stages][max_stages]; @@ -76,7 +66,7 @@ void CascadeConfig::CalcFeedFlows() { for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { flow_eqns[fill_idx][row_idx] = 0; } - // Required do to the artificial 'Max Stages' defn. Only calculate + // Required to do the artificial 'Max Stages' defn. Only calculate // non-zero matrix elements where stages really exist. if (row_idx < n_stages) { int stg_i = row_idx - n_strip; @@ -85,13 +75,13 @@ void CascadeConfig::CalcFeedFlows() { if (row_idx != 0) { std::map::iterator it = stgs_config.find(stg_i - 1); if (it != stgs_config.end()) { - flow_eqns[col_idx - 1][row_idx] = it->second.cut; + flow_eqns[col_idx - 1][row_idx] = it->second.cut(); } } if (row_idx != n_stages - 1) { std::map::iterator it = stgs_config.find(stg_i + 1); if (it != stgs_config.end()) { - flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut); + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut()); } } // Add the external feed for the cascade @@ -120,7 +110,7 @@ void CascadeConfig::CalcFeedFlows() { int i = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { - it->second.feed_flow = flows[0][i]; + it->second.feed_flow(flows[0][i]); i++; } } @@ -133,17 +123,20 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, // Initialisation of Feeding stage (I == 0) StageConfig stg; - stg.alpha = -1; - stg.DU = -1; + stg.alpha(-1); + stg.DU(-1); stg.centrifuge = centrifuge; - stg.BuildIdealStg(f_assay, precision); + stg.feed_assay(f_assay); + stg.precision(precision); + stg.BuildIdealStg(); int stg_i = 0; ideal_stgs[stg_i] = stg; - double ref_alpha = ideal_stgs[0].alpha; - double ref_du = ideal_stgs[0].DU; + double ref_alpha = ideal_stgs[0].alpha(); + double ref_du = ideal_stgs[0].DU(); // Calculate number of enriching stages - while (stg.product_assay < product_assay) { - stg.BuildIdealStg(stg.product_assay, precision); + while (stg.product_assay() < product_assay) { + stg.feed_assay(stg.product_assay()); + stg.BuildIdealStg(); stg_i++; ideal_stgs.insert(std::make_pair(stg_i, stg)); } @@ -152,8 +145,9 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg_i = 0; stg = ideal_stgs[stg_i]; // Calculate number of stripping stages - while (stg.tail_assay > waste_assay) { - stg.BuildIdealStg(stg.tail_assay, precision); + while (stg.tail_assay() > waste_assay) { + stg.feed_assay(stg.tail_assay()); + stg.BuildIdealStg(); stg_i--; ideal_stgs.insert(std::make_pair(stg_i, stg)); } @@ -162,7 +156,6 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, } void CascadeConfig::PopulateStages() { - double machine_tol = 0.01; int n_stages = n_enrich + n_strip; for (int i = 0; i < n_stages; i++) { @@ -172,14 +165,7 @@ void CascadeConfig::PopulateStages() { std::cout << "Bad Stage number" << std::endl; exit(1); } - double n_mach_exact = it->second.MachinesPerStage(); - // unless the ideal number of machines is Very close to an integer value, - // round up to next integer to preserve steady-state flow balance - int n_mach = (int)n_mach_exact; - if (std::abs(n_mach_exact - n_mach) > machine_tol) { - n_mach = int(n_mach_exact) + 1; - } - it->second.n_machines = n_mach; + it->second.MachinesNeededPerStage(); } } @@ -187,7 +173,7 @@ int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { - machines += it->second.n_machines; + machines += it->second.n_machines(); } return machines; } @@ -213,29 +199,29 @@ void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { n_machines = machines_needed; } -CascadeConfig CascadeConfig::ModelMissUsedCascade(double f_assay, +CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, int modeling_opt, double precision) { - CascadeConfig miss_used_cascade = (*this); - miss_used_cascade.PropagateAssay(f_assay); + CascadeConfig misuse_cascade = (*this); + misuse_cascade.PropagateAssay(f_assay); switch (modeling_opt) { default: - miss_used_cascade.ComputeAssay(f_assay, precision); + misuse_cascade.ComputeAssay(f_assay, precision); break; case 1: - miss_used_cascade.UpdateCut(); - miss_used_cascade.UpdateFlow(); + misuse_cascade.UpdateCut(); + misuse_cascade.UpdateFlow(); break; } - return miss_used_cascade; + return misuse_cascade; } void CascadeConfig::UpdateFlow() { - // recompute the flow according to the new cuts + // recompute the flow according to the new cuts (*this).CalcFeedFlows(); - + double ratio = 1; std::map::iterator it; for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); @@ -243,17 +229,17 @@ void CascadeConfig::UpdateFlow() { std::map::iterator it_real = (*this).stgs_config.find(it->first); double max_stg_flow = - it_real->second.n_machines * it_real->second.centrifuge.feed; - double stg_flow_ratio = it->second.feed_flow / max_stg_flow; - if (ratio < stg_flow_ratio) { + it_real->second.n_machines() * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow() / max_stg_flow; + if (ratio > stg_flow_ratio) { ratio = stg_flow_ratio; } } for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { - it->second.feed_flow *= 1. / ratio; + it->second.feed_flow(it->second.feed_flow() * ratio); } - (*this).feed_flow *= 1. / ratio; + (*this).feed_flow *= ratio; } void CascadeConfig::UpdateCut() { @@ -265,9 +251,9 @@ void CascadeConfig::UpdateCut() { } void CascadeConfig::PropagateAssay(double f_assay) { - // Initialiase Feeding stage + // Initialise Feeding stage std::map::iterator it = (*this).stgs_config.find(0); - it->second.feed_assay = f_assay; + it->second.feed_assay(f_assay); it->second.ProductAssay(); it->second.TailAssay(); @@ -280,7 +266,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { it_feed = (*this).stgs_config.find(it->first - 1); if (it->first > 0) { if (it_feed != (*this).stgs_config.end()) { - it->second.feed_assay = it_feed->second.product_assay; + it->second.feed_assay(it_feed->second.product_assay()); } // Update Product and Tail assay from feed assay it->second.ProductAssay(); @@ -295,7 +281,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { it_feed = (*this).stgs_config.find(it->first + 1); if (it->first < 0) { if (it_feed != (*this).stgs_config.end()) { - it->second.feed_assay = it_feed->second.tail_assay; + it->second.feed_assay(it_feed->second.tail_assay()); } // Update Product and Tail assay from feed assay it->second.ProductAssay(); @@ -308,7 +294,7 @@ void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; while (DeltaEnrichment((*this), previous_cascade) > precision) { previous_cascade = (*this); - (*this).stgs_config = IterrateEnrichment((*this), f_assay); + (*this).stgs_config = IterateEnrichment((*this), f_assay); } } @@ -328,17 +314,17 @@ double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, p_enrichments.stgs_config.find(it->first); if (it2 != p_enrichments.stgs_config.end()) { square_feed_diff += - pow(it->second.feed_assay - it2->second.feed_assay, 2); + pow(it->second.feed_assay() - it2->second.feed_assay(), 2); square_product_diff += - pow(it->second.product_assay - it2->second.product_assay, 2); + pow(it->second.product_assay() - it2->second.product_assay(), 2); square_waste_diff += - pow(it->second.tail_assay - it2->second.tail_assay, 2); + pow(it->second.tail_assay() - it2->second.tail_assay(), 2); } } return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::IterrateEnrichment( +std::map CascadeConfig::IterateEnrichment( CascadeConfig cascade, double f_assay) { CascadeConfig updated_enrichment = cascade; @@ -364,12 +350,12 @@ std::map CascadeConfig::IterrateEnrichment( up_flow = 0; if (it_down != cascade.stgs_config.end()) { - down_assay = it_down->second.product_assay; - down_flow = it_down->second.feed_flow * it_down->second.cut; + down_assay = it_down->second.product_assay(); + down_flow = it_down->second.feed_flow() * it_down->second.cut(); } if (it_up != cascade.stgs_config.end()) { - up_assay = it_up->second.tail_assay; - up_flow = it_up->second.feed_flow * (1 - it_up->second.cut); + up_assay = it_up->second.tail_assay(); + up_flow = it_up->second.feed_flow() * (1 - it_up->second.cut()); } // Mix the Product and the Tail to have the correct Feed Assay @@ -386,7 +372,7 @@ std::map CascadeConfig::IterrateEnrichment( updated_enrichment.stgs_config.find(i); // Update Stage feed assay - it_new->second.feed_assay = stg_f_assay; + it_new->second.feed_assay(stg_f_assay); // Update Beta values (from feed) -- Alpha & Cut are cte it_new->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index e4bce3e..4590299 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -29,13 +29,13 @@ class CascadeConfig { // Solve the flow matrix from the stages cuts void CalcFeedFlows(); - // DO something ?! + // Establish machines needed in each stage void PopulateStages(); - - // Scale the Casacde to meet the limitation in max feed or max centrifuges + + // Scale the Cascade to meet the limitation in max feed or max centrifuges void ScaleCascade(double max_feed, int max_centrifuges); - CascadeConfig ModelMissUsedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); + CascadeConfig ModelMisuseCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay void PropagateAssay(double f_assay); @@ -57,7 +57,7 @@ class CascadeConfig { // total number of machine in the Cascade int n_machines; // real feed flow (constrained by the cascade design/total number of - // machine/max feed flow + // machine/max feed flow) double feed_flow; //design feed assay @@ -66,14 +66,14 @@ class CascadeConfig { double design_product_assay; //design tail assay double design_tail_assay; - + // Method to check the assays different between 2 cascades double DeltaEnrichment(CascadeConfig actual_enrichments, CascadeConfig previous_enrichment); - // method computing one iteration, of the algorithm used to get the response - // to non ideal feed assay - std::map IterrateEnrichment(CascadeConfig cascade, + // method computing one iteration of the algorithm used to get the response + // to non ideal feed assay + std::map IterateEnrichment(CascadeConfig cascade, double feed_assay); }; diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 32940c0..37dfa21 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -61,16 +61,16 @@ TEST(CascadeStage_Test, TestCascade) { EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); // Now test assays when cascade is modified away from ideal design - // (cascade optimized for natural uranium feed, now use 20% enriched + // (cascade optimized for natural uranium feed, now use 20% enriched) double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.ModelMissUsedCascade(feed_assay_mod, 0, 1e-31); + cascade.ModelMisuseCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = - cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; + cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay(); double mod_waste_assay = - cascade_non_ideal.stgs_config[-n_stage_waste].product_assay; + cascade_non_ideal.stgs_config[-n_stage_waste].product_assay(); double pycode_mod_product_assay = 0.8189; EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); @@ -97,9 +97,9 @@ TEST(CascadeStage_Test, TestCascadeDesign) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); for (int i = 0; i < pycode_flows.size(); i++) { - EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow, + EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow(), pycode_flows[i], tol_num); - int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines; + int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines(); EXPECT_EQ(nmach, pycode_machines[i]); } @@ -129,12 +129,12 @@ TEST(CascadeStage_Test, TestUpdateAssay) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); double product_assay = - cascade.stgs_config[cascade.n_enrich - 1].product_assay; - double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); double feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); @@ -145,13 +145,13 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMissUsedCascade(fa, 0, 1e-17); - product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; - tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade = cascade.ModelMisuseCascade(fa, 0, 1e-17); + product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); tail_from_assay = product_flow * (product_assay - fa) / (fa - tail_assay); @@ -167,12 +167,12 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); double product_assay = - cascade.stgs_config[cascade.n_enrich - 1].product_assay; - double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); double feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); @@ -183,12 +183,12 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMissUsedCascade(fa, 1, 1e-17); - double alpha_ref = cascade.stgs_config[0].alpha; + cascade = cascade.ModelMisuseCascade(fa, 1, 1e-17); + double alpha_ref = cascade.stgs_config[0].alpha(); std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ - EXPECT_EQ(alpha_ref, it->second.alpha); - EXPECT_EQ(alpha_ref, it->second.beta); + EXPECT_EQ(alpha_ref, it->second.alpha()); + EXPECT_EQ(alpha_ref, it->second.beta()); } } diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From 64ab3c2a9b372bb1ffa6d027fcac2e619097ff49 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:19:11 -0500 Subject: [PATCH 050/116] Removing some file not suppose to be there yet --- src/CascadeEnrich_tests.h | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h deleted file mode 100644 index 025911b..0000000 --- a/src/CascadeEnrich_tests.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ -#define MBMORE_SRC_CASCADEENRICH_TESTS_ - -#include - -#include - -#include "test_context.h" -#include "env.h" -#include "exchange_context.h" -#include "material.h" - -#include "CascadeEnrich.h" -#include "CascadeConfig.h" - -namespace mbmore { - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class CascadeEnrichTest : public ::testing::Test { - protected: - cyclus::TestContext tc_; - CascadeEnrich* src_facility; - std::string feed_commod, product_commod, feed_recipe, tails_commod; - cyclus::Composition::Ptr recipe; - TestFacility* trader; - - double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; - - bool order_prefs; - - double reserves; - - virtual void SetUp(); - virtual void TearDown(); - void InitParameters(); - void SetUpSource(); - cyclus::Material::Ptr GetMat(double qty); - /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 - cyclus::Material::Ptr GetReqMat(double qty, double enr); - void DoAddMat(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoRequest(); - cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); - /// @param nreqs the total number of requests - /// @param nvalid the number of requests that are valid - boost::shared_ptr< cyclus::ExchangeContext > - GetContext(int nreqs, int nvalid); -}; - -} // namespace cycamore -#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From 3c1329bb7e09a8033ad10efd756b7e2339263051 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:23:35 -0500 Subject: [PATCH 051/116] readd missing file --- src/CascadeEnrich_tests.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h new file mode 100644 index 0000000..22a650d --- /dev/null +++ b/src/CascadeEnrich_tests.h @@ -0,0 +1,51 @@ +#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ +#define MBMORE_SRC_CASCADEENRICH_TESTS_ + +#include + +#include + +#include "test_context.h" +#include "env.h" +#include "exchange_context.h" +#include "material.h" + +#include "CascadeEnrich.h" + +namespace mbmore { + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class CascadeEnrichTest : public ::testing::Test { + protected: + cyclus::TestContext tc_; + CascadeEnrich* src_facility; + std::string feed_commod, product_commod, feed_recipe, tails_commod; + cyclus::Composition::Ptr recipe; + TestFacility* trader; + + double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; + + bool order_prefs; + + double reserves; + + virtual void SetUp(); + virtual void TearDown(); + void InitParameters(); + void SetUpSource(); + cyclus::Material::Ptr GetMat(double qty); + /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 + cyclus::Material::Ptr GetReqMat(double qty, double enr); + void DoAddMat(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoRequest(); + cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); + /// @param nreqs the total number of requests + /// @param nvalid the number of requests that are valid + boost::shared_ptr< cyclus::ExchangeContext > + GetContext(int nreqs, int nvalid); +}; + +} // namespace cycamore +#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From a4300b1e6c5cd50e3fb3d16af438c2f09ba121ac Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 8 Nov 2019 13:51:10 -0600 Subject: [PATCH 052/116] Calculate machines if it hasn't been done before (FindTotalMachines()) --- src/CascadeConfig.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 64c7815..710b9a6 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -173,6 +173,7 @@ int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + if (it->second.n_machines() == -1) it->second.MachinesNeededPerStage(); machines += it->second.n_machines(); } return machines; From fc89c1c3909dd1a05fce17d5244855cf93a2b746 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 8 Nov 2019 14:04:13 -0600 Subject: [PATCH 053/116] Adding case comments & DeltaEnrichment precision. --- src/CascadeConfig.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 710b9a6..96260ef 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -206,6 +206,8 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, CascadeConfig misuse_cascade = (*this); misuse_cascade.PropagateAssay(f_assay); + // Default: alpha, cut = constant; beta = varying + // Case 1: alpha = beta, cut = varying switch (modeling_opt) { default: misuse_cascade.ComputeAssay(f_assay, precision); @@ -293,16 +295,17 @@ void CascadeConfig::PropagateAssay(double f_assay) { void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade) > precision) { + while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { previous_cascade = (*this); (*this).stgs_config = IterateEnrichment((*this), f_assay); } } double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, - CascadeConfig p_enrichments) { + CascadeConfig p_enrichments, + double precision) { if (p_enrichments.n_enrich == 0) { - return 100.; + return 100. * std::abs(precision); } double square_feed_diff = 0; double square_product_diff = 0; From 6e88d48a65c8fb8da2cba700f40fb70b4e94176a Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 8 Nov 2019 14:08:33 -0600 Subject: [PATCH 054/116] Correcting CascadeConfig definition --- src/CascadeConfig.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index 4590299..d2c754f 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -69,7 +69,8 @@ class CascadeConfig { // Method to check the assays different between 2 cascades double DeltaEnrichment(CascadeConfig actual_enrichments, - CascadeConfig previous_enrichment); + CascadeConfig previous_enrichment, + double precision); // method computing one iteration of the algorithm used to get the response // to non ideal feed assay From 2ef25f3f2fc3b74841d668b521715e482a9eb8c3 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Fri, 8 Nov 2019 14:49:06 -0600 Subject: [PATCH 055/116] Update src/StageConfig.h Co-Authored-By: Jordan Stomps --- src/StageConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StageConfig.h b/src/StageConfig.h index b5f9759..03f5066 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -29,7 +29,7 @@ class StageConfig { double feed_flow_; // number of centrifuges in the stage - int n_machines_; + int n_machines_ = -1; // Feed assay double feed_assay_; From 2a327facc1399f8340edcf2baf9e00abd5dd64f5 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 11 Nov 2019 13:39:40 -0600 Subject: [PATCH 056/116] Make precision absolute to avoid user-entered negative value. --- src/CascadeConfig.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 96260ef..61ddbee 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -295,7 +295,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { + while (DeltaEnrichment((*this), previous_cascade, precision) > std::abs(precision)) { previous_cascade = (*this); (*this).stgs_config = IterateEnrichment((*this), f_assay); } From fdb1e182b3ad39545bb1cc35499e334ad0fceeb8 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 13 Nov 2019 13:33:03 -0600 Subject: [PATCH 057/116] Removed reference to pycode since expected values changed --- src/StageConfig_tests.cc | 45 ++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index f3b1830..19ab231 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -8,11 +8,9 @@ namespace mbmore { -// Benchmarked against mbmore_enrich_compare.ipynb -// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +// Benchmarked using a regression test (expected values calculated manually) namespace stageconfig_test { // Fixed for a cascade separating out U235 from U238 in UF6 gas -// Fixed for a cascade separating out U235 from U238 in UF6 gas double M = 0.352; // kg/mol UF6 double dM = 0.003; // kg/mol U238 - U235 double x = 1000; // Pressure ratio (Glaser) @@ -22,16 +20,14 @@ double flow_internal = 2.0; double eff = 1.0; double cut = 0.5; -// Centrifuge params used in Python test code -// (based on Glaser SGS 2009 paper) +// Centrifgue parameters based on Glaser SGS 2009 paper double v_a = 485; // m/s double height = 0.5; // meters double diameter = 0.15; // meters double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec double temp = 320.0; // Kelvin -// Cascade params used in Python test code (Enrichment_Calculations.ipynb) -// found in enrich_calcs repo listed above. +// Cascade params used in in calculating expected values const double feed_assay = 0.0071; const double prod_assay = 0.035; const double waste_assay = 0.001; @@ -39,6 +35,7 @@ const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, flow_internal); + // del U=7.0323281e-08 alpha=1.16321 double delU = centrifuge.ComputeDeltaU(cut); @@ -69,17 +66,17 @@ TEST(StageConfig_Test, TestAssays) { EXPECT_NEAR(stage.tail_assay(), target_w_assay, tol); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Calculate ideal SWU params of single machinefeed_assay (separation potential delU -// and separation factor alpha) +// Calculate ideal SWU params of single machinefeed_assay +// (separation potential delU and separation factor alpha) TEST(StageConfig_Test, TestSWU) { - double pycode_U = 7.03232816847e-08; + double expected_U = 7.03232816847e-08; double tol = 1e-9; StageConfig stage(feed_assay, feed_m, cut, delU, -1, 1e-16); - double pycode_alpha = 1.16321; + double expected_alpha = 1.16321; double tol_alpha = 1e-2; - EXPECT_NEAR(stage.alpha(), pycode_alpha, tol_alpha); + EXPECT_NEAR(stage.alpha(), expected_alpha, tol_alpha); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -94,18 +91,18 @@ TEST(StageConfig_Test, TestIdeal) { // All expected numbers were calculated using the methods used // and are trusted to be correct (regression test). - double pycode_alpha = 1.18181; + double expected_alpha = 1.18181; double tol_alpha = 1e-2; - double pycode_cut = 0.4589269; + double expected_cut = 0.4589269; double tol_cut = 1e-3; - double pycode_U = 7.4221362040947e-08; + double expected_U = 7.4221362040947e-08; double tol_DU = 1e-9; - EXPECT_NEAR(stage_ideal.alpha(), pycode_alpha, tol_alpha); - EXPECT_NEAR(stage_ideal.cut(), pycode_cut, tol_cut); - EXPECT_NEAR(stage_ideal.DU(), pycode_U, tol_DU); + EXPECT_NEAR(stage_ideal.alpha(), expected_alpha, tol_alpha); + EXPECT_NEAR(stage_ideal.cut(), expected_cut, tol_cut); + EXPECT_NEAR(stage_ideal.DU(), expected_U, tol_DU); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -117,15 +114,13 @@ TEST(StageConfig_Test, TestStages) { stage.ProductAssay(); stage.MachinesNeededPerStage(); - double pycode_product_assay_s = 0.0082492; + double expected_product_assay_s = 0.0082492; - // cent_feed_flow = (2 * DU / M) * ((1 - cut) / cut) / pow((alpha - 1.), 2.) - // N_machines = feed_flow / cent_feed_flow - // centrifuge feed flow should be equal to feed_m (from Glaser) - int pycode_n_mach_e = 19; + // Calculated using equations from 2009 Glaser paper + int expected_n_mach_e = 19; - EXPECT_NEAR(stage.n_machines(), pycode_n_mach_e, tol_num); - EXPECT_NEAR(stage.product_assay(), pycode_product_assay_s, tol_assay); + EXPECT_NEAR(stage.n_machines(), expected_n_mach_e, tol_num); + EXPECT_NEAR(stage.product_assay(), expected_product_assay_s, tol_assay); } } // namespace enrichfunctiontests From 0fa3ae79a727c7d7aa47eb00b21482e03729857d Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 13 Nov 2019 13:59:52 -0600 Subject: [PATCH 058/116] Updating expected number of machines in TestCascadeDesign --- src/CascadeConfig_tests.cc | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 37dfa21..fb23879 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -8,8 +8,7 @@ namespace mbmore { -// Benchmarked against mbmore_enrich_compare.ipynb -// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +// Benchmarked using a regression test (expected values calculated manually) namespace cascadeconfig_tests { // Fixed for a cascade separating out U235 from U238 in UF6 gas const double M = 0.352; // kg/mol UF6 @@ -21,15 +20,14 @@ const double flow_internal = 2.0; const double eff = 1.0; const double cut = 0.5; -// Centrifuge params used in Python test code -// (based on Glaser SGS 2009 paper) +// Centrifuge parameters based on Glaser SGS 2009 paper const double v_a = 485; // m/s const double height = 0.5; // meters const double diameter = 0.15; // meters const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec const double temp = 320.0; // Kelvin -// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +// Cascade params used in calculating expected values const double feed_assay = 0.0071; const double product_assay = 0.035; const double waste_assay = 0.001; @@ -37,6 +35,7 @@ const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, flow_internal); + // del U=7.0323281e-08 alpha=1.16321 double delU = centrifuge.ComputeDeltaU(cut); @@ -51,14 +50,14 @@ TEST(CascadeStage_Test, TestCascade) { CascadeConfig cascade; cascade.centrifuge = centrifuge; cascade.BuildIdealCascade(feed_assay, product_assay, waste_assay, 1e-8); - int pycode_n_enrich_stage = 11; - int pycode_n_strip_stage = 12; + int expected_n_enrich_stage = 11; + int expected_n_strip_stage = 12; // integer int n_stage_enrich = cascade.n_enrich; int n_stage_waste = cascade.n_strip; - EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); - EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); + EXPECT_EQ(n_stage_enrich, expected_n_enrich_stage); + EXPECT_EQ(n_stage_waste, expected_n_strip_stage); // Now test assays when cascade is modified away from ideal design // (cascade optimized for natural uranium feed, now use 20% enriched) @@ -72,11 +71,11 @@ TEST(CascadeStage_Test, TestCascade) { double mod_waste_assay = cascade_non_ideal.stgs_config[-n_stage_waste].product_assay(); - double pycode_mod_product_assay = 0.8189; - EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); + double expected_mod_product_assay = 0.8189; + EXPECT_NEAR(mod_product_assay, expected_mod_product_assay, tol_assay); - double pycode_mod_waste_assay = 0.11198; - EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); + double expected_mod_waste_assay = 0.11198; + EXPECT_NEAR(mod_waste_assay, expected_mod_waste_assay, tol_assay); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -87,39 +86,42 @@ TEST(CascadeStage_Test, TestCascadeDesign) { double pa = 0.20; double wa = 0.05; - std::vector pycode_flows = { + std::vector expected_flows = { 0.00030693, 0.00061387, 0.0009208, 0.00122774, 0.00153467, 0.00127889, 0.00102311, 0.00076734, 0.00051156, 0.00025578}; - std::vector pycode_machines = {80, 149, 210, 264, 312, - 241, 180, 127, 80, 38}; + std::vector expected_machines = {25, 46, 65, 82, 97, 76, + 57, 40, 26, 13}; + //std::vector expected_machines = {80, 149, 210, 264, 312, +// 241, 180, 127, 80, 38}; CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); - for (int i = 0; i < pycode_flows.size(); i++) { + for (int i = 0; i < expected_flows.size(); i++) { EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow(), - pycode_flows[i], tol_num); + expected_flows[i], tol_num); int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines(); - EXPECT_EQ(nmach, pycode_machines[i]); + EXPECT_EQ(nmach, expected_machines[i]); } // not enough machines int max_centrifuges = 80; cascade.ScaleCascade(feed_c, max_centrifuges); - int py_tot_mach = 80; - double py_opt_feed = 1.30116169899e-05; + int expected_tot_mach = 80; + double expected_opt_feed = 4.11669203083e-05; + //double expected_opt_feed = 1.30116169899e-05; - EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); - EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); // more machines than requested capacity max_centrifuges = 1000; cascade.ScaleCascade(feed_c, max_centrifuges); - py_tot_mach = 999; - py_opt_feed = 0.0001667; + expected_tot_mach = 999; + expected_opt_feed = 0.0001667; - EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); - EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); } TEST(CascadeStage_Test, TestUpdateAssay) { From 32ffd307dd3e9abe8474f9315ac53cc8749cf5dd Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 15 Nov 2019 15:03:05 -0600 Subject: [PATCH 059/116] Recalculating expected cascade feed flows and adding test-case comments --- src/CascadeConfig_tests.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index fb23879..fba9127 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -45,7 +45,7 @@ const double tol_num = 1e-2; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Ideal cascade design, and then using away from ideal design - +// TEST(CascadeStage_Test, TestCascade) { CascadeConfig cascade; cascade.centrifuge = centrifuge; @@ -79,7 +79,7 @@ TEST(CascadeStage_Test, TestCascade) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// tests the steady state flow rates for a cascade +// Tests the steady state flow rates for a cascade // TEST(CascadeStage_Test, TestCascadeDesign) { double fa = 0.10; @@ -92,8 +92,6 @@ TEST(CascadeStage_Test, TestCascadeDesign) { std::vector expected_machines = {25, 46, 65, 82, 97, 76, 57, 40, 26, 13}; - //std::vector expected_machines = {80, 149, 210, 264, 312, -// 241, 180, 127, 80, 38}; CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); @@ -109,21 +107,23 @@ TEST(CascadeStage_Test, TestCascadeDesign) { cascade.ScaleCascade(feed_c, max_centrifuges); int expected_tot_mach = 80; double expected_opt_feed = 4.11669203083e-05; - //double expected_opt_feed = 1.30116169899e-05; EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); // more machines than requested capacity - max_centrifuges = 1000; + max_centrifuges = 600; cascade.ScaleCascade(feed_c, max_centrifuges); - expected_tot_mach = 999; - expected_opt_feed = 0.0001667; + expected_tot_mach = 527; + expected_opt_feed = 0.0002814; EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Tests feed flows in misue model A, where alpha & cut are constant +// TEST(CascadeStage_Test, TestUpdateAssay) { double fa = 0.10; double pa = 0.20; @@ -162,6 +162,9 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Test feed flows in misuse model B, where alpha = beta +// TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { double fa = 0.10; double pa = 0.20; From e7776dde3eadb2929420a4e8030239786d823202 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 26 Nov 2019 11:55:51 -0600 Subject: [PATCH 060/116] Minor changes to comments based on initial review. --- src/CascadeEnrich.cc | 15 +++++++-------- src/CascadeEnrich.h | 25 +++++++++++-------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index cbc7ac5..e1e91e9 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -52,7 +52,7 @@ void CascadeEnrich::EnterNotify() { using cyclus::Material; cyclus::Facility::EnterNotify(); centrifuge = CentrifugeConfig(); - // Update Centrifuge paramter from the user input: + // Update Centrifuge parameter from the user input: centrifuge.v_a = centrifuge_velocity; centrifuge.height = height; centrifuge.diameter = diameter; @@ -78,7 +78,7 @@ void CascadeEnrich::EnterNotify() { std::cout << " machine: " << it->second.n_machines; std::cout << std::endl; } - std::cout << "Dsign Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; + std::cout << "Design Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; if (max_feed_inventory > 0) { inventory.capacity(max_feed_inventory); } @@ -273,8 +273,8 @@ CascadeEnrich::GetMatlBids( for (it = commod_requests.begin(); it != commod_requests.end(); ++it) { Request* req = *it; Material::Ptr offer = Offer_(req->target()); - // The offer might not match the required enrichment ! it just produce - // what it can according to the cascade configuration and the feed asays + // The offer might not match the required enrichment ! It just produces + // what it can according to the cascade configuration and the feed assays commod_port->AddBid(req, offer, this); } @@ -352,15 +352,14 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, using cyclus::toolkit::UraniumAssay; using cyclus::toolkit::FeedQty; using cyclus::toolkit::TailsQty; + // get enrichment parameters double feed_qty = FeedRequired(qty); - double feed_assay = FeedAssay(feed_qty); double product_assay = ProductAssay(feed_assay); - - double tails_assay = TailsAssay(FeedAssay(feed_qty)); double tails_mass = TailsFlow(feed_qty); + // Determine the composition of the natural uranium // (ie. U-235+U-238/TotalMass) double pop_qty = inventory.quantity(); @@ -508,7 +507,7 @@ double CascadeEnrich::ProductFlow(double feed_flow) { double feed_assay = FeedAssay(feed_flow); double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); - + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; double product_flow = last_stg.feed_flow * last_stg.cut; return feed_ratio * FlowPerMon(product_flow); diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 56837c5..5d62865 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -81,25 +81,23 @@ class CascadeEnrich : public cyclus::Facility { /// @param time is the time to perform the tock virtual void Tock(); - /// @brief The Enrichment request Materials of its given - /// commodity. + /// @brief The Enrichment request Materials of its given commodity. virtual std::set::Ptr> GetMatlRequests(); /// @brief The Enrichment adjusts preferences for offers of - /// natural uranium it has received to maximize U-235 content - /// Any offers that have zero U-235 content are not accepted + /// natural uranium it has received to maximize U-235 content. + /// Any offers that have zero U-235 content are not accepted. virtual void AdjustMatlPrefs(cyclus::PrefMap::type& prefs); - /// @brief The Enrichment place accepted trade Materials in their - /// Inventory + /// @brief The Enrichment place accepted trade Materials in their Inventory. virtual void AcceptMatlTrades( const std::vector, cyclus::Material::Ptr> >& responses); /// @brief Responds to each request for this facility's commodity. If a given /// request is more than this facility's inventory or SWU capacity, it will - /// offer its minimum of its capacities. + /// offer the minimum of its capacities. virtual std::set::Ptr> GetMatlBids( cyclus::CommodMap::type& commod_requests); @@ -172,14 +170,13 @@ class CascadeEnrich : public cyclus::Facility { void RecordEnrichment_(double natural_u); - // Not physical constants but fixed assumptions for a cascade separating - // out U235 from U238 in UF6 gas -//group all the characteristic of a centrifuges + // Not physical constants but fixed assumptions for a cascade separating out + // U235 from U238 in UF6 gas group all the characteristic of a centrifuges CentrifugeConfig centrifuge; CascadeConfig cascade; double precision = 1e-15; - - + + const double secpermonth = 60.*60.*24.*(365.25/12.); // Set to design_tails at beginning of simulation. Gets reset if @@ -213,7 +210,7 @@ class CascadeEnrich : public cyclus::Facility { "doc": "amount of natural uranium stored at the enrichment " \ "facility at the beginning of the simulation (kg)" } double initial_feed; - + #pragma cyclus var { \ "default": 1e299, "tooltip": "max inventory of feed material (kg)", \ "uilabel": "Maximum Feed Inventory", \ @@ -304,7 +301,7 @@ class CascadeEnrich : public cyclus::Facility { "uilabel" : "Max feed rate for single centrifuge (mg/sec)", \ "doc" : "maximum feed rate for a single centrifuge (mg/sec)"} double machine_feed; - + #pragma cyclus var { \ "default": 0, \ "userlevel": 10, \ From 7f836021510e73c3f23149c2209ef8a9ebd3ca15 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 3 Dec 2019 15:50:51 -0600 Subject: [PATCH 061/116] Commenting changes in CascadeEnrich.h --- src/CascadeEnrich.h | 88 ++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 5d62865..184d25e 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -45,40 +45,40 @@ class CascadeEnrich : public cyclus::Facility { "niche": "enrichment facility", \ "doc": \ "The CascadeEnrich facility based on the Cycamore Enrich facility. " \ - "timesteps (see README for full implementation documentation ",\ + "timesteps (see README for full implementation documentation ",\ } public: // --- Module Members --- - /// Constructor for the CascadeEnrich class - /// @param ctx the cyclus context for access to simulation-wide parameters + /// Constructor for the CascadeEnrich class + /// @param ctx the cyclus context for access to simulation-wide parameters CascadeEnrich(cyclus::Context* ctx); - /// Destructor for the CascadeEnrich class + /// Destructor for the CascadeEnrich class virtual ~CascadeEnrich(); #pragma cyclus - /// Print information about this agent + /// Print information about this agent virtual std::string str(); // --- - // --- Facility Members --- - /// perform module-specific tasks when entering the simulation - //virtual void Build(cyclus::Agent* parent); - // --- + /// --- Facility Members --- + /// Perform module-specific tasks when entering the simulation + /// virtual void Build(cyclus::Agent* parent); + /// --- // --- Agent Members --- - /// Each facility is prompted to do its beginning-of-time-step - /// stuff at the tick of the timer. + /// Each facility is prompted to do its beginning-of-time-step + /// stuff at the tick of the timer. virtual void EnterNotify(); - /// @param time is the time to perform the tick + /// @param time is the time to perform the tick virtual void Tick(); - /// Each facility is prompted to its end-of-time-step - /// stuff on the tock of the timer. + /// Each facility is prompted to its end-of-time-step + /// stuff on the tock of the timer. - /// @param time is the time to perform the tock + /// @param time is the time to perform the tock virtual void Tock(); /// @brief The Enrichment request Materials of its given commodity. @@ -88,6 +88,8 @@ class CascadeEnrich : public cyclus::Facility { /// @brief The Enrichment adjusts preferences for offers of /// natural uranium it has received to maximize U-235 content. /// Any offers that have zero U-235 content are not accepted. + /// + /// @param prefs is the preference map with all requests. virtual void AdjustMatlPrefs(cyclus::PrefMap::type& prefs); /// @brief The Enrichment place accepted trade Materials in their Inventory. @@ -98,6 +100,8 @@ class CascadeEnrich : public cyclus::Facility { /// @brief Responds to each request for this facility's commodity. If a given /// request is more than this facility's inventory or SWU capacity, it will /// offer the minimum of its capacities. + /// + /// @param commod_requests is a cyclus map of requests for this facility virtual std::set::Ptr> GetMatlBids( cyclus::CommodMap::type& commod_requests); @@ -120,7 +124,7 @@ class CascadeEnrich : public cyclus::Facility { // TODO: MAKE THESE CONVERSIONS TOOLKIT FNS and have them explicitly check // timestep duration - // Convert input file flows kg/mon to SI units + /// --- Convert input file flows kg/mon to SI units --- inline double FlowPerSec(double flow_per_mon) { return flow_per_mon / secpermonth; } @@ -132,11 +136,13 @@ class CascadeEnrich : public cyclus::Facility { inline double Mg2kgPerSec(double feed_mg_per_sec) { return feed_mg_per_sec / (1e6); } + /// --- - /// @brief Determines if a particular material is a valid request to respond - /// to. Valid requests must contain U235 and U238 and must have a relative - /// U235-to-U238 ratio less than this facility's tails_assay(). - /// @return true if the above description is met by the material + /// @brief Determines if a particular material is a valid request to respond + /// to. Valid requests must contain U235 and U238 and must have a relative + /// U235-to-U238 ratio less than this facility's tails_assay(). + /// + /// @return true if the above description is met by the material bool ValidReq(const cyclus::Material::Ptr mat); inline const cyclus::toolkit::ResBuf& Tails() const { @@ -144,34 +150,34 @@ class CascadeEnrich : public cyclus::Facility { } private: - /// @brief calculates the feed assay based on the unenriched inventory + /// @brief calculates the feed assay based on the unenriched inventory double FeedAssay(double quantity); - /// @brief adds a material into the natural uranium inventory - /// @throws if the material is not the same composition as the feed_recipe + /// @brief adds a material into the natural uranium inventory + /// @throws if the material is not the same composition as the feed_recipe void AddMat_(cyclus::Material::Ptr mat); - /// @brief generates a request for this facility given its current state. - /// Quantity of the material will be equal to remaining inventory size. + /// @brief generates a request for this facility given its current state. + /// Quantity of the material will be equal to remaining inventory size. cyclus::Material::Ptr Request_(); - /// @brief Generates a material offer for a given request. The response - /// composition will be comprised only of U235 and U238 at their relative - /// ratio in the requested material. The response quantity will be the - /// same as the requested commodity. + /// @brief Generates a material offer for a given request. The response + /// composition will be comprised only of U235 and U238 at their relative + /// ratio in the requested material. The response quantity will be the + /// same as the requested commodity. /// - /// @param req the requested material being responded to + /// @param req the requested material being responded to cyclus::Material::Ptr Offer_(cyclus::Material::Ptr req); cyclus::Material::Ptr Enrich_(cyclus::Material::Ptr mat, double qty); - /// @brief records and enrichment with the cyclus::Recorder + /// @brief records and enrichment with the cyclus::Recorder void RecordEnrichment_(double natural_u); // Not physical constants but fixed assumptions for a cascade separating out - // U235 from U238 in UF6 gas group all the characteristic of a centrifuges + // U235 from U238 in UF6 gas group all the characteristic of a centrifuges. CentrifugeConfig centrifuge; CascadeConfig cascade; double precision = 1e-15; @@ -225,9 +231,9 @@ class CascadeEnrich : public cyclus::Facility { "default": 100, \ "tooltip": "design feed flow (kg/mon)", \ "uilabel": "Design Feed Flow", \ - "doc": "Target amount of feed material to be processed by the" \ - " facility (kg/mon). Either this or max_centrifuges is used to constrain" \ - " the cascade design" } + "doc": "Target amount of feed material to be processed by the " \ + "facility (kg/mon). Either this or max_centrifuges is used to constrain " \ + "the cascade design" } double design_feed_flow; #pragma cyclus var { \ @@ -271,35 +277,35 @@ class CascadeEnrich : public cyclus::Facility { "default" : 485.0, \ "tooltip" : "Centrifuge velocity (m/s)", \ "uilabel" : "Centrifuge velocity (m/s)", \ - "doc" : "operational centrifuge velocity (m/s) at the outer radius (a)"} + "doc" : "operational centrifuge velocity (m/s) at the outer radius (a)" } double centrifuge_velocity; #pragma cyclus var { \ "default" : 0.5, \ "tooltip" : "Centrifuge height (m)", \ "uilabel" : "Centrifuge height (m)", \ - "doc" : "height of centrifuge (m)"} + "doc" : "height of centrifuge (m)" } double height; #pragma cyclus var { \ "default" : 0.15, \ "tooltip" : "Centrifuge diameter (m)", \ "uilabel" : "Centrifuge diameter (m)", \ - "doc" : "diameter of centrifuge (m)"} + "doc" : "diameter of centrifuge (m)" } double diameter; #pragma cyclus var { \ "default" : 2, \ "tooltip" : "Centrifuge L/F* ", \ "uilabel" : "Centrifuge Countercurrent to feed ratio", \ - "doc" : "Countercurrent to feed ratio"} + "doc" : "Countercurrent to feed ratio" } double L_over_F; #pragma cyclus var { \ "default" : 15.0, \ "tooltip" : "Centrifuge feed rate (mg/sec)", \ "uilabel" : "Max feed rate for single centrifuge (mg/sec)", \ - "doc" : "maximum feed rate for a single centrifuge (mg/sec)"} + "doc" : "maximum feed rate for a single centrifuge (mg/sec)" } double machine_feed; #pragma cyclus var { \ @@ -310,7 +316,7 @@ class CascadeEnrich : public cyclus::Facility { "doc": "Miss-use modeling option: " \ " - 0: alpha-theta fix -- beta varies, " \ " - 1: alpha=beta fix -- theta varies, " \ - " - 2: alpha*beta fix "} + " - 2: alpha*beta fix " } int miss_use_model; From 2f5ccc1532e7ee9c8f2bfdbd4404f29c4c9f7ee8 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 5 Dec 2019 13:54:47 -0600 Subject: [PATCH 062/116] Updating stages/cascade language in CascadeEnrich.cc calls --- src/CascadeEnrich.cc | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index e1e91e9..4d9913a 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -68,14 +68,14 @@ void CascadeEnrich::EnterNotify() { for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++) { std::cout << "stg " << it->first; - std::cout << " FA: " << it->second.feed_assay; - std::cout << " PA: " << it->second.product_assay; - std::cout << " TA: " << it->second.tail_assay; - std::cout << " feed_flow: " << it->second.feed_flow; - std::cout << " cut: " << it->second.cut; - std::cout << " alpha: " << it->second.alpha; - std::cout << " beta: " << it->second.beta; - std::cout << " machine: " << it->second.n_machines; + std::cout << " FA: " << it->second.feed_assay(); + std::cout << " PA: " << it->second.product_assay(); + std::cout << " TA: " << it->second.tail_assay(); + std::cout << " feed_flow: " << it->second.feed_flow(); + std::cout << " cut: " << it->second.cut(); + std::cout << " alpha: " << it->second.alpha(); + std::cout << " beta: " << it->second.beta(); + std::cout << " machine: " << it->second.n_machines(); std::cout << std::endl; } std::cout << "Design Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; @@ -122,9 +122,10 @@ CascadeEnrich::GetMatlRequests() { return ports; } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Sort offers of input material to have higher preference for more -// U-235 content +// U-235 content void CascadeEnrich::AdjustMatlPrefs( cyclus::PrefMap::type& prefs) { using cyclus::Bid; @@ -181,6 +182,7 @@ void CascadeEnrich::AcceptMatlTrades( AddMat_(it->second); } } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::AddMat_(cyclus::Material::Ptr mat) { // Elements and isotopes other than U-235, U-238 are sent directly to tails @@ -223,6 +225,7 @@ void CascadeEnrich::AddMat_(cyclus::Material::Ptr mat) { << " to its inventory, which is holding " << inventory.quantity() << " total."; } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::set::Ptr> CascadeEnrich::GetMatlBids( @@ -408,6 +411,7 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, return response; } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::RecordEnrichment_(double natural_u) { using cyclus::Context; @@ -431,6 +435,7 @@ cyclus::Material::Ptr CascadeEnrich::Request_() { return cyclus::Material::CreateUntracked(qty, context()->GetRecipe(feed_recipe)); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cyclus::Material::Ptr CascadeEnrich::Offer_(cyclus::Material::Ptr mat) { double feed_assay = FeedAssay(mat->quantity()); @@ -443,6 +448,7 @@ cyclus::Material::Ptr CascadeEnrich::Offer_(cyclus::Material::Ptr mat) { return cyclus::Material::CreateUntracked( mat->quantity(), cyclus::Composition::CreateFromAtom(comp)); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CascadeEnrich::ValidReq(const cyclus::Material::Ptr mat) { cyclus::toolkit::MatQuery q(mat); @@ -450,6 +456,7 @@ bool CascadeEnrich::ValidReq(const cyclus::Material::Ptr mat) { double u238 = q.atom_frac(922380000); return (u238 > 0 && u235 / (u235 + u238) > tails_assay); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double CascadeEnrich::FeedAssay(double quantity) { using cyclus::Material; @@ -465,16 +472,17 @@ double CascadeEnrich::FeedAssay(double quantity) { } double CascadeEnrich::ProductAssay(double feed_assay) { - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); - return cascade_tmp.stgs_config.rbegin()->second.product_assay; + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.rbegin()->second.product_assay(); } + double CascadeEnrich::TailsAssay(double feed_assay) { - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); - return cascade_tmp.stgs_config.begin()->second.tail_assay; + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.begin()->second.tail_assay(); } double CascadeEnrich::MaxFeedFlow(double feed_assay){ - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); return FlowPerMon(cascade_tmp.FeedFlow()); @@ -506,10 +514,10 @@ double CascadeEnrich::FeedRequired(double prod_qty) { double CascadeEnrich::ProductFlow(double feed_flow) { double feed_assay = FeedAssay(feed_flow); double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); - StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; - double product_flow = last_stg.feed_flow * last_stg.cut; + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second(); + double product_flow = last_stg.feed_flow() * last_stg.cut(); return feed_ratio * FlowPerMon(product_flow); } From 1f1a3556172f71ccedcdedf60c1918e8097777ce Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 063/116] initial import --- src/CMakeLists.txt | 3 + src/CascadeConfig.cc | 384 +++++++++++++++++++++++++++++++++++++ src/CascadeConfig.h | 76 ++++++++ src/CascadeConfig_tests.cc | 196 +++++++++++++++++++ src/CascadeEnrich_tests.h | 1 + 5 files changed, 660 insertions(+) create mode 100644 src/CascadeConfig.cc create mode 100644 src/CascadeConfig.h create mode 100644 src/CascadeConfig_tests.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ae6747..b8e3464 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,8 +3,11 @@ USE_CYCLUS("mbmore" "mytest") USE_CYCLUS("mbmore" "behavior_functions") USE_CYCLUS("mbmore" "RandomEnrich") + USE_CYCLUS("mbmore" "CentrifugeConfig") USE_CYCLUS("mbmore" "StageConfig") +USE_CYCLUS("mbmore" "CascadeConfig") + USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") USE_CYCLUS("mbmore" "InteractRegion") diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc new file mode 100644 index 0000000..c5d02e6 --- /dev/null +++ b/src/CascadeConfig.cc @@ -0,0 +1,384 @@ +// Implements the CascadeEnrich class +#include "CascadeConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbmore { + +CascadeConfig::CascadeConfig() + : n_enrich(0), + n_strip(0), + n_machines(0), + feed_flow(0), + feed_assay(0), + design_product_assay(0), + design_tail_assay(0) {} + +CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, + double p_assay, double t_assay, + double max_feed_flow, int max_centrifuge, + double precision) { + centrifuge = centrifuge_; + feed_assay = f_assay; + design_product_assay = p_assay; + design_tail_assay = t_assay; + + feed_flow = max_feed_flow; + n_machines = max_centrifuge; + BuildIdealCascade(f_assay, p_assay, t_assay, precision); + DesignCascade(max_feed_flow, max_centrifuge); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate steady-state flow rates into each stage +// Linear system of equations in form AX = B, where A is nxn square matrix +// of linear equations for the flow rates of each stage and B are the external +// feeds for the stage. External feed is zero for all stages accept cascade +// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] +// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html +// +void CascadeConfig::CalcFeedFlows() { + // This is the Max # of stages in It cannot be passed in due to + // how memory is allocated and so must be hardcoded. It's been chosen + // to be much larger than it should ever need to be + + // total number of stages + int n_stages = n_enrich + n_strip; + int max_stages = n_stages; + if (n_stages > max_stages) { + std::cout << "To many stages in the can't calculated the " + "thoerritical flows..." + << std::endl; + exit(1); + } + + // Build Array with pointers + double flow_eqns[max_stages][max_stages]; + double flows[1][max_stages]; + + // build matrix of equations in this pattern + // [[ -1, 1-cut, 0, 0, 0] [[0] + // [cut, -1, 1-cut, 0, 0] [0] + // [ 0, cut, -1, 1-cut, 0] * X = [-1*feed] + // [ 0, 0, cut, -1, 1-cut] [0] + // [ 0, 0, 0, cut, -1]] [0]] + // + for (int row_idx = 0; row_idx < max_stages; row_idx++) { + // fill the array with zeros, then update individual elements as nonzero + flows[0][row_idx] = 0; + for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { + flow_eqns[fill_idx][row_idx] = 0; + } + // Required do to the artificial 'Max Stages' defn. Only calculate + // non-zero matrix elements where stages really exist. + if (row_idx < n_stages) { + int stg_i = row_idx - n_strip; + int col_idx = n_strip + stg_i; + flow_eqns[col_idx][row_idx] = -1.; + if (row_idx != 0) { + std::map::iterator it = stgs_config.find(stg_i - 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx - 1][row_idx] = it->second.cut; + } + } + if (row_idx != n_stages - 1) { + std::map::iterator it = stgs_config.find(stg_i + 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut); + } + } + // Add the external feed for the cascade + if (stg_i == 0) { + flows[0][row_idx] = -1. * feed_flow; + } + } + } + + // LAPACK solver variables + int nrhs = 1; // 1 column solution + int lda = max_stages; // must be >= MAX(1,N) + int ldb = max_stages; // must be >= MAX(1,N) + int ipiv[max_stages]; + int info; + + // Solve the linear system + dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, + &info); + + // Check for success + if (info != 0) { + std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; + } + + int i = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + it->second.feed_flow = flows[0][i]; + i++; + } +} + +void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, + double waste_assay, double precision) { + std::map ideal_stgs; + int ideal_enrich_stage = 0; + int ideal_strip_stage = 0; + + // Initialisation of Feeding stage (I == 0) + StageConfig stg; + stg.alpha = -1; + stg.DU = -1; + stg.centrifuge = centrifuge; + stg.BuildIdealStg(f_assay, precision); + int stg_i = 0; + ideal_stgs[stg_i] = stg; + double ref_alpha = ideal_stgs[0].alpha; + double ref_du = ideal_stgs[0].DU; + // Calculate number of enriching stages + while (stg.product_assay < product_assay) { + stg.BuildIdealStg(stg.product_assay, precision); + stg_i++; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_enrich = stg_i + 1; + // reset + stg_i = 0; + stg = ideal_stgs[stg_i]; + // Calculate number of stripping stages + while (stg.tail_assay > waste_assay) { + stg.BuildIdealStg(stg.tail_assay, precision); + stg_i--; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_strip = -stg_i; + stgs_config = ideal_stgs; +} + + +void CascadeConfig::CalcStageFeatures() { + double machine_tol = 0.01; + int n_stages = n_enrich + n_strip; + + for (int i = 0; i < n_stages; i++) { + int curr_stage = i - n_strip; + std::map::iterator it = stgs_config.find(curr_stage); + if (it == stgs_config.end()) { + std::cout << "Bad Stage number" << std::endl; + exit(1); + } + double n_mach_exact = it->second.MachinesPerStage(); + // unless the ideal number of machines is Very close to an integer value, + // round up to next integer to preserve steady-state flow balance + int n_mach = (int)n_mach_exact; + if (std::abs(n_mach_exact - n_mach) > machine_tol) { + n_mach = int(n_mach_exact) + 1; + } + it->second.n_machines = n_mach; + } +} + + +int CascadeConfig::FindTotalMachines() { + int machines = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + machines += it->second.n_machines; + } + return machines; +} + +void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { + // Determine the ideal steady-state feed flows for this cascade design given + // the maximum potential design feed rate + feed_flow = max_feed; + CalcFeedFlows(); + CalcStageFeatures(); + + // Do design parameters require more centrifuges than what is available? + int machines_needed = FindTotalMachines(); + double max_feed_from_machine = max_feed; + while (machines_needed > max_centrifuges) { + double scaling_ratio = (double)machines_needed / (double)max_centrifuges; + max_feed_from_machine = max_feed_from_machine / scaling_ratio; + feed_flow = max_feed_from_machine; + CalcFeedFlows(); + CalcStageFeatures(); + machines_needed = FindTotalMachines(); + } + n_machines = machines_needed; +} + +CascadeConfig CascadeConfig::Compute_Assay(double f_assay, double precision, + bool u_cut) { + CascadeConfig actual_cascade = (*this); + + // Initialiase Feeding stage + std::map::iterator it = actual_cascade.stgs_config.find(0); + it->second.feed_assay = f_assay; + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + + // Propagate initialisation to all stages + for (int i = 0; i < actual_cascade.n_enrich; i++){ + it = actual_cascade.stgs_config.find(i); + std::map::iterator it_feed; + + // Enrich stage -> feed = Product from Previous Stage + it_feed = actual_cascade.stgs_config.find(it->first - 1); + if (it->first > 0 && it_feed != actual_cascade.stgs_config.end()) { + it->second.feed_assay = it_feed->second.product_assay; + } + + // Update Product and Tail assay from feed assay + if (it->first != 0) { + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + for (int i = 1; i <= actual_cascade.n_strip; i++){ + it = actual_cascade.stgs_config.find(-i); + std::map::iterator it_feed; + + // Striping stage -> feed = tails from Next Stage + it_feed = actual_cascade.stgs_config.find(it->first + 1); + if (it->first < 0 && it_feed != actual_cascade.stgs_config.end()) { + it->second.feed_assay = it_feed->second.tail_assay; + } + + // Update Product and Tail assay from feed assay + if (it->first != 0) { + if (u_cut) { + it->second.CutByAlphaBeta(); + } + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + if(u_cut){ + actual_cascade.CalcFeedFlows(); + double ratio = 1; + for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ + std::map::iterator it_real = (*this).stgs_config.find(it->first); + double max_stg_flow = it_real->second.n_machines *it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + if (ratio < stg_flow_ratio){ + ratio = stg_flow_ratio; + } + } + for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ + it->second.feed_flow *= 1./ratio; + } + actual_cascade.feed_flow *= 1./ratio; + return actual_cascade; + } + // Looping to get the equilibrium + CascadeConfig previous_cascade; + while (Diff_enrichment(actual_cascade, previous_cascade) > precision) { + previous_cascade = actual_cascade; + actual_cascade.stgs_config = Update_enrichment(actual_cascade, f_assay, u_cut); + } + return actual_cascade; +} + +double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, + CascadeConfig p_enrichments) { + if (p_enrichments.n_enrich == 0) { + return 100.; + } + double square_feed_diff = 0; + double square_product_diff = 0; + double square_waste_diff = 0; + std::map::iterator it; + for (it = a_enrichments.stgs_config.begin(); + it != a_enrichments.stgs_config.end(); it++) { + int i = it->first; + std::map::iterator it2 = + p_enrichments.stgs_config.find(it->first); + if (it2 != p_enrichments.stgs_config.end()) { + square_feed_diff += + pow(it->second.feed_assay - it2->second.feed_assay, 2); + square_product_diff += + pow(it->second.product_assay - it2->second.product_assay, 2); + square_waste_diff += + pow(it->second.tail_assay - it2->second.tail_assay, 2); + } + } + return square_feed_diff + square_product_diff + square_waste_diff; +} + +std::map CascadeConfig::Update_enrichment( + CascadeConfig cascade, double f_assay, bool u_cut) { + CascadeConfig updated_enrichment = cascade; + + // mixing variables + double down_assay = 0; + double up_assay = 0; + double down_flow = 0; + double up_flow = 0; + double stg_feed_flow = 0; + std::map::iterator it; + + // Get the Flow and Assay quantity + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); + it++) { + int i = it->first; + std::map::iterator it_up = + cascade.stgs_config.find(i + 1); + std::map::iterator it_down = + cascade.stgs_config.find(i - 1); + down_assay = 0; + up_assay = 0; + down_flow = 0; + up_flow = 0; + + if (it_down != cascade.stgs_config.end()) { + down_assay = it_down->second.product_assay; + down_flow = it_down->second.feed_flow * it_down->second.cut; + } + if (it_up != cascade.stgs_config.end()) { + up_assay = it_up->second.tail_assay; + up_flow = it_up->second.feed_flow * (1 - it_up->second.cut); + } + + // Mix the Product and the Tail to have the correct Feed Assay + double stg_f_assay = + (down_assay * down_flow + up_assay * up_flow) / (down_flow + up_flow); + if (i == 0) { // add Feed flow in the entry stage + stg_f_assay = (down_assay * down_flow + up_assay * up_flow + + f_assay * cascade.feed_flow) / + (down_flow + up_flow + cascade.feed_flow); + stg_feed_flow = down_flow + up_flow + cascade.feed_flow; + } + + std::map::iterator it_new = + updated_enrichment.stgs_config.find(i); + + // Update Stage feed assay + it_new->second.feed_assay = stg_f_assay; + // Update Beta values (from feed) -- Alpha & Cut are cte + if(u_cut){ + it_new->second.CutByAlphaBeta(); + } else{ + it_new->second.BetaByAlphaAndCut(); + } + // Recompute Product Assay and Tail Assay + it_new->second.ProductAssay(); + it_new->second.TailAssay(); + } + + return updated_enrichment.stgs_config; +} +} // namespace mbmore diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h new file mode 100644 index 0000000..cb2735b --- /dev/null +++ b/src/CascadeConfig.h @@ -0,0 +1,76 @@ +#ifndef MBMORE_SRC_CASCADE_H_ +#define MBMORE_SRC_CASCADE_H_ + +#include +#include + +#include "CentrifugeConfig.h" +#include "StageConfig.h" + +namespace mbmore { +// LAPACK solver for system of linear equations +extern "C" { +void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipivot, double *b, + int *ldb, int *info); +} + +class CascadeConfig { + public: + CascadeConfig() ; + CascadeConfig(CentrifugeConfig centrifuge, double f_assay, double p_assay, + double t_assay, double max_feed_flow, int max_centrifuge, + double precision = 1e-8); + // Build a full cascade such as all stage follow alpha = beta = const. Get + // alpha/beta value from feeding stage. From the design feed/product/assay + void BuildIdealCascade(double f_assay, double p_assay, double w_assay, + double precision = 1e-8); + // Get the total number of machine in the Cascade + int FindTotalMachines(); + + // Solve the flow matrix from the stages cuts + void CalcFeedFlows(); + // DO something ?! + void CalcStageFeatures(); + // Scale the Casacde to meet the limitation in max feed or max centrifuges + void DesignCascade(double max_feed, int max_centrifuges); + + // Compute the response of the cascade to a non ideal feed assay + CascadeConfig Compute_Assay(double feed_assay, double precision, bool u_cut = false); + + double FeedFlow() { return feed_flow; } + // Configuration of the centrifuges in the stages + CentrifugeConfig centrifuge; + // Map of all the stage configuration + std::map stgs_config; + // number of enrich stages + int n_enrich; + // number of stripping stages + int n_strip; + + private: + // total number of machine in the Cascade + int n_machines; + // real feed flow (constrained by the cascade design/total number of + // machine/max feed flow + double feed_flow; + + //design feed assay + double feed_assay; + //design product assay + double design_product_assay; + //design tail assay + double design_tail_assay; + + // Method to check the assays different between 2 cascades + double Diff_enrichment(CascadeConfig actual_enrichments, + CascadeConfig previous_enrichement); + + // method computing one iteration, of the algorithm used to get the response + // to non ideal feed assay + std::map Update_enrichment(CascadeConfig cascade, + double feed_assay, bool u_cut = false); +}; + +} // namespace mbmore + +#endif // MBMORE_SRC_CASCADE_H_ diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc new file mode 100644 index 0000000..4a64971 --- /dev/null +++ b/src/CascadeConfig_tests.cc @@ -0,0 +1,196 @@ +#include + +#include "CascadeConfig.h" + +#include "agent_tests.h" +#include "context.h" +#include "facility_tests.h" + +namespace mbmore { + +// Benchmarked against mbmore_enrich_compare.ipynb +// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +namespace cascadeconfig_tests { +// Fixed for a cascade separating out U235 from U238 in UF6 gas +const double M = 0.352; // kg/mol UF6 +const double dM = 0.003; // kg/mol U238 - U235 +const double x = 1000; // Pressure ratio (Glaser) + +// General cascade assumptions +const double flow_internal = 2.0; +const double eff = 1.0; +const double cut = 0.5; + +// Centrifuge params used in Python test code +// (based on Glaser SGS 2009 paper) +const double v_a = 485; // m/s +const double height = 0.5; // meters +const double diameter = 0.15; // meters +const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec +const double temp = 320.0; // Kelvin + +// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +const double feed_assay = 0.0071; +const double product_assay = 0.035; +const double waste_assay = 0.001; +const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, + flow_internal); +// del U=7.0323281e-08 alpha=1.16321 +double delU = centrifuge.ComputeDeltaU(cut); + +const double tol_assay = 1e-5; +const double tol_qty = 1e-6; +const double tol_num = 1e-2; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Ideal cascade design, and then using away from ideal design + +TEST(CascadeStage_Test, TestCascade) { + CascadeConfig cascade; + cascade.centrifuge = centrifuge; + cascade.BuildIdealCascade(feed_assay, product_assay, waste_assay, 1e-8); + int pycode_n_enrich_stage = 11; + int pycode_n_strip_stage = 12; + // integer + int n_stage_enrich = cascade.n_enrich; + int n_stage_waste = cascade.n_strip; + + EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); + EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); + + // Now test assays when cascade is modified away from ideal design + // (cascade optimized for natural uranium feed, now use 20% enriched + double feed_assay_mod = 0.20; + cascade.DesignCascade(feed_c, 1000000); + CascadeConfig cascade_non_ideal = + cascade.Compute_Assay(feed_assay_mod, 1e-31); + + double mod_product_assay = + cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; + double mod_waste_assay = + cascade_non_ideal.stgs_config[-n_stage_waste].product_assay; + + double pycode_mod_product_assay = 0.8189; + EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); + + double pycode_mod_waste_assay = 0.11198; + EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// tests the steady state flow rates for a cascade +// +TEST(CascadeStage_Test, TestCascadeDesign) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + std::vector pycode_flows = { + 0.00030693, 0.00061387, 0.0009208, 0.00122774, 0.00153467, + 0.00127889, 0.00102311, 0.00076734, 0.00051156, 0.00025578}; + + std::vector pycode_machines = {80, 149, 210, 264, 312, + 241, 180, 127, 80, 38}; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); + + for (int i = 0; i < pycode_flows.size(); i++) { + EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow, + pycode_flows[i], tol_num); + int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines; + EXPECT_EQ(nmach, pycode_machines[i]); + } + + // not enough machines + int max_centrifuges = 80; + cascade.DesignCascade(feed_c, max_centrifuges); + int py_tot_mach = 80; + double py_opt_feed = 1.30116169899e-05; + + EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + + // more machines than requested capacity + max_centrifuges = 1000; + cascade.DesignCascade(feed_c, max_centrifuges); + py_tot_mach = 999; + py_opt_feed = 0.0001667; + + EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); +} + +TEST(CascadeStage_Test, TestUpdateAssay) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); + double product_assay = + cascade.stgs_config[cascade.n_enrich - 1].product_assay; + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + + double feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + double tail_from_assay = + product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); + + fa = 0.2; + cascade = cascade.Compute_Assay(fa, 1e-17); + product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; + tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + tail_from_assay = product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); +} + +TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { + double fa = 0.10; + double pa = 0.20; + double wa = 0.05; + + CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); + double product_assay = + cascade.stgs_config[cascade.n_enrich - 1].product_assay; + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * + cascade.stgs_config[cascade.n_enrich - 1].cut; + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * + (1 - cascade.stgs_config[-cascade.n_strip].cut); + + double feed_from_assay = + product_flow * (product_assay - tail_assay) / (fa - tail_assay); + double tail_from_assay = + product_flow * (product_assay - fa) / (fa - tail_assay); + + EXPECT_NEAR(cascade.FeedFlow(), feed_from_assay, 1e-3); + EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); + + fa = 0.2; + cascade = cascade.Compute_Assay(fa, 1e-17, true); + double alpha_ref = cascade.stgs_config[0].alpha; + std::map::iterator it; + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ + EXPECT_EQ(alpha_ref, it->second.alpha); + EXPECT_EQ(alpha_ref, it->second.beta); + } +} + +} // namespace cascadeconfig_tests +} // namespace mbmore diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From 1746f33e66c3e46392a7910d44380eae7e211fcd Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 17:28:59 -0500 Subject: [PATCH 064/116] some reshape on the cascade config --- src/CascadeConfig.cc | 147 ++++++++++++++++++++----------------- src/CascadeConfig.h | 20 +++-- src/CascadeConfig_tests.cc | 12 +-- 3 files changed, 100 insertions(+), 79 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index c5d02e6..9ae97db 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -33,7 +33,7 @@ CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, feed_flow = max_feed_flow; n_machines = max_centrifuge; BuildIdealCascade(f_assay, p_assay, t_assay, precision); - DesignCascade(max_feed_flow, max_centrifuge); + ScaleCascade(max_feed_flow, max_centrifuge); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -161,8 +161,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stgs_config = ideal_stgs; } - -void CascadeConfig::CalcStageFeatures() { +void CascadeConfig::PopulateStages() { double machine_tol = 0.01; int n_stages = n_enrich + n_strip; @@ -184,7 +183,6 @@ void CascadeConfig::CalcStageFeatures() { } } - int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; @@ -194,12 +192,12 @@ int CascadeConfig::FindTotalMachines() { return machines; } -void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { +void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { // Determine the ideal steady-state feed flows for this cascade design given // the maximum potential design feed rate feed_flow = max_feed; CalcFeedFlows(); - CalcStageFeatures(); + PopulateStages(); // Do design parameters require more centrifuges than what is available? int machines_needed = FindTotalMachines(); @@ -209,91 +207,112 @@ void CascadeConfig::DesignCascade(double max_feed, int max_centrifuges) { max_feed_from_machine = max_feed_from_machine / scaling_ratio; feed_flow = max_feed_from_machine; CalcFeedFlows(); - CalcStageFeatures(); + PopulateStages(); machines_needed = FindTotalMachines(); } n_machines = machines_needed; } -CascadeConfig CascadeConfig::Compute_Assay(double f_assay, double precision, - bool u_cut) { - CascadeConfig actual_cascade = (*this); +CascadeConfig CascadeConfig::ModelMissUsedCascade(double f_assay, + int modeling_opt, + double precision) { + CascadeConfig miss_used_cascade = (*this); + miss_used_cascade.PropagateAssay(f_assay); + + switch (modeling_opt) { + default: + miss_used_cascade.ComputeAssay(f_assay, precision); + break; + + case 1: + miss_used_cascade.UpdateCut(); + miss_used_cascade.UpdateFlow(); + break; + } + return miss_used_cascade; +} - // Initialiase Feeding stage - std::map::iterator it = actual_cascade.stgs_config.find(0); - it->second.feed_assay = f_assay; - if (u_cut) { +void CascadeConfig::UpdateFlow() { + // recompute the flow according to the new cuts + (*this).CalcFeedFlows(); + + double ratio = 1; + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + std::map::iterator it_real = + (*this).stgs_config.find(it->first); + double max_stg_flow = + it_real->second.n_machines * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + if (ratio < stg_flow_ratio) { + ratio = stg_flow_ratio; + } + } + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + it->second.feed_flow *= 1. / ratio; + } + (*this).feed_flow *= 1. / ratio; +} + +void CascadeConfig::UpdateCut() { + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { it->second.CutByAlphaBeta(); } +} + +void CascadeConfig::PropagateAssay(double f_assay) { + // Initialiase Feeding stage + std::map::iterator it = (*this).stgs_config.find(0); + it->second.feed_assay = f_assay; it->second.ProductAssay(); it->second.TailAssay(); // Propagate initialisation to all stages - for (int i = 0; i < actual_cascade.n_enrich; i++){ - it = actual_cascade.stgs_config.find(i); + for (int i = 0; i < (*this).n_enrich; i++) { + it = (*this).stgs_config.find(i); std::map::iterator it_feed; // Enrich stage -> feed = Product from Previous Stage - it_feed = actual_cascade.stgs_config.find(it->first - 1); - if (it->first > 0 && it_feed != actual_cascade.stgs_config.end()) { - it->second.feed_assay = it_feed->second.product_assay; - } - - // Update Product and Tail assay from feed assay - if (it->first != 0) { - if (u_cut) { - it->second.CutByAlphaBeta(); + it_feed = (*this).stgs_config.find(it->first - 1); + if (it->first > 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay = it_feed->second.product_assay; } + // Update Product and Tail assay from feed assay it->second.ProductAssay(); it->second.TailAssay(); } } - for (int i = 1; i <= actual_cascade.n_strip; i++){ - it = actual_cascade.stgs_config.find(-i); + for (int i = 1; i <= (*this).n_strip; i++) { + it = (*this).stgs_config.find(-i); std::map::iterator it_feed; // Striping stage -> feed = tails from Next Stage - it_feed = actual_cascade.stgs_config.find(it->first + 1); - if (it->first < 0 && it_feed != actual_cascade.stgs_config.end()) { - it->second.feed_assay = it_feed->second.tail_assay; - } - - // Update Product and Tail assay from feed assay - if (it->first != 0) { - if (u_cut) { - it->second.CutByAlphaBeta(); + it_feed = (*this).stgs_config.find(it->first + 1); + if (it->first < 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay = it_feed->second.tail_assay; } + // Update Product and Tail assay from feed assay it->second.ProductAssay(); it->second.TailAssay(); } } - if(u_cut){ - actual_cascade.CalcFeedFlows(); - double ratio = 1; - for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ - std::map::iterator it_real = (*this).stgs_config.find(it->first); - double max_stg_flow = it_real->second.n_machines *it_real->second.centrifuge.feed; - double stg_flow_ratio = it->second.feed_flow / max_stg_flow; - if (ratio < stg_flow_ratio){ - ratio = stg_flow_ratio; - } - } - for (it = actual_cascade.stgs_config.begin(); it != actual_cascade.stgs_config.end(); it++){ - it->second.feed_flow *= 1./ratio; - } - actual_cascade.feed_flow *= 1./ratio; - return actual_cascade; - } - // Looping to get the equilibrium +} + +void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (Diff_enrichment(actual_cascade, previous_cascade) > precision) { - previous_cascade = actual_cascade; - actual_cascade.stgs_config = Update_enrichment(actual_cascade, f_assay, u_cut); + while (DeltaEnrichment((*this), previous_cascade) > precision) { + previous_cascade = (*this); + (*this).stgs_config = IterrateEnrichment((*this), f_assay); } - return actual_cascade; } -double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, +double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, CascadeConfig p_enrichments) { if (p_enrichments.n_enrich == 0) { return 100.; @@ -319,8 +338,8 @@ double CascadeConfig::Diff_enrichment(CascadeConfig a_enrichments, return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::Update_enrichment( - CascadeConfig cascade, double f_assay, bool u_cut) { +std::map CascadeConfig::IterrateEnrichment( + CascadeConfig cascade, double f_assay) { CascadeConfig updated_enrichment = cascade; // mixing variables @@ -369,11 +388,7 @@ std::map CascadeConfig::Update_enrichment( // Update Stage feed assay it_new->second.feed_assay = stg_f_assay; // Update Beta values (from feed) -- Alpha & Cut are cte - if(u_cut){ - it_new->second.CutByAlphaBeta(); - } else{ - it_new->second.BetaByAlphaAndCut(); - } + it_new->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay it_new->second.ProductAssay(); it_new->second.TailAssay(); diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index cb2735b..e4bce3e 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -30,12 +30,18 @@ class CascadeConfig { // Solve the flow matrix from the stages cuts void CalcFeedFlows(); // DO something ?! - void CalcStageFeatures(); + void PopulateStages(); + // Scale the Casacde to meet the limitation in max feed or max centrifuges - void DesignCascade(double max_feed, int max_centrifuges); + void ScaleCascade(double max_feed, int max_centrifuges); + + CascadeConfig ModelMissUsedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay - CascadeConfig Compute_Assay(double feed_assay, double precision, bool u_cut = false); + void PropagateAssay(double f_assay); + void ComputeAssay(double f_assay, double precision = 1e-8); + void UpdateCut(); + void UpdateFlow(); double FeedFlow() { return feed_flow; } // Configuration of the centrifuges in the stages @@ -62,13 +68,13 @@ class CascadeConfig { double design_tail_assay; // Method to check the assays different between 2 cascades - double Diff_enrichment(CascadeConfig actual_enrichments, - CascadeConfig previous_enrichement); + double DeltaEnrichment(CascadeConfig actual_enrichments, + CascadeConfig previous_enrichment); // method computing one iteration, of the algorithm used to get the response // to non ideal feed assay - std::map Update_enrichment(CascadeConfig cascade, - double feed_assay, bool u_cut = false); + std::map IterrateEnrichment(CascadeConfig cascade, + double feed_assay); }; } // namespace mbmore diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 4a64971..32940c0 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -63,9 +63,9 @@ TEST(CascadeStage_Test, TestCascade) { // Now test assays when cascade is modified away from ideal design // (cascade optimized for natural uranium feed, now use 20% enriched double feed_assay_mod = 0.20; - cascade.DesignCascade(feed_c, 1000000); + cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.Compute_Assay(feed_assay_mod, 1e-31); + cascade.ModelMissUsedCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; @@ -105,7 +105,7 @@ TEST(CascadeStage_Test, TestCascadeDesign) { // not enough machines int max_centrifuges = 80; - cascade.DesignCascade(feed_c, max_centrifuges); + cascade.ScaleCascade(feed_c, max_centrifuges); int py_tot_mach = 80; double py_opt_feed = 1.30116169899e-05; @@ -114,7 +114,7 @@ TEST(CascadeStage_Test, TestCascadeDesign) { // more machines than requested capacity max_centrifuges = 1000; - cascade.DesignCascade(feed_c, max_centrifuges); + cascade.ScaleCascade(feed_c, max_centrifuges); py_tot_mach = 999; py_opt_feed = 0.0001667; @@ -145,7 +145,7 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.Compute_Assay(fa, 1e-17); + cascade = cascade.ModelMissUsedCascade(fa, 0, 1e-17); product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * @@ -183,7 +183,7 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.Compute_Assay(fa, 1e-17, true); + cascade = cascade.ModelMissUsedCascade(fa, 1, 1e-17); double alpha_ref = cascade.stgs_config[0].alpha; std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ From 6c0a266d053ef4a7f2366995ca8add9d215486bd Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:19:11 -0500 Subject: [PATCH 065/116] Removing some file not suppose to be there yet --- src/CascadeEnrich_tests.h | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h deleted file mode 100644 index 025911b..0000000 --- a/src/CascadeEnrich_tests.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ -#define MBMORE_SRC_CASCADEENRICH_TESTS_ - -#include - -#include - -#include "test_context.h" -#include "env.h" -#include "exchange_context.h" -#include "material.h" - -#include "CascadeEnrich.h" -#include "CascadeConfig.h" - -namespace mbmore { - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class CascadeEnrichTest : public ::testing::Test { - protected: - cyclus::TestContext tc_; - CascadeEnrich* src_facility; - std::string feed_commod, product_commod, feed_recipe, tails_commod; - cyclus::Composition::Ptr recipe; - TestFacility* trader; - - double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; - - bool order_prefs; - - double reserves; - - virtual void SetUp(); - virtual void TearDown(); - void InitParameters(); - void SetUpSource(); - cyclus::Material::Ptr GetMat(double qty); - /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 - cyclus::Material::Ptr GetReqMat(double qty, double enr); - void DoAddMat(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoRequest(); - cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); - /// @param nreqs the total number of requests - /// @param nvalid the number of requests that are valid - boost::shared_ptr< cyclus::ExchangeContext > - GetContext(int nreqs, int nvalid); -}; - -} // namespace cycamore -#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From f1ffe7d8cb3339833de2f046b034015c40535b29 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:14:46 -0500 Subject: [PATCH 066/116] removing methods reimplemented in CascadeConfig --- src/enrich_functions.cc | 122 ---------------------- src/enrich_functions_tests.cc | 187 ---------------------------------- 2 files changed, 309 deletions(-) delete mode 100644 src/enrich_functions_tests.cc diff --git a/src/enrich_functions.cc b/src/enrich_functions.cc index 16c8f31..c0c593b 100644 --- a/src/enrich_functions.cc +++ b/src/enrich_functions.cc @@ -44,38 +44,6 @@ std::pair StagesPerCascade(double alpha, double feed_assay, // Determine number of stages required to reach ideal cascade product assay // (requires integer number of stages, so output may exceed target assay) -std::pair FindNStages(double alpha, double feed_assay, - double product_assay, double waste_assay) { - using std::pair; - - int ideal_enrich_stage = 0; - int ideal_strip_stage = 0; - double stage_feed_assay = feed_assay; - double stage_product_assay = feed_assay; - double stage_waste_assay = feed_assay; // start w/waste of 1st enrich stage - - // Calculate number of enriching stages - while (stage_product_assay < product_assay) { - stage_product_assay = ProductAssayByAlpha(alpha, stage_feed_assay); - if (ideal_enrich_stage == 0) { - stage_waste_assay = WasteAssayByAlpha(alpha, stage_feed_assay); - } - ideal_enrich_stage += 1; - stage_feed_assay = stage_product_assay; - } - // Calculate number of stripping stages - stage_feed_assay = stage_waste_assay; - while (stage_waste_assay > waste_assay) { - stage_waste_assay = WasteAssayByAlpha(alpha, stage_feed_assay); - ideal_strip_stage += 1; - stage_feed_assay = stage_waste_assay; - } - - std::pair stages = - std::make_pair(ideal_enrich_stage, ideal_strip_stage); - return stages; -} - double ProductAssayFromNStages(double alpha, double feed_assay, double enrich_stages) { double A = @@ -135,86 +103,6 @@ double DelUByCascadeConfig(double product_assay, double waste_assay, return U_cascade / feed_assay; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Calculate steady-state flow rates into each cascade stage -// Linear system of equations in form AX = B, where A is nxn square matrix -// of linear equations for the flow rates of each stage and B are the external -// feeds for the stage. External feed is zero for all stages accept cascade -// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] -// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html -// -std::vector CalcFeedFlows(std::pair n_st, double cascade_feed, - double cut) { - // This is the Max # of stages in cascade. It cannot be passed in due to - // how memory is allocated and so must be hardcoded. It's been chosen - // to be much larger than it should ever need to be - int max_stages = 100; - - int n_enrich = n_st.first; - int n_strip = n_st.second; - int n_stages = n_st.first + n_st.second; - - // LAPACK takes the external flow feeds as B, and then returns a modified - // version of the same array now representing the solution flow rates. - - // Build Array with pointers - double flow_eqns[max_stages][max_stages]; - double flows[1][max_stages]; - - // build matrix of equations in this pattern - // [[ -1, 1-cut, 0, 0, 0] [[0] - // [cut, -1, 1-cut, 0, 0] [0] - // [ 0, cut, -1, 1-cut, 0] * X = [-1*cascade_feed] - // [ 0, 0, cut, -1, 1-cut] [0] - // [ 0, 0, 0, cut, -1]] [0]] - // - for (int row_idx = 0; row_idx < max_stages; row_idx++) { - // fill the array with zeros, then update individual elements as nonzero - flows[0][row_idx] = 0; - for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { - flow_eqns[fill_idx][row_idx] = 0; - } - // Required do to the artificial 'Max Stages' defn. Only calculate - // non-zero matrix elements where stages really exist. - if (row_idx < n_stages) { - int i = row_idx - n_strip; - int col_idx = n_strip + i; - flow_eqns[col_idx][row_idx] = -1; - if (col_idx != 0) { - flow_eqns[col_idx - 1][row_idx] = cut; - } - if (col_idx != n_stages - 1) { - flow_eqns[col_idx + 1][row_idx] = (1 - cut); - } - // Add the external feed for the cascade - if (i == 0) { - flows[0][row_idx] = -1 * cascade_feed; - } - } - } - - // LAPACK solver variables - int nrhs = 1; // 1 column solution - int lda = max_stages; // must be >= MAX(1,N) - int ldb = max_stages; // must be >= MAX(1,N) - int ipiv[max_stages]; - int info; - - // Solve the linear system - dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, - &info); - - // Check for success - if (info != 0) { - std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; - } - - std::vector final_flows; - for (int i = 0; i < n_stages; i++) { - final_flows.push_back(flows[0][i]); - } - return final_flows; -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine number of machines in each stage of the cascade, and total // output flow from each stage @@ -279,16 +167,6 @@ std::vector> CalcStageFeatures( return stage_info; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Determine total number of machines in the cascade from machines per stage -int FindTotalMachines(std::vector> stage_info) { - int machines_needed = 0; - std::vector>::const_iterator it; - for (it = stage_info.begin(); it != stage_info.end(); it++) { - machines_needed += it->first; - } - return machines_needed; -} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::pair DesignCascade(double design_feed, diff --git a/src/enrich_functions_tests.cc b/src/enrich_functions_tests.cc deleted file mode 100644 index ca2473d..0000000 --- a/src/enrich_functions_tests.cc +++ /dev/null @@ -1,187 +0,0 @@ -#include - -#include "enrich_functions.h" - -#include "agent_tests.h" -#include "context.h" -#include "facility_tests.h" - -namespace mbmore { - - // Benchmarked against mbmore_enrich_compare.ipynb - // https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs - namespace enrichfunctiontests { - // Fixed for a cascade separating out U235 from U238 in UF6 gas - const double M = 0.352; // kg/mol UF6 - const double dM = 0.003; // kg/mol U238 - U235 - const double x = 1000; // Pressure ratio (Glaser) - - // General cascade assumptions - const double flow_internal = 2.0 ; - const double eff = 1.0; - const double cut = 0.5; - - // Centrifuge params used in Python test code - // (based on Glaser SGS 2009 paper) - const double v_a = 485; // m/s - const double height = 0.5; // meters - const double diameter = 0.15; // meters - const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec - const double temp = 320.0 ; //Kelvin - - // Cascade params used in Python test code (Enrichment_Calculations.ipynb) - const double feed_assay = 0.0071; - const double product_assay = 0.035; - const double waste_assay = 0.001; - const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec - const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec - - //del U=7.0323281e-08 alpha=1.16321 - double delU = CalcDelU(v_a, height, diameter, feed_m, temp, cut, eff, - M, dM, x, flow_internal); - - double alpha = AlphaBySwu(delU, feed_m, cut, M); - const double tol_assay = 1e-5; - const double tol_qty = 1e-6; - const double tol_num = 1e-2; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Ideal cascade design, and then using away from ideal design - -TEST(Enrich_Functions_Test, TestCascade) { - double n_machines = MachinesPerCascade(delU, product_assay, - waste_assay, feed_c, product_c); - - double pycode_n_mach = 25990.392; - EXPECT_NEAR(n_machines, pycode_n_mach, tol_num); - - std::pair n_stages = FindNStages(alpha, feed_assay, - product_assay, - waste_assay); - int pycode_n_enrich_stage = 11; - int pycode_n_strip_stage = 13; - - - // int n_stage_enrich = (int) n_stages.first + 1; // Round up to next integer - // int n_stage_waste = (int) n_stages.second + 1; // Round up to next integer - int n_stage_enrich = n_stages.first; - int n_stage_waste = n_stages.second; - - EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); - EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); - - // Now test assays when cascade is modified away from ideal design - // (cascade optimized for natural uranium feed, now use 20% enriched - double feed_assay_mod = 0.20; - - double mod_product_assay = ProductAssayFromNStages(alpha, feed_assay_mod, - n_stage_enrich); - double mod_waste_assay = WasteAssayFromNStages(alpha, feed_assay_mod, - n_stage_waste); - - std::cout << "alpha " << alpha << " feed " << feed_assay_mod << " nstage " << n_stage_enrich << " unrounded stages " << n_stages.first << std::endl; - double pycode_mod_product_assay = 0.60085; - double pycode_mod_waste_assay = 0.0290846; - EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); - EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); - } - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine the output of the first enrich/strip stage of a cascade - // based on the design params for the cascade - TEST(Enrich_Functions_Test, TestStages) { - double product_assay_s = ProductAssayByAlpha(alpha, feed_assay); - double n_mach_e = MachinesPerStage(alpha, delU, feed_c); - double product_s = ProductPerEnrStage(alpha, feed_assay, - product_assay_s, feed_c); - - double enrich_waste = feed_c - product_s; - double enrich_waste_assay = (feed_c * feed_assay - product_s * - product_assay_s)/enrich_waste; - - double pycode_product_assay_s = 0.0082492; - double pycode_n_mach_e = 53.287; - double pycode_product_s = 0.0001408; - - EXPECT_NEAR(n_mach_e, pycode_n_mach_e, tol_num); - EXPECT_NEAR(product_assay_s, pycode_product_assay_s, tol_assay); - EXPECT_NEAR(product_s, pycode_product_s, tol_qty); - - double n_mach_w = MachinesPerStage(alpha, delU, enrich_waste); - double strip_waste_assay = WasteAssayByAlpha(alpha, enrich_waste_assay); - - // This AVERY EQN doesn't work for some reason - // double strip_waste = WastePerStripStage(alpha, enrich_waste_assay, - // strip_waste_assay, enrich_waste); - - double pycode_n_mach_w = 26.6127; - double pycode_waste_assay_s = 0.005117; - // double pycode_waste_s = 8.60660553717e-05; - - EXPECT_NEAR(n_mach_w, pycode_n_mach_w, tol_num); - EXPECT_NEAR(strip_waste_assay, pycode_waste_assay_s, tol_assay); - // EXPECT_NEAR(strip_waste, pycode_waste_s, tol_qty); - - } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// tests the steady state flow rates for a cascade -// -TEST(Enrich_Functions_Test, TestCascadeDesign) { - double fa = 0.10; - double pa = 0.20; - double wa = 0.05; - - std::vector pycode_flows = {0.00030693, 0.00061387, 0.0009208 , - 0.00122774, 0.00153467, 0.00127889, - 0.00102311, 0.00076734, 0.00051156, - 0.00025578}; - - - std::vector pycode_machines={59, 117, 175, 233, 291, 243, 194, - 146, 97, 49}; - - std::pair n_stages = FindNStages(alpha, fa, pa, wa); - std::vector flows = CalcFeedFlows(n_stages, feed_c, cut); - - // if # Machines for the stage is within tol_num of an integer - // then round down. Otherwise round up to the next integer machine to - // preserve steady-state flow calculations. - std::vector> stage_info = - CalcStageFeatures(fa, alpha, delU, cut, n_stages, flows); - - for (int i = 0; i < pycode_flows.size(); i++){ - EXPECT_NEAR(flows[i], pycode_flows[i], tol_num); - int nmach = stage_info[i].first; - EXPECT_EQ(nmach, pycode_machines[i]); - } - - // not enough machines - int max_centrifuges = 80; - std::pair design_params = DesignCascade(feed_c, alpha, delU, - cut, max_centrifuges, - n_stages); - int py_tot_mach = 79; - double py_opt_feed = 1.30116169899e-05; - - EXPECT_EQ(py_tot_mach, design_params.first); - EXPECT_NEAR(py_opt_feed, design_params.second, tol_qty); - - // more machines than requested capacity - max_centrifuges = 1000; - design_params = DesignCascade(feed_c, alpha, delU, - cut, max_centrifuges, - n_stages); - py_tot_mach = 986; - py_opt_feed = 0.000172728; - - EXPECT_EQ(py_tot_mach, design_params.first); - EXPECT_NEAR(py_opt_feed, design_params.second, tol_qty); - -} - - - } // namespace enrichfunctiontests -} // namespace mbmore From 6c7b7c0ec0b76d8300f8763813ba4e96e2d80e71 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:20:06 -0500 Subject: [PATCH 067/116] removing methods reimplemented in CascadeConfig --- src/enrich_functions.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/enrich_functions.h b/src/enrich_functions.h index 9916b70..cba6f99 100644 --- a/src/enrich_functions.h +++ b/src/enrich_functions.h @@ -15,11 +15,6 @@ extern "C" { } - // Calculates the number of stages needed in a cascade given the separation - // potential of a single centrifuge and the material assays - std::pair - FindNStages(double alpha, double feed_assay, double product_assay, - double Nwc); // Calculates the product assay after N enriching stages double ProductAssayFromNStages(double alpha, double feed_assay, @@ -68,10 +63,6 @@ extern "C" { double product_flow, double waste_flow, double feed_assay); - // Solves system of linear eqns to determine steady state flow rates - // in each stage of cascade - std::vector CalcFeedFlows(std::pair n_st, - double cascade_feed, double cut); // Determines the number of machines and product in each stage based // on the steady-state flows defined for the cascade. @@ -81,8 +72,6 @@ extern "C" { std::pair n_st, std::vector feed_flow); - // Determine total number of machines in the cascade from machines per stage - int FindTotalMachines(std::vector> stage_info); std::pair DesignCascade( double design_feed, double design_alpha, double design_delU, double cut, From 6e24a01a8748a90b33a8a3a793cd9ab22d099188 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:23:35 -0500 Subject: [PATCH 068/116] readd missing file --- src/CascadeEnrich_tests.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h new file mode 100644 index 0000000..22a650d --- /dev/null +++ b/src/CascadeEnrich_tests.h @@ -0,0 +1,51 @@ +#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ +#define MBMORE_SRC_CASCADEENRICH_TESTS_ + +#include + +#include + +#include "test_context.h" +#include "env.h" +#include "exchange_context.h" +#include "material.h" + +#include "CascadeEnrich.h" + +namespace mbmore { + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class CascadeEnrichTest : public ::testing::Test { + protected: + cyclus::TestContext tc_; + CascadeEnrich* src_facility; + std::string feed_commod, product_commod, feed_recipe, tails_commod; + cyclus::Composition::Ptr recipe; + TestFacility* trader; + + double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; + + bool order_prefs; + + double reserves; + + virtual void SetUp(); + virtual void TearDown(); + void InitParameters(); + void SetUpSource(); + cyclus::Material::Ptr GetMat(double qty); + /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 + cyclus::Material::Ptr GetReqMat(double qty, double enr); + void DoAddMat(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoRequest(); + cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); + /// @param nreqs the total number of requests + /// @param nvalid the number of requests that are valid + boost::shared_ptr< cyclus::ExchangeContext > + GetContext(int nreqs, int nvalid); +}; + +} // namespace cycamore +#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From ee9021db51ff0f67e911957860a75ea8e4550b01 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 18 Oct 2019 09:30:29 -0500 Subject: [PATCH 069/116] Updating calls to StageConfig w/ Getters/Setters --- src/CascadeConfig.cc | 82 +++++++++++++++++++------------------- src/CascadeConfig.h | 14 +++---- src/CascadeConfig_tests.cc | 6 +-- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 9ae97db..53256c1 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -53,8 +53,8 @@ void CascadeConfig::CalcFeedFlows() { int n_stages = n_enrich + n_strip; int max_stages = n_stages; if (n_stages > max_stages) { - std::cout << "To many stages in the can't calculated the " - "thoerritical flows..." + std::cout << "Too many stages in the cascade." + "Can't calculate the theoretical flows..." << std::endl; exit(1); } @@ -76,7 +76,7 @@ void CascadeConfig::CalcFeedFlows() { for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { flow_eqns[fill_idx][row_idx] = 0; } - // Required do to the artificial 'Max Stages' defn. Only calculate + // Required to do the artificial 'Max Stages' defn. Only calculate // non-zero matrix elements where stages really exist. if (row_idx < n_stages) { int stg_i = row_idx - n_strip; @@ -85,13 +85,13 @@ void CascadeConfig::CalcFeedFlows() { if (row_idx != 0) { std::map::iterator it = stgs_config.find(stg_i - 1); if (it != stgs_config.end()) { - flow_eqns[col_idx - 1][row_idx] = it->second.cut; + flow_eqns[col_idx - 1][row_idx] = it->second.cut(); } } if (row_idx != n_stages - 1) { std::map::iterator it = stgs_config.find(stg_i + 1); if (it != stgs_config.end()) { - flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut); + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut()); } } // Add the external feed for the cascade @@ -120,7 +120,7 @@ void CascadeConfig::CalcFeedFlows() { int i = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { - it->second.feed_flow = flows[0][i]; + it->second.feed_flow(flows[0][i]); i++; } } @@ -133,17 +133,17 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, // Initialisation of Feeding stage (I == 0) StageConfig stg; - stg.alpha = -1; - stg.DU = -1; + stg.alpha(-1); + stg.DU(-1); stg.centrifuge = centrifuge; stg.BuildIdealStg(f_assay, precision); int stg_i = 0; ideal_stgs[stg_i] = stg; - double ref_alpha = ideal_stgs[0].alpha; - double ref_du = ideal_stgs[0].DU; + double ref_alpha = ideal_stgs[0].alpha(); + double ref_du = ideal_stgs[0].DU(); // Calculate number of enriching stages - while (stg.product_assay < product_assay) { - stg.BuildIdealStg(stg.product_assay, precision); + while (stg.product_assay() < product_assay) { + stg.BuildIdealStg(); stg_i++; ideal_stgs.insert(std::make_pair(stg_i, stg)); } @@ -152,8 +152,9 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg_i = 0; stg = ideal_stgs[stg_i]; // Calculate number of stripping stages - while (stg.tail_assay > waste_assay) { - stg.BuildIdealStg(stg.tail_assay, precision); + while (stg.tail_assay() > waste_assay) { + stg.product_assay(stg.tail_assay()) + stg.BuildIdealStg(); stg_i--; ideal_stgs.insert(std::make_pair(stg_i, stg)); } @@ -172,14 +173,15 @@ void CascadeConfig::PopulateStages() { std::cout << "Bad Stage number" << std::endl; exit(1); } - double n_mach_exact = it->second.MachinesPerStage(); + it->second.MachinesNeededPerStage(); + double n_mach_exact = it->second.n_machines(); // unless the ideal number of machines is Very close to an integer value, // round up to next integer to preserve steady-state flow balance int n_mach = (int)n_mach_exact; if (std::abs(n_mach_exact - n_mach) > machine_tol) { n_mach = int(n_mach_exact) + 1; } - it->second.n_machines = n_mach; + it->second.n_machines(n_mach); } } @@ -187,7 +189,7 @@ int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { - machines += it->second.n_machines; + machines += it->second.n_machines(); } return machines; } @@ -213,29 +215,29 @@ void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { n_machines = machines_needed; } -CascadeConfig CascadeConfig::ModelMissUsedCascade(double f_assay, +CascadeConfig CascadeConfig::ModelMisusedCascade(double f_assay, int modeling_opt, double precision) { - CascadeConfig miss_used_cascade = (*this); - miss_used_cascade.PropagateAssay(f_assay); + CascadeConfig misused_cascade = (*this); + misused_cascade.PropagateAssay(f_assay); switch (modeling_opt) { default: - miss_used_cascade.ComputeAssay(f_assay, precision); + misused_cascade.ComputeAssay(f_assay, precision); break; case 1: - miss_used_cascade.UpdateCut(); - miss_used_cascade.UpdateFlow(); + misused_cascade.UpdateCut(); + misused_cascade.UpdateFlow(); break; } - return miss_used_cascade; + return misused_cascade; } void CascadeConfig::UpdateFlow() { - // recompute the flow according to the new cuts + // recompute the flow according to the new cuts (*this).CalcFeedFlows(); - + double ratio = 1; std::map::iterator it; for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); @@ -243,15 +245,15 @@ void CascadeConfig::UpdateFlow() { std::map::iterator it_real = (*this).stgs_config.find(it->first); double max_stg_flow = - it_real->second.n_machines * it_real->second.centrifuge.feed; - double stg_flow_ratio = it->second.feed_flow / max_stg_flow; + it_real->second.n_machines() * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow() / max_stg_flow; if (ratio < stg_flow_ratio) { ratio = stg_flow_ratio; } } for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { - it->second.feed_flow *= 1. / ratio; + it->second.feed_flow(second.feed_flow() * (1. / ratio)); } (*this).feed_flow *= 1. / ratio; } @@ -267,7 +269,7 @@ void CascadeConfig::UpdateCut() { void CascadeConfig::PropagateAssay(double f_assay) { // Initialiase Feeding stage std::map::iterator it = (*this).stgs_config.find(0); - it->second.feed_assay = f_assay; + it->second.feed_assay(f_assay); it->second.ProductAssay(); it->second.TailAssay(); @@ -280,7 +282,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { it_feed = (*this).stgs_config.find(it->first - 1); if (it->first > 0) { if (it_feed != (*this).stgs_config.end()) { - it->second.feed_assay = it_feed->second.product_assay; + it->second.feed_assay(it_feed->second.product_assay()); } // Update Product and Tail assay from feed assay it->second.ProductAssay(); @@ -295,7 +297,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { it_feed = (*this).stgs_config.find(it->first + 1); if (it->first < 0) { if (it_feed != (*this).stgs_config.end()) { - it->second.feed_assay = it_feed->second.tail_assay; + it->second.feed_assay(it_feed->second.tail_assay()); } // Update Product and Tail assay from feed assay it->second.ProductAssay(); @@ -328,11 +330,11 @@ double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, p_enrichments.stgs_config.find(it->first); if (it2 != p_enrichments.stgs_config.end()) { square_feed_diff += - pow(it->second.feed_assay - it2->second.feed_assay, 2); + pow(it->second.feed_assay() - it2->second.feed_assay(), 2); square_product_diff += - pow(it->second.product_assay - it2->second.product_assay, 2); + pow(it->second.product_assay() - it2->second.product_assay(), 2); square_waste_diff += - pow(it->second.tail_assay - it2->second.tail_assay, 2); + pow(it->second.tail_assay() - it2->second.tail_assay(), 2); } } return square_feed_diff + square_product_diff + square_waste_diff; @@ -364,12 +366,12 @@ std::map CascadeConfig::IterrateEnrichment( up_flow = 0; if (it_down != cascade.stgs_config.end()) { - down_assay = it_down->second.product_assay; - down_flow = it_down->second.feed_flow * it_down->second.cut; + down_assay = it_down->second.product_assay(); + down_flow = it_down->second.feed_flow() * it_down->second.cut(); } if (it_up != cascade.stgs_config.end()) { - up_assay = it_up->second.tail_assay; - up_flow = it_up->second.feed_flow * (1 - it_up->second.cut); + up_assay = it_up->second.tail_assay(); + up_flow = it_up->second.feed_flow() * (1 - it_up->second.cut()); } // Mix the Product and the Tail to have the correct Feed Assay @@ -386,7 +388,7 @@ std::map CascadeConfig::IterrateEnrichment( updated_enrichment.stgs_config.find(i); // Update Stage feed assay - it_new->second.feed_assay = stg_f_assay; + it_new->second.feed_assay(stg_f_assay); // Update Beta values (from feed) -- Alpha & Cut are cte it_new->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index e4bce3e..ae4ec5e 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -29,13 +29,13 @@ class CascadeConfig { // Solve the flow matrix from the stages cuts void CalcFeedFlows(); - // DO something ?! + // Establish machines needed in each stage void PopulateStages(); - - // Scale the Casacde to meet the limitation in max feed or max centrifuges + + // Scale the Cascade to meet the limitation in max feed or max centrifuges void ScaleCascade(double max_feed, int max_centrifuges); - CascadeConfig ModelMissUsedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); + CascadeConfig ModelMisusedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay void PropagateAssay(double f_assay); @@ -57,7 +57,7 @@ class CascadeConfig { // total number of machine in the Cascade int n_machines; // real feed flow (constrained by the cascade design/total number of - // machine/max feed flow + // machine/max feed flow) double feed_flow; //design feed assay @@ -71,8 +71,8 @@ class CascadeConfig { double DeltaEnrichment(CascadeConfig actual_enrichments, CascadeConfig previous_enrichment); - // method computing one iteration, of the algorithm used to get the response - // to non ideal feed assay + // method computing one iteration of the algorithm used to get the response + // to non ideal feed assay std::map IterrateEnrichment(CascadeConfig cascade, double feed_assay); }; diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 32940c0..9d4dc6e 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -65,7 +65,7 @@ TEST(CascadeStage_Test, TestCascade) { double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.ModelMissUsedCascade(feed_assay_mod, 0, 1e-31); + cascade.ModelMisusedCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; @@ -145,7 +145,7 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMissUsedCascade(fa, 0, 1e-17); + cascade = cascade.ModelMisusedCascade(fa, 0, 1e-17); product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * @@ -183,7 +183,7 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMissUsedCascade(fa, 1, 1e-17); + cascade = cascade.ModelMisusedCascade(fa, 1, 1e-17); double alpha_ref = cascade.stgs_config[0].alpha; std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ From 00588f6827036d0f025be7efba57bc5fa1568205 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 28 Oct 2019 14:12:41 -0500 Subject: [PATCH 070/116] Updating BuildIdealStg calls by first updating ProductAssay --- src/CascadeConfig.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 53256c1..2701ad4 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -136,13 +136,16 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg.alpha(-1); stg.DU(-1); stg.centrifuge = centrifuge; - stg.BuildIdealStg(f_assay, precision); + stg.feed_assay(f_assay); + stg.precision(precision); + stg.BuildIdealStg(); int stg_i = 0; ideal_stgs[stg_i] = stg; double ref_alpha = ideal_stgs[0].alpha(); double ref_du = ideal_stgs[0].DU(); // Calculate number of enriching stages while (stg.product_assay() < product_assay) { + stg.feed_assay(stg.product_assay()); stg.BuildIdealStg(); stg_i++; ideal_stgs.insert(std::make_pair(stg_i, stg)); @@ -153,7 +156,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg = ideal_stgs[stg_i]; // Calculate number of stripping stages while (stg.tail_assay() > waste_assay) { - stg.product_assay(stg.tail_assay()) + stg.feed_assay(stg.tail_assay()) stg.BuildIdealStg(); stg_i--; ideal_stgs.insert(std::make_pair(stg_i, stg)); From f52f32f9babbe19c748c9c54674a3dfe26c67b31 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 29 Oct 2019 14:43:40 -0500 Subject: [PATCH 071/116] Minor grammar changes. --- src/CascadeConfig.cc | 8 ++++---- src/CascadeConfig.h | 4 ++-- src/CascadeConfig_tests.cc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 2701ad4..6a7b7d4 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -256,7 +256,7 @@ void CascadeConfig::UpdateFlow() { } for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { - it->second.feed_flow(second.feed_flow() * (1. / ratio)); + it->second.feed_flow(second.feed_flow() / ratio); } (*this).feed_flow *= 1. / ratio; } @@ -270,7 +270,7 @@ void CascadeConfig::UpdateCut() { } void CascadeConfig::PropagateAssay(double f_assay) { - // Initialiase Feeding stage + // Initialise Feeding stage std::map::iterator it = (*this).stgs_config.find(0); it->second.feed_assay(f_assay); it->second.ProductAssay(); @@ -313,7 +313,7 @@ void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; while (DeltaEnrichment((*this), previous_cascade) > precision) { previous_cascade = (*this); - (*this).stgs_config = IterrateEnrichment((*this), f_assay); + (*this).stgs_config = IterateEnrichment((*this), f_assay); } } @@ -343,7 +343,7 @@ double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::IterrateEnrichment( +std::map CascadeConfig::IterateEnrichment( CascadeConfig cascade, double f_assay) { CascadeConfig updated_enrichment = cascade; diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index ae4ec5e..982d3fa 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -66,14 +66,14 @@ class CascadeConfig { double design_product_assay; //design tail assay double design_tail_assay; - + // Method to check the assays different between 2 cascades double DeltaEnrichment(CascadeConfig actual_enrichments, CascadeConfig previous_enrichment); // method computing one iteration of the algorithm used to get the response // to non ideal feed assay - std::map IterrateEnrichment(CascadeConfig cascade, + std::map IterateEnrichment(CascadeConfig cascade, double feed_assay); }; diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 9d4dc6e..fbd9a0d 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -61,7 +61,7 @@ TEST(CascadeStage_Test, TestCascade) { EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); // Now test assays when cascade is modified away from ideal design - // (cascade optimized for natural uranium feed, now use 20% enriched + // (cascade optimized for natural uranium feed, now use 20% enriched) double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = From c481b8655dedfc35a8fe6aa2c53d4a3a0fe7b698 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 30 Oct 2019 15:15:29 -0500 Subject: [PATCH 072/116] Adding Stages functionality to test cases --- src/CascadeConfig.cc | 14 +++++----- src/CascadeConfig.h | 2 +- src/CascadeConfig_tests.cc | 56 +++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 6a7b7d4..7abaa6d 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -218,23 +218,23 @@ void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { n_machines = machines_needed; } -CascadeConfig CascadeConfig::ModelMisusedCascade(double f_assay, +CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, int modeling_opt, double precision) { - CascadeConfig misused_cascade = (*this); - misused_cascade.PropagateAssay(f_assay); + CascadeConfig misuse_cascade = (*this); + misuse_cascade.PropagateAssay(f_assay); switch (modeling_opt) { default: - misused_cascade.ComputeAssay(f_assay, precision); + misuse_cascade.ComputeAssay(f_assay, precision); break; case 1: - misused_cascade.UpdateCut(); - misused_cascade.UpdateFlow(); + misuse_cascade.UpdateCut(); + misuse_cascade.UpdateFlow(); break; } - return misused_cascade; + return misuse_cascade; } void CascadeConfig::UpdateFlow() { diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index 982d3fa..4590299 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -35,7 +35,7 @@ class CascadeConfig { // Scale the Cascade to meet the limitation in max feed or max centrifuges void ScaleCascade(double max_feed, int max_centrifuges); - CascadeConfig ModelMisusedCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); + CascadeConfig ModelMisuseCascade(double f_assay, int modeling_opt = 0, double precision = 1e-8); // Compute the response of the cascade to a non ideal feed assay void PropagateAssay(double f_assay); diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index fbd9a0d..37dfa21 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -65,12 +65,12 @@ TEST(CascadeStage_Test, TestCascade) { double feed_assay_mod = 0.20; cascade.ScaleCascade(feed_c, 1000000); CascadeConfig cascade_non_ideal = - cascade.ModelMisusedCascade(feed_assay_mod, 0, 1e-31); + cascade.ModelMisuseCascade(feed_assay_mod, 0, 1e-31); double mod_product_assay = - cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay; + cascade_non_ideal.stgs_config[n_stage_enrich - 1].product_assay(); double mod_waste_assay = - cascade_non_ideal.stgs_config[-n_stage_waste].product_assay; + cascade_non_ideal.stgs_config[-n_stage_waste].product_assay(); double pycode_mod_product_assay = 0.8189; EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); @@ -97,9 +97,9 @@ TEST(CascadeStage_Test, TestCascadeDesign) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); for (int i = 0; i < pycode_flows.size(); i++) { - EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow, + EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow(), pycode_flows[i], tol_num); - int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines; + int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines(); EXPECT_EQ(nmach, pycode_machines[i]); } @@ -129,12 +129,12 @@ TEST(CascadeStage_Test, TestUpdateAssay) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); double product_assay = - cascade.stgs_config[cascade.n_enrich - 1].product_assay; - double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); double feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); @@ -145,13 +145,13 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMisusedCascade(fa, 0, 1e-17); - product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay; - tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade = cascade.ModelMisuseCascade(fa, 0, 1e-17); + product_assay = cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); tail_from_assay = product_flow * (product_assay - fa) / (fa - tail_assay); @@ -167,12 +167,12 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 100); double product_assay = - cascade.stgs_config[cascade.n_enrich - 1].product_assay; - double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay; - double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow * - cascade.stgs_config[cascade.n_enrich - 1].cut; - double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow * - (1 - cascade.stgs_config[-cascade.n_strip].cut); + cascade.stgs_config[cascade.n_enrich - 1].product_assay(); + double tail_assay = cascade.stgs_config[-cascade.n_strip].tail_assay(); + double product_flow = cascade.stgs_config[cascade.n_enrich - 1].feed_flow() * + cascade.stgs_config[cascade.n_enrich - 1].cut(); + double tail_flow = cascade.stgs_config[-cascade.n_strip].feed_flow() * + (1 - cascade.stgs_config[-cascade.n_strip].cut()); double feed_from_assay = product_flow * (product_assay - tail_assay) / (fa - tail_assay); @@ -183,12 +183,12 @@ TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); fa = 0.2; - cascade = cascade.ModelMisusedCascade(fa, 1, 1e-17); - double alpha_ref = cascade.stgs_config[0].alpha; + cascade = cascade.ModelMisuseCascade(fa, 1, 1e-17); + double alpha_ref = cascade.stgs_config[0].alpha(); std::map::iterator it; for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++){ - EXPECT_EQ(alpha_ref, it->second.alpha); - EXPECT_EQ(alpha_ref, it->second.beta); + EXPECT_EQ(alpha_ref, it->second.alpha()); + EXPECT_EQ(alpha_ref, it->second.beta()); } } From 8846850c7c211353d6a596551989781e62a5aba0 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 073/116] initial import --- src/CascadeEnrich_tests.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From 95fc2bc346a94c818f98c852bbbd18b4726994c1 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:19:11 -0500 Subject: [PATCH 074/116] Removing some file not suppose to be there yet --- src/CascadeEnrich_tests.h | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h deleted file mode 100644 index 025911b..0000000 --- a/src/CascadeEnrich_tests.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ -#define MBMORE_SRC_CASCADEENRICH_TESTS_ - -#include - -#include - -#include "test_context.h" -#include "env.h" -#include "exchange_context.h" -#include "material.h" - -#include "CascadeEnrich.h" -#include "CascadeConfig.h" - -namespace mbmore { - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class CascadeEnrichTest : public ::testing::Test { - protected: - cyclus::TestContext tc_; - CascadeEnrich* src_facility; - std::string feed_commod, product_commod, feed_recipe, tails_commod; - cyclus::Composition::Ptr recipe; - TestFacility* trader; - - double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; - - bool order_prefs; - - double reserves; - - virtual void SetUp(); - virtual void TearDown(); - void InitParameters(); - void SetUpSource(); - cyclus::Material::Ptr GetMat(double qty); - /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 - cyclus::Material::Ptr GetReqMat(double qty, double enr); - void DoAddMat(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoRequest(); - cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); - /// @param nreqs the total number of requests - /// @param nvalid the number of requests that are valid - boost::shared_ptr< cyclus::ExchangeContext > - GetContext(int nreqs, int nvalid); -}; - -} // namespace cycamore -#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From a203be6084e27ad95be3733bdacbde28fe5729db Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:23:35 -0500 Subject: [PATCH 075/116] readd missing file --- src/CascadeEnrich_tests.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h new file mode 100644 index 0000000..22a650d --- /dev/null +++ b/src/CascadeEnrich_tests.h @@ -0,0 +1,51 @@ +#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ +#define MBMORE_SRC_CASCADEENRICH_TESTS_ + +#include + +#include + +#include "test_context.h" +#include "env.h" +#include "exchange_context.h" +#include "material.h" + +#include "CascadeEnrich.h" + +namespace mbmore { + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class CascadeEnrichTest : public ::testing::Test { + protected: + cyclus::TestContext tc_; + CascadeEnrich* src_facility; + std::string feed_commod, product_commod, feed_recipe, tails_commod; + cyclus::Composition::Ptr recipe; + TestFacility* trader; + + double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; + + bool order_prefs; + + double reserves; + + virtual void SetUp(); + virtual void TearDown(); + void InitParameters(); + void SetUpSource(); + cyclus::Material::Ptr GetMat(double qty); + /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 + cyclus::Material::Ptr GetReqMat(double qty, double enr); + void DoAddMat(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoRequest(); + cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); + /// @param nreqs the total number of requests + /// @param nvalid the number of requests that are valid + boost::shared_ptr< cyclus::ExchangeContext > + GetContext(int nreqs, int nvalid); +}; + +} // namespace cycamore +#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From 9a1844dd9eb312ec9d8ad98c446d684bfb4883b5 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 076/116] initial import --- src/CascadeConfig.cc | 27 ++++----------------------- src/CascadeEnrich_tests.h | 1 + 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 7abaa6d..64c7815 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -45,19 +45,9 @@ CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, // http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html // void CascadeConfig::CalcFeedFlows() { - // This is the Max # of stages in It cannot be passed in due to - // how memory is allocated and so must be hardcoded. It's been chosen - // to be much larger than it should ever need to be - // total number of stages int n_stages = n_enrich + n_strip; int max_stages = n_stages; - if (n_stages > max_stages) { - std::cout << "Too many stages in the cascade." - "Can't calculate the theoretical flows..." - << std::endl; - exit(1); - } // Build Array with pointers double flow_eqns[max_stages][max_stages]; @@ -156,7 +146,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, stg = ideal_stgs[stg_i]; // Calculate number of stripping stages while (stg.tail_assay() > waste_assay) { - stg.feed_assay(stg.tail_assay()) + stg.feed_assay(stg.tail_assay()); stg.BuildIdealStg(); stg_i--; ideal_stgs.insert(std::make_pair(stg_i, stg)); @@ -166,7 +156,6 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, } void CascadeConfig::PopulateStages() { - double machine_tol = 0.01; int n_stages = n_enrich + n_strip; for (int i = 0; i < n_stages; i++) { @@ -177,14 +166,6 @@ void CascadeConfig::PopulateStages() { exit(1); } it->second.MachinesNeededPerStage(); - double n_mach_exact = it->second.n_machines(); - // unless the ideal number of machines is Very close to an integer value, - // round up to next integer to preserve steady-state flow balance - int n_mach = (int)n_mach_exact; - if (std::abs(n_mach_exact - n_mach) > machine_tol) { - n_mach = int(n_mach_exact) + 1; - } - it->second.n_machines(n_mach); } } @@ -250,15 +231,15 @@ void CascadeConfig::UpdateFlow() { double max_stg_flow = it_real->second.n_machines() * it_real->second.centrifuge.feed; double stg_flow_ratio = it->second.feed_flow() / max_stg_flow; - if (ratio < stg_flow_ratio) { + if (ratio > stg_flow_ratio) { ratio = stg_flow_ratio; } } for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { - it->second.feed_flow(second.feed_flow() / ratio); + it->second.feed_flow(it->second.feed_flow() * ratio); } - (*this).feed_flow *= 1. / ratio; + (*this).feed_flow *= ratio; } void CascadeConfig::UpdateCut() { diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h index 22a650d..025911b 100644 --- a/src/CascadeEnrich_tests.h +++ b/src/CascadeEnrich_tests.h @@ -11,6 +11,7 @@ #include "material.h" #include "CascadeEnrich.h" +#include "CascadeConfig.h" namespace mbmore { From fbb159bf2a1bf3139cceea67895fc2580da1d406 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:19:11 -0500 Subject: [PATCH 077/116] Removing some file not suppose to be there yet --- src/CascadeEnrich_tests.h | 52 --------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h deleted file mode 100644 index 025911b..0000000 --- a/src/CascadeEnrich_tests.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ -#define MBMORE_SRC_CASCADEENRICH_TESTS_ - -#include - -#include - -#include "test_context.h" -#include "env.h" -#include "exchange_context.h" -#include "material.h" - -#include "CascadeEnrich.h" -#include "CascadeConfig.h" - -namespace mbmore { - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class CascadeEnrichTest : public ::testing::Test { - protected: - cyclus::TestContext tc_; - CascadeEnrich* src_facility; - std::string feed_commod, product_commod, feed_recipe, tails_commod; - cyclus::Composition::Ptr recipe; - TestFacility* trader; - - double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; - - bool order_prefs; - - double reserves; - - virtual void SetUp(); - virtual void TearDown(); - void InitParameters(); - void SetUpSource(); - cyclus::Material::Ptr GetMat(double qty); - /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 - cyclus::Material::Ptr GetReqMat(double qty, double enr); - void DoAddMat(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoRequest(); - cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); - cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); - /// @param nreqs the total number of requests - /// @param nvalid the number of requests that are valid - boost::shared_ptr< cyclus::ExchangeContext > - GetContext(int nreqs, int nvalid); -}; - -} // namespace cycamore -#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From ffc56beb8e1aa25a1fde5e6ba51bcd75a980165c Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:23:35 -0500 Subject: [PATCH 078/116] readd missing file --- src/CascadeEnrich_tests.h | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/CascadeEnrich_tests.h diff --git a/src/CascadeEnrich_tests.h b/src/CascadeEnrich_tests.h new file mode 100644 index 0000000..22a650d --- /dev/null +++ b/src/CascadeEnrich_tests.h @@ -0,0 +1,51 @@ +#ifndef MBMORE_SRC_CASCADEENRICH_TESTS_ +#define MBMORE_SRC_CASCADEENRICH_TESTS_ + +#include + +#include + +#include "test_context.h" +#include "env.h" +#include "exchange_context.h" +#include "material.h" + +#include "CascadeEnrich.h" + +namespace mbmore { + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +class CascadeEnrichTest : public ::testing::Test { + protected: + cyclus::TestContext tc_; + CascadeEnrich* src_facility; + std::string feed_commod, product_commod, feed_recipe, tails_commod; + cyclus::Composition::Ptr recipe; + TestFacility* trader; + + double feed_assay, tails_assay, inv_size, swu_capacity, max_enrich; + + bool order_prefs; + + double reserves; + + virtual void SetUp(); + virtual void TearDown(); + void InitParameters(); + void SetUpSource(); + cyclus::Material::Ptr GetMat(double qty); + /// @param enr the enrichment percent, i.e. for 5 w/o, enr = 0.05 + cyclus::Material::Ptr GetReqMat(double qty, double enr); + void DoAddMat(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoRequest(); + cyclus::Material::Ptr DoBid(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoOffer(cyclus::Material::Ptr mat); + cyclus::Material::Ptr DoEnrich(cyclus::Material::Ptr mat, double qty); + /// @param nreqs the total number of requests + /// @param nvalid the number of requests that are valid + boost::shared_ptr< cyclus::ExchangeContext > + GetContext(int nreqs, int nvalid); +}; + +} // namespace cycamore +#endif // MBMORE_SRC_CASCADEENRICH_FACILITY_TESTS_ From f9fc717dac19150a306454ee8cb60ff3c3271bd1 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 8 Nov 2019 13:51:10 -0600 Subject: [PATCH 079/116] Calculate machines if it hasn't been done before (FindTotalMachines()) --- src/CascadeConfig.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 64c7815..710b9a6 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -173,6 +173,7 @@ int CascadeConfig::FindTotalMachines() { int machines = 0; std::map::iterator it; for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + if (it->second.n_machines() == -1) it->second.MachinesNeededPerStage(); machines += it->second.n_machines(); } return machines; From 422931fbc12fecb65a7fdecc3e6663e4f9822333 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 8 Nov 2019 14:04:13 -0600 Subject: [PATCH 080/116] Adding case comments & DeltaEnrichment precision. --- src/CascadeConfig.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 710b9a6..96260ef 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -206,6 +206,8 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, CascadeConfig misuse_cascade = (*this); misuse_cascade.PropagateAssay(f_assay); + // Default: alpha, cut = constant; beta = varying + // Case 1: alpha = beta, cut = varying switch (modeling_opt) { default: misuse_cascade.ComputeAssay(f_assay, precision); @@ -293,16 +295,17 @@ void CascadeConfig::PropagateAssay(double f_assay) { void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade) > precision) { + while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { previous_cascade = (*this); (*this).stgs_config = IterateEnrichment((*this), f_assay); } } double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, - CascadeConfig p_enrichments) { + CascadeConfig p_enrichments, + double precision) { if (p_enrichments.n_enrich == 0) { - return 100.; + return 100. * std::abs(precision); } double square_feed_diff = 0; double square_product_diff = 0; From f6319633a091b4e88bc49a915cf466ffb76f8c61 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 8 Nov 2019 14:08:33 -0600 Subject: [PATCH 081/116] Correcting CascadeConfig definition --- src/CascadeConfig.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index 4590299..d2c754f 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -69,7 +69,8 @@ class CascadeConfig { // Method to check the assays different between 2 cascades double DeltaEnrichment(CascadeConfig actual_enrichments, - CascadeConfig previous_enrichment); + CascadeConfig previous_enrichment, + double precision); // method computing one iteration of the algorithm used to get the response // to non ideal feed assay From 347b384f57f29d2531f605aa2568b7d93cbe2a4d Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Mon, 11 Nov 2019 13:39:40 -0600 Subject: [PATCH 082/116] Make precision absolute to avoid user-entered negative value. --- src/CascadeConfig.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 96260ef..61ddbee 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -295,7 +295,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { void CascadeConfig::ComputeAssay(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { + while (DeltaEnrichment((*this), previous_cascade, precision) > std::abs(precision)) { previous_cascade = (*this); (*this).stgs_config = IterateEnrichment((*this), f_assay); } From 4594214f953c23ee560634bd7a9500f654041da3 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 13 Nov 2019 13:59:52 -0600 Subject: [PATCH 083/116] Updating expected number of machines in TestCascadeDesign --- src/CascadeConfig_tests.cc | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 37dfa21..fb23879 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -8,8 +8,7 @@ namespace mbmore { -// Benchmarked against mbmore_enrich_compare.ipynb -// https://github.com/mbmcgarry/data_analysis/tree/master/enrich_calcs +// Benchmarked using a regression test (expected values calculated manually) namespace cascadeconfig_tests { // Fixed for a cascade separating out U235 from U238 in UF6 gas const double M = 0.352; // kg/mol UF6 @@ -21,15 +20,14 @@ const double flow_internal = 2.0; const double eff = 1.0; const double cut = 0.5; -// Centrifuge params used in Python test code -// (based on Glaser SGS 2009 paper) +// Centrifuge parameters based on Glaser SGS 2009 paper const double v_a = 485; // m/s const double height = 0.5; // meters const double diameter = 0.15; // meters const double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec const double temp = 320.0; // Kelvin -// Cascade params used in Python test code (Enrichment_Calculations.ipynb) +// Cascade params used in calculating expected values const double feed_assay = 0.0071; const double product_assay = 0.035; const double waste_assay = 0.001; @@ -37,6 +35,7 @@ const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, flow_internal); + // del U=7.0323281e-08 alpha=1.16321 double delU = centrifuge.ComputeDeltaU(cut); @@ -51,14 +50,14 @@ TEST(CascadeStage_Test, TestCascade) { CascadeConfig cascade; cascade.centrifuge = centrifuge; cascade.BuildIdealCascade(feed_assay, product_assay, waste_assay, 1e-8); - int pycode_n_enrich_stage = 11; - int pycode_n_strip_stage = 12; + int expected_n_enrich_stage = 11; + int expected_n_strip_stage = 12; // integer int n_stage_enrich = cascade.n_enrich; int n_stage_waste = cascade.n_strip; - EXPECT_EQ(n_stage_enrich, pycode_n_enrich_stage); - EXPECT_EQ(n_stage_waste, pycode_n_strip_stage); + EXPECT_EQ(n_stage_enrich, expected_n_enrich_stage); + EXPECT_EQ(n_stage_waste, expected_n_strip_stage); // Now test assays when cascade is modified away from ideal design // (cascade optimized for natural uranium feed, now use 20% enriched) @@ -72,11 +71,11 @@ TEST(CascadeStage_Test, TestCascade) { double mod_waste_assay = cascade_non_ideal.stgs_config[-n_stage_waste].product_assay(); - double pycode_mod_product_assay = 0.8189; - EXPECT_NEAR(mod_product_assay, pycode_mod_product_assay, tol_assay); + double expected_mod_product_assay = 0.8189; + EXPECT_NEAR(mod_product_assay, expected_mod_product_assay, tol_assay); - double pycode_mod_waste_assay = 0.11198; - EXPECT_NEAR(mod_waste_assay, pycode_mod_waste_assay, tol_assay); + double expected_mod_waste_assay = 0.11198; + EXPECT_NEAR(mod_waste_assay, expected_mod_waste_assay, tol_assay); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -87,39 +86,42 @@ TEST(CascadeStage_Test, TestCascadeDesign) { double pa = 0.20; double wa = 0.05; - std::vector pycode_flows = { + std::vector expected_flows = { 0.00030693, 0.00061387, 0.0009208, 0.00122774, 0.00153467, 0.00127889, 0.00102311, 0.00076734, 0.00051156, 0.00025578}; - std::vector pycode_machines = {80, 149, 210, 264, 312, - 241, 180, 127, 80, 38}; + std::vector expected_machines = {25, 46, 65, 82, 97, 76, + 57, 40, 26, 13}; + //std::vector expected_machines = {80, 149, 210, 264, 312, +// 241, 180, 127, 80, 38}; CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); - for (int i = 0; i < pycode_flows.size(); i++) { + for (int i = 0; i < expected_flows.size(); i++) { EXPECT_NEAR(cascade.stgs_config[i - cascade.n_strip].feed_flow(), - pycode_flows[i], tol_num); + expected_flows[i], tol_num); int nmach = cascade.stgs_config[i - cascade.n_strip].n_machines(); - EXPECT_EQ(nmach, pycode_machines[i]); + EXPECT_EQ(nmach, expected_machines[i]); } // not enough machines int max_centrifuges = 80; cascade.ScaleCascade(feed_c, max_centrifuges); - int py_tot_mach = 80; - double py_opt_feed = 1.30116169899e-05; + int expected_tot_mach = 80; + double expected_opt_feed = 4.11669203083e-05; + //double expected_opt_feed = 1.30116169899e-05; - EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); - EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); // more machines than requested capacity max_centrifuges = 1000; cascade.ScaleCascade(feed_c, max_centrifuges); - py_tot_mach = 999; - py_opt_feed = 0.0001667; + expected_tot_mach = 999; + expected_opt_feed = 0.0001667; - EXPECT_EQ(py_tot_mach, cascade.FindTotalMachines()); - EXPECT_NEAR(py_opt_feed, cascade.FeedFlow(), tol_qty); + EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); + EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); } TEST(CascadeStage_Test, TestUpdateAssay) { From d3240fd52106912c66d4c7287e3bb3606b2a545f Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 15 Nov 2019 15:03:05 -0600 Subject: [PATCH 084/116] Recalculating expected cascade feed flows and adding test-case comments --- src/CascadeConfig_tests.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index fb23879..fba9127 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -45,7 +45,7 @@ const double tol_num = 1e-2; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Ideal cascade design, and then using away from ideal design - +// TEST(CascadeStage_Test, TestCascade) { CascadeConfig cascade; cascade.centrifuge = centrifuge; @@ -79,7 +79,7 @@ TEST(CascadeStage_Test, TestCascade) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// tests the steady state flow rates for a cascade +// Tests the steady state flow rates for a cascade // TEST(CascadeStage_Test, TestCascadeDesign) { double fa = 0.10; @@ -92,8 +92,6 @@ TEST(CascadeStage_Test, TestCascadeDesign) { std::vector expected_machines = {25, 46, 65, 82, 97, 76, 57, 40, 26, 13}; - //std::vector expected_machines = {80, 149, 210, 264, 312, -// 241, 180, 127, 80, 38}; CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); @@ -109,21 +107,23 @@ TEST(CascadeStage_Test, TestCascadeDesign) { cascade.ScaleCascade(feed_c, max_centrifuges); int expected_tot_mach = 80; double expected_opt_feed = 4.11669203083e-05; - //double expected_opt_feed = 1.30116169899e-05; EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); // more machines than requested capacity - max_centrifuges = 1000; + max_centrifuges = 600; cascade.ScaleCascade(feed_c, max_centrifuges); - expected_tot_mach = 999; - expected_opt_feed = 0.0001667; + expected_tot_mach = 527; + expected_opt_feed = 0.0002814; EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Tests feed flows in misue model A, where alpha & cut are constant +// TEST(CascadeStage_Test, TestUpdateAssay) { double fa = 0.10; double pa = 0.20; @@ -162,6 +162,9 @@ TEST(CascadeStage_Test, TestUpdateAssay) { EXPECT_NEAR(tail_flow, tail_from_assay, 1e-3); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Test feed flows in misuse model B, where alpha = beta +// TEST(CascadeStage_Test, TestUpdateAlphaBetaFix) { double fa = 0.10; double pa = 0.20; From 5aed737fbd139c0f7b3cc4b37b21e5ce3ca9b6d9 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:21:00 -0500 Subject: [PATCH 085/116] initial addition --- src/CascadeEnrich.cc | 317 ++++++++++++++++++++----------------- src/CascadeEnrich.h | 210 ++++++++++-------------- src/CascadeEnrich_tests.cc | 248 +++-------------------------- 3 files changed, 281 insertions(+), 494 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index 64dc116..cbc7ac5 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -1,48 +1,46 @@ // Implements the CascadeEnrich class #include "CascadeEnrich.h" #include "behavior_functions.h" -#include "enrich_functions.h" #include "sim_init.h" #include +#include #include #include #include #include -#include - namespace mbmore { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) +CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) : cyclus::Facility(ctx), - feed_recipe(""), - max_centrifuges(), - design_feed_assay(), - design_product_assay(), - design_tails_assay(), - centrifuge_velocity(485.0), - temp(320.0), - height(0.5), - diameter(0.15), - machine_feed(15), - max_enrich(1), - design_feed_flow(0), - feed_commod(""), - product_commod(""), - tails_commod(""), - order_prefs(true) {} + feed_recipe(""), + max_centrifuges(), + design_feed_assay(), + design_product_assay(), + design_tails_assay(), + centrifuge_velocity(485.0), + temp(320.0), + height(0.5), + diameter(0.15), + machine_feed(15), + max_enrich(1), + design_feed_flow(100), + L_over_F(2), + feed_commod(""), + product_commod(""), + tails_commod(""), + miss_use_model(0), + order_prefs(true) {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CascadeEnrich::~CascadeEnrich() {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::string CascadeEnrich::str() { std::stringstream ss; - ss << cyclus::Facility::str() - << " with enrichment facility parameters:" - << " * SWU capacity: " << SwuCapacity() - << " * Tails assay: " << tails_assay << " * Feed assay: " << FeedAssay() + ss << cyclus::Facility::str() << " with enrichment facility parameters:" + << " * Tails assay: " << design_tails_assay << " * Feed assay: " << design_feed_assay << " * Input cyclus::Commodity: " << feed_commod << " * Output cyclus::Commodity: " << product_commod << " * Tails cyclus::Commodity: " << tails_commod; @@ -50,72 +48,59 @@ std::string CascadeEnrich::str() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CascadeEnrich::Build(cyclus::Agent* parent) { +void CascadeEnrich::EnterNotify() { using cyclus::Material; - - tails_assay = design_tails_assay; - - // Calculate ideal machine performance - double design_delU = CalcDelU(centrifuge_velocity, height, diameter, - Mg2kgPerSec(machine_feed), temp, - cut, eff, M, dM, x, flow_internal); - double design_alpha = AlphaBySwu(design_delU, Mg2kgPerSec(machine_feed), - cut, M); - - // Design ideal cascade based on target feed flow and product assay - std::pair n_stages = - FindNStages(design_alpha, design_feed_assay, design_product_assay, - design_tails_assay); - - // TODO DELETE THIS, STAGES ARE ALREADY INTS - // set as internal state variables - // int truncates but we need # of stages to assure target values, - // so if the number is 5.1 we need 6. - // n_enrich_stages = int(n_stages.first) + 1; - // n_strip_stages = int(n_stages.second) + 1; - n_enrich_stages = n_stages.first; - n_strip_stages = n_stages.second; - - std::pair cascade_info = DesignCascade(FlowPerSec(design_feed_flow), - design_alpha, - design_delU, - cut, max_centrifuges, - n_stages); - - max_feed_inventory = FlowPerMon(cascade_info.second); - // Number of machines times swu per machine - SwuCapacity(cascade_info.first * FlowPerMon(design_delU)); - - Facility::Build(parent); + cyclus::Facility::EnterNotify(); + centrifuge = CentrifugeConfig(); + // Update Centrifuge paramter from the user input: + centrifuge.v_a = centrifuge_velocity; + centrifuge.height = height; + centrifuge.diameter = diameter; + centrifuge.feed = machine_feed / 1000 / 1000; + centrifuge.temp = temp; + centrifuge.flow_internal = L_over_F; + + cascade = CascadeConfig(centrifuge, design_feed_assay, design_product_assay, + design_tails_assay, FlowPerSec(design_feed_flow), + max_centrifuges, precision); + + std::map::iterator it; + for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); + it++) { + std::cout << "stg " << it->first; + std::cout << " FA: " << it->second.feed_assay; + std::cout << " PA: " << it->second.product_assay; + std::cout << " TA: " << it->second.tail_assay; + std::cout << " feed_flow: " << it->second.feed_flow; + std::cout << " cut: " << it->second.cut; + std::cout << " alpha: " << it->second.alpha; + std::cout << " beta: " << it->second.beta; + std::cout << " machine: " << it->second.n_machines; + std::cout << std::endl; + } + std::cout << "Dsign Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; + if (max_feed_inventory > 0) { + inventory.capacity(max_feed_inventory); + } if (initial_feed > 0) { - inventory.Push( - Material::Create( - this, initial_feed, context()->GetRecipe(feed_recipe))); + inventory.Push(Material::Create(this, initial_feed, + context()->GetRecipe(feed_recipe))); } - LOG(cyclus::LEV_DEBUG2, "EnrFac") << "CascadeEnrich " - << " entering the simuluation: "; + << " entering the simuluation: "; LOG(cyclus::LEV_DEBUG2, "EnrFac") << str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CascadeEnrich::Tick() { - - current_swu_capacity = SwuCapacity(); - - } +void CascadeEnrich::Tick() {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::Tock() { using cyclus::toolkit::RecordTimeSeries; - LOG(cyclus::LEV_INFO4, "EnrFac") << prototype() << " used " - << intra_timestep_swu_ << " SWU"; - RecordTimeSeries(this, intra_timestep_swu_); LOG(cyclus::LEV_INFO4, "EnrFac") << prototype() << " used " << intra_timestep_feed_ << " feed"; RecordTimeSeries(this, intra_timestep_feed_); - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -149,7 +134,6 @@ void CascadeEnrich::AdjustMatlPrefs( if (order_prefs == false) { return; } - cyclus::PrefMap::type::iterator reqit; // Loop over all requests @@ -168,7 +152,7 @@ void CascadeEnrich::AdjustMatlPrefs( bool u235_mass = 0; for (int bidit = 0; bidit < bids_vector.size(); bidit++) { - int new_pref = bidit + 1; + int new_pref = bidit + 10; // For any bids with U-235 qty=0, set pref to zero. if (!u235_mass) { @@ -188,11 +172,11 @@ void CascadeEnrich::AdjustMatlPrefs( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::AcceptMatlTrades( const std::vector, - cyclus::Material::Ptr> >& responses) { + cyclus::Material::Ptr>>& responses) { // see // http://stackoverflow.com/questions/5181183/boostshared-ptr-and-inheritance std::vector, - cyclus::Material::Ptr> >::const_iterator it; + cyclus::Material::Ptr>>::const_iterator it; for (it = responses.begin(); it != responses.end(); ++it) { AddMat_(it->second); } @@ -241,7 +225,8 @@ void CascadeEnrich::AddMat_(cyclus::Material::Ptr mat) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::set::Ptr> -CascadeEnrich::GetMatlBids(cyclus::CommodMap::type& out_requests) { +CascadeEnrich::GetMatlBids( + cyclus::CommodMap::type& out_requests) { using cyclus::Bid; using cyclus::BidPortfolio; using cyclus::CapacityConstraint; @@ -287,27 +272,34 @@ CascadeEnrich::GetMatlBids(cyclus::CommodMap::type& out_reques std::vector*>::iterator it; for (it = commod_requests.begin(); it != commod_requests.end(); ++it) { Request* req = *it; - Material::Ptr mat = req->target(); - double request_enrich = cyclus::toolkit::UraniumAssay(mat); - if (ValidReq(req->target()) && - ((request_enrich < max_enrich) || - (cyclus::AlmostEq(request_enrich, max_enrich)))) { - Material::Ptr offer = Offer_(req->target()); - commod_port->AddBid(req, offer, this); - } + Material::Ptr offer = Offer_(req->target()); + // The offer might not match the required enrichment ! it just produce + // what it can according to the cascade configuration and the feed asays + commod_port->AddBid(req, offer, this); } - Converter::Ptr sc(new SWUConverter(FeedAssay(), tails_assay)); - Converter::Ptr nc(new NatUConverter(FeedAssay(), tails_assay)); - CapacityConstraint swu(swu_capacity, sc); - CapacityConstraint natu(inventory.quantity(), nc); - commod_port->AddConstraint(swu); - commod_port->AddConstraint(natu); - - LOG(cyclus::LEV_INFO5, "EnrFac") - << prototype() << " adding a swu constraint of " << swu.capacity(); + // overbidding (bidding on every offer) + // add an overall production capacity constraint + + // correct the actual inventory quantity by the amount of Uranium in it... + double feed_qty = inventory.quantity(); + Material::Ptr natu_matl = inventory.Pop(feed_qty, cyclus::eps_rsrc()); + inventory.Push(natu_matl); + cyclus::toolkit::MatQuery mq(natu_matl); + std::set nucs; + nucs.insert(922350000); + nucs.insert(922380000); + double u_frac = mq.mass_frac(nucs); + double cor_feed_qty = feed_qty * u_frac; + double production_capacity = + ProductFlow(std::min(cor_feed_qty, MaxFeedFlow(FeedAssay(feed_qty)))); + cyclus::CapacityConstraint production_contraint( + production_capacity); + commod_port->AddConstraint(production_contraint); LOG(cyclus::LEV_INFO5, "EnrFac") - << prototype() << " adding a natu constraint of " << natu.capacity(); + << prototype() << " adding production capacity constraint of " + << production_capacity; + ports.insert(commod_port); } return ports; @@ -315,21 +307,18 @@ CascadeEnrich::GetMatlBids(cyclus::CommodMap::type& out_reques // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::GetMatlTrades( - const std::vector >& trades, + const std::vector>& trades, std::vector, - cyclus::Material::Ptr> >& responses) { + cyclus::Material::Ptr>>& responses) { using cyclus::Material; using cyclus::Trade; - intra_timestep_swu_ = 0; intra_timestep_feed_ = 0; - - std::vector >::const_iterator it; + std::vector>::const_iterator it; for (it = trades.begin(); it != trades.end(); ++it) { double qty = it->amt; std::string commod_type = it->bid->request()->commodity(); Material::Ptr response; - // Figure out whether material is tails or enriched, // if tails then make transfer of material if (commod_type == tails_commod) { @@ -352,29 +341,26 @@ void CascadeEnrich::GetMatlTrades( ss << "is being asked to provide more than its current inventory."; throw cyclus::ValueError(Agent::InformErrorMsg(ss.str())); } - if (cyclus::IsNegative(current_swu_capacity)) { - throw cyclus::ValueError("EnrFac " + prototype() + - " is being asked to provide more than" + - " its SWU capacity."); - } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, - double qty) { + double qty) { using cyclus::Material; using cyclus::ResCast; using cyclus::toolkit::Assays; using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; using cyclus::toolkit::FeedQty; using cyclus::toolkit::TailsQty; - // get enrichment parameters - Assays assays(FeedAssay(), UraniumAssay(mat), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); + double feed_qty = FeedRequired(qty); + + double feed_assay = FeedAssay(feed_qty); + double product_assay = ProductAssay(feed_assay); + + double tails_assay = TailsAssay(FeedAssay(feed_qty)); + double tails_mass = TailsFlow(feed_qty); // Determine the composition of the natural uranium // (ie. U-235+U-238/TotalMass) double pop_qty = inventory.quantity(); @@ -386,8 +372,7 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, nucs.insert(922350000); nucs.insert(922380000); double natu_frac = mq.mass_frac(nucs); - double feed_req = natu_req / natu_frac; - + double feed_req = feed_qty / natu_frac; // pop amount from inventory and blob it into one material Material::Ptr r; try { @@ -398,12 +383,9 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, r = inventory.Pop(feed_req, cyclus::eps_rsrc()); } } catch (cyclus::Error& e) { - NatUConverter nc(FeedAssay(), tails_assay); std::stringstream ss; ss << " tried to remove " << feed_req << " from its inventory of size " - << inventory.quantity() - << " and the conversion of the material into natu is " - << nc.convert(mat); + << inventory.quantity(); throw cyclus::ValueError(Agent::InformErrorMsg(ss.str())); } @@ -413,46 +395,34 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, Material::Ptr response = r->ExtractComp(qty, comp); tails.Push(r); - current_swu_capacity -= swu_req; - - intra_timestep_swu_ += swu_req; - intra_timestep_feed_ += feed_req; - RecordEnrichment_(feed_req, swu_req); + RecordEnrichment_(feed_req); LOG(cyclus::LEV_INFO5, "EnrFac") << prototype() << " has performed an enrichment: "; LOG(cyclus::LEV_INFO5, "EnrFac") << " * Feed Qty: " << feed_req; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Feed Assay: " - << assays.Feed() * 100; + LOG(cyclus::LEV_INFO5, "EnrFac") << " * Feed Assay: " << feed_assay * 100; LOG(cyclus::LEV_INFO5, "EnrFac") << " * Product Qty: " << qty; LOG(cyclus::LEV_INFO5, "EnrFac") << " * Product Assay: " - << assays.Product() * 100; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Qty: " - << TailsQty(qty, assays); - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Assay: " - << assays.Tails() * 100; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * SWU: " << swu_req; - LOG(cyclus::LEV_INFO5, "EnrFac") << " * Current SWU capacity: " - << current_swu_capacity; + << product_assay * 100; + LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Qty: " << tails_mass; + LOG(cyclus::LEV_INFO5, "EnrFac") << " * Tails Assay: " << tails_assay * 100; return response; } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CascadeEnrich::RecordEnrichment_(double natural_u, double swu) { +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CascadeEnrich::RecordEnrichment_(double natural_u) { using cyclus::Context; using cyclus::Agent; LOG(cyclus::LEV_DEBUG1, "EnrFac") << prototype() << " has enriched a material:"; LOG(cyclus::LEV_DEBUG1, "EnrFac") << " * Amount: " << natural_u; - LOG(cyclus::LEV_DEBUG1, "EnrFac") << " * SWU: " << swu; Context* ctx = Agent::context(); ctx->NewDatum("Enrichments") ->AddVal("ID", id()) ->AddVal("Time", ctx->time()) ->AddVal("Natural_Uranium", natural_u) - ->AddVal("SWU", swu) ->Record(); } @@ -464,10 +434,13 @@ cyclus::Material::Ptr CascadeEnrich::Request_() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cyclus::Material::Ptr CascadeEnrich::Offer_(cyclus::Material::Ptr mat) { - cyclus::toolkit::MatQuery q(mat); + double feed_assay = FeedAssay(mat->quantity()); + double product_assay = ProductAssay(feed_assay); + cyclus::CompMap comp; - comp[922350000] = q.atom_frac(922350000); - comp[922380000] = q.atom_frac(922380000); + comp[922350000] = product_assay; + comp[922380000] = 1 - product_assay; + return cyclus::Material::CreateUntracked( mat->quantity(), cyclus::Composition::CreateFromAtom(comp)); } @@ -479,22 +452,76 @@ bool CascadeEnrich::ValidReq(const cyclus::Material::Ptr mat) { return (u238 > 0 && u235 / (u235 + u238) > tails_assay); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double CascadeEnrich::FeedAssay() { +double CascadeEnrich::FeedAssay(double quantity) { using cyclus::Material; if (inventory.empty()) { return 0; } - double pop_qty = inventory.quantity(); + double pop_qty = std::min(inventory.quantity(), quantity); cyclus::Material::Ptr fission_matl = inventory.Pop(pop_qty, cyclus::eps_rsrc()); inventory.Push(fission_matl); return cyclus::toolkit::UraniumAssay(fission_matl); } +double CascadeEnrich::ProductAssay(double feed_assay) { + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.rbegin()->second.product_assay; +} +double CascadeEnrich::TailsAssay(double feed_assay) { + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.begin()->second.tail_assay; +} + +double CascadeEnrich::MaxFeedFlow(double feed_assay){ + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + + return FlowPerMon(cascade_tmp.FeedFlow()); + +} + +double CascadeEnrich::FeedRequired(double prod_qty) { + double max_feed_flow = MaxFeedFlow(FeedAssay(inventory.quantity())); + double max_product_flow = ProductFlow(max_feed_flow); + double feed_required = max_feed_flow / max_product_flow * prod_qty; + + max_feed_flow = MaxFeedFlow(FeedAssay(feed_required)); + max_product_flow = ProductFlow(max_feed_flow); + double corrected_feed_required = max_feed_flow / max_product_flow * prod_qty; + double diff_feed = std::abs(feed_required - corrected_feed_required); + + while (diff_feed > precision) { + // reset feed_required + feed_required = corrected_feed_required; + + max_feed_flow = MaxFeedFlow(FeedAssay(feed_required)); + max_product_flow = ProductFlow(max_feed_flow); + corrected_feed_required = max_feed_flow / max_product_flow * prod_qty; + diff_feed = std::abs(feed_required - corrected_feed_required); + } + + return corrected_feed_required; +} + +double CascadeEnrich::ProductFlow(double feed_flow) { + double feed_assay = FeedAssay(feed_flow); + double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); + CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; + double product_flow = last_stg.feed_flow * last_stg.cut; + return feed_ratio * FlowPerMon(product_flow); +} + +double CascadeEnrich::TailsFlow(double feed_flow) { + // this assume mass flow conservation + return feed_flow - ProductFlow(feed_flow); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - extern "C" cyclus::Agent* ConstructCascadeEnrich(cyclus::Context* ctx) { return new CascadeEnrich(ctx); } - + } // namespace mbmore diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index eceb46a..56837c5 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -5,6 +5,8 @@ #include "cyclus.h" #include "sim_init.h" +#include "CascadeConfig.h" +#include "CentrifugeConfig.h" /* Working with cycamore Develop build: 3ada148442de636d @@ -37,77 +39,6 @@ B) Change cascade feed assay */ namespace mbmore { -/// @class SWUConverter -/// -/// @brief The SWUConverter is a simple Converter class for material to -/// determine the amount of SWU required for their proposed enrichment -class SWUConverter : public cyclus::Converter { - public: - SWUConverter(double feed_commod, double tails) - : feed_(feed_commod), tails_(tails) {} - virtual ~SWUConverter() {} - - /// @brief provides a conversion for the SWU required - virtual double convert( - cyclus::Material::Ptr m, cyclus::Arc const* a = NULL, - cyclus::ExchangeTranslationContext const* ctx = - NULL) const { - cyclus::toolkit::Assays assays(feed_, cyclus::toolkit::UraniumAssay(m), - tails_); - return cyclus::toolkit::SwuRequired(m->quantity(), assays); - } - - /// @returns true if Converter is a SWUConverter and feed and tails equal - virtual bool operator==(Converter& other) const { - SWUConverter* cast = dynamic_cast(&other); - return cast != NULL && feed_ == cast->feed_ && tails_ == cast->tails_; - } - - private: - double feed_, tails_; -}; - - -/// @class NatUConverter -/// -/// @brief The NatUConverter is a simple Converter class for material to -/// determine the amount of natural uranium required for their proposed -/// enrichment -class NatUConverter : public cyclus::Converter { - public: - NatUConverter(double feed_commod, double tails) - : feed_(feed_commod), tails_(tails) {} - virtual ~NatUConverter() {} - - // virtual std::string version() { return CYCAMORE_VERSION; } - - /// @brief provides a conversion for the amount of natural Uranium required - virtual double convert( - cyclus::Material::Ptr m, cyclus::Arc const* a = NULL, - cyclus::ExchangeTranslationContext const* ctx = - NULL) const { - cyclus::toolkit::Assays assays(feed_, cyclus::toolkit::UraniumAssay(m), - tails_); - cyclus::toolkit::MatQuery mq(m); - std::set nucs; - nucs.insert(922350000); - nucs.insert(922380000); - - double natu_frac = mq.mass_frac(nucs); - double natu_req = cyclus::toolkit::FeedQty(m->quantity(), assays); - return natu_req / natu_frac; - } - - /// @returns true if Converter is a NatUConverter and feed and tails equal - virtual bool operator==(Converter& other) const { - NatUConverter* cast = dynamic_cast(&other); - return cast != NULL && feed_ == cast->feed_ && tails_ == cast->tails_; - } - - private: - double feed_, tails_; -}; - class CascadeEnrich : public cyclus::Facility { #pragma cyclus note { \ @@ -134,13 +65,13 @@ class CascadeEnrich : public cyclus::Facility { // --- Facility Members --- /// perform module-specific tasks when entering the simulation - virtual void Build(cyclus::Agent* parent); + //virtual void Build(cyclus::Agent* parent); // --- // --- Agent Members --- /// Each facility is prompted to do its beginning-of-time-step /// stuff at the tick of the timer. - + virtual void EnterNotify(); /// @param time is the time to perform the tick virtual void Tick(); @@ -188,13 +119,6 @@ class CascadeEnrich : public cyclus::Facility { inventory.capacity(size); } - inline void SwuCapacity(double capacity) { - swu_capacity = capacity; - current_swu_capacity = swu_capacity; - } - - inline double SwuCapacity() const { return swu_capacity; } - // TODO: MAKE THESE CONVERSIONS TOOLKIT FNS and have them explicitly check // timestep duration @@ -208,9 +132,9 @@ class CascadeEnrich : public cyclus::Facility { } inline double Mg2kgPerSec(double feed_mg_per_sec) { - return feed_mg_per_sec / (1e6); + return feed_mg_per_sec / (1e6); } - + /// @brief Determines if a particular material is a valid request to respond /// to. Valid requests must contain U235 and U238 and must have a relative /// U235-to-U238 ratio less than this facility's tails_assay(). @@ -223,7 +147,7 @@ class CascadeEnrich : public cyclus::Facility { private: /// @brief calculates the feed assay based on the unenriched inventory - double FeedAssay(); + double FeedAssay(double quantity); /// @brief adds a material into the natural uranium inventory @@ -245,55 +169,64 @@ class CascadeEnrich : public cyclus::Facility { cyclus::Material::Ptr Enrich_(cyclus::Material::Ptr mat, double qty); /// @brief records and enrichment with the cyclus::Recorder - void RecordEnrichment_(double natural_u, double swu); + void RecordEnrichment_(double natural_u); + + + // Not physical constants but fixed assumptions for a cascade separating + // out U235 from U238 in UF6 gas +//group all the characteristic of a centrifuges + CentrifugeConfig centrifuge; + CascadeConfig cascade; + double precision = 1e-15; + + + const double secpermonth = 60.*60.*24.*(365.25/12.); // Set to design_tails at beginning of simulation. Gets reset if // facility is used off-design - double tails_assay; + double tails_assay; - // These state variables are constrained by the design input params at - // the start of the simulation: - // Set by max feed for an individual machine - double design_delU; - double design_alpha; - // Set by design assays (feed, product, tails) int n_enrich_stages; int n_strip_stages; // Set by maximum allowable centrifuges - double max_feed_inventory; - double swu_capacity; - - // Not physical constants but fixed assumptions for a cascade separating - // out U235 from U238 in UF6 gas - const double M = 0.352; // kg/mol UF6 - const double dM = 0.003; // kg/mol U238 - U235 - const double x = 1000; // Pressure ratio (Glaser) - - const double flow_internal = 2.0; // can vary from 2-4 - const double eff = 1.0; // typical efficiencies <0.6 - const double cut = 0.5; // target for ideal cascade + double ProductAssay(double feed_assay); + double ProductFlow(double feed_flow); + double TailsAssay(double feed_assay); + double TailsFlow(double feed_flow); + double FeedRequired(double prod_qty); + double MaxFeedFlow(double feed_assay); - const double secpermonth = 60*60*24*(365.25/12); - - private: #pragma cyclus var { \ "tooltip" : "feed recipe", \ "doc" : "recipe for enrichment facility feed commodity", \ - "uilabel" : "Feed Recipe", "uitype" : "recipe" } + "uilabel" : "Feed Recipe", \ + "uitype" : "recipe" } std::string feed_recipe; #pragma cyclus var { \ - "default": 0, "tooltip": "initial uranium reserves (kg)", \ + "default": 0, \ + "tooltip": "initial uranium reserves (kg)", \ "uilabel": "Initial Feed Inventory", \ "doc": "amount of natural uranium stored at the enrichment " \ "facility at the beginning of the simulation (kg)" } double initial_feed; + + #pragma cyclus var { \ + "default": 1e299, "tooltip": "max inventory of feed material (kg)", \ + "uilabel": "Maximum Feed Inventory", \ + "uitype": "range", \ + "range": [0.0, 1e299], \ + "doc": "maximum total inventory of natural uranium in " \ + "the enrichment facility (kg)" \ + } + double max_feed_inventory; #pragma cyclus var { \ - "default": 0, "tooltip": "design feed flow (kg/mon)", \ + "default": 100, \ + "tooltip": "design feed flow (kg/mon)", \ "uilabel": "Design Feed Flow", \ "doc": "Target amount of feed material to be processed by the" \ " facility (kg/mon). Either this or max_centrifuges is used to constrain" \ @@ -301,63 +234,90 @@ class CascadeEnrich : public cyclus::Facility { double design_feed_flow; #pragma cyclus var { \ - "default" : 0, "tooltip" : "number of centrifuges available ", \ + "default" : 1000, \ + "tooltip" : "number of centrifuges available ", \ "uilabel" : "Number of Centrifuges", \ "doc" : "number of centrifuges available to make the cascade" } int max_centrifuges; // TODO: USE FEED RECIPE TO DETERMINE FEED ASSAY!!! #pragma cyclus var { \ - "default": 0.0071, "tooltip": "initial uranium reserves (kg)", \ + "default": 0.0071, \ + "tooltip": "initial uranium reserves (kg)", \ "uilabel": "Initial feed assay", \ "doc": "desired fraction of U235 in feed material (should be consistent "\ "with feed recipe" } double design_feed_assay; #pragma cyclus var { \ - "default" : 0.035, "tooltip" : "Initial target product assay", \ + "default" : 0.035, \ + "tooltip" : "Initial target product assay", \ "uilabel" : "Target product assay", \ "doc" : "desired fraction of U235 in product" } double design_product_assay; #pragma cyclus var { \ - "default" : 0.003, "tooltip" : "Initial target tails assay", \ + "default" : 0.003, \ + "tooltip" : "Initial target tails assay", \ "uilabel" : "Target tails assay", \ "doc" : "desired fraction of U235 in tails" } double design_tails_assay; #pragma cyclus var { \ - "default" : 320.0, "tooltip" : "Centrifuge temperature (Kelvin)", \ + "default" : 320.0, \ + "tooltip" : "Centrifuge temperature (Kelvin)", \ "uilabel" : "Centrifuge temperature (Kelvin)", \ "doc" : "temperature at which centrifuges are operated (Kelvin)" } double temp; #pragma cyclus var { \ - "default" : 485.0, "tooltip" : "Centrifuge velocity (m/s)", \ + "default" : 485.0, \ + "tooltip" : "Centrifuge velocity (m/s)", \ "uilabel" : "Centrifuge velocity (m/s)", \ "doc" : "operational centrifuge velocity (m/s) at the outer radius (a)"} double centrifuge_velocity; #pragma cyclus var { \ - "default" : 0.5, "tooltip" : "Centrifuge height (m)", \ + "default" : 0.5, \ + "tooltip" : "Centrifuge height (m)", \ "uilabel" : "Centrifuge height (m)", \ "doc" : "height of centrifuge (m)"} double height; #pragma cyclus var { \ - "default" : 0.15, "tooltip" : "Centrifuge diameter (m)", \ + "default" : 0.15, \ + "tooltip" : "Centrifuge diameter (m)", \ "uilabel" : "Centrifuge diameter (m)", \ "doc" : "diameter of centrifuge (m)"} double diameter; #pragma cyclus var { \ - "default" : 15.0, "tooltip" : "Centrifuge feed rate (mg/sec)", \ + "default" : 2, \ + "tooltip" : "Centrifuge L/F* ", \ + "uilabel" : "Centrifuge Countercurrent to feed ratio", \ + "doc" : "Countercurrent to feed ratio"} + double L_over_F; + +#pragma cyclus var { \ + "default" : 15.0, \ + "tooltip" : "Centrifuge feed rate (mg/sec)", \ "uilabel" : "Max feed rate for single centrifuge (mg/sec)", \ "doc" : "maximum feed rate for a single centrifuge (mg/sec)"} double machine_feed; + + #pragma cyclus var { \ + "default": 0, \ + "userlevel": 10, \ + "tooltip": "Modeling option for miss-use calculation", \ + "uilabel": "Miss-use Modeling", \ + "doc": "Miss-use modeling option: " \ + " - 0: alpha-theta fix -- beta varies, " \ + " - 1: alpha=beta fix -- theta varies, " \ + " - 2: alpha*beta fix "} + int miss_use_model; + - // Input params from cycamore::Enrichment #pragma cyclus var { \ "default": 1, \ @@ -386,34 +346,34 @@ class CascadeEnrich : public cyclus::Facility { #pragma cyclus var { \ "tooltip" : "feed commodity", \ "doc" : "feed commodity that the enrichment facility accepts", \ - "uilabel" : "Feed Commodity", "uitype" : "incommodity" } + "uilabel" : "Feed Commodity", \ + "uitype" : "incommodity" } std::string feed_commod; #pragma cyclus var { \ "tooltip" : "product commodity", \ "doc" : "product commodity that the enrichment facility generates", \ - "uilabel" : "Product Commodity", "uitype" : "outcommodity" } + "uilabel" : "Product Commodity", \ + "uitype" : "outcommodity" } std::string product_commod; #pragma cyclus var { \ "tooltip" : "tails commodity", \ "doc" : "tails commodity supplied by enrichment facility", \ - "uilabel" : "Tails Commodity", "uitype" : "outcommodity" } + "uilabel" : "Tails Commodity", \ + "uitype" : "outcommodity" } std::string tails_commod; - double current_swu_capacity; #pragma cyclus var {} cyclus::toolkit::ResBuf tails; // depleted u // used to total intra-timestep swu and natu usage for meeting requests - // these help enable time series generation. - double intra_timestep_swu_; double intra_timestep_feed_; // END LEGACY -#pragma cyclus var { 'capacity' : 'max_feed_inventory' } cyclus::toolkit::ResBuf inventory; // natural u friend class CascadeEnrichTest; diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index cbcf745..87e83b9 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -20,9 +20,9 @@ using cyclus::Material; namespace mbmore { -namespace cascadenrichtest{ +namespace cascadenrichtest { - Composition::Ptr c_nou235() { +Composition::Ptr c_nou235() { cyclus::CompMap m; m[922380000] = 1.0; return Composition::CreateFromMass(m); @@ -62,10 +62,10 @@ TEST_F(CascadeEnrichTest, RequestQty) { " natu1 " " enr_u " " tails " - " 1.0 " - " 0.003 "; + " 0.003 " + " 1000 "; - int simdur = 10; + int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); @@ -80,14 +80,14 @@ TEST_F(CascadeEnrichTest, RequestQty) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); // Should be only one transaction into the EF, - // and it should be exactly 1kg of natu - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 1e-10) + // and it should be exactly 207.8928179411368kg of natu + EXPECT_EQ(1, qr.rows.size()); + EXPECT_NEAR(1000, m->quantity(), 1e-3) << "matched trade provides the wrong quantity of material"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, CheckSWUConstraint) { +TEST_F(CascadeEnrichTest, CheckFlowConstraint) { // Tests that request for enrichment that exceeds the SWU constraint // fulfilled only up to the available SWU. // Also confirms that initial_feed flag works. @@ -99,8 +99,7 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { " enr_u " " tails " " 0.003 " - " 1000 " - " 195 "; + " 1000 "; int simdur = 1; @@ -120,8 +119,8 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.1) - << "traded quantity exceeds SWU constraint"; + EXPECT_NEAR(10, m->quantity(), 0.1) + << "traded quantity differ from flow contraints"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -135,7 +134,8 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { " enr_u " " tails " " 0.003 " - " 243 "; + " 200 " + " 50 "; int simdur = 1; @@ -155,59 +155,10 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.01) + EXPECT_NEAR(5.831, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, RequestEnrich) { - // this tests verifies that requests for output material exceeding - // the maximum allowed enrichment are not fulfilled. - - std::string config = - " natu " - " natu1 " - " enr_u " - " tails " - " 0.003 " - " 0.20 "; - - int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, - simdur); - sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); - sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddRecipe("heu", cascadenrichtest::c_heu()); - - sim.AddSource("natu").recipe("natu1").Finalize(); - sim.AddSink("enr_u").recipe("leu").capacity(1.0).Finalize(); - sim.AddSink("enr_u").recipe("heu").Finalize(); - - int id = sim.Run(); - - std::vector conds; - conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); - QueryResult qr = sim.db().Query("Transactions", &conds); - Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - - // Should be only one transaction out of the EF, - // and it should be 1kg of LEU - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 0.01) - << "Not providing the requested quantity"; - - CompMap got = m->comp()->mass(); - CompMap want = cascadenrichtest::c_leu()->mass(); - cyclus::compmath::Normalize(&got); - cyclus::compmath::Normalize(&want); - - CompMap::iterator it; - for (it = want.begin(); it != want.end(); ++it) { - EXPECT_DOUBLE_EQ(it->second, got[it->first]) - << "nuclide qty off: " << pyne::nucname::name(it->first); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. @@ -226,7 +177,7 @@ TEST_F(CascadeEnrichTest, TradeTails) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").Finalize(); sim.AddSink("tails").Finalize(); @@ -258,7 +209,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("tails").Finalize(); @@ -270,7 +221,8 @@ TEST_F(CascadeEnrichTest, TailsQty) { QueryResult qr = sim.db().Query("Transactions", &conds); Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - // Should be 2 tails transactions, one from each LEU sink, each 4.084kg. + // Should be 2 tails transactions, one from each LEU sink, each 3.787453kg. + // (1* (0.0403193-0.00271456) / (0.0071-0.00271456) -1)/2. = 3.787453 EXPECT_EQ(2, qr.rows.size()); cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare( @@ -280,7 +232,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(8.168, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } @@ -291,7 +243,7 @@ TEST_F(CascadeEnrichTest, BidPrefs) { std::string config = " natu " - " natu1 " + " natu2 " " enr_u " " tails " " 0.003 " @@ -303,9 +255,10 @@ TEST_F(CascadeEnrichTest, BidPrefs) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("natu2", cascadenrichtest::c_natu2()); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSource("natu").recipe("natu1").capacity(1).Finalize(); - sim.AddSource("natu").recipe("natu2").capacity(1).Finalize(); + sim.AddSource("natu").recipe("natu2").capacity(2).Finalize(); int id = sim.Run(); @@ -422,7 +375,7 @@ void CascadeEnrichTest::InitParameters() { tails_assay = 0.002; swu_capacity = 100; //** - inv_size = 5; + inv_size = 105.5; reserves = 105.5; } @@ -436,7 +389,6 @@ void CascadeEnrichTest::SetUpSource() { src_facility->tails_assay = tails_assay; src_facility->max_enrich = max_enrich; src_facility->SetMaxInventorySize(inv_size); - src_facility->SwuCapacity(swu_capacity); src_facility->initial_feed = reserves; } @@ -521,158 +473,6 @@ TEST_F(CascadeEnrichTest, ValidReq) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, ConstraintConverters) { - // Tests the SWU and NatU converters to make sure that amount of - // feed and SWU required are correct to fulfill the enrichment request. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::MatQuery; - using mbmore::SWUConverter; - cyclus::Env::SetNucDataPath(); - - double qty = 5; // 5 kg - double product_assay = 0.05; // of 5 w/o enriched U - CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - v[94239] = 0.5; // 94239 shouldn't be taken into account - Material::Ptr target = - Material::CreateUntracked(qty, Composition::CreateFromMass(v)); - - std::set nucs; - nucs.insert(922350000); - nucs.insert(922380000); - - MatQuery mq(target); - double mass_frac = mq.mass_frac(nucs); - - SWUConverter swuc(feed_assay, tails_assay); - NatUConverter natuc(feed_assay, tails_assay); - - Material::Ptr offer = DoOffer(target); - - EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001); - EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Enrich) { - // this test asks the facility to enrich a material that results in an amount - // of natural uranium required that is exactly its inventory level. that - // inventory will be comprised of two materials to test the manifest/absorb - // strategy employed in Enrich_. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - - double qty = 5; // kg - double product_assay = 0.05; // of 5 w/o enriched U - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - double tails_qty = TailsQty(qty, assays); - - double swu_cap = swu_req * 5; - src_facility->SwuCapacity(swu_cap); - src_facility->SetMaxInventorySize(natu_req); - DoAddMat(GetMat(natu_req / 2)); - DoAddMat(GetMat(natu_req / 2)); - - Material::Ptr response; - EXPECT_NO_THROW(response = DoEnrich(target, qty)); - EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty); - - MatQuery q(response); - EXPECT_EQ(response->quantity(), qty); - EXPECT_EQ(q.mass_frac(922350000), product_assay); - EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay); - - // test too much natu request - DoAddMat(GetMat(natu_req - 1)); - EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Response) { - // this test asks the facility to respond to multiple requests for enriched - // uranium. two requests are provided, whose total equals the swu capacity of - // the facility while not exceeding its inventory capacity (that's taken care - // of in the Enrich tests). - // - // note that response quantity and quality need not be tested, because they - // are covered by the Enrich and RequestEnrich tests - using cyclus::Bid; - using cyclus::CompMap; - using cyclus::Material; - using cyclus::Request; - using cyclus::Trade; - using cyclus::toolkit::Assays; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::UraniumAssay; - - // problem set up - std::vector > trades; - std::vector< - std::pair, cyclus::Material::Ptr> > - responses; - - double qty = 5; // kg - double trade_qty = qty / 3; - double product_assay = 0.05; // of 5 w/o enriched U - - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - - src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat - src_facility->SwuCapacity(swu_req); // swu capacitated - - src_facility->GetMatlTrades(trades, responses); - - // set up state - DoAddMat(GetMat(natu_req * 2)); - - src_facility->GetMatlTrades(trades, responses); - - Request* req = - Request::Create(target, trader, product_commod); - Bid* bid = Bid::Create(req, target, src_facility); - Trade trade(req, bid, trade_qty); - trades.push_back(trade); - - // 2 trades, SWU = SWU cap - ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3, -1 * cyclus::eps()); - trades.push_back(trade); - responses.clear(); - EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses)); - EXPECT_EQ(responses.size(), 2); -} } // namespace cycamore From 8d428b9f19fc400e669a8185b52693008c5814ed Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Fri, 11 May 2018 09:50:03 -0500 Subject: [PATCH 086/116] working version --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b8e3464..29c1b60 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,7 @@ USE_CYCLUS("mbmore" "RandomEnrich") USE_CYCLUS("mbmore" "CentrifugeConfig") USE_CYCLUS("mbmore" "StageConfig") USE_CYCLUS("mbmore" "CascadeConfig") +USE_CYCLUS("mbmore" "CascadeEnrich") USE_CYCLUS("mbmore" "RandomSink") USE_CYCLUS("mbmore" "StateInst") From df2136727bc8c69a9c66c56991726bd922dba2d8 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:21:46 -0500 Subject: [PATCH 087/116] readd missing file --- src/CascadeEnrich_tests.cc | 248 +++++++++++++++++++++++++++++++++---- 1 file changed, 224 insertions(+), 24 deletions(-) diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index 87e83b9..cbcf745 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -20,9 +20,9 @@ using cyclus::Material; namespace mbmore { -namespace cascadenrichtest { +namespace cascadenrichtest{ -Composition::Ptr c_nou235() { + Composition::Ptr c_nou235() { cyclus::CompMap m; m[922380000] = 1.0; return Composition::CreateFromMass(m); @@ -62,10 +62,10 @@ TEST_F(CascadeEnrichTest, RequestQty) { " natu1 " " enr_u " " tails " - " 0.003 " - " 1000 "; + " 1.0 " + " 0.003 "; - int simdur = 1; + int simdur = 10; cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); @@ -80,14 +80,14 @@ TEST_F(CascadeEnrichTest, RequestQty) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); // Should be only one transaction into the EF, - // and it should be exactly 207.8928179411368kg of natu - EXPECT_EQ(1, qr.rows.size()); - EXPECT_NEAR(1000, m->quantity(), 1e-3) + // and it should be exactly 1kg of natu + EXPECT_EQ(1.0, qr.rows.size()); + EXPECT_NEAR(1.0, m->quantity(), 1e-10) << "matched trade provides the wrong quantity of material"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, CheckFlowConstraint) { +TEST_F(CascadeEnrichTest, CheckSWUConstraint) { // Tests that request for enrichment that exceeds the SWU constraint // fulfilled only up to the available SWU. // Also confirms that initial_feed flag works. @@ -99,7 +99,8 @@ TEST_F(CascadeEnrichTest, CheckFlowConstraint) { " enr_u " " tails " " 0.003 " - " 1000 "; + " 1000 " + " 195 "; int simdur = 1; @@ -119,8 +120,8 @@ TEST_F(CascadeEnrichTest, CheckFlowConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(10, m->quantity(), 0.1) - << "traded quantity differ from flow contraints"; + EXPECT_NEAR(5.0, m->quantity(), 0.1) + << "traded quantity exceeds SWU constraint"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -134,8 +135,7 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { " enr_u " " tails " " 0.003 " - " 200 " - " 50 "; + " 243 "; int simdur = 1; @@ -155,10 +155,59 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.831, m->quantity(), 0.01) + EXPECT_NEAR(5.0, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, RequestEnrich) { + // this tests verifies that requests for output material exceeding + // the maximum allowed enrichment are not fulfilled. + + std::string config = + " natu " + " natu1 " + " enr_u " + " tails " + " 0.003 " + " 0.20 "; + + int simdur = 2; + cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, + simdur); + sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); + sim.AddRecipe("leu", cascadenrichtest::c_leu()); + sim.AddRecipe("heu", cascadenrichtest::c_heu()); + + sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSink("enr_u").recipe("leu").capacity(1.0).Finalize(); + sim.AddSink("enr_u").recipe("heu").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); + QueryResult qr = sim.db().Query("Transactions", &conds); + Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); + + // Should be only one transaction out of the EF, + // and it should be 1kg of LEU + EXPECT_EQ(1.0, qr.rows.size()); + EXPECT_NEAR(1.0, m->quantity(), 0.01) + << "Not providing the requested quantity"; + + CompMap got = m->comp()->mass(); + CompMap want = cascadenrichtest::c_leu()->mass(); + cyclus::compmath::Normalize(&got); + cyclus::compmath::Normalize(&want); + + CompMap::iterator it; + for (it = want.begin(); it != want.end(); ++it) { + EXPECT_DOUBLE_EQ(it->second, got[it->first]) + << "nuclide qty off: " << pyne::nucname::name(it->first); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. @@ -177,7 +226,7 @@ TEST_F(CascadeEnrichTest, TradeTails) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); + sim.AddSource("natu").recipe("natu1").Finalize(); sim.AddSink("enr_u").recipe("leu").Finalize(); sim.AddSink("tails").Finalize(); @@ -209,7 +258,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); + sim.AddSource("natu").recipe("natu1").Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("tails").Finalize(); @@ -221,8 +270,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { QueryResult qr = sim.db().Query("Transactions", &conds); Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - // Should be 2 tails transactions, one from each LEU sink, each 3.787453kg. - // (1* (0.0403193-0.00271456) / (0.0071-0.00271456) -1)/2. = 3.787453 + // Should be 2 tails transactions, one from each LEU sink, each 4.084kg. EXPECT_EQ(2, qr.rows.size()); cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare( @@ -232,7 +280,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(8.168, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } @@ -243,7 +291,7 @@ TEST_F(CascadeEnrichTest, BidPrefs) { std::string config = " natu " - " natu2 " + " natu1 " " enr_u " " tails " " 0.003 " @@ -255,10 +303,9 @@ TEST_F(CascadeEnrichTest, BidPrefs) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("natu2", cascadenrichtest::c_natu2()); - sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSource("natu").recipe("natu1").capacity(1).Finalize(); - sim.AddSource("natu").recipe("natu2").capacity(2).Finalize(); + sim.AddSource("natu").recipe("natu2").capacity(1).Finalize(); int id = sim.Run(); @@ -375,7 +422,7 @@ void CascadeEnrichTest::InitParameters() { tails_assay = 0.002; swu_capacity = 100; //** - inv_size = 105.5; + inv_size = 5; reserves = 105.5; } @@ -389,6 +436,7 @@ void CascadeEnrichTest::SetUpSource() { src_facility->tails_assay = tails_assay; src_facility->max_enrich = max_enrich; src_facility->SetMaxInventorySize(inv_size); + src_facility->SwuCapacity(swu_capacity); src_facility->initial_feed = reserves; } @@ -473,6 +521,158 @@ TEST_F(CascadeEnrichTest, ValidReq) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, ConstraintConverters) { + // Tests the SWU and NatU converters to make sure that amount of + // feed and SWU required are correct to fulfill the enrichment request. + using cyclus::CompMap; + using cyclus::Material; + using cyclus::toolkit::MatQuery; + using cyclus::Composition; + using cyclus::toolkit::Assays; + using cyclus::toolkit::UraniumAssay; + using cyclus::toolkit::SwuRequired; + using cyclus::toolkit::FeedQty; + using cyclus::toolkit::MatQuery; + using mbmore::SWUConverter; + cyclus::Env::SetNucDataPath(); + + double qty = 5; // 5 kg + double product_assay = 0.05; // of 5 w/o enriched U + CompMap v; + v[922350000] = product_assay; + v[922380000] = 1 - product_assay; + v[94239] = 0.5; // 94239 shouldn't be taken into account + Material::Ptr target = + Material::CreateUntracked(qty, Composition::CreateFromMass(v)); + + std::set nucs; + nucs.insert(922350000); + nucs.insert(922380000); + + MatQuery mq(target); + double mass_frac = mq.mass_frac(nucs); + + SWUConverter swuc(feed_assay, tails_assay); + NatUConverter natuc(feed_assay, tails_assay); + + Material::Ptr offer = DoOffer(target); + + EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001); + EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, Enrich) { + // this test asks the facility to enrich a material that results in an amount + // of natural uranium required that is exactly its inventory level. that + // inventory will be comprised of two materials to test the manifest/absorb + // strategy employed in Enrich_. + using cyclus::CompMap; + using cyclus::Material; + using cyclus::toolkit::MatQuery; + using cyclus::Composition; + using cyclus::toolkit::Assays; + using cyclus::toolkit::UraniumAssay; + using cyclus::toolkit::SwuRequired; + using cyclus::toolkit::FeedQty; + + double qty = 5; // kg + double product_assay = 0.05; // of 5 w/o enriched U + cyclus::CompMap v; + v[922350000] = product_assay; + v[922380000] = 1 - product_assay; + // target qty need not be = to request qty + Material::Ptr target = cyclus::Material::CreateUntracked( + qty + 10, cyclus::Composition::CreateFromMass(v)); + + Assays assays(feed_assay, UraniumAssay(target), tails_assay); + double swu_req = SwuRequired(qty, assays); + double natu_req = FeedQty(qty, assays); + double tails_qty = TailsQty(qty, assays); + + double swu_cap = swu_req * 5; + src_facility->SwuCapacity(swu_cap); + src_facility->SetMaxInventorySize(natu_req); + DoAddMat(GetMat(natu_req / 2)); + DoAddMat(GetMat(natu_req / 2)); + + Material::Ptr response; + EXPECT_NO_THROW(response = DoEnrich(target, qty)); + EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty); + + MatQuery q(response); + EXPECT_EQ(response->quantity(), qty); + EXPECT_EQ(q.mass_frac(922350000), product_assay); + EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay); + + // test too much natu request + DoAddMat(GetMat(natu_req - 1)); + EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, Response) { + // this test asks the facility to respond to multiple requests for enriched + // uranium. two requests are provided, whose total equals the swu capacity of + // the facility while not exceeding its inventory capacity (that's taken care + // of in the Enrich tests). + // + // note that response quantity and quality need not be tested, because they + // are covered by the Enrich and RequestEnrich tests + using cyclus::Bid; + using cyclus::CompMap; + using cyclus::Material; + using cyclus::Request; + using cyclus::Trade; + using cyclus::toolkit::Assays; + using cyclus::toolkit::FeedQty; + using cyclus::toolkit::SwuRequired; + using cyclus::toolkit::UraniumAssay; + + // problem set up + std::vector > trades; + std::vector< + std::pair, cyclus::Material::Ptr> > + responses; + + double qty = 5; // kg + double trade_qty = qty / 3; + double product_assay = 0.05; // of 5 w/o enriched U + + cyclus::CompMap v; + v[922350000] = product_assay; + v[922380000] = 1 - product_assay; + // target qty need not be = to request qty + Material::Ptr target = cyclus::Material::CreateUntracked( + qty + 10, cyclus::Composition::CreateFromMass(v)); + + Assays assays(feed_assay, UraniumAssay(target), tails_assay); + double swu_req = SwuRequired(qty, assays); + double natu_req = FeedQty(qty, assays); + + src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat + src_facility->SwuCapacity(swu_req); // swu capacitated + + src_facility->GetMatlTrades(trades, responses); + + // set up state + DoAddMat(GetMat(natu_req * 2)); + + src_facility->GetMatlTrades(trades, responses); + + Request* req = + Request::Create(target, trader, product_commod); + Bid* bid = Bid::Create(req, target, src_facility); + Trade trade(req, bid, trade_qty); + trades.push_back(trade); + + // 2 trades, SWU = SWU cap + ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3, -1 * cyclus::eps()); + trades.push_back(trade); + responses.clear(); + EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses)); + EXPECT_EQ(responses.size(), 2); +} } // namespace cycamore From d641fd5d3f4b1ddc24aa5382bdcb5563055e6e92 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 17 May 2018 09:51:55 -0500 Subject: [PATCH 088/116] fix unit_test --- src/CascadeEnrich_tests.cc | 248 ++++--------------------------------- 1 file changed, 24 insertions(+), 224 deletions(-) diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index cbcf745..87e83b9 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -20,9 +20,9 @@ using cyclus::Material; namespace mbmore { -namespace cascadenrichtest{ +namespace cascadenrichtest { - Composition::Ptr c_nou235() { +Composition::Ptr c_nou235() { cyclus::CompMap m; m[922380000] = 1.0; return Composition::CreateFromMass(m); @@ -62,10 +62,10 @@ TEST_F(CascadeEnrichTest, RequestQty) { " natu1 " " enr_u " " tails " - " 1.0 " - " 0.003 "; + " 0.003 " + " 1000 "; - int simdur = 10; + int simdur = 1; cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); @@ -80,14 +80,14 @@ TEST_F(CascadeEnrichTest, RequestQty) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); // Should be only one transaction into the EF, - // and it should be exactly 1kg of natu - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 1e-10) + // and it should be exactly 207.8928179411368kg of natu + EXPECT_EQ(1, qr.rows.size()); + EXPECT_NEAR(1000, m->quantity(), 1e-3) << "matched trade provides the wrong quantity of material"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, CheckSWUConstraint) { +TEST_F(CascadeEnrichTest, CheckFlowConstraint) { // Tests that request for enrichment that exceeds the SWU constraint // fulfilled only up to the available SWU. // Also confirms that initial_feed flag works. @@ -99,8 +99,7 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { " enr_u " " tails " " 0.003 " - " 1000 " - " 195 "; + " 1000 "; int simdur = 1; @@ -120,8 +119,8 @@ TEST_F(CascadeEnrichTest, CheckSWUConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.1) - << "traded quantity exceeds SWU constraint"; + EXPECT_NEAR(10, m->quantity(), 0.1) + << "traded quantity differ from flow contraints"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -135,7 +134,8 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { " enr_u " " tails " " 0.003 " - " 243 "; + " 200 " + " 50 "; int simdur = 1; @@ -155,59 +155,10 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.0, m->quantity(), 0.01) + EXPECT_NEAR(5.831, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, RequestEnrich) { - // this tests verifies that requests for output material exceeding - // the maximum allowed enrichment are not fulfilled. - - std::string config = - " natu " - " natu1 " - " enr_u " - " tails " - " 0.003 " - " 0.20 "; - - int simdur = 2; - cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, - simdur); - sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); - sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddRecipe("heu", cascadenrichtest::c_heu()); - - sim.AddSource("natu").recipe("natu1").Finalize(); - sim.AddSink("enr_u").recipe("leu").capacity(1.0).Finalize(); - sim.AddSink("enr_u").recipe("heu").Finalize(); - - int id = sim.Run(); - - std::vector conds; - conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); - QueryResult qr = sim.db().Query("Transactions", &conds); - Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - - // Should be only one transaction out of the EF, - // and it should be 1kg of LEU - EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(1.0, m->quantity(), 0.01) - << "Not providing the requested quantity"; - - CompMap got = m->comp()->mass(); - CompMap want = cascadenrichtest::c_leu()->mass(); - cyclus::compmath::Normalize(&got); - cyclus::compmath::Normalize(&want); - - CompMap::iterator it; - for (it = want.begin(); it != want.end(); ++it) { - EXPECT_DOUBLE_EQ(it->second, got[it->first]) - << "nuclide qty off: " << pyne::nucname::name(it->first); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. @@ -226,7 +177,7 @@ TEST_F(CascadeEnrichTest, TradeTails) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").Finalize(); sim.AddSink("tails").Finalize(); @@ -258,7 +209,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("leu", cascadenrichtest::c_leu()); - sim.AddSource("natu").recipe("natu1").Finalize(); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("enr_u").recipe("leu").capacity(0.5).Finalize(); sim.AddSink("tails").Finalize(); @@ -270,7 +221,8 @@ TEST_F(CascadeEnrichTest, TailsQty) { QueryResult qr = sim.db().Query("Transactions", &conds); Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); - // Should be 2 tails transactions, one from each LEU sink, each 4.084kg. + // Should be 2 tails transactions, one from each LEU sink, each 3.787453kg. + // (1* (0.0403193-0.00271456) / (0.0071-0.00271456) -1)/2. = 3.787453 EXPECT_EQ(2, qr.rows.size()); cyclus::SqlStatement::Ptr stmt = sim.db().db().Prepare( @@ -280,7 +232,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(8.168, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } @@ -291,7 +243,7 @@ TEST_F(CascadeEnrichTest, BidPrefs) { std::string config = " natu " - " natu1 " + " natu2 " " enr_u " " tails " " 0.003 " @@ -303,9 +255,10 @@ TEST_F(CascadeEnrichTest, BidPrefs) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("natu2", cascadenrichtest::c_natu2()); + sim.AddSource("natu").recipe("natu1").capacity(200).Finalize(); sim.AddSource("natu").recipe("natu1").capacity(1).Finalize(); - sim.AddSource("natu").recipe("natu2").capacity(1).Finalize(); + sim.AddSource("natu").recipe("natu2").capacity(2).Finalize(); int id = sim.Run(); @@ -422,7 +375,7 @@ void CascadeEnrichTest::InitParameters() { tails_assay = 0.002; swu_capacity = 100; //** - inv_size = 5; + inv_size = 105.5; reserves = 105.5; } @@ -436,7 +389,6 @@ void CascadeEnrichTest::SetUpSource() { src_facility->tails_assay = tails_assay; src_facility->max_enrich = max_enrich; src_facility->SetMaxInventorySize(inv_size); - src_facility->SwuCapacity(swu_capacity); src_facility->initial_feed = reserves; } @@ -521,158 +473,6 @@ TEST_F(CascadeEnrichTest, ValidReq) { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, ConstraintConverters) { - // Tests the SWU and NatU converters to make sure that amount of - // feed and SWU required are correct to fulfill the enrichment request. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::MatQuery; - using mbmore::SWUConverter; - cyclus::Env::SetNucDataPath(); - - double qty = 5; // 5 kg - double product_assay = 0.05; // of 5 w/o enriched U - CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - v[94239] = 0.5; // 94239 shouldn't be taken into account - Material::Ptr target = - Material::CreateUntracked(qty, Composition::CreateFromMass(v)); - - std::set nucs; - nucs.insert(922350000); - nucs.insert(922380000); - - MatQuery mq(target); - double mass_frac = mq.mass_frac(nucs); - - SWUConverter swuc(feed_assay, tails_assay); - NatUConverter natuc(feed_assay, tails_assay); - - Material::Ptr offer = DoOffer(target); - - EXPECT_NEAR(swuc.convert(target), swuc.convert(offer), 0.001); - EXPECT_NEAR(natuc.convert(target) * mass_frac, natuc.convert(offer), 0.001); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Enrich) { - // this test asks the facility to enrich a material that results in an amount - // of natural uranium required that is exactly its inventory level. that - // inventory will be comprised of two materials to test the manifest/absorb - // strategy employed in Enrich_. - using cyclus::CompMap; - using cyclus::Material; - using cyclus::toolkit::MatQuery; - using cyclus::Composition; - using cyclus::toolkit::Assays; - using cyclus::toolkit::UraniumAssay; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::FeedQty; - - double qty = 5; // kg - double product_assay = 0.05; // of 5 w/o enriched U - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - double tails_qty = TailsQty(qty, assays); - - double swu_cap = swu_req * 5; - src_facility->SwuCapacity(swu_cap); - src_facility->SetMaxInventorySize(natu_req); - DoAddMat(GetMat(natu_req / 2)); - DoAddMat(GetMat(natu_req / 2)); - - Material::Ptr response; - EXPECT_NO_THROW(response = DoEnrich(target, qty)); - EXPECT_DOUBLE_EQ(src_facility->Tails().quantity(), tails_qty); - - MatQuery q(response); - EXPECT_EQ(response->quantity(), qty); - EXPECT_EQ(q.mass_frac(922350000), product_assay); - EXPECT_EQ(q.mass_frac(922380000), 1 - product_assay); - - // test too much natu request - DoAddMat(GetMat(natu_req - 1)); - EXPECT_THROW(response = DoEnrich(target, qty), cyclus::Error); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TEST_F(CascadeEnrichTest, Response) { - // this test asks the facility to respond to multiple requests for enriched - // uranium. two requests are provided, whose total equals the swu capacity of - // the facility while not exceeding its inventory capacity (that's taken care - // of in the Enrich tests). - // - // note that response quantity and quality need not be tested, because they - // are covered by the Enrich and RequestEnrich tests - using cyclus::Bid; - using cyclus::CompMap; - using cyclus::Material; - using cyclus::Request; - using cyclus::Trade; - using cyclus::toolkit::Assays; - using cyclus::toolkit::FeedQty; - using cyclus::toolkit::SwuRequired; - using cyclus::toolkit::UraniumAssay; - - // problem set up - std::vector > trades; - std::vector< - std::pair, cyclus::Material::Ptr> > - responses; - - double qty = 5; // kg - double trade_qty = qty / 3; - double product_assay = 0.05; // of 5 w/o enriched U - - cyclus::CompMap v; - v[922350000] = product_assay; - v[922380000] = 1 - product_assay; - // target qty need not be = to request qty - Material::Ptr target = cyclus::Material::CreateUntracked( - qty + 10, cyclus::Composition::CreateFromMass(v)); - - Assays assays(feed_assay, UraniumAssay(target), tails_assay); - double swu_req = SwuRequired(qty, assays); - double natu_req = FeedQty(qty, assays); - - src_facility->SetMaxInventorySize(natu_req * 4); // not capacitated by nat - src_facility->SwuCapacity(swu_req); // swu capacitated - - src_facility->GetMatlTrades(trades, responses); - - // set up state - DoAddMat(GetMat(natu_req * 2)); - - src_facility->GetMatlTrades(trades, responses); - - Request* req = - Request::Create(target, trader, product_commod); - Bid* bid = Bid::Create(req, target, src_facility); - Trade trade(req, bid, trade_qty); - trades.push_back(trade); - - // 2 trades, SWU = SWU cap - ASSERT_GT(src_facility->SwuCapacity() - 2 * swu_req / 3, -1 * cyclus::eps()); - trades.push_back(trade); - responses.clear(); - EXPECT_NO_THROW(src_facility->GetMatlTrades(trades, responses)); - EXPECT_EQ(responses.size(), 2); -} } // namespace cycamore From dfe11c08e71f8e6ef2a5e5bdd85343dbee43174a Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 26 Nov 2019 11:55:51 -0600 Subject: [PATCH 089/116] Minor changes to comments based on initial review. --- src/CascadeEnrich.cc | 15 +++++++-------- src/CascadeEnrich.h | 25 +++++++++++-------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index cbc7ac5..e1e91e9 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -52,7 +52,7 @@ void CascadeEnrich::EnterNotify() { using cyclus::Material; cyclus::Facility::EnterNotify(); centrifuge = CentrifugeConfig(); - // Update Centrifuge paramter from the user input: + // Update Centrifuge parameter from the user input: centrifuge.v_a = centrifuge_velocity; centrifuge.height = height; centrifuge.diameter = diameter; @@ -78,7 +78,7 @@ void CascadeEnrich::EnterNotify() { std::cout << " machine: " << it->second.n_machines; std::cout << std::endl; } - std::cout << "Dsign Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; + std::cout << "Design Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; if (max_feed_inventory > 0) { inventory.capacity(max_feed_inventory); } @@ -273,8 +273,8 @@ CascadeEnrich::GetMatlBids( for (it = commod_requests.begin(); it != commod_requests.end(); ++it) { Request* req = *it; Material::Ptr offer = Offer_(req->target()); - // The offer might not match the required enrichment ! it just produce - // what it can according to the cascade configuration and the feed asays + // The offer might not match the required enrichment ! It just produces + // what it can according to the cascade configuration and the feed assays commod_port->AddBid(req, offer, this); } @@ -352,15 +352,14 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, using cyclus::toolkit::UraniumAssay; using cyclus::toolkit::FeedQty; using cyclus::toolkit::TailsQty; + // get enrichment parameters double feed_qty = FeedRequired(qty); - double feed_assay = FeedAssay(feed_qty); double product_assay = ProductAssay(feed_assay); - - double tails_assay = TailsAssay(FeedAssay(feed_qty)); double tails_mass = TailsFlow(feed_qty); + // Determine the composition of the natural uranium // (ie. U-235+U-238/TotalMass) double pop_qty = inventory.quantity(); @@ -508,7 +507,7 @@ double CascadeEnrich::ProductFlow(double feed_flow) { double feed_assay = FeedAssay(feed_flow); double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); - + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; double product_flow = last_stg.feed_flow * last_stg.cut; return feed_ratio * FlowPerMon(product_flow); diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 56837c5..5d62865 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -81,25 +81,23 @@ class CascadeEnrich : public cyclus::Facility { /// @param time is the time to perform the tock virtual void Tock(); - /// @brief The Enrichment request Materials of its given - /// commodity. + /// @brief The Enrichment request Materials of its given commodity. virtual std::set::Ptr> GetMatlRequests(); /// @brief The Enrichment adjusts preferences for offers of - /// natural uranium it has received to maximize U-235 content - /// Any offers that have zero U-235 content are not accepted + /// natural uranium it has received to maximize U-235 content. + /// Any offers that have zero U-235 content are not accepted. virtual void AdjustMatlPrefs(cyclus::PrefMap::type& prefs); - /// @brief The Enrichment place accepted trade Materials in their - /// Inventory + /// @brief The Enrichment place accepted trade Materials in their Inventory. virtual void AcceptMatlTrades( const std::vector, cyclus::Material::Ptr> >& responses); /// @brief Responds to each request for this facility's commodity. If a given /// request is more than this facility's inventory or SWU capacity, it will - /// offer its minimum of its capacities. + /// offer the minimum of its capacities. virtual std::set::Ptr> GetMatlBids( cyclus::CommodMap::type& commod_requests); @@ -172,14 +170,13 @@ class CascadeEnrich : public cyclus::Facility { void RecordEnrichment_(double natural_u); - // Not physical constants but fixed assumptions for a cascade separating - // out U235 from U238 in UF6 gas -//group all the characteristic of a centrifuges + // Not physical constants but fixed assumptions for a cascade separating out + // U235 from U238 in UF6 gas group all the characteristic of a centrifuges CentrifugeConfig centrifuge; CascadeConfig cascade; double precision = 1e-15; - - + + const double secpermonth = 60.*60.*24.*(365.25/12.); // Set to design_tails at beginning of simulation. Gets reset if @@ -213,7 +210,7 @@ class CascadeEnrich : public cyclus::Facility { "doc": "amount of natural uranium stored at the enrichment " \ "facility at the beginning of the simulation (kg)" } double initial_feed; - + #pragma cyclus var { \ "default": 1e299, "tooltip": "max inventory of feed material (kg)", \ "uilabel": "Maximum Feed Inventory", \ @@ -304,7 +301,7 @@ class CascadeEnrich : public cyclus::Facility { "uilabel" : "Max feed rate for single centrifuge (mg/sec)", \ "doc" : "maximum feed rate for a single centrifuge (mg/sec)"} double machine_feed; - + #pragma cyclus var { \ "default": 0, \ "userlevel": 10, \ From 3f357e16ae197e1043f5b96975b065a0d95efbd3 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 3 Dec 2019 15:50:51 -0600 Subject: [PATCH 090/116] Commenting changes in CascadeEnrich.h --- src/CascadeEnrich.h | 88 ++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 5d62865..184d25e 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -45,40 +45,40 @@ class CascadeEnrich : public cyclus::Facility { "niche": "enrichment facility", \ "doc": \ "The CascadeEnrich facility based on the Cycamore Enrich facility. " \ - "timesteps (see README for full implementation documentation ",\ + "timesteps (see README for full implementation documentation ",\ } public: // --- Module Members --- - /// Constructor for the CascadeEnrich class - /// @param ctx the cyclus context for access to simulation-wide parameters + /// Constructor for the CascadeEnrich class + /// @param ctx the cyclus context for access to simulation-wide parameters CascadeEnrich(cyclus::Context* ctx); - /// Destructor for the CascadeEnrich class + /// Destructor for the CascadeEnrich class virtual ~CascadeEnrich(); #pragma cyclus - /// Print information about this agent + /// Print information about this agent virtual std::string str(); // --- - // --- Facility Members --- - /// perform module-specific tasks when entering the simulation - //virtual void Build(cyclus::Agent* parent); - // --- + /// --- Facility Members --- + /// Perform module-specific tasks when entering the simulation + /// virtual void Build(cyclus::Agent* parent); + /// --- // --- Agent Members --- - /// Each facility is prompted to do its beginning-of-time-step - /// stuff at the tick of the timer. + /// Each facility is prompted to do its beginning-of-time-step + /// stuff at the tick of the timer. virtual void EnterNotify(); - /// @param time is the time to perform the tick + /// @param time is the time to perform the tick virtual void Tick(); - /// Each facility is prompted to its end-of-time-step - /// stuff on the tock of the timer. + /// Each facility is prompted to its end-of-time-step + /// stuff on the tock of the timer. - /// @param time is the time to perform the tock + /// @param time is the time to perform the tock virtual void Tock(); /// @brief The Enrichment request Materials of its given commodity. @@ -88,6 +88,8 @@ class CascadeEnrich : public cyclus::Facility { /// @brief The Enrichment adjusts preferences for offers of /// natural uranium it has received to maximize U-235 content. /// Any offers that have zero U-235 content are not accepted. + /// + /// @param prefs is the preference map with all requests. virtual void AdjustMatlPrefs(cyclus::PrefMap::type& prefs); /// @brief The Enrichment place accepted trade Materials in their Inventory. @@ -98,6 +100,8 @@ class CascadeEnrich : public cyclus::Facility { /// @brief Responds to each request for this facility's commodity. If a given /// request is more than this facility's inventory or SWU capacity, it will /// offer the minimum of its capacities. + /// + /// @param commod_requests is a cyclus map of requests for this facility virtual std::set::Ptr> GetMatlBids( cyclus::CommodMap::type& commod_requests); @@ -120,7 +124,7 @@ class CascadeEnrich : public cyclus::Facility { // TODO: MAKE THESE CONVERSIONS TOOLKIT FNS and have them explicitly check // timestep duration - // Convert input file flows kg/mon to SI units + /// --- Convert input file flows kg/mon to SI units --- inline double FlowPerSec(double flow_per_mon) { return flow_per_mon / secpermonth; } @@ -132,11 +136,13 @@ class CascadeEnrich : public cyclus::Facility { inline double Mg2kgPerSec(double feed_mg_per_sec) { return feed_mg_per_sec / (1e6); } + /// --- - /// @brief Determines if a particular material is a valid request to respond - /// to. Valid requests must contain U235 and U238 and must have a relative - /// U235-to-U238 ratio less than this facility's tails_assay(). - /// @return true if the above description is met by the material + /// @brief Determines if a particular material is a valid request to respond + /// to. Valid requests must contain U235 and U238 and must have a relative + /// U235-to-U238 ratio less than this facility's tails_assay(). + /// + /// @return true if the above description is met by the material bool ValidReq(const cyclus::Material::Ptr mat); inline const cyclus::toolkit::ResBuf& Tails() const { @@ -144,34 +150,34 @@ class CascadeEnrich : public cyclus::Facility { } private: - /// @brief calculates the feed assay based on the unenriched inventory + /// @brief calculates the feed assay based on the unenriched inventory double FeedAssay(double quantity); - /// @brief adds a material into the natural uranium inventory - /// @throws if the material is not the same composition as the feed_recipe + /// @brief adds a material into the natural uranium inventory + /// @throws if the material is not the same composition as the feed_recipe void AddMat_(cyclus::Material::Ptr mat); - /// @brief generates a request for this facility given its current state. - /// Quantity of the material will be equal to remaining inventory size. + /// @brief generates a request for this facility given its current state. + /// Quantity of the material will be equal to remaining inventory size. cyclus::Material::Ptr Request_(); - /// @brief Generates a material offer for a given request. The response - /// composition will be comprised only of U235 and U238 at their relative - /// ratio in the requested material. The response quantity will be the - /// same as the requested commodity. + /// @brief Generates a material offer for a given request. The response + /// composition will be comprised only of U235 and U238 at their relative + /// ratio in the requested material. The response quantity will be the + /// same as the requested commodity. /// - /// @param req the requested material being responded to + /// @param req the requested material being responded to cyclus::Material::Ptr Offer_(cyclus::Material::Ptr req); cyclus::Material::Ptr Enrich_(cyclus::Material::Ptr mat, double qty); - /// @brief records and enrichment with the cyclus::Recorder + /// @brief records and enrichment with the cyclus::Recorder void RecordEnrichment_(double natural_u); // Not physical constants but fixed assumptions for a cascade separating out - // U235 from U238 in UF6 gas group all the characteristic of a centrifuges + // U235 from U238 in UF6 gas group all the characteristic of a centrifuges. CentrifugeConfig centrifuge; CascadeConfig cascade; double precision = 1e-15; @@ -225,9 +231,9 @@ class CascadeEnrich : public cyclus::Facility { "default": 100, \ "tooltip": "design feed flow (kg/mon)", \ "uilabel": "Design Feed Flow", \ - "doc": "Target amount of feed material to be processed by the" \ - " facility (kg/mon). Either this or max_centrifuges is used to constrain" \ - " the cascade design" } + "doc": "Target amount of feed material to be processed by the " \ + "facility (kg/mon). Either this or max_centrifuges is used to constrain " \ + "the cascade design" } double design_feed_flow; #pragma cyclus var { \ @@ -271,35 +277,35 @@ class CascadeEnrich : public cyclus::Facility { "default" : 485.0, \ "tooltip" : "Centrifuge velocity (m/s)", \ "uilabel" : "Centrifuge velocity (m/s)", \ - "doc" : "operational centrifuge velocity (m/s) at the outer radius (a)"} + "doc" : "operational centrifuge velocity (m/s) at the outer radius (a)" } double centrifuge_velocity; #pragma cyclus var { \ "default" : 0.5, \ "tooltip" : "Centrifuge height (m)", \ "uilabel" : "Centrifuge height (m)", \ - "doc" : "height of centrifuge (m)"} + "doc" : "height of centrifuge (m)" } double height; #pragma cyclus var { \ "default" : 0.15, \ "tooltip" : "Centrifuge diameter (m)", \ "uilabel" : "Centrifuge diameter (m)", \ - "doc" : "diameter of centrifuge (m)"} + "doc" : "diameter of centrifuge (m)" } double diameter; #pragma cyclus var { \ "default" : 2, \ "tooltip" : "Centrifuge L/F* ", \ "uilabel" : "Centrifuge Countercurrent to feed ratio", \ - "doc" : "Countercurrent to feed ratio"} + "doc" : "Countercurrent to feed ratio" } double L_over_F; #pragma cyclus var { \ "default" : 15.0, \ "tooltip" : "Centrifuge feed rate (mg/sec)", \ "uilabel" : "Max feed rate for single centrifuge (mg/sec)", \ - "doc" : "maximum feed rate for a single centrifuge (mg/sec)"} + "doc" : "maximum feed rate for a single centrifuge (mg/sec)" } double machine_feed; #pragma cyclus var { \ @@ -310,7 +316,7 @@ class CascadeEnrich : public cyclus::Facility { "doc": "Miss-use modeling option: " \ " - 0: alpha-theta fix -- beta varies, " \ " - 1: alpha=beta fix -- theta varies, " \ - " - 2: alpha*beta fix "} + " - 2: alpha*beta fix " } int miss_use_model; From 2cbda220dd27dcfa57c654e5fe2d308ffd95ebb0 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 5 Dec 2019 13:54:47 -0600 Subject: [PATCH 091/116] Updating stages/cascade language in CascadeEnrich.cc calls --- src/CascadeEnrich.cc | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index e1e91e9..4d9913a 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -68,14 +68,14 @@ void CascadeEnrich::EnterNotify() { for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); it++) { std::cout << "stg " << it->first; - std::cout << " FA: " << it->second.feed_assay; - std::cout << " PA: " << it->second.product_assay; - std::cout << " TA: " << it->second.tail_assay; - std::cout << " feed_flow: " << it->second.feed_flow; - std::cout << " cut: " << it->second.cut; - std::cout << " alpha: " << it->second.alpha; - std::cout << " beta: " << it->second.beta; - std::cout << " machine: " << it->second.n_machines; + std::cout << " FA: " << it->second.feed_assay(); + std::cout << " PA: " << it->second.product_assay(); + std::cout << " TA: " << it->second.tail_assay(); + std::cout << " feed_flow: " << it->second.feed_flow(); + std::cout << " cut: " << it->second.cut(); + std::cout << " alpha: " << it->second.alpha(); + std::cout << " beta: " << it->second.beta(); + std::cout << " machine: " << it->second.n_machines(); std::cout << std::endl; } std::cout << "Design Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; @@ -122,9 +122,10 @@ CascadeEnrich::GetMatlRequests() { return ports; } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Sort offers of input material to have higher preference for more -// U-235 content +// U-235 content void CascadeEnrich::AdjustMatlPrefs( cyclus::PrefMap::type& prefs) { using cyclus::Bid; @@ -181,6 +182,7 @@ void CascadeEnrich::AcceptMatlTrades( AddMat_(it->second); } } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::AddMat_(cyclus::Material::Ptr mat) { // Elements and isotopes other than U-235, U-238 are sent directly to tails @@ -223,6 +225,7 @@ void CascadeEnrich::AddMat_(cyclus::Material::Ptr mat) { << " to its inventory, which is holding " << inventory.quantity() << " total."; } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - std::set::Ptr> CascadeEnrich::GetMatlBids( @@ -408,6 +411,7 @@ cyclus::Material::Ptr CascadeEnrich::Enrich_(cyclus::Material::Ptr mat, return response; } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CascadeEnrich::RecordEnrichment_(double natural_u) { using cyclus::Context; @@ -431,6 +435,7 @@ cyclus::Material::Ptr CascadeEnrich::Request_() { return cyclus::Material::CreateUntracked(qty, context()->GetRecipe(feed_recipe)); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cyclus::Material::Ptr CascadeEnrich::Offer_(cyclus::Material::Ptr mat) { double feed_assay = FeedAssay(mat->quantity()); @@ -443,6 +448,7 @@ cyclus::Material::Ptr CascadeEnrich::Offer_(cyclus::Material::Ptr mat) { return cyclus::Material::CreateUntracked( mat->quantity(), cyclus::Composition::CreateFromAtom(comp)); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CascadeEnrich::ValidReq(const cyclus::Material::Ptr mat) { cyclus::toolkit::MatQuery q(mat); @@ -450,6 +456,7 @@ bool CascadeEnrich::ValidReq(const cyclus::Material::Ptr mat) { double u238 = q.atom_frac(922380000); return (u238 > 0 && u235 / (u235 + u238) > tails_assay); } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double CascadeEnrich::FeedAssay(double quantity) { using cyclus::Material; @@ -465,16 +472,17 @@ double CascadeEnrich::FeedAssay(double quantity) { } double CascadeEnrich::ProductAssay(double feed_assay) { - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); - return cascade_tmp.stgs_config.rbegin()->second.product_assay; + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.rbegin()->second.product_assay(); } + double CascadeEnrich::TailsAssay(double feed_assay) { - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); - return cascade_tmp.stgs_config.begin()->second.tail_assay; + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + return cascade_tmp.stgs_config.begin()->second.tail_assay(); } double CascadeEnrich::MaxFeedFlow(double feed_assay){ - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); return FlowPerMon(cascade_tmp.FeedFlow()); @@ -506,10 +514,10 @@ double CascadeEnrich::FeedRequired(double prod_qty) { double CascadeEnrich::ProductFlow(double feed_flow) { double feed_assay = FeedAssay(feed_flow); double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); - CascadeConfig cascade_tmp = cascade.ModelMissUsedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); - StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; - double product_flow = last_stg.feed_flow * last_stg.cut; + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second(); + double product_flow = last_stg.feed_flow() * last_stg.cut(); return feed_ratio * FlowPerMon(product_flow); } From e2600d16514d9b304ed7e7913674c640b8720d60 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 13 Dec 2019 11:53:40 -0600 Subject: [PATCH 092/116] Editing miss_use references. --- src/CascadeEnrich.cc | 12 ++++++------ src/CascadeEnrich.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index 4d9913a..a7cd5c3 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -31,7 +31,7 @@ CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) feed_commod(""), product_commod(""), tails_commod(""), - miss_use_model(0), + misuse_model(0), order_prefs(true) {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CascadeEnrich::~CascadeEnrich() {} @@ -472,17 +472,17 @@ double CascadeEnrich::FeedAssay(double quantity) { } double CascadeEnrich::ProductAssay(double feed_assay) { - CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); return cascade_tmp.stgs_config.rbegin()->second.product_assay(); } double CascadeEnrich::TailsAssay(double feed_assay) { - CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); return cascade_tmp.stgs_config.begin()->second.tail_assay(); } double CascadeEnrich::MaxFeedFlow(double feed_assay){ - CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); return FlowPerMon(cascade_tmp.FeedFlow()); @@ -514,9 +514,9 @@ double CascadeEnrich::FeedRequired(double prod_qty) { double CascadeEnrich::ProductFlow(double feed_flow) { double feed_assay = FeedAssay(feed_flow); double feed_ratio = feed_flow / MaxFeedFlow(feed_assay); - CascadeConfig cascade_tmp = cascade.ModelMisusedCascade(feed_assay, miss_use_model, precision); + CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); - StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second(); + StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; double product_flow = last_stg.feed_flow() * last_stg.cut(); return feed_ratio * FlowPerMon(product_flow); } diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 184d25e..bc3e832 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -311,13 +311,13 @@ class CascadeEnrich : public cyclus::Facility { #pragma cyclus var { \ "default": 0, \ "userlevel": 10, \ - "tooltip": "Modeling option for miss-use calculation", \ - "uilabel": "Miss-use Modeling", \ - "doc": "Miss-use modeling option: " \ + "tooltip": "Modeling option for misuse calculation", \ + "uilabel": "Misuse Modeling", \ + "doc": "Misuse modeling option: " \ " - 0: alpha-theta fix -- beta varies, " \ " - 1: alpha=beta fix -- theta varies, " \ " - 2: alpha*beta fix " } - int miss_use_model; + int misuse_model; From dfb698770060e9565869da6c4e5463fb116b9218 Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 093/116] initial import - maintaining CascadeConfig.* from add_cascade_enrich --- src/CascadeConfig.cc | 40 +++++++++++++++++++++++++++++----------- src/CascadeConfig.h | 10 +++++++++- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 61ddbee..5ff19bb 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -217,6 +217,10 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, misuse_cascade.UpdateCut(); misuse_cascade.UpdateFlow(); break; + + case 2: + miss_used_cascade.ComputeAssayByGamma(f_assay, precision); + break; } return misuse_cascade; } @@ -293,7 +297,7 @@ void CascadeConfig::PropagateAssay(double f_assay) { } } -void CascadeConfig::ComputeAssay(double f_assay, double precision) { +void CascadeConfig::ComputeAssayByAlpha(double f_assay, double precision) { CascadeConfig previous_cascade; while (DeltaEnrichment((*this), previous_cascade, precision) > std::abs(precision)) { previous_cascade = (*this); @@ -341,13 +345,13 @@ std::map CascadeConfig::IterateEnrichment( std::map::iterator it; // Get the Flow and Assay quantity - for (it = cascade.stgs_config.begin(); it != cascade.stgs_config.end(); + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); it++) { int i = it->first; std::map::iterator it_up = - cascade.stgs_config.find(i + 1); + (*this).stgs_config.find(i + 1); std::map::iterator it_down = - cascade.stgs_config.find(i - 1); + (*this).stgs_config.find(i - 1); down_assay = 0; up_assay = 0; down_flow = 0; @@ -367,9 +371,9 @@ std::map CascadeConfig::IterateEnrichment( (down_assay * down_flow + up_assay * up_flow) / (down_flow + up_flow); if (i == 0) { // add Feed flow in the entry stage stg_f_assay = (down_assay * down_flow + up_assay * up_flow + - f_assay * cascade.feed_flow) / - (down_flow + up_flow + cascade.feed_flow); - stg_feed_flow = down_flow + up_flow + cascade.feed_flow; + f_assay * (*this).feed_flow) / + (down_flow + up_flow + (*this).feed_flow); + stg_feed_flow = down_flow + up_flow + (*this).feed_flow; } std::map::iterator it_new = @@ -378,12 +382,26 @@ std::map CascadeConfig::IterateEnrichment( // Update Stage feed assay it_new->second.feed_assay(stg_f_assay); // Update Beta values (from feed) -- Alpha & Cut are cte - it_new->second.BetaByAlphaAndCut(); + it->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay - it_new->second.ProductAssay(); - it_new->second.TailAssay(); + it->second.ProductAssay(); + it->second.TailAssay(); } +} - return updated_enrichment.stgs_config; +void CascadeConfig::UpdateByGamma(){ + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + double gamma = it->second.alpha * it->second.beta; + // Recompute Product Assay + it->second.ProductAssayByGamma(gamma); + // Alpha by Product assay + it->second.AlphaByProductAssay(); + // Beta and tail assay... + it->second.BetaByAlphaAndCut(); + it->second.TailAssay(); + } } + } // namespace mbmore diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index d2c754f..0c1e687 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -39,7 +39,15 @@ class CascadeConfig { // Compute the response of the cascade to a non ideal feed assay void PropagateAssay(double f_assay); - void ComputeAssay(double f_assay, double precision = 1e-8); + + + // Propagate iterratively the assay assuming + // Alpha constant + void ComputeAssayByAlpha(double f_assay, double precision = 1e-8); + // Gamma constant + void ComputeAssayByGamma(double f_assay, double precision = 1e-8); + + void UpdateCut(); void UpdateFlow(); From e03726c9bdd14185d1294af760c03dda7c4d10bd Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Wed, 16 May 2018 15:31:18 -0500 Subject: [PATCH 094/116] adding unit test for stage method, fixing Product by Gamma calculation - maintaining StageConfig* from add_cascade_enrich --- src/StageConfig_tests.cc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 19ab231..7e935f6 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -105,6 +105,32 @@ TEST(StageConfig_Test, TestIdeal) { EXPECT_NEAR(stage_ideal.DU(), expected_U, tol_DU); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST(StageConfig_Test, ProductAssayByGamma) { + double gamma = 1.3798316056650026; + double target_product_assay = 0.00821; + double theta_ = 0.46040372309; + double feed_assay_ = 0.007; + StageConfig stage(feed_assay_, feed_c, theta_, delU, -1, 1e-16); + + EXPECT_NEAR(target_product_assay,stage.ProductAssayByGamma(gamma), 1e-5); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST(StageConfig_Test, AlphaByProductAssay) { + double gamma = 1.3798316056650026; + double target_product_assay = 0.00821; + double theta_ = 0.46040372309; + double feed_assay_ = 0.007; + StageConfig stage(feed_assay_, feed_c, theta_, delU, -1, 1e-16); + stage.feed_assay = 0.1; + stage.product_assay = 0.3; + double alpha_ = 0.3/(1-0.3)*(1-0.1)/0.1; + + EXPECT_NEAR(alpha_,stage.AlphaByProductAssay(), 1e-5); +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Determine the output of the first enrich/strip stage of a cascade // based on the design params for the cascade From 7e2c152a7ee612f5713adc8f4c4c6b2187049e3b Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Wed, 16 May 2018 16:00:18 -0500 Subject: [PATCH 095/116] removing secondpermonth mention in centrifugeconfig (not used) --- src/CentrifugeConfig.cc | 2 -- src/CentrifugeConfig.h | 1 - 2 files changed, 3 deletions(-) diff --git a/src/CentrifugeConfig.cc b/src/CentrifugeConfig.cc index 6ed994f..bc6003c 100644 --- a/src/CentrifugeConfig.cc +++ b/src/CentrifugeConfig.cc @@ -45,7 +45,6 @@ CentrifugeConfig::CentrifugeConfig() { D_rho = 2.2e-5; // kg/m/s gas_const = 8.314; // J/K/mol M_238 = 0.238; // kg/mol - secpermonth = 60. * 60. * 24. * (365.25 / 12.); } CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, double feed_, double T_, @@ -65,7 +64,6 @@ CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, double fee D_rho = 2.2e-5; // kg/m/s gas_const = 8.314; // J/K/mol M_238 = 0.238; // kg/mol - secpermonth = 60. * 60. * 24. * (365.25 / 12.); } double CentrifugeConfig::ComputeDeltaU(double cut) { diff --git a/src/CentrifugeConfig.h b/src/CentrifugeConfig.h index f04f0e2..91b4c85 100644 --- a/src/CentrifugeConfig.h +++ b/src/CentrifugeConfig.h @@ -32,7 +32,6 @@ class CentrifugeConfig { double D_rho; // kg/m/s double gas_const; // J/K/mol double M_238; // kg/mol - double secpermonth; // obvious ?! // two method to compute some part of the solution to the Raetz equation double CalcCTherm(double v_a, double temp, double dM); From af44fd74c47a77462ebf556161db3ddbefbd8f0a Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Wed, 16 May 2018 16:25:05 -0500 Subject: [PATCH 096/116] allow to have differnet timestep size --- src/CascadeEnrich.cc | 15 +++++++++------ src/CascadeEnrich.h | 8 ++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index a7cd5c3..c17548a 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -31,8 +31,10 @@ CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) feed_commod(""), product_commod(""), tails_commod(""), - misuse_model(0), - order_prefs(true) {} + miss_use_model(0), + order_prefs(true) { + secpertimestep = (*this).context()->sim_info().dt; + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CascadeEnrich::~CascadeEnrich() {} @@ -59,6 +61,7 @@ void CascadeEnrich::EnterNotify() { centrifuge.feed = machine_feed / 1000 / 1000; centrifuge.temp = temp; centrifuge.flow_internal = L_over_F; + secpertimestep = (*this).context()->sim_info().dt; cascade = CascadeConfig(centrifuge, design_feed_assay, design_product_assay, design_tails_assay, FlowPerSec(design_feed_flow), @@ -78,7 +81,7 @@ void CascadeEnrich::EnterNotify() { std::cout << " machine: " << it->second.n_machines(); std::cout << std::endl; } - std::cout << "Design Feed Flow " << FlowPerMon(cascade.FeedFlow()) << std::endl; + std::cout << "Dsign Feed Flow " << FlowPerDt(cascade.FeedFlow()) << std::endl; if (max_feed_inventory > 0) { inventory.capacity(max_feed_inventory); } @@ -484,7 +487,7 @@ double CascadeEnrich::TailsAssay(double feed_assay) { double CascadeEnrich::MaxFeedFlow(double feed_assay){ CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); - return FlowPerMon(cascade_tmp.FeedFlow()); + return FlowPerDt(cascade_tmp.FeedFlow()); } @@ -517,8 +520,8 @@ double CascadeEnrich::ProductFlow(double feed_flow) { CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; - double product_flow = last_stg.feed_flow() * last_stg.cut(); - return feed_ratio * FlowPerMon(product_flow); + double product_flow = last_stg.feed_flow * last_stg.cut; + return feed_ratio * FlowPerDt(product_flow); } double CascadeEnrich::TailsFlow(double feed_flow) { diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index bc3e832..c36c635 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -126,11 +126,11 @@ class CascadeEnrich : public cyclus::Facility { /// --- Convert input file flows kg/mon to SI units --- inline double FlowPerSec(double flow_per_mon) { - return flow_per_mon / secpermonth; + return flow_per_mon / secpertimestep; } - inline double FlowPerMon(double flow_per_sec) { - return flow_per_sec * secpermonth; + inline double FlowPerDt(double flow_per_sec) { + return flow_per_sec * secpertimestep; } inline double Mg2kgPerSec(double feed_mg_per_sec) { @@ -183,7 +183,7 @@ class CascadeEnrich : public cyclus::Facility { double precision = 1e-15; - const double secpermonth = 60.*60.*24.*(365.25/12.); + double secpertimestep = 60.*60.*24.*(365.25/12.); // Set to design_tails at beginning of simulation. Gets reset if // facility is used off-design From 9aaabeee73fdda6abd4da3d95a3c09926f28d7ed Mon Sep 17 00:00:00 2001 From: Mouginot B Date: Thu, 10 May 2018 15:38:47 -0500 Subject: [PATCH 097/116] initial import - maintaining CascadeConfig* from add_cascade_enrich --- src/CascadeConfig.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 5ff19bb..7b3be36 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -221,6 +221,10 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, case 2: miss_used_cascade.ComputeAssayByGamma(f_assay, precision); break; + + case 2: + miss_used_cascade.ComputeAssayByGamma(f_assay, precision); + break; } return misuse_cascade; } From 5ad55c2836dabb1c7480d27af90f809c6b3f06c7 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 23 Jan 2020 15:44:17 -0600 Subject: [PATCH 098/116] Updating refs to stages and misuse --- src/CascadeEnrich.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index c17548a..8d4cbf5 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -31,7 +31,7 @@ CascadeEnrich::CascadeEnrich(cyclus::Context* ctx) feed_commod(""), product_commod(""), tails_commod(""), - miss_use_model(0), + misuse_model(0), order_prefs(true) { secpertimestep = (*this).context()->sim_info().dt; } @@ -520,7 +520,7 @@ double CascadeEnrich::ProductFlow(double feed_flow) { CascadeConfig cascade_tmp = cascade.ModelMisuseCascade(feed_assay, misuse_model, precision); StageConfig last_stg = cascade_tmp.stgs_config.rbegin()->second; - double product_flow = last_stg.feed_flow * last_stg.cut; + double product_flow = last_stg.feed_flow() * last_stg.cut(); return feed_ratio * FlowPerDt(product_flow); } From 19858132d246614ea34f48aed847582c3de7f21a Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 23 Jan 2020 16:18:51 -0600 Subject: [PATCH 099/116] Readding ComputeAssayByGamma method --- src/CascadeConfig.cc | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 7b3be36..48bb0a5 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -210,7 +210,7 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, // Case 1: alpha = beta, cut = varying switch (modeling_opt) { default: - misuse_cascade.ComputeAssay(f_assay, precision); + misuse_cascade.ComputeAssayByAlpha(f_assay, precision); break; case 1: @@ -219,11 +219,7 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, break; case 2: - miss_used_cascade.ComputeAssayByGamma(f_assay, precision); - break; - - case 2: - miss_used_cascade.ComputeAssayByGamma(f_assay, precision); + misuse_cascade.ComputeAssayByGamma(f_assay, precision); break; } return misuse_cascade; @@ -309,6 +305,15 @@ void CascadeConfig::ComputeAssayByAlpha(double f_assay, double precision) { } } +void CascadeConfig::ComputeAssayByGamma(double f_assay, double precision) { + CascadeConfig previous_cascade; + while (DeltaEnrichment((*this), previous_cascade) > precision) { + previous_cascade = (*this); + (*this).IterrateEnrichment(f_assay); + (*this).UpdateByGamma(); + } +} + double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, CascadeConfig p_enrichments, double precision) { @@ -391,21 +396,7 @@ std::map CascadeConfig::IterateEnrichment( it->second.ProductAssay(); it->second.TailAssay(); } -} -void CascadeConfig::UpdateByGamma(){ - std::map::iterator it; - for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); - it++) { - double gamma = it->second.alpha * it->second.beta; - // Recompute Product Assay - it->second.ProductAssayByGamma(gamma); - // Alpha by Product assay - it->second.AlphaByProductAssay(); - // Beta and tail assay... - it->second.BetaByAlphaAndCut(); - it->second.TailAssay(); - } + return updated_enrichment.stgs_config; } - } // namespace mbmore From c6f9e9da2339f9c482259f7a9eee9bc8be9c32f9 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 24 Jan 2020 11:38:29 -0600 Subject: [PATCH 100/116] Including changes to void IterateEnrichment --- src/CascadeConfig.cc | 42 +++++++++++++++++++++++++++++++++--------- src/CascadeConfig.h | 9 ++++++--- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 48bb0a5..7f0eadf 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -206,8 +206,9 @@ CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, CascadeConfig misuse_cascade = (*this); misuse_cascade.PropagateAssay(f_assay); - // Default: alpha, cut = constant; beta = varying + // Default: alpha & cut = constant; beta = varying // Case 1: alpha = beta, cut = varying + // Case 2: gamma & cut = constant, alpha & veta = varying switch (modeling_opt) { default: misuse_cascade.ComputeAssayByAlpha(f_assay, precision); @@ -299,9 +300,10 @@ void CascadeConfig::PropagateAssay(double f_assay) { void CascadeConfig::ComputeAssayByAlpha(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade, precision) > std::abs(precision)) { + while (DeltaEnrichment((*this), previous_cascade) > precision) { previous_cascade = (*this); - (*this).stgs_config = IterateEnrichment((*this), f_assay); + (*this).IterrateEnrichment(f_assay); + (*this).UpdateByAlpha(); } } @@ -341,9 +343,8 @@ double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, return square_feed_diff + square_product_diff + square_waste_diff; } -std::map CascadeConfig::IterateEnrichment( - CascadeConfig cascade, double f_assay) { - CascadeConfig updated_enrichment = cascade; +void CascadeConfig::IterateEnrichment(double f_assay) { + CascadeConfig updated_enrichment = (*this); // mixing variables double down_assay = 0; @@ -366,11 +367,11 @@ std::map CascadeConfig::IterateEnrichment( down_flow = 0; up_flow = 0; - if (it_down != cascade.stgs_config.end()) { + if (it_down != (*this).stgs_config.end()) { down_assay = it_down->second.product_assay(); down_flow = it_down->second.feed_flow() * it_down->second.cut(); } - if (it_up != cascade.stgs_config.end()) { + if (it_up != (*this).stgs_config.end()) { up_assay = it_up->second.tail_assay(); up_flow = it_up->second.feed_flow() * (1 - it_up->second.cut()); } @@ -390,13 +391,36 @@ std::map CascadeConfig::IterateEnrichment( // Update Stage feed assay it_new->second.feed_assay(stg_f_assay); + } + + (*this).stgs_config = updated_enrichment.stgs_config; +} + +void CascadeConfig::UpdateByAlpha(){ + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { // Update Beta values (from feed) -- Alpha & Cut are cte it->second.BetaByAlphaAndCut(); // Recompute Product Assay and Tail Assay it->second.ProductAssay(); it->second.TailAssay(); } +} - return updated_enrichment.stgs_config; +void CascadeConfig::UpdateByGamma(){ + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + double gamma = it->second.alpha() * it->second.beta(); + // Recompute Product Assay + it->second.ProductAssayByGamma(gamma); + // Alpha by Product assay + it->second.AlphaByProductAssay(); + // Beta and tail assay... + it->second.BetaByAlphaAndCut(); + it->second.TailAssay(); + } } + } // namespace mbmore diff --git a/src/CascadeConfig.h b/src/CascadeConfig.h index 0c1e687..9116512 100644 --- a/src/CascadeConfig.h +++ b/src/CascadeConfig.h @@ -80,10 +80,13 @@ class CascadeConfig { CascadeConfig previous_enrichment, double precision); - // method computing one iteration of the algorithm used to get the response + // method computing one iteration, of the algorithm used to get the response // to non ideal feed assay - std::map IterateEnrichment(CascadeConfig cascade, - double feed_assay); + void IterateEnrichment(double feed_assay); + // recompute product assay, beta and tails assay from alpha, cut and feed assay + void UpdateByAlpha(); + //recompute alpha, product assay, beta and tails assay from gamma, cut and feed assay + void UpdateByGamma(); }; } // namespace mbmore From 27df1efd22ea2d88080ccd74a00296fd95b5e5d9 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 29 Jan 2020 12:05:43 -0600 Subject: [PATCH 101/116] Re-adding stage functions for calculating alpha and product --- src/CascadeConfig.cc | 8 ++++---- src/StageConfig.cc | 15 +++++++++++++++ src/StageConfig.h | 8 ++++++++ src/StageConfig_tests.cc | 12 +++++++----- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 7f0eadf..1ab3b92 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -300,18 +300,18 @@ void CascadeConfig::PropagateAssay(double f_assay) { void CascadeConfig::ComputeAssayByAlpha(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade) > precision) { + while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { previous_cascade = (*this); - (*this).IterrateEnrichment(f_assay); + (*this).IterateEnrichment(f_assay); (*this).UpdateByAlpha(); } } void CascadeConfig::ComputeAssayByGamma(double f_assay, double precision) { CascadeConfig previous_cascade; - while (DeltaEnrichment((*this), previous_cascade) > precision) { + while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { previous_cascade = (*this); - (*this).IterrateEnrichment(f_assay); + (*this).IterateEnrichment(f_assay); (*this).UpdateByGamma(); } } diff --git a/src/StageConfig.cc b/src/StageConfig.cc index c543f31..9fb8a79 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -109,6 +109,10 @@ void StageConfig::AlphaByDU() { alpha_ = 1. + std::sqrt((2. * (DU_ / M) * (1. - cut_) / (cut_ * feed))); } +void StageConfig::AlphaByProductAssay(){ + alpha_ = (1 - feed_assay_)/feed_assay_ * product_assay_/(1 - product_assay_); +} + void StageConfig::BetaByAlphaAndCut() { ProductAssay(); double waste_assay = (feed_assay_ - cut_ * product_assay_) / (1. - cut_); @@ -116,6 +120,17 @@ void StageConfig::BetaByAlphaAndCut() { beta_ = feed_assay_ / (1. - feed_assay_) * (1. - waste_assay) / waste_assay; } +void StageConfig::ProductAssayByGamma(double gamma){ + double product_assay_ = ( - sqrt( pow( (feed_assay_ - cut_) * gamma, 2) + + gamma * ( 2*feed_assay_ + 2*cut_ + - 2*pow(feed_assay_, 2) + - 2*pow(cut_, 2)) + + pow(feed_assay_ + cut_ -1, 2)) + + gamma*(feed_assay_ + cut_) + - feed_assay_ - cut_ + 1 ) + / (2*cut_ * (gamma -1)); +} + void StageConfig::CutByAlphaBeta() { ProductAssay(); TailAssay(); diff --git a/src/StageConfig.h b/src/StageConfig.h index 03f5066..9731f9d 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -55,11 +55,17 @@ class StageConfig { // calculate Alpha value using the dU, Cut and the centrifuge feed flow value void AlphaByDU(); + // calculate Alpha from the feed assay and the product assay; + void AlphaByProductAssay(); + // Compute Beta value from alpha value, cut and feed assay void BetaByAlphaAndCut(); // recompute Cut value assuming Alpha and Beta fixed void CutByAlphaBeta(); + // Compute Product from gamma + void ProductAssayByGamma(double gamma); + // Compute Product assay from feed assay and alpha void ProductAssay(); // Compute Waste assay from feed assay and beta @@ -80,6 +86,8 @@ class StageConfig { void beta(double b) {beta_ = b;} void feed_flow(double f) {feed_flow_ = f;} void feed_assay(double fa) {feed_assay_ = fa;} + double product_assay(double pa) {product_assay_ = pa;} + double tail_assay(double ta) {tail_assay_ = ta;} // Getter methods double precision() {return precision_;} diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 7e935f6..9f84d43 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -108,12 +108,13 @@ TEST(StageConfig_Test, TestIdeal) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST(StageConfig_Test, ProductAssayByGamma) { double gamma = 1.3798316056650026; - double target_product_assay = 0.00821; + double target_product_assay = 0.00822; double theta_ = 0.46040372309; double feed_assay_ = 0.007; StageConfig stage(feed_assay_, feed_c, theta_, delU, -1, 1e-16); + stage.ProductAssayByGamma(gamma); - EXPECT_NEAR(target_product_assay,stage.ProductAssayByGamma(gamma), 1e-5); + EXPECT_NEAR(target_product_assay,stage.product_assay(), 1e-5); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -123,11 +124,12 @@ TEST(StageConfig_Test, AlphaByProductAssay) { double theta_ = 0.46040372309; double feed_assay_ = 0.007; StageConfig stage(feed_assay_, feed_c, theta_, delU, -1, 1e-16); - stage.feed_assay = 0.1; - stage.product_assay = 0.3; + stage.feed_assay(0.1); + stage.product_assay(0.3); double alpha_ = 0.3/(1-0.3)*(1-0.1)/0.1; + stage.AlphaByProductAssay(); - EXPECT_NEAR(alpha_,stage.AlphaByProductAssay(), 1e-5); + EXPECT_NEAR(alpha_,stage.alpha(), 1e-5); } From 7ff109182797c756112df5aced3a57fe1cd9488c Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 12 Feb 2020 11:00:59 -0600 Subject: [PATCH 102/116] Removing FlowPerSec() method from cascade config --- src/CascadeEnrich.cc | 2 +- src/CascadeEnrich.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index 8d4cbf5..4a1419f 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -64,7 +64,7 @@ void CascadeEnrich::EnterNotify() { secpertimestep = (*this).context()->sim_info().dt; cascade = CascadeConfig(centrifuge, design_feed_assay, design_product_assay, - design_tails_assay, FlowPerSec(design_feed_flow), + design_tails_assay, design_feed_flow, max_centrifuges, precision); std::map::iterator it; diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index c36c635..4a3e8db 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -232,7 +232,7 @@ class CascadeEnrich : public cyclus::Facility { "tooltip": "design feed flow (kg/mon)", \ "uilabel": "Design Feed Flow", \ "doc": "Target amount of feed material to be processed by the " \ - "facility (kg/mon). Either this or max_centrifuges is used to constrain " \ + "facility (kg/s). Either this or max_centrifuges is used to constrain " \ "the cascade design" } double design_feed_flow; From 2f58beb37651ee4548dc2b798cf58e87770753d1 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Thu, 20 Feb 2020 10:16:48 -0600 Subject: [PATCH 103/116] Removal of M in alpha and feed_flow calcs. WIP FeedFlowTime test. --- src/CascadeConfig.cc | 16 +++++----- src/CascadeEnrich.h | 2 +- src/CascadeEnrich_tests.cc | 62 +++++++++++++++++++++++++++++++++++++- src/StageConfig.cc | 8 ++--- src/StageConfig.h | 8 ++--- src/StageConfig_tests.cc | 1 + 6 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/CascadeConfig.cc b/src/CascadeConfig.cc index 1ab3b92..4b5f955 100644 --- a/src/CascadeConfig.cc +++ b/src/CascadeConfig.cc @@ -122,13 +122,7 @@ void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, int ideal_strip_stage = 0; // Initialisation of Feeding stage (I == 0) - StageConfig stg; - stg.alpha(-1); - stg.DU(-1); - stg.centrifuge = centrifuge; - stg.feed_assay(f_assay); - stg.precision(precision); - stg.BuildIdealStg(); + StageConfig stg(centrifuge, f_assay, precision); int stg_i = 0; ideal_stgs[stg_i] = stg; double ref_alpha = ideal_stgs[0].alpha(); @@ -186,8 +180,14 @@ void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { CalcFeedFlows(); PopulateStages(); - // Do design parameters require more centrifuges than what is available? int machines_needed = FindTotalMachines(); + + if (max_centrifuges == -1) { + n_machines = machines_needed; + return; + } + + // Do design parameters require more centrifuges than what is available? double max_feed_from_machine = max_feed; while (machines_needed > max_centrifuges) { double scaling_ratio = (double)machines_needed / (double)max_centrifuges; diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 4a3e8db..2b8dc54 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -237,7 +237,7 @@ class CascadeEnrich : public cyclus::Facility { double design_feed_flow; #pragma cyclus var { \ - "default" : 1000, \ + "default" : -1, \ "tooltip" : "number of centrifuges available ", \ "uilabel" : "Number of Centrifuges", \ "doc" : "number of centrifuges available to make the cascade" } diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index 87e83b9..6f29142 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -145,7 +145,7 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("heu", cascadenrichtest::c_heu()); - sim.AddSink("enr_u").recipe("heu").capacity(10).Finalize(); + sim.AddSink("enr_u").recipe("heu").capacity(20).Finalize(); int id = sim.Run(); @@ -159,6 +159,66 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { << "traded quantity exceeds capacity constraint"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TEST_F(CascadeEnrichTest, FeedFlowTime) { + // Tests that simulations using different timesteps reach the + // same equilibrium value, all other parameters held the same. + + std::string config = + " natu " + " natu1 " + " enr_u " + " tails " + " 0.003 " + " 1e09 "; + + int simdur = 1; + + // Running sim with daily timestep + cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, + simdur); + cyclus::SimInfo SI(1, 0, 1, "", "never"); + SI.dt = 3600*24; + cyclus::Context* ctx = sim.context(); + ctx->InitSim(SI); + + sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); + sim.AddRecipe("heu", cascadenrichtest::c_heu()); + sim.AddSink("enr_u").recipe("heu").Finalize(); + + int id = sim.Run(); + + std::vector conds; + conds.push_back(Cond("Commodity", "==", std::string("enr_u"))); + QueryResult qr = sim.db().Query("Transactions", &conds); + Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); + + double day_q = m->quantity(); + + // Running sim with yearly timestep + cyclus::MockSim sim2(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, + simdur); + cyclus::SimInfo SI2(1, 0, 1, "", "never"); + SI2.dt = 3600*24*365.25; + cyclus::Context* ctx2 = sim2.context(); + ctx->InitSim(SI2); + + sim2.AddRecipe("natu1", cascadenrichtest::c_natu1()); + sim2.AddRecipe("heu", cascadenrichtest::c_heu()); + sim2.AddSink("enr_u").recipe("heu").Finalize(); + + int id2 = sim2.Run(); + + std::vector conds2; + conds2.push_back(Cond("Commodity", "==", std::string("enr_u"))); + QueryResult qr2 = sim2.db().Query("Transactions", &conds2); + Material::Ptr m2 = sim2.GetMaterial(qr2.GetVal("ResourceId")); + + double year_q = m2->quantity(); + + EXPECT_NEAR(day_q*365.25,year_q, 0.01); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST_F(CascadeEnrichTest, TradeTails) { // this tests whether tails are being traded. diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 9fb8a79..7459cea 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -12,8 +12,8 @@ namespace mbmore { -StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, double feed__, - double precision__) +StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, + double precision__, double feed__) : centrifuge(cent), feed_assay_(f_assay), feed_flow_(feed__), @@ -106,7 +106,7 @@ void StageConfig::AlphaByDU() { double feed = centrifuge.feed; double M = centrifuge.M; // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - alpha_ = 1. + std::sqrt((2. * (DU_ / M) * (1. - cut_) / (cut_ * feed))); + alpha_ = 1. + std::sqrt((2. * (DU_) * (1. - cut_) / (cut_ * feed))); } void StageConfig::AlphaByProductAssay(){ @@ -156,7 +156,7 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { // centrifuge feed flow (centrifuge.feed). // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - double cfeed_flow = (2 * DU_ / centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); + double cfeed_flow = (2 * DU_) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); double n_exact = feed_flow_ / cfeed_flow; // Adds a machine if fractional amount is needed diff --git a/src/StageConfig.h b/src/StageConfig.h index 9731f9d..53e3529 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -20,9 +20,9 @@ class StageConfig { // cut value of the stage double cut_; // dU value of the stage (calculated form the centrifuges config with the cut) - double DU_; + double DU_ = -1; // Feed to Product enrichment ratio - double alpha_; + double alpha_ = -1; // Feed to Tail enrichment ratio double beta_; // Feed flow (g/s) @@ -42,8 +42,8 @@ class StageConfig { // Setup a empty stage StageConfig() { ; } // Design an ideal stage for a specific feed assay and feed flow - StageConfig(CentrifugeConfig cent, double f_assay, double feed_flow, - double precision = 1e-8); + StageConfig(CentrifugeConfig cent, double f_assay, + double precision = 1e-8, double feed_flow = -1); // Design an ideal stage for a specific feed assay and feed flow StageConfig(double f_assay, double feed_flow, double cut_, double DU_, double alpha_ = -1, double precision = 1e-8); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 9f84d43..5b74bde 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -142,6 +142,7 @@ TEST(StageConfig_Test, TestStages) { stage.ProductAssay(); stage.MachinesNeededPerStage(); + //double expected_product_assay_s = 0.007782156959583; double expected_product_assay_s = 0.0082492; // Calculated using equations from 2009 Glaser paper From f14c7f2927742abb2158b454c7a02274ef8a79a9 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 25 Mar 2020 16:56:47 -0500 Subject: [PATCH 104/116] Add Alpha-Beta dU test t StageConfig --- src/CascadeConfig_tests.cc | 4 ++-- src/CascadeEnrich.cc | 2 +- src/CascadeEnrich.h | 20 +++++++++++++++++-- src/CascadeEnrich_tests.cc | 14 ++++++++++---- src/CentrifugeConfig.cc | 24 +++++++++++------------ src/CentrifugeConfig.h | 2 +- src/CentrifugeConfig_tests.cc | 4 ++-- src/StageConfig.cc | 4 ++-- src/StageConfig_tests.cc | 36 +++++++++++++++++++++++++++++++++-- 9 files changed, 82 insertions(+), 28 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index fba9127..c840741 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -16,7 +16,7 @@ const double dM = 0.003; // kg/mol U238 - U235 const double x = 1000; // Pressure ratio (Glaser) // General cascade assumptions -const double flow_internal = 2.0; +const double flow_ratio = 2.0; const double eff = 1.0; const double cut = 0.5; @@ -34,7 +34,7 @@ const double waste_assay = 0.001; const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, - flow_internal); + flow_ratio); // del U=7.0323281e-08 alpha=1.16321 double delU = centrifuge.ComputeDeltaU(cut); diff --git a/src/CascadeEnrich.cc b/src/CascadeEnrich.cc index 4a1419f..99d7c8c 100644 --- a/src/CascadeEnrich.cc +++ b/src/CascadeEnrich.cc @@ -60,7 +60,7 @@ void CascadeEnrich::EnterNotify() { centrifuge.diameter = diameter; centrifuge.feed = machine_feed / 1000 / 1000; centrifuge.temp = temp; - centrifuge.flow_internal = L_over_F; + centrifuge.flow_ratio = L_over_F; secpertimestep = (*this).context()->sim_info().dt; cascade = CascadeConfig(centrifuge, design_feed_assay, design_product_assay, diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 2b8dc54..234d689 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -228,8 +228,8 @@ class CascadeEnrich : public cyclus::Facility { double max_feed_inventory; #pragma cyclus var { \ - "default": 100, \ - "tooltip": "design feed flow (kg/mon)", \ + "default": 0.000015, \ + "tooltip": "design feed flow (kg/s)", \ "uilabel": "Design Feed Flow", \ "doc": "Target amount of feed material to be processed by the " \ "facility (kg/s). Either this or max_centrifuges is used to constrain " \ @@ -308,6 +308,22 @@ class CascadeEnrich : public cyclus::Facility { "doc" : "maximum feed rate for a single centrifuge (mg/sec)" } double machine_feed; +#pragma cyclus var { \ + "default" : 1000., \ + "tooltip" : "Internal Pressure Ratio", \ + "uilabel" : "Centrifuge internal pressure ratio", \ + "doc" : "Pressure ratio parameter for centrifuge design"\ + "that drives the r1 / r2 ratio."} + double x; + +#pragma cyclus var { \ + "default" : 1.0, \ + "tooltip" : "Overall centrifuge efficiency", \ + "uilabel" : "Overall centrifuge efficiency", \ + "doc" : "Centrifuge efficiency parameter that describes"\ + "its effective separative performance."} + double eff; + #pragma cyclus var { \ "default": 0, \ "userlevel": 10, \ diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index 6f29142..64313e9 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -170,11 +170,13 @@ TEST_F(CascadeEnrichTest, FeedFlowTime) { " enr_u " " tails " " 0.003 " - " 1e09 "; + " 1e09 " + " 300"; int simdur = 1; - // Running sim with daily timestep + //-------------------------------------------------------------------- + // BEGIN: Daily timestep sim cyclus::MockSim sim(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); cyclus::SimInfo SI(1, 0, 1, "", "never"); @@ -195,13 +197,15 @@ TEST_F(CascadeEnrichTest, FeedFlowTime) { double day_q = m->quantity(); - // Running sim with yearly timestep + // END: Daily timestep sim + //-------------------------------------------------------------------- + // BEGIN: Yearly timestep sim cyclus::MockSim sim2(cyclus::AgentSpec(":mbmore:CascadeEnrich"), config, simdur); cyclus::SimInfo SI2(1, 0, 1, "", "never"); SI2.dt = 3600*24*365.25; cyclus::Context* ctx2 = sim2.context(); - ctx->InitSim(SI2); + ctx2->InitSim(SI2); sim2.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim2.AddRecipe("heu", cascadenrichtest::c_heu()); @@ -215,7 +219,9 @@ TEST_F(CascadeEnrichTest, FeedFlowTime) { Material::Ptr m2 = sim2.GetMaterial(qr2.GetVal("ResourceId")); double year_q = m2->quantity(); + // END: Yearly timestep sim + // Check if, scaling for timestep, the same quantity is produced EXPECT_NEAR(day_q*365.25,year_q, 0.01); } diff --git a/src/CentrifugeConfig.cc b/src/CentrifugeConfig.cc index bc6003c..d61d29e 100644 --- a/src/CentrifugeConfig.cc +++ b/src/CentrifugeConfig.cc @@ -8,7 +8,7 @@ #include #include -/* +/* @article{alexander_glaser_characteristics_2008, title = {Characteristics of the {Gas} {Centrifuge} for {Uranium} {Enrichment} and {Their} {Relevance} for {Nuclear} {Weapon} {Proliferation}}, issn = {1547-7800}, @@ -34,11 +34,11 @@ CentrifugeConfig::CentrifugeConfig() { eff = 1.0; x = 1000; - flow_internal = 2.0; + flow_ratio = 2.0; // default UF6 0.352 kg/mol M = 0.352; - + // default 0.003kg/mol (u235/U238) dM = 0.003; // SEE GLASER P2 @@ -57,7 +57,7 @@ CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, double fee eff = eff_; x = x_; - flow_internal = flow_; + flow_ratio = flow_; M = M_; dM = dM_; @@ -67,7 +67,7 @@ CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, double fee } double CentrifugeConfig::ComputeDeltaU(double cut) { - + // Inputs that are effectively constants: double a = diameter / 2.0; // outer radius @@ -88,28 +88,28 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { // Glaser eqn 12 // Vertical location of feed - double Z_p = height * (1.0 - cut) * (1.0 + flow_internal) / - (1.0 - cut + flow_internal); + double Z_p = height * (1.0 - cut) * (1.0 + flow_ratio) / + (1.0 - cut + flow_ratio); // Glaser eqn 3 // Converting from molecular mass to atomic mass (assuming U238) // Warning: This assumption is only valid at low enrichment // TODO: EXPLICITLY CALCULATE ATOMIC MASS GIVEN FEED ASSAY double C1 = (2.0 * M_PI * (D_rho * M_238 / M) / (log(r2 / r1))); - // double C1 = (2.0 * M_PI * D_rho / (log(r2 / r1))); + //double C1 = (2.0 * M_PI * D_rho / (log(r2 / r1))); double A_p = C1 * (1.0 / feed) * - (cut / ((1.0 + flow_internal) * (1.0 - cut + flow_internal))); + (cut / ((1.0 + flow_ratio) * (1.0 - cut + flow_ratio))); double A_w = C1 * (1.0 / feed) * - ((1.0 - cut) / (flow_internal * (1.0 - cut + flow_internal))); + ((1.0 - cut) / (flow_ratio * (1.0 - cut + flow_ratio))); double C_therm = CalcCTherm(v_a, temp, dM); // defining terms in the Ratz equation double r1_over_r2_sq = r1_over_r2*r1_over_r2; double C_scale = pow((r2 / a), 4) * (1 - r1_over_r2_sq)*(1 - r1_over_r2_sq); - double bracket1 = (1 + flow_internal) / cut; + double bracket1 = (1 + flow_ratio) / cut; double exp1 = exp(-1.0 * A_p * Z_p); - double bracket2 = flow_internal / (1 - cut); + double bracket2 = flow_ratio / (1 - cut); double exp2 = exp(-1.0 * A_w * (height - Z_p)); // Glaser eqn 10 (Ratz Equation) diff --git a/src/CentrifugeConfig.h b/src/CentrifugeConfig.h index 91b4c85..e190b07 100644 --- a/src/CentrifugeConfig.h +++ b/src/CentrifugeConfig.h @@ -19,7 +19,7 @@ class CentrifugeConfig { double dM; // molar mass diff between the 2 components of the gas default 0.003kg/mol (u235/U238) double M; // gas molar mass, default UF6 0.352 kg/mol double x; // pressure ration -> drive r1/r2 ratio - double flow_internal; // countercurrent-to-feed ratios k range between 2 and 4 + double flow_ratio; // countercurrent-to-feed ratios k range between 2 and 4 double v_a; // peripheral velocities double height; // centrifugre height diff --git a/src/CentrifugeConfig_tests.cc b/src/CentrifugeConfig_tests.cc index b22421a..881ff93 100644 --- a/src/CentrifugeConfig_tests.cc +++ b/src/CentrifugeConfig_tests.cc @@ -18,7 +18,7 @@ TEST(CentrifugeConfig_Test, TestSWU) { double x = 1000; // Pressure ratio (Glaser) // General cascade assumptions - double flow_internal = 2.0; + double flow_ratio = 2.0; double eff = 1.0; double cut = 0.5; @@ -31,7 +31,7 @@ TEST(CentrifugeConfig_Test, TestSWU) { double temp = 320.0; // Kelvin CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, - x, flow_internal); + x, flow_ratio); // del U=7.0323281e-08 alpha=1.16321 double delU = centrifuge.ComputeDeltaU(cut); diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 7459cea..d1a4779 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -106,7 +106,7 @@ void StageConfig::AlphaByDU() { double feed = centrifuge.feed; double M = centrifuge.M; // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - alpha_ = 1. + std::sqrt((2. * (DU_) * (1. - cut_) / (cut_ * feed))); + alpha_ = 1. + std::sqrt((2. * (DU_/M) * (1. - cut_) / (cut_ * feed))); } void StageConfig::AlphaByProductAssay(){ @@ -156,7 +156,7 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { // centrifuge feed flow (centrifuge.feed). // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - double cfeed_flow = (2 * DU_) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); + double cfeed_flow = (2 * DU_/centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); double n_exact = feed_flow_ / cfeed_flow; // Adds a machine if fractional amount is needed diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 5b74bde..844d1b2 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -16,7 +16,7 @@ double dM = 0.003; // kg/mol U238 - U235 double x = 1000; // Pressure ratio (Glaser) // General cascade assumptions -double flow_internal = 2.0; +double flow_ratio = 2.0; double eff = 1.0; double cut = 0.5; @@ -34,7 +34,7 @@ const double waste_assay = 0.001; const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, - flow_internal); + flow_ratio); // del U=7.0323281e-08 alpha=1.16321 double delU = centrifuge.ComputeDeltaU(cut); @@ -152,5 +152,37 @@ TEST(StageConfig_Test, TestStages) { EXPECT_NEAR(stage.product_assay(), expected_product_assay_s, tol_assay); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Verify that, for a P1-type centrifuge, results are in agreement +// with those presented by Glaser paper. +TEST(StageConfig_Test, AlphaBeta) { + // P1-type parameters + double v_a = 320; // m/s + double Z = 1.8; // m + double d = 0.10; // m + double eff = 0.564; + double x = 1000.; + double flow_ratio = 2.0; + double temp = 320; // K + double M = 0.352; // kg/mol UF6 + double dM = 0.003; // kg/mol U238 - U235 + double feed = 12.6 / 1000. / 1000.; // mg/s -> kg/s + double cut = 0.5; + double f_assay = 0.00720; + + CentrifugeConfig cent(v_a, Z, d, feed, temp, eff, M, dM, x, flow_ratio); + + double delU = cent.ComputeDeltaU(cut); + + double delU_e = 2.5 / (365.25 * 24 * 60 * 60); + EXPECT_NEAR(delU, 1.0, 1e-8); + + StageConfig stg(f_assay, feed, cut, delU); + + double ab_e = 1.29; + EXPECT_NEAR(stg.alpha() * stg.beta(), ab_e, 0.0001); + +} + } // namespace enrichfunctiontests } // namespace mbmore From 880c24f555d58030fd3042d34dfc08e313f8237b Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot Date: Wed, 25 Mar 2020 15:43:58 -0500 Subject: [PATCH 105/116] add SWU --- src/StageConfig.cc | 10 ++++++++++ src/StageConfig.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index d1a4779..86e6799 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -1,5 +1,6 @@ // Implements the CascadeEnrich class #include "StageConfig.h" +#include "cyclus.h" #include #include @@ -165,6 +166,15 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { n_machines_ = int(n_exact) + 1; } +} +double StageConfig::SWU(){ + using cyclus::toolkit::Assays; + using cyclus::toolkit::SwuRequired; + if(product_assay_ == -1 || feed_assay_ == -1 || tail_assay_ == 1 || feed_flow_ == -1) + return -1; + + return SwuRequired(feed_flow_, Assays(feed_assay_, product_assay_, tail_assay_)); + } } // namespace mbmore diff --git a/src/StageConfig.h b/src/StageConfig.h index 53e3529..59f10b8 100644 --- a/src/StageConfig.h +++ b/src/StageConfig.h @@ -63,6 +63,9 @@ class StageConfig { // recompute Cut value assuming Alpha and Beta fixed void CutByAlphaBeta(); + // return the SWU of the stage + double SWU(); + // Compute Product from gamma void ProductAssayByGamma(double gamma); From e1134aec038dcce862a03a393a198bf1c93d8340 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot Date: Mon, 8 Jun 2020 15:02:46 -0500 Subject: [PATCH 106/116] ignore vscode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d5193fa..b362b7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vscode build/ *~ src/tmp/* \ No newline at end of file From 7f4e6db1ffc9da49b649fddf16b022e420fa33cb Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot Date: Mon, 8 Jun 2020 15:03:02 -0500 Subject: [PATCH 107/116] convert feed from UF6 to U --- src/CentrifugeConfig.cc | 63 +++++++++++++++++++++++------------------ src/StageConfig.cc | 50 +++++++++++++++++--------------- 2 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/CentrifugeConfig.cc b/src/CentrifugeConfig.cc index d61d29e..a9e4603 100644 --- a/src/CentrifugeConfig.cc +++ b/src/CentrifugeConfig.cc @@ -10,22 +10,24 @@ /* @article{alexander_glaser_characteristics_2008, - title = {Characteristics of the {Gas} {Centrifuge} for {Uranium} {Enrichment} and {Their} {Relevance} for {Nuclear} {Weapon} {Proliferation}}, - issn = {1547-7800}, - doi = {10.1080/08929880802335998}, - number = {16}, - journal = {Science and Global Security}, - author = {Alexander Glaser}, - year = {2008}, - pages = {1--25}, - annote = {From Tamara}, - file = {2008aglaser_sgsvol16.pdf:/Users/mouginot/Zotero/storage/UAGA49FS/2008aglaser_sgsvol16.pdf:application/pdf} + title = {Characteristics of the {Gas} {Centrifuge} for {Uranium} +{Enrichment} and {Their} {Relevance} for {Nuclear} {Weapon} {Proliferation}}, + issn = {1547-7800}, + doi = {10.1080/08929880802335998}, + number = {16}, + journal = {Science and Global Security}, + author = {Alexander Glaser}, + year = {2008}, + pages = {1--25}, + annote = {From Tamara}, + file = +{2008aglaser_sgsvol16.pdf:/Users/mouginot/Zotero/storage/UAGA49FS/2008aglaser_sgsvol16.pdf:application/pdf} } */ namespace mbmore { CentrifugeConfig::CentrifugeConfig() { -// Standard Values for a P1-type centrifuges + // Standard Values for a P1-type centrifuges v_a = 320; height = 1.8; diameter = 0.10; @@ -47,8 +49,10 @@ CentrifugeConfig::CentrifugeConfig() { M_238 = 0.238; // kg/mol } -CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, double feed_, double T_, - double eff_, double M_, double dM_, double x_, double flow_){ +CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, + double feed_, double T_, double eff_, + double M_, double dM_, double x_, + double flow_) { v_a = v_a_; height = h_; diameter = d_; @@ -67,7 +71,6 @@ CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, double fee } double CentrifugeConfig::ComputeDeltaU(double cut) { - // Inputs that are effectively constants: double a = diameter / 2.0; // outer radius @@ -78,9 +81,9 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { // Glaser: if v_a < 380 then r1_over_r2 = cte = 0.534 double r1_over_r2 = 0; - if (v_a > 380){ - r1_over_r2 = std::sqrt( - 1.0 - (2.0 * gas_const * temp * log(x)) / M / (v_a*v_a) ); + if (v_a > 380) { + r1_over_r2 = + std::sqrt(1.0 - (2.0 * gas_const * temp * log(x)) / M / (v_a * v_a)); } else { r1_over_r2 = 0.534; } @@ -88,25 +91,29 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { // Glaser eqn 12 // Vertical location of feed - double Z_p = height * (1.0 - cut) * (1.0 + flow_ratio) / - (1.0 - cut + flow_ratio); + double Z_p = + height * (1.0 - cut) * (1.0 + flow_ratio) / (1.0 - cut + flow_ratio); // Glaser eqn 3 // Converting from molecular mass to atomic mass (assuming U238) // Warning: This assumption is only valid at low enrichment // TODO: EXPLICITLY CALCULATE ATOMIC MASS GIVEN FEED ASSAY - double C1 = (2.0 * M_PI * (D_rho * M_238 / M) / (log(r2 / r1))); - //double C1 = (2.0 * M_PI * D_rho / (log(r2 / r1))); - double A_p = C1 * (1.0 / feed) * + + // converting feed from UF6 to U + double ratio_UF6_U = M_238 / M; + double feed_U = feed * ratio_UF6_U; + + double C1 = (2.0 * M_PI * D_rho * ratio_UF6_U / (log(r2 / r1))); + double A_p = C1 * (1.0 / feed_U) * (cut / ((1.0 + flow_ratio) * (1.0 - cut + flow_ratio))); - double A_w = C1 * (1.0 / feed) * + double A_w = C1 * (1.0 / feed_U) * ((1.0 - cut) / (flow_ratio * (1.0 - cut + flow_ratio))); double C_therm = CalcCTherm(v_a, temp, dM); // defining terms in the Ratz equation - double r1_over_r2_sq = r1_over_r2*r1_over_r2; - double C_scale = pow((r2 / a), 4) * (1 - r1_over_r2_sq)*(1 - r1_over_r2_sq); + double r1_over_r2_sq = pow(r1_over_r2, 2); + double C_scale = pow((r2 / a), 4) * pow(1 - r1_over_r2_sq, 2); double bracket1 = (1 + flow_ratio) / cut; double exp1 = exp(-1.0 * A_p * Z_p); double bracket2 = flow_ratio / (1 - cut); @@ -114,15 +121,15 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { // Glaser eqn 10 (Ratz Equation) double major_term = - 0.5 * cut * (1.0 - cut) * (C_therm*C_therm) * C_scale * + 0.5 * cut * (1.0 - cut) * (C_therm * C_therm) * C_scale * pow(((bracket1 * (1 - exp1)) + (bracket2 * (1 - exp2))), 2); // kg/s - double del_U = feed * major_term * eff; // kg/s + double del_U = feed_U * major_term; //* eff; // kg/s return del_U; } double CentrifugeConfig::CalcCTherm(double v_a, double temp, double dM) { - return dM * (v_a*v_a) / (2.0 * gas_const * temp); + return dM * (v_a * v_a) / (2.0 * gas_const * temp); } double CentrifugeConfig::CalcV(double assay) { diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 86e6799..f20e26f 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -1,6 +1,6 @@ // Implements the CascadeEnrich class #include "StageConfig.h" -#include "cyclus.h" +#include "cyclus.h" #include #include @@ -21,8 +21,8 @@ StageConfig::StageConfig(CentrifugeConfig cent, double f_assay, precision_(precision__) { BuildIdealStg(); } -StageConfig::StageConfig(double f_assay, double feed__, double cut__, double DU__, - double alpha__, double precision__) +StageConfig::StageConfig(double f_assay, double feed__, double cut__, + double DU__, double alpha__, double precision__) : centrifuge(), feed_assay_(f_assay), feed_flow_(feed__), @@ -104,14 +104,19 @@ void StageConfig::TailAssay() { } void StageConfig::AlphaByDU() { - double feed = centrifuge.feed; - double M = centrifuge.M; + double M = centrifuge.M; // UF6 kg/mol + double M_238 = 0.238; // U kg/mol + double ratio_UF6_U = M_238 / M; + + // converting feed from UF6 to U + double feed = centrifuge.feed * ratio_UF6_U; // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - alpha_ = 1. + std::sqrt((2. * (DU_/M) * (1. - cut_) / (cut_ * feed))); + alpha_ = 1. + std::sqrt((2. * DU_ * (1. - cut_) / (cut_ * feed))); } -void StageConfig::AlphaByProductAssay(){ - alpha_ = (1 - feed_assay_)/feed_assay_ * product_assay_/(1 - product_assay_); +void StageConfig::AlphaByProductAssay() { + alpha_ = + (1 - feed_assay_) / feed_assay_ * product_assay_ / (1 - product_assay_); } void StageConfig::BetaByAlphaAndCut() { @@ -121,15 +126,13 @@ void StageConfig::BetaByAlphaAndCut() { beta_ = feed_assay_ / (1. - feed_assay_) * (1. - waste_assay) / waste_assay; } -void StageConfig::ProductAssayByGamma(double gamma){ - double product_assay_ = ( - sqrt( pow( (feed_assay_ - cut_) * gamma, 2) - + gamma * ( 2*feed_assay_ + 2*cut_ - - 2*pow(feed_assay_, 2) - - 2*pow(cut_, 2)) - + pow(feed_assay_ + cut_ -1, 2)) - + gamma*(feed_assay_ + cut_) - - feed_assay_ - cut_ + 1 ) - / (2*cut_ * (gamma -1)); +void StageConfig::ProductAssayByGamma(double gamma) { + product_assay_ = (-sqrt(pow((feed_assay_ - cut_) * gamma, 2) + + gamma * (2 * feed_assay_ + 2 * cut_ - + 2 * pow(feed_assay_, 2) - 2 * pow(cut_, 2)) + + pow(feed_assay_ + cut_ - 1, 2)) + + gamma * (feed_assay_ + cut_) - feed_assay_ - cut_ + 1) / + (2 * cut_ * (gamma - 1)); } void StageConfig::CutByAlphaBeta() { @@ -157,7 +160,8 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { // centrifuge feed flow (centrifuge.feed). // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - double cfeed_flow = (2 * DU_/centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); + double cfeed_flow = + (2 * DU_ / centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); double n_exact = feed_flow_ / cfeed_flow; // Adds a machine if fractional amount is needed @@ -165,16 +169,16 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { if (std::abs(n_exact - n_machines_) > tolerance) { n_machines_ = int(n_exact) + 1; } - } -double StageConfig::SWU(){ +double StageConfig::SWU() { using cyclus::toolkit::Assays; using cyclus::toolkit::SwuRequired; - if(product_assay_ == -1 || feed_assay_ == -1 || tail_assay_ == 1 || feed_flow_ == -1) + if (product_assay_ == -1 || feed_assay_ == -1 || tail_assay_ == 1 || + feed_flow_ == -1) return -1; - return SwuRequired(feed_flow_, Assays(feed_assay_, product_assay_, tail_assay_)); - + return SwuRequired(feed_flow_, + Assays(feed_assay_, product_assay_, tail_assay_)); } } // namespace mbmore From 45c0d3d375ca3c9255487f7e5e18bd29af9fba58 Mon Sep 17 00:00:00 2001 From: Baptiste Mouginot <15145274+bam241@users.noreply.github.com> Date: Mon, 8 Jun 2020 15:10:27 -0500 Subject: [PATCH 108/116] Update src/StageConfig.cc Co-authored-by: Jordan Stomps --- src/StageConfig.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index f20e26f..14dc009 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -161,7 +161,7 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 double cfeed_flow = - (2 * DU_ / centrifuge.M) * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); + 2 * DU_ * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); double n_exact = feed_flow_ / cfeed_flow; // Adds a machine if fractional amount is needed From 688d0642fe5de3ce3e321a3efe7b0b8e2ff2cd33 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 17 Jun 2020 10:02:38 -0500 Subject: [PATCH 109/116] Corrected ratio additions to Avery's formula --- .../CascadeConfig-checkpoint.cc | 426 ++++++++++++++++++ src/CentrifugeConfig.cc | 4 +- src/StageConfig.cc | 10 +- src/StageConfig_tests.cc | 18 + 4 files changed, 453 insertions(+), 5 deletions(-) create mode 100644 src/.ipynb_checkpoints/CascadeConfig-checkpoint.cc diff --git a/src/.ipynb_checkpoints/CascadeConfig-checkpoint.cc b/src/.ipynb_checkpoints/CascadeConfig-checkpoint.cc new file mode 100644 index 0000000..4b5f955 --- /dev/null +++ b/src/.ipynb_checkpoints/CascadeConfig-checkpoint.cc @@ -0,0 +1,426 @@ +// Implements the CascadeEnrich class +#include "CascadeConfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbmore { + +CascadeConfig::CascadeConfig() + : n_enrich(0), + n_strip(0), + n_machines(0), + feed_flow(0), + feed_assay(0), + design_product_assay(0), + design_tail_assay(0) {} + +CascadeConfig::CascadeConfig(CentrifugeConfig centrifuge_, double f_assay, + double p_assay, double t_assay, + double max_feed_flow, int max_centrifuge, + double precision) { + centrifuge = centrifuge_; + feed_assay = f_assay; + design_product_assay = p_assay; + design_tail_assay = t_assay; + + feed_flow = max_feed_flow; + n_machines = max_centrifuge; + BuildIdealCascade(f_assay, p_assay, t_assay, precision); + ScaleCascade(max_feed_flow, max_centrifuge); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Calculate steady-state flow rates into each stage +// Linear system of equations in form AX = B, where A is nxn square matrix +// of linear equations for the flow rates of each stage and B are the external +// feeds for the stage. External feed is zero for all stages accept cascade +// feed stage (F_0) stages start with last strip stage [-2, -1, 0, 1, 2] +// http://www.physics.utah.edu/~detar/phys6720/handouts/lapack.html +// +void CascadeConfig::CalcFeedFlows() { + + int n_stages = n_enrich + n_strip; + int max_stages = n_stages; + + // Build Array with pointers + double flow_eqns[max_stages][max_stages]; + double flows[1][max_stages]; + + // build matrix of equations in this pattern + // [[ -1, 1-cut, 0, 0, 0] [[0] + // [cut, -1, 1-cut, 0, 0] [0] + // [ 0, cut, -1, 1-cut, 0] * X = [-1*feed] + // [ 0, 0, cut, -1, 1-cut] [0] + // [ 0, 0, 0, cut, -1]] [0]] + // + for (int row_idx = 0; row_idx < max_stages; row_idx++) { + // fill the array with zeros, then update individual elements as nonzero + flows[0][row_idx] = 0; + for (int fill_idx = 0; fill_idx < max_stages; fill_idx++) { + flow_eqns[fill_idx][row_idx] = 0; + } + // Required to do the artificial 'Max Stages' defn. Only calculate + // non-zero matrix elements where stages really exist. + if (row_idx < n_stages) { + int stg_i = row_idx - n_strip; + int col_idx = n_strip + stg_i; + flow_eqns[col_idx][row_idx] = -1.; + if (row_idx != 0) { + std::map::iterator it = stgs_config.find(stg_i - 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx - 1][row_idx] = it->second.cut(); + } + } + if (row_idx != n_stages - 1) { + std::map::iterator it = stgs_config.find(stg_i + 1); + if (it != stgs_config.end()) { + flow_eqns[col_idx + 1][row_idx] = (1 - it->second.cut()); + } + } + // Add the external feed for the cascade + if (stg_i == 0) { + flows[0][row_idx] = -1. * feed_flow; + } + } + } + + // LAPACK solver variables + int nrhs = 1; // 1 column solution + int lda = max_stages; // must be >= MAX(1,N) + int ldb = max_stages; // must be >= MAX(1,N) + int ipiv[max_stages]; + int info; + + // Solve the linear system + dgesv_(&n_stages, &nrhs, &flow_eqns[0][0], &lda, ipiv, &flows[0][0], &ldb, + &info); + + // Check for success + if (info != 0) { + std::cerr << "LAPACK linear solver dgesv returned error " << info << "\n"; + } + + int i = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + it->second.feed_flow(flows[0][i]); + i++; + } +} + +void CascadeConfig::BuildIdealCascade(double f_assay, double product_assay, + double waste_assay, double precision) { + std::map ideal_stgs; + int ideal_enrich_stage = 0; + int ideal_strip_stage = 0; + + // Initialisation of Feeding stage (I == 0) + StageConfig stg(centrifuge, f_assay, precision); + int stg_i = 0; + ideal_stgs[stg_i] = stg; + double ref_alpha = ideal_stgs[0].alpha(); + double ref_du = ideal_stgs[0].DU(); + // Calculate number of enriching stages + while (stg.product_assay() < product_assay) { + stg.feed_assay(stg.product_assay()); + stg.BuildIdealStg(); + stg_i++; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_enrich = stg_i + 1; + // reset + stg_i = 0; + stg = ideal_stgs[stg_i]; + // Calculate number of stripping stages + while (stg.tail_assay() > waste_assay) { + stg.feed_assay(stg.tail_assay()); + stg.BuildIdealStg(); + stg_i--; + ideal_stgs.insert(std::make_pair(stg_i, stg)); + } + n_strip = -stg_i; + stgs_config = ideal_stgs; +} + +void CascadeConfig::PopulateStages() { + int n_stages = n_enrich + n_strip; + + for (int i = 0; i < n_stages; i++) { + int curr_stage = i - n_strip; + std::map::iterator it = stgs_config.find(curr_stage); + if (it == stgs_config.end()) { + std::cout << "Bad Stage number" << std::endl; + exit(1); + } + it->second.MachinesNeededPerStage(); + } +} + +int CascadeConfig::FindTotalMachines() { + int machines = 0; + std::map::iterator it; + for (it = stgs_config.begin(); it != stgs_config.end(); it++) { + if (it->second.n_machines() == -1) it->second.MachinesNeededPerStage(); + machines += it->second.n_machines(); + } + return machines; +} + +void CascadeConfig::ScaleCascade(double max_feed, int max_centrifuges) { + // Determine the ideal steady-state feed flows for this cascade design given + // the maximum potential design feed rate + feed_flow = max_feed; + CalcFeedFlows(); + PopulateStages(); + + int machines_needed = FindTotalMachines(); + + if (max_centrifuges == -1) { + n_machines = machines_needed; + return; + } + + // Do design parameters require more centrifuges than what is available? + double max_feed_from_machine = max_feed; + while (machines_needed > max_centrifuges) { + double scaling_ratio = (double)machines_needed / (double)max_centrifuges; + max_feed_from_machine = max_feed_from_machine / scaling_ratio; + feed_flow = max_feed_from_machine; + CalcFeedFlows(); + PopulateStages(); + machines_needed = FindTotalMachines(); + } + n_machines = machines_needed; +} + +CascadeConfig CascadeConfig::ModelMisuseCascade(double f_assay, + int modeling_opt, + double precision) { + CascadeConfig misuse_cascade = (*this); + misuse_cascade.PropagateAssay(f_assay); + + // Default: alpha & cut = constant; beta = varying + // Case 1: alpha = beta, cut = varying + // Case 2: gamma & cut = constant, alpha & veta = varying + switch (modeling_opt) { + default: + misuse_cascade.ComputeAssayByAlpha(f_assay, precision); + break; + + case 1: + misuse_cascade.UpdateCut(); + misuse_cascade.UpdateFlow(); + break; + + case 2: + misuse_cascade.ComputeAssayByGamma(f_assay, precision); + break; + } + return misuse_cascade; +} + +void CascadeConfig::UpdateFlow() { + // recompute the flow according to the new cuts + (*this).CalcFeedFlows(); + + double ratio = 1; + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + std::map::iterator it_real = + (*this).stgs_config.find(it->first); + double max_stg_flow = + it_real->second.n_machines() * it_real->second.centrifuge.feed; + double stg_flow_ratio = it->second.feed_flow() / max_stg_flow; + if (ratio > stg_flow_ratio) { + ratio = stg_flow_ratio; + } + } + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + it->second.feed_flow(it->second.feed_flow() * ratio); + } + (*this).feed_flow *= ratio; +} + +void CascadeConfig::UpdateCut() { + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + it->second.CutByAlphaBeta(); + } +} + +void CascadeConfig::PropagateAssay(double f_assay) { + // Initialise Feeding stage + std::map::iterator it = (*this).stgs_config.find(0); + it->second.feed_assay(f_assay); + it->second.ProductAssay(); + it->second.TailAssay(); + + // Propagate initialisation to all stages + for (int i = 0; i < (*this).n_enrich; i++) { + it = (*this).stgs_config.find(i); + std::map::iterator it_feed; + + // Enrich stage -> feed = Product from Previous Stage + it_feed = (*this).stgs_config.find(it->first - 1); + if (it->first > 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay(it_feed->second.product_assay()); + } + // Update Product and Tail assay from feed assay + it->second.ProductAssay(); + it->second.TailAssay(); + } + } + for (int i = 1; i <= (*this).n_strip; i++) { + it = (*this).stgs_config.find(-i); + std::map::iterator it_feed; + + // Striping stage -> feed = tails from Next Stage + it_feed = (*this).stgs_config.find(it->first + 1); + if (it->first < 0) { + if (it_feed != (*this).stgs_config.end()) { + it->second.feed_assay(it_feed->second.tail_assay()); + } + // Update Product and Tail assay from feed assay + it->second.ProductAssay(); + it->second.TailAssay(); + } + } +} + +void CascadeConfig::ComputeAssayByAlpha(double f_assay, double precision) { + CascadeConfig previous_cascade; + while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { + previous_cascade = (*this); + (*this).IterateEnrichment(f_assay); + (*this).UpdateByAlpha(); + } +} + +void CascadeConfig::ComputeAssayByGamma(double f_assay, double precision) { + CascadeConfig previous_cascade; + while (DeltaEnrichment((*this), previous_cascade, precision) > precision) { + previous_cascade = (*this); + (*this).IterateEnrichment(f_assay); + (*this).UpdateByGamma(); + } +} + +double CascadeConfig::DeltaEnrichment(CascadeConfig a_enrichments, + CascadeConfig p_enrichments, + double precision) { + if (p_enrichments.n_enrich == 0) { + return 100. * std::abs(precision); + } + double square_feed_diff = 0; + double square_product_diff = 0; + double square_waste_diff = 0; + std::map::iterator it; + for (it = a_enrichments.stgs_config.begin(); + it != a_enrichments.stgs_config.end(); it++) { + int i = it->first; + std::map::iterator it2 = + p_enrichments.stgs_config.find(it->first); + if (it2 != p_enrichments.stgs_config.end()) { + square_feed_diff += + pow(it->second.feed_assay() - it2->second.feed_assay(), 2); + square_product_diff += + pow(it->second.product_assay() - it2->second.product_assay(), 2); + square_waste_diff += + pow(it->second.tail_assay() - it2->second.tail_assay(), 2); + } + } + return square_feed_diff + square_product_diff + square_waste_diff; +} + +void CascadeConfig::IterateEnrichment(double f_assay) { + CascadeConfig updated_enrichment = (*this); + + // mixing variables + double down_assay = 0; + double up_assay = 0; + double down_flow = 0; + double up_flow = 0; + double stg_feed_flow = 0; + std::map::iterator it; + + // Get the Flow and Assay quantity + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + int i = it->first; + std::map::iterator it_up = + (*this).stgs_config.find(i + 1); + std::map::iterator it_down = + (*this).stgs_config.find(i - 1); + down_assay = 0; + up_assay = 0; + down_flow = 0; + up_flow = 0; + + if (it_down != (*this).stgs_config.end()) { + down_assay = it_down->second.product_assay(); + down_flow = it_down->second.feed_flow() * it_down->second.cut(); + } + if (it_up != (*this).stgs_config.end()) { + up_assay = it_up->second.tail_assay(); + up_flow = it_up->second.feed_flow() * (1 - it_up->second.cut()); + } + + // Mix the Product and the Tail to have the correct Feed Assay + double stg_f_assay = + (down_assay * down_flow + up_assay * up_flow) / (down_flow + up_flow); + if (i == 0) { // add Feed flow in the entry stage + stg_f_assay = (down_assay * down_flow + up_assay * up_flow + + f_assay * (*this).feed_flow) / + (down_flow + up_flow + (*this).feed_flow); + stg_feed_flow = down_flow + up_flow + (*this).feed_flow; + } + + std::map::iterator it_new = + updated_enrichment.stgs_config.find(i); + + // Update Stage feed assay + it_new->second.feed_assay(stg_f_assay); + } + + (*this).stgs_config = updated_enrichment.stgs_config; +} + +void CascadeConfig::UpdateByAlpha(){ + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + // Update Beta values (from feed) -- Alpha & Cut are cte + it->second.BetaByAlphaAndCut(); + // Recompute Product Assay and Tail Assay + it->second.ProductAssay(); + it->second.TailAssay(); + } +} + +void CascadeConfig::UpdateByGamma(){ + std::map::iterator it; + for (it = (*this).stgs_config.begin(); it != (*this).stgs_config.end(); + it++) { + double gamma = it->second.alpha() * it->second.beta(); + // Recompute Product Assay + it->second.ProductAssayByGamma(gamma); + // Alpha by Product assay + it->second.AlphaByProductAssay(); + // Beta and tail assay... + it->second.BetaByAlphaAndCut(); + it->second.TailAssay(); + } +} + +} // namespace mbmore diff --git a/src/CentrifugeConfig.cc b/src/CentrifugeConfig.cc index a9e4603..658dbc4 100644 --- a/src/CentrifugeConfig.cc +++ b/src/CentrifugeConfig.cc @@ -75,7 +75,7 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { double a = diameter / 2.0; // outer radius - // withdrawl radius for heavy isotope + // withdrawal radius for heavy isotope // Glaser 2009 says operationally it ranges from 0.96-0.99 double r2 = 0.975 * a; @@ -87,7 +87,7 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { } else { r1_over_r2 = 0.534; } - double r1 = r2 * r1_over_r2; // withdrawl radius for ligher isotope + double r1 = r2 * r1_over_r2; // withdrawal radius for lighter isotope // Glaser eqn 12 // Vertical location of feed diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 14dc009..30565d5 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -159,10 +159,14 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { // n_machines: the denominator should be equal to the // centrifuge feed flow (centrifuge.feed). + double M = centrifuge.M; // UF6 kg/mol + double M_238 = 0.238; // U kg/mol + double ratio_UF6_U = M_238 / M; + // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - double cfeed_flow = - 2 * DU_ * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.); - double n_exact = feed_flow_ / cfeed_flow; + double centrifuge_feed_flow = + 2 * DU_ * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.) / ratio_UF6_U; + double n_exact = this->feed_flow_ / (centrifuge_feed_flow); // Adds a machine if fractional amount is needed n_machines_ = int(n_exact); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 844d1b2..97adf20 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -184,5 +184,23 @@ TEST(StageConfig_Test, AlphaBeta) { } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Verify that the centrifuge feed flow can be reconstructed if alpha +// is not provided. +TEST(StageConfig_Test, FeedFlow) { + StageConfig stage(feed_assay, feed_c, cut, delU, -1, 1e-16); + + double M = centrifuge.M; // UF6 kg/mol + double M_238 = 0.238; // U kg/mol + double ratio_UF6_U = M_238 / M; + + // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 + double centrifuge_feed_flow = + 2 * stage.DU() * ((1 - stage.cut()) / stage.cut()) + / pow((stage.alpha() - 1.), 2.) / ratio_UF6_U; + + EXPECT_NEAR(centrifuge_feed_flow,stage.centrifuge.feed,1e-6); +} + } // namespace enrichfunctiontests } // namespace mbmore From fdcf7ab320a1998f3c00eeee6e30d33c6236da76 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 17 Jun 2020 10:19:35 -0500 Subject: [PATCH 110/116] Corrected StageConfig->TestStages expected value --- src/StageConfig.cc | 2 +- src/StageConfig_tests.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StageConfig.cc b/src/StageConfig.cc index 30565d5..c87dec2 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -166,7 +166,7 @@ void StageConfig::MachinesNeededPerStage(double tolerance) { // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 double centrifuge_feed_flow = 2 * DU_ * ((1 - cut_) / cut_) / pow((alpha_ - 1.), 2.) / ratio_UF6_U; - double n_exact = this->feed_flow_ / (centrifuge_feed_flow); + double n_exact = (*this).feed_flow_ / (centrifuge_feed_flow); // Adds a machine if fractional amount is needed n_machines_ = int(n_exact); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 97adf20..2082978 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -146,7 +146,7 @@ TEST(StageConfig_Test, TestStages) { double expected_product_assay_s = 0.0082492; // Calculated using equations from 2009 Glaser paper - int expected_n_mach_e = 19; + int expected_n_mach_e = ceil(feed_c/feed_m); EXPECT_NEAR(stage.n_machines(), expected_n_mach_e, tol_num); EXPECT_NEAR(stage.product_assay(), expected_product_assay_s, tol_assay); From 2a4c8991da9dff1015a4b02efb37067f5e3b3385 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 19 Jun 2020 18:00:01 -0500 Subject: [PATCH 111/116] Updated expected numbers for TestSWU tests --- src/CentrifugeConfig_tests.cc | 5 +++-- src/StageConfig.cc | 4 ++-- src/StageConfig_tests.cc | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CentrifugeConfig_tests.cc b/src/CentrifugeConfig_tests.cc index 881ff93..a4b4e4a 100644 --- a/src/CentrifugeConfig_tests.cc +++ b/src/CentrifugeConfig_tests.cc @@ -23,6 +23,7 @@ TEST(CentrifugeConfig_Test, TestSWU) { double cut = 0.5; // Centrifuge params used in Python test code + // found at CNERG/enrich_calc:mbmore_unit_tests // (based on Glaser SGS 2009 paper) double v_a = 485; // m/s double height = 0.5; // meters @@ -32,10 +33,10 @@ TEST(CentrifugeConfig_Test, TestSWU) { CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, flow_ratio); - // del U=7.0323281e-08 alpha=1.16321 + // dU=8.638345e-08 alpha=1.130517 double delU = centrifuge.ComputeDeltaU(cut); - double pycode_U = 7.03232816847e-08; + double pycode_U = 8.638345e-08; double tol = 1e-9; EXPECT_NEAR(delU, pycode_U, tol); diff --git a/src/StageConfig.cc b/src/StageConfig.cc index c87dec2..b7d5b44 100644 --- a/src/StageConfig.cc +++ b/src/StageConfig.cc @@ -109,9 +109,9 @@ void StageConfig::AlphaByDU() { double ratio_UF6_U = M_238 / M; // converting feed from UF6 to U - double feed = centrifuge.feed * ratio_UF6_U; + double feed_U = centrifuge.feed * ratio_UF6_U; // "Uranium Enrichment By Gas Centrifuge" D.G. Avery & E. Davies pg. 18 - alpha_ = 1. + std::sqrt((2. * DU_ * (1. - cut_) / (cut_ * feed))); + alpha_ = 1. + std::sqrt((2. * DU_ * (1. - cut_) / (cut_ * feed_U))); } void StageConfig::AlphaByProductAssay() { diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 2082978..2016799 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -9,6 +9,7 @@ namespace mbmore { // Benchmarked using a regression test (expected values calculated manually) +// Calculations can be found at CNERG/enrich_calc:mbmore_unit_tests namespace stageconfig_test { // Fixed for a cascade separating out U235 from U238 in UF6 gas double M = 0.352; // kg/mol UF6 @@ -69,12 +70,12 @@ TEST(StageConfig_Test, TestAssays) { // Calculate ideal SWU params of single machinefeed_assay // (separation potential delU and separation factor alpha) TEST(StageConfig_Test, TestSWU) { - double expected_U = 7.03232816847e-08; + double expected_U = 8.638345e-08; double tol = 1e-9; StageConfig stage(feed_assay, feed_m, cut, delU, -1, 1e-16); - double expected_alpha = 1.16321; + double expected_alpha = 1.130517; double tol_alpha = 1e-2; EXPECT_NEAR(stage.alpha(), expected_alpha, tol_alpha); } From a8af774360d4a9209b7b67ee28a795f2ff222f33 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 23 Jun 2020 12:01:08 -0500 Subject: [PATCH 112/116] Updating and fixing the rest of StageConfig_tests --- src/StageConfig_tests.cc | 44 +++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 2016799..c2d3041 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -37,7 +37,7 @@ const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, flow_ratio); -// del U=7.0323281e-08 alpha=1.16321 +// del U=8.638345e-08 alpha=1.130517 double delU = centrifuge.ComputeDeltaU(cut); const double tol_assay = 1e-5; @@ -90,15 +90,14 @@ TEST(StageConfig_Test, TestIdeal) { stage_ideal.BuildIdealStg(); stage_ideal.precision(1e-16); - // All expected numbers were calculated using the methods used - // and are trusted to be correct (regression test). - double expected_alpha = 1.18181; + double expected_alpha = 1.130517; double tol_alpha = 1e-2; - double expected_cut = 0.4589269; + // These value found by regression test and is + // working as intended as of committing this line. + double expected_cut = 0.4685952; double tol_cut = 1e-3; - - double expected_U = 7.4221362040947e-08; + double expected_U = 8.281007e-08; double tol_DU = 1e-9; EXPECT_NEAR(stage_ideal.alpha(), expected_alpha, tol_alpha); @@ -143,8 +142,7 @@ TEST(StageConfig_Test, TestStages) { stage.ProductAssay(); stage.MachinesNeededPerStage(); - //double expected_product_assay_s = 0.007782156959583; - double expected_product_assay_s = 0.0082492; + double expected_product_assay_s = 0.0080192; // Calculated using equations from 2009 Glaser paper int expected_n_mach_e = ceil(feed_c/feed_m); @@ -155,33 +153,37 @@ TEST(StageConfig_Test, TestStages) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Verify that, for a P1-type centrifuge, results are in agreement -// with those presented by Glaser paper. +// with those presented by Glaser's paper. TEST(StageConfig_Test, AlphaBeta) { // P1-type parameters - double v_a = 320; // m/s + v_a = 320; // m/s + eff = 0.564; + x = 1000.; + flow_ratio = 2.0; + temp = 320; // K + M = 0.352; // kg/mol UF6 + dM = 0.003; // kg/mol U238 - U235 + cut = 0.5; double Z = 1.8; // m double d = 0.10; // m - double eff = 0.564; - double x = 1000.; - double flow_ratio = 2.0; - double temp = 320; // K - double M = 0.352; // kg/mol UF6 - double dM = 0.003; // kg/mol U238 - U235 double feed = 12.6 / 1000. / 1000.; // mg/s -> kg/s - double cut = 0.5; double f_assay = 0.00720; CentrifugeConfig cent(v_a, Z, d, feed, temp, eff, M, dM, x, flow_ratio); double delU = cent.ComputeDeltaU(cut); - double delU_e = 2.5 / (365.25 * 24 * 60 * 60); - EXPECT_NEAR(delU, 1.0, 1e-8); + // Glaser's paper value is delU_e = 2.5 / (365.25 * 24 * 60 * 60) + // The answer below is apprx. 6% different. + // WIP to reconcile the difference. + double delU_e = 8.40508e-8; + EXPECT_NEAR(delU, delU_e, 1e-8); StageConfig stg(f_assay, feed, cut, delU); double ab_e = 1.29; - EXPECT_NEAR(stg.alpha() * stg.beta(), ab_e, 0.0001); + double tol_ab = 0.01; + EXPECT_NEAR(stg.alpha() * stg.beta(), ab_e, tol_ab); } From 7e0b4b1a069d11c6e5bc046862e15315cfc47d59 Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 23 Jun 2020 12:43:05 -0500 Subject: [PATCH 113/116] Updating and fixing CascadeConfig_tests --- src/CascadeConfig_tests.cc | 26 ++++++++++++++------------ src/StageConfig_tests.cc | 4 ++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index c840741..0da3b01 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -36,7 +36,7 @@ const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, flow_ratio); -// del U=7.0323281e-08 alpha=1.16321 +// del U=8.638345e-08 alpha=1.130517 double delU = centrifuge.ComputeDeltaU(cut); const double tol_assay = 1e-5; @@ -47,11 +47,13 @@ const double tol_num = 1e-2; // Ideal cascade design, and then using away from ideal design // TEST(CascadeStage_Test, TestCascade) { + // These expected values are found by regression test + // and are working as intended as of committing this line. CascadeConfig cascade; cascade.centrifuge = centrifuge; cascade.BuildIdealCascade(feed_assay, product_assay, waste_assay, 1e-8); - int expected_n_enrich_stage = 11; - int expected_n_strip_stage = 12; + int expected_n_enrich_stage = 13; + int expected_n_strip_stage = 15; // integer int n_stage_enrich = cascade.n_enrich; int n_stage_waste = cascade.n_strip; @@ -71,10 +73,10 @@ TEST(CascadeStage_Test, TestCascade) { double mod_waste_assay = cascade_non_ideal.stgs_config[-n_stage_waste].product_assay(); - double expected_mod_product_assay = 0.8189; + double expected_mod_product_assay = 0.791461; EXPECT_NEAR(mod_product_assay, expected_mod_product_assay, tol_assay); - double expected_mod_waste_assay = 0.11198; + double expected_mod_waste_assay = 0.097997; EXPECT_NEAR(mod_waste_assay, expected_mod_waste_assay, tol_assay); } @@ -90,8 +92,8 @@ TEST(CascadeStage_Test, TestCascadeDesign) { 0.00030693, 0.00061387, 0.0009208, 0.00122774, 0.00153467, 0.00127889, 0.00102311, 0.00076734, 0.00051156, 0.00025578}; - std::vector expected_machines = {25, 46, 65, 82, 97, 76, - 57, 40, 26, 13}; + std::vector expected_machines = {25, 46, 66, 84, 100, 115, + 94, 74, 57, 41}; CascadeConfig cascade(centrifuge, fa, pa, wa, feed_c, 1000000); @@ -103,18 +105,18 @@ TEST(CascadeStage_Test, TestCascadeDesign) { } // not enough machines - int max_centrifuges = 80; + int max_centrifuges = 40; cascade.ScaleCascade(feed_c, max_centrifuges); - int expected_tot_mach = 80; - double expected_opt_feed = 4.11669203083e-05; + int expected_tot_mach = 40; + double expected_opt_feed = 1.261064e-05; EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); EXPECT_NEAR(expected_opt_feed, cascade.FeedFlow(), tol_qty); // more machines than requested capacity - max_centrifuges = 600; + max_centrifuges = 800; cascade.ScaleCascade(feed_c, max_centrifuges); - expected_tot_mach = 527; + expected_tot_mach = 741; expected_opt_feed = 0.0002814; EXPECT_EQ(expected_tot_mach, cascade.FindTotalMachines()); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index c2d3041..8a4ace5 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -93,8 +93,8 @@ TEST(StageConfig_Test, TestIdeal) { double expected_alpha = 1.130517; double tol_alpha = 1e-2; - // These value found by regression test and is - // working as intended as of committing this line. + // These expected values are found by regression test + // and are working as intended as of committing this line. double expected_cut = 0.4685952; double tol_cut = 1e-3; double expected_U = 8.281007e-08; From afa14a7f7a7c7fef3ab319c6309478160c10890c Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Tue, 23 Jun 2020 13:45:18 -0500 Subject: [PATCH 114/116] Updating and fixing CascadeEnrichTests --- src/CascadeEnrich_tests.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/CascadeEnrich_tests.cc b/src/CascadeEnrich_tests.cc index 64313e9..41cfab5 100644 --- a/src/CascadeEnrich_tests.cc +++ b/src/CascadeEnrich_tests.cc @@ -109,7 +109,7 @@ TEST_F(CascadeEnrichTest, CheckFlowConstraint) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("heu", cascadenrichtest::c_heu()); - sim.AddSink("enr_u").recipe("heu").capacity(10).Finalize(); + sim.AddSink("enr_u").recipe("heu").capacity(4).Finalize(); int id = sim.Run(); @@ -119,7 +119,7 @@ TEST_F(CascadeEnrichTest, CheckFlowConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(10, m->quantity(), 0.1) + EXPECT_NEAR(4, m->quantity(), 0.1) << "traded quantity differ from flow contraints"; } @@ -145,7 +145,7 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { sim.AddRecipe("natu1", cascadenrichtest::c_natu1()); sim.AddRecipe("heu", cascadenrichtest::c_heu()); - sim.AddSink("enr_u").recipe("heu").capacity(20).Finalize(); + sim.AddSink("enr_u").recipe("heu").capacity(100).Finalize(); int id = sim.Run(); @@ -155,7 +155,7 @@ TEST_F(CascadeEnrichTest, CheckCapConstraint) { Material::Ptr m = sim.GetMaterial(qr.GetVal("ResourceId")); EXPECT_EQ(1.0, qr.rows.size()); - EXPECT_NEAR(5.831, m->quantity(), 0.01) + EXPECT_NEAR(24.691, m->quantity(), 0.01) << "traded quantity exceeds capacity constraint"; } @@ -298,7 +298,7 @@ TEST_F(CascadeEnrichTest, TailsQty) { stmt->BindText(1, "tails"); stmt->Step(); - EXPECT_NEAR(7.575, stmt->GetDouble(0), 0.01) + EXPECT_NEAR(7.100, stmt->GetDouble(0), 0.01) << "Not providing the requested quantity"; } From 9eca5e922b5a98d5d8d9f1811182f2f6607b0a4b Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Wed, 24 Jun 2020 11:09:04 -0500 Subject: [PATCH 115/116] Removing efficiency considerations --- src/CascadeConfig_tests.cc | 3 +-- src/CascadeEnrich.h | 8 -------- src/CentrifugeConfig.cc | 9 +++------ src/CentrifugeConfig.h | 3 +-- src/CentrifugeConfig_tests.cc | 3 +-- src/StageConfig_tests.cc | 6 ++---- 6 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/CascadeConfig_tests.cc b/src/CascadeConfig_tests.cc index 0da3b01..ca7a93d 100644 --- a/src/CascadeConfig_tests.cc +++ b/src/CascadeConfig_tests.cc @@ -17,7 +17,6 @@ const double x = 1000; // Pressure ratio (Glaser) // General cascade assumptions const double flow_ratio = 2.0; -const double eff = 1.0; const double cut = 0.5; // Centrifuge parameters based on Glaser SGS 2009 paper @@ -33,7 +32,7 @@ const double product_assay = 0.035; const double waste_assay = 0.001; const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec -CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, M, dM, x, flow_ratio); // del U=8.638345e-08 alpha=1.130517 diff --git a/src/CascadeEnrich.h b/src/CascadeEnrich.h index 234d689..5549dbb 100644 --- a/src/CascadeEnrich.h +++ b/src/CascadeEnrich.h @@ -316,14 +316,6 @@ class CascadeEnrich : public cyclus::Facility { "that drives the r1 / r2 ratio."} double x; -#pragma cyclus var { \ - "default" : 1.0, \ - "tooltip" : "Overall centrifuge efficiency", \ - "uilabel" : "Overall centrifuge efficiency", \ - "doc" : "Centrifuge efficiency parameter that describes"\ - "its effective separative performance."} - double eff; - #pragma cyclus var { \ "default": 0, \ "userlevel": 10, \ diff --git a/src/CentrifugeConfig.cc b/src/CentrifugeConfig.cc index 658dbc4..e6d83f8 100644 --- a/src/CentrifugeConfig.cc +++ b/src/CentrifugeConfig.cc @@ -34,7 +34,6 @@ CentrifugeConfig::CentrifugeConfig() { feed = 15. / 1000. / 1000.; temp = 320; - eff = 1.0; x = 1000; flow_ratio = 2.0; @@ -50,16 +49,14 @@ CentrifugeConfig::CentrifugeConfig() { } CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, - double feed_, double T_, double eff_, - double M_, double dM_, double x_, - double flow_) { + double feed_, double T_, double M_, + double dM_, double x_, double flow_) { v_a = v_a_; height = h_; diameter = d_; feed = feed_; temp = T_; - eff = eff_; x = x_; flow_ratio = flow_; @@ -123,7 +120,7 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { double major_term = 0.5 * cut * (1.0 - cut) * (C_therm * C_therm) * C_scale * pow(((bracket1 * (1 - exp1)) + (bracket2 * (1 - exp2))), 2); // kg/s - double del_U = feed_U * major_term; //* eff; // kg/s + double del_U = feed_U * major_term; // kg/s return del_U; } diff --git a/src/CentrifugeConfig.h b/src/CentrifugeConfig.h index e190b07..e84ba15 100644 --- a/src/CentrifugeConfig.h +++ b/src/CentrifugeConfig.h @@ -12,7 +12,7 @@ class CentrifugeConfig { public: CentrifugeConfig(); CentrifugeConfig(double v_a, double h, double d, double feed, double T, - double eff, double M, double dM, double x, double i_flow); + double M, double dM, double x, double i_flow); double ComputeDeltaU(double cut); // compute the solution of the Raetz equation using all the paramters valus and the provided cut value @@ -26,7 +26,6 @@ class CentrifugeConfig { double diameter; // centrifuge diameter double feed; // feed flow rate double temp; // average gas temperature - double eff; // efficiency private: double D_rho; // kg/m/s diff --git a/src/CentrifugeConfig_tests.cc b/src/CentrifugeConfig_tests.cc index a4b4e4a..ee571e6 100644 --- a/src/CentrifugeConfig_tests.cc +++ b/src/CentrifugeConfig_tests.cc @@ -19,7 +19,6 @@ TEST(CentrifugeConfig_Test, TestSWU) { // General cascade assumptions double flow_ratio = 2.0; - double eff = 1.0; double cut = 0.5; // Centrifuge params used in Python test code @@ -31,7 +30,7 @@ TEST(CentrifugeConfig_Test, TestSWU) { double feed_m = 15 * 60 * 60 / ((1e3) * 60 * 60 * 1000.0); // kg/sec double temp = 320.0; // Kelvin - CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, + CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, M, dM, x, flow_ratio); // dU=8.638345e-08 alpha=1.130517 double delU = centrifuge.ComputeDeltaU(cut); diff --git a/src/StageConfig_tests.cc b/src/StageConfig_tests.cc index 8a4ace5..eeae9e0 100644 --- a/src/StageConfig_tests.cc +++ b/src/StageConfig_tests.cc @@ -18,7 +18,6 @@ double x = 1000; // Pressure ratio (Glaser) // General cascade assumptions double flow_ratio = 2.0; -double eff = 1.0; double cut = 0.5; // Centrifgue parameters based on Glaser SGS 2009 paper @@ -34,7 +33,7 @@ const double prod_assay = 0.035; const double waste_assay = 0.001; const double feed_c = 739 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec const double product_c = 77 / (30.4 * 24 * 60 * 60); // kg/month -> kg/sec -CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, eff, M, dM, x, +CentrifugeConfig centrifuge(v_a, height, diameter, feed_m, temp, M, dM, x, flow_ratio); // del U=8.638345e-08 alpha=1.130517 @@ -157,7 +156,6 @@ TEST(StageConfig_Test, TestStages) { TEST(StageConfig_Test, AlphaBeta) { // P1-type parameters v_a = 320; // m/s - eff = 0.564; x = 1000.; flow_ratio = 2.0; temp = 320; // K @@ -169,7 +167,7 @@ TEST(StageConfig_Test, AlphaBeta) { double feed = 12.6 / 1000. / 1000.; // mg/s -> kg/s double f_assay = 0.00720; - CentrifugeConfig cent(v_a, Z, d, feed, temp, eff, M, dM, x, flow_ratio); + CentrifugeConfig cent(v_a, Z, d, feed, temp, M, dM, x, flow_ratio); double delU = cent.ComputeDeltaU(cut); From a44c1993de53506fe476bcaea4190d4c58d3685e Mon Sep 17 00:00:00 2001 From: Jordan Stomps Date: Fri, 6 Nov 2020 13:08:26 -0600 Subject: [PATCH 116/116] Initial design_cut implementation; two CascadeEnrich tests broken --- src/CentrifugeConfig.cc | 4 +++- src/CentrifugeConfig.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/CentrifugeConfig.cc b/src/CentrifugeConfig.cc index e6d83f8..43fcb00 100644 --- a/src/CentrifugeConfig.cc +++ b/src/CentrifugeConfig.cc @@ -36,6 +36,7 @@ CentrifugeConfig::CentrifugeConfig() { x = 1000; flow_ratio = 2.0; + design_cut = 0.5; // default UF6 0.352 kg/mol M = 0.352; @@ -59,6 +60,7 @@ CentrifugeConfig::CentrifugeConfig(double v_a_, double h_, double d_, x = x_; flow_ratio = flow_; + design_cut = 0.5; M = M_; dM = dM_; @@ -89,7 +91,7 @@ double CentrifugeConfig::ComputeDeltaU(double cut) { // Glaser eqn 12 // Vertical location of feed double Z_p = - height * (1.0 - cut) * (1.0 + flow_ratio) / (1.0 - cut + flow_ratio); + height * (1.0 - design_cut) * (1.0 + flow_ratio) / (1.0 - design_cut + flow_ratio); // Glaser eqn 3 // Converting from molecular mass to atomic mass (assuming U238) diff --git a/src/CentrifugeConfig.h b/src/CentrifugeConfig.h index e84ba15..ea107d9 100644 --- a/src/CentrifugeConfig.h +++ b/src/CentrifugeConfig.h @@ -32,6 +32,8 @@ class CentrifugeConfig { double gas_const; // J/K/mol double M_238; // kg/mol + double design_cut; // used for calculating the rectifier length + // two method to compute some part of the solution to the Raetz equation double CalcCTherm(double v_a, double temp, double dM); double CalcV(double assay);