Chi-Tech
point_reactor_kinetics.cc
Go to the documentation of this file.
2
5
6#include "ChiObjectFactory.h"
7
8#include "chi_runtime.h"
9#include "chi_log.h"
10
11#include <numeric>
12
13namespace prk
14{
15
17
18/**Sets input parameters.*/
20{
22
23 params.SetDocGroup("prk");
24
25 params.ChangeExistingParamToOptional("name", "prk_TransientSolver");
26
27 std::vector<double> default_lambdas = {
28 0.0124, 0.0304, 0.111, 0.301, 1.14, 3.01};
29 std::vector<double> default_betas = {
30 0.00021, 0.00142, 0.00127, 0.00257, 0.00075, 0.00027};
31
33 "precursor_lambdas", default_lambdas, "An array of decay constants");
35 "precursor_betas",
36 default_betas,
37 "An array of fractional delayed neutron fractions");
38
40 "gen_time", 1.0e-5, "Neutron generation time [s]");
41 params.AddOptionalParameter("initial_rho", 0.0, "Initial reactivity [$]");
43 "initial_source", 1.0, "Initial source strength [/s]");
44
46 "initial_population", 1.0, "Initial neutron population");
47
49 "time_integration", "implicit_euler", "Time integration scheme to use");
50
51 using namespace chi_data_types;
52 auto time_intgl_list = AllowableRangeList::New(
53 {"explicit_euler", "implicit_euler", "crank_nicolson"});
54
55 params.ConstrainParameterRange("time_integration",
56 std::move(time_intgl_list));
57
58 params.ConstrainParameterRange("gen_time",
59 AllowableRangeLowLimit::New(1.0e-12));
60 params.ConstrainParameterRange("initial_source",
61 AllowableRangeLowLimit::New(0.0));
62 params.ConstrainParameterRange("initial_population",
63 AllowableRangeLowLimit::New(0.0));
64 return params;
65}
66
67/**Constructor.*/
69 : chi_physics::Solver(params.GetParamValue<std::string>("name")),
70 lambdas_(params.GetParamVectorValue<double>("precursor_lambdas")),
71 betas_(params.GetParamVectorValue<double>("precursor_betas")),
72 gen_time_(params.GetParamValue<double>("gen_time")),
73 rho_(params.GetParamValue<double>("initial_rho")),
74 source_strength_(params.GetParamValue<double>("initial_source")),
75 time_integration_(params.GetParamValue<std::string>("time_integration")),
76 num_precursors_(lambdas_.size())
77{
78 Chi::log.Log() << "Created solver " << TextName();
79 {
80 std::stringstream outstr;
81 outstr << "lambdas = ";
82 for (double val : lambdas_)
83 outstr << val << " ";
84 Chi::log.Log() << outstr.str();
85 }
86 {
87 std::stringstream outstr;
88 outstr << "betas = ";
89 for (double val : betas_)
90 outstr << val << " ";
91 Chi::log.Log() << outstr.str();
92 }
93}
94
95/**Initialize function.*/
97{
98 // Check size
99 if (lambdas_.size() != betas_.size())
100 throw std::logic_error(TextName() +
101 ": Number of precursors cannot be "
102 "deduced from precursor data because "
103 "the data lists are of different size.");
104
105 beta_ = std::accumulate(betas_.begin(), betas_.end(), /*init_val=*/0.0);
106
107 // ============================= Initializing linalg items
108 const auto& J = num_precursors_;
109 A_ = chi_math::DynamicMatrix<double>(J + 1, J + 1, 0.0);
110 I_ = A_;
111 I_.SetDiagonal(1.0);
112
114
115 // ============================= Assembling system
116 A_[0][0] = beta_ * (rho_ - 1.0) / gen_time_;
117 for (size_t j = 1; j <= J; ++j)
118 {
119 A_[0][j] = lambdas_[j - 1];
120 A_[j][j] = -lambdas_[j - 1];
121 A_[j][0] = betas_[j - 1] / gen_time_;
122 }
123
124 q_.resize(J + 1, 0.0);
125 q_[0] = source_strength_;
126
127 // ============================= Initializing x
128 // If there is a source and the reactivity is < 0 then
129 // there exists a unique solution.
130 if (source_strength_ > 0.0 and rho_ < 0.0)
131 {
132 const auto b_theta = -1.0 * q_;
133
134 x_t_ = A_.Inverse() * b_theta;
135 }
136 // Otherwise we initialize the system as a critical system with
137 // no source.
138 else
139 {
140 auto A_temp = A_;
141 auto b_temp = x_t_;
142 b_temp.Set(0.0);
143 b_temp[0] = 1.0;
144 for (auto& val : A_temp[0])
145 val = 0.0;
146 A_temp[0][0] = 1.0;
147
148 x_t_ = A_temp.Inverse() * b_temp;
149 }
150
151 Chi::log.Log() << "Final: " << x_t_.PrintStr();
152}
153
154/**Execution function.*/
156{
158
159 while (timestepper_->IsActive())
160 {
161 physics_ev_pub.SolverStep(*this);
162 physics_ev_pub.SolverAdvance(*this);
163 }
164}
165
166/**Step function*/
168{
169 Chi::log.Log() << "Solver \"" + TextName() + "\" " +
170 timestepper_->StringTimeInfo();
171
172 const double dt = timestepper_->TimeStepSize();
173
174 A_[0][0] = beta_ * (rho_ - 1.0) / gen_time_;
175
176 if (time_integration_ == "implicit_euler" or
177 time_integration_ == "crank_nicolson")
178 {
179 double theta = 1.0;
180
181 if (time_integration_ == "implicit_euler") theta = 1.0;
182 else if (time_integration_ == "crank_nicolson")
183 theta = 0.5;
184
185 const double inv_tau = theta * dt;
186
187 auto A_theta = I_ - inv_tau * A_;
188 auto b_theta = x_t_ + inv_tau * q_;
189
190 auto x_theta = A_theta.Inverse() * b_theta;
191
192 x_tp1_ = x_t_ + (1.0 / theta) * (x_theta - x_t_);
193 }
194 else if (time_integration_ == "explicit_euler")
195 {
196 x_tp1_ = x_t_ + dt * A_ * x_t_ + dt * q_;
197 }
198 else
199 ChiLogicalError("Unsupported time integration scheme.");
200
201 period_tph_ = dt / log(x_tp1_[0] / x_t_[0]);
202
203 if (period_tph_ > 0.0 and period_tph_ > 1.0e6) period_tph_ = 1.0e6;
204 if (period_tph_ < 0.0 and period_tph_ < -1.0e6) period_tph_ = -1.0e6;
205}
206
207/**Advance time values function.*/
209{
210 x_t_ = x_tp1_;
211 timestepper_->Advance();
212}
213
216{
217 const auto param_name = params.GetParamValue<std::string>("name");
218
219 if (param_name == "neutron_population")
220 return chi::ParameterBlock("", x_t_[0]);
221 else if (param_name == "population_next")
223 else if (param_name == "period")
225 else if (param_name == "rho")
226 return chi::ParameterBlock("", rho_);
227 else if (param_name == "solution")
229 else if (param_name == "time_integration")
231 else if (param_name == "time_next")
232 return chi::ParameterBlock("", TimeNew());
233 else if (param_name == "test_arb_info")
234 {
236
237 block.AddParameter("name", TextName());
238 block.AddParameter("time_integration", time_integration_);
239 block.AddParameter("rho", rho_);
240 block.AddParameter("max_timesteps", timestepper_->MaxTimeSteps());
241
242 return block;
243 }
244 else
245 ChiInvalidArgument("Unsupported info name \"" + param_name + "\".");
246}
247
248// ##################################################################
249/**Returns the population at the previous time step.*/
250double TransientSolver::PopulationPrev() const { return x_t_[0]; }
251/**Returns the population at the next time step.*/
252double TransientSolver::PopulationNew() const { return x_tp1_[0]; }
253
254/**Returns the period computed for the last time step.*/
255double TransientSolver::Period() const { return period_tph_; }
256
257/**Returns the time computed for the last time step.*/
258double TransientSolver::TimePrev() const { return timestepper_->Time(); }
259
260/**Returns the time computed for the next time step.*/
262{
263 return timestepper_->Time() + timestepper_->TimeStepSize();
264}
265
266/**Returns the solution at the previous time step.*/
267std::vector<double> TransientSolver::SolutionPrev() const
268{
269 return x_t_.elements_;
270}
271/**Returns the solution at the next time step.*/
272std::vector<double> TransientSolver::SolutionNew() const
273{
274 return x_tp1_.elements_;
275}
276
277// ##################################################################
278/**Sets the value of rho.*/
279void TransientSolver::SetRho(double value) { rho_ = value; }
280
281/**\addtogroup prk
282 *
283 * \section Properties Properties that can be set
284 * The following properties can be set via the lua call
285 * `chi_lua::chiSolverSetProperties`
286 * \copydoc prk::TransientSolver::SetProperties
287 * */
288
289 /** PRK Transient solver settable properties:
290 * - `rho`, The current reactivity
291
292Parents:
293\copydoc chi_physics::Solver::SetProperties*/
295{
297
298 for (const auto& param : params)
299 {
300 const std::string& param_name = param.Name();
301 if (param_name == "rho") SetRho(param.GetValue<double>());
302 }
303}
304
305} // namespace prk
#define ChiLogicalError(message)
#define ChiInvalidArgument(message)
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
void SetDocGroup(const std::string &doc_group)
void ConstrainParameterRange(const std::string &param_name, AllowableRangePtr allowable_range)
void AddOptionalParameter(const std::string &name, T value, const std::string &doc_string)
void AddOptionalParameterArray(const std::string &name, const std::vector< T > &array, const std::string &doc_string)
void ChangeExistingParamToOptional(const std::string &name, T value, const std::string &doc_string="")
void AddParameter(ParameterBlock block)
T GetParamValue(const std::string &param_name) const
DynamicMatrix Inverse() const
void SetDiagonal(DynamicVector< NumberFormat > &V)
void resize(size_t dim)
std::vector< NumberFormat > elements_
void Set(NumberFormat value)
std::string PrintStr() const
static PhysicsEventPublisher & GetInstance()
std::string TextName() const
Definition: chi_solver.cc:116
static chi::InputParameters GetInputParameters()
Definition: chi_solver.cc:16
std::shared_ptr< TimeStepper > timestepper_
Definition: chi_solver.h:59
virtual void SetProperties(const chi::ParameterBlock &params)
Definition: chi_solver.cc:195
TransientSolver(const chi::InputParameters &params)
void SetProperties(const chi::ParameterBlock &params) override
chi_math::DynamicMatrix< double > A_
std::vector< double > lambdas_
std::vector< double > betas_
std::vector< double > SolutionNew() const
chi::ParameterBlock GetInfo(const chi::ParameterBlock &params) const override
chi_math::DynamicVector< double > q_
chi_math::DynamicVector< double > x_tp1_
chi_math::DynamicVector< double > x_t_
chi_math::DynamicMatrix< double > I_
static chi::InputParameters GetInputParameters()
std::vector< double > SolutionPrev() const
RegisterChiObject(prk, TransientSolver)