Chi-Tech
poweriteration_keigen2.cc
Go to the documentation of this file.
2
5
7
9
10#include "chi_runtime.h"
11#include "chi_log.h"
12#include "utils/chi_timer.h"
13
14#include <iomanip>
15
16namespace lbs
17{
18
20 double tolerance,
21 int max_iterations,
22 double& k_eff)
23{
24 const std::string fname = "lbs::PowerIterationKEigen";
25
26 for (auto& wgs_solver : lbs_solver.GetWGSSolvers())
27 {
28 auto context = wgs_solver->GetContext();
29 auto wgs_context =
30 std::dynamic_pointer_cast<lbs::WGSContext<Mat,Vec,KSP>>(context);
31
32 if (not wgs_context) throw std::logic_error(fname + ": Cast failed.");
33
34 wgs_context->lhs_src_scope_ = APPLY_WGS_SCATTER_SOURCES;
35 wgs_context->rhs_src_scope_ = APPLY_AGS_SCATTER_SOURCES |
37 }
38
39 if (lbs_solver.Groupsets().size() > 1)
40 throw std::invalid_argument(fname + ": The \"power1\" method can only "
41 "be used with a single groupset.");
42
43 auto& basic_options = lbs_solver.GetBasicOptions();
44 auto& q_moments_local = lbs_solver.QMomentsLocal();
45 auto& phi_old_local = lbs_solver.PhiOldLocal();
46 auto& phi_new_local = lbs_solver.PhiNewLocal();
47 auto primary_ags_solver = lbs_solver.GetPrimaryAGSSolver();
48 auto& groupsets = lbs_solver.Groupsets();
49 auto active_set_source_function = lbs_solver.GetActiveSetSourceFunction();
50
51 auto& front_gs = groupsets.front();
52 auto& front_wgs_solver = lbs_solver.GetWGSSolvers()[front_gs.id_];
53 auto frons_wgs_context = std::dynamic_pointer_cast<lbs::WGSContext<Mat,Vec,KSP>>(
54 front_wgs_solver->GetContext());
55
56 front_gs.apply_wgdsa_ = true;
57 front_gs.wgdsa_tol_ = basic_options("PISA_MIP_L_ABS_TOL").FloatValue();
58 front_gs.wgdsa_max_iters_ =
59 static_cast<int>(basic_options("PISA_MIP_L_MAX_ITS").IntegerValue());
60 lbs_solver.InitWGDSA(front_gs, /*vaccum_bcs_are_dirichlet=*/false);
61 front_gs.apply_wgdsa_ = false;
62
63 int pisa_verbose_level =
64 static_cast<int>(basic_options("PISA_VERBOSE_LEVEL").IntegerValue());
65
66 auto& diff_solver = *front_gs.wgdsa_solver_;
67
68 auto nl_diff_context = std::make_shared<acceleration::NLKEigenDiffContext>(
69 diff_solver, lbs_solver, pisa_verbose_level);
70
71 acceleration::NLKEigenDiffSolver nl_keigen_diff_solver(nl_diff_context);
72
73 auto& tolerances = nl_keigen_diff_solver.ToleranceOptions();
74
75 tolerances.nl_abs_tol_ = basic_options("PISA_NL_ABS_TOL").FloatValue();
76 tolerances.nl_rel_tol_ = basic_options("PISA_NL_REL_TOL").FloatValue();
77 tolerances.nl_sol_tol_ = basic_options("PISA_NL_SOL_TOL").FloatValue();
78 tolerances.nl_max_its_ =
79 static_cast<int>(basic_options("PISA_NL_MAX_ITS").IntegerValue());
80
81 tolerances.l_abs_tol_ = basic_options("PISA_L_ABS_TOL").FloatValue();
82 tolerances.l_rel_tol_ = basic_options("PISA_L_REL_TOL").FloatValue();
83 tolerances.l_max_its_ =
84 static_cast<int>(basic_options("PISA_L_MAX_ITS").IntegerValue());
85 tolerances.l_gmres_restart_intvl_ =
86 static_cast<int>(basic_options("PISA_L_MAX_ITS").IntegerValue());
87
88 double F_prev = 1.0;
89 k_eff = 1.0;
90 double k_eff_prev = 1.0;
91 double k_eff_change = 1.0;
92
93 /**Lambda for the creation of fission sources.*/
94 auto SetLBSFissionSource = [&active_set_source_function,&front_gs]
95 (const VecDbl& input, VecDbl& output)
96 {
97 chi_math::Set(output, 0.0);
98 active_set_source_function(front_gs, output,
99 input,
102 };
103
104 //================================================== Start power iterations
105 primary_ags_solver->SetVerbosity(lbs_solver.Options().verbose_ags_iterations);
106 int nit = 0;
107 bool converged = false;
108 while (nit < max_iterations)
109 {
110 nl_diff_context->phi_l_ = lbs_solver.WGSCopyOnlyPhi0(front_gs, phi_old_local);
111
112 SetLBSFissionSource(/*input*/phi_old_local, /*output*/q_moments_local);
113 chi_math::Scale(q_moments_local, 1.0/k_eff);
114
115 auto Sffull = q_moments_local;
116 nl_diff_context->Sf_ = lbs_solver.WGSCopyOnlyPhi0(front_gs, q_moments_local);
117
118 //====================================== This solves the inners for transport
119 // produces phi at l+1/2
120 primary_ags_solver->Setup();
121 primary_ags_solver->Solve();
122
123 //lph_i = l + 1/2, i
124 nl_diff_context->phi_lph_i_ = lbs_solver.WGSCopyOnlyPhi0(front_gs, phi_new_local);
125
126 //lph_ip1 = l + 1/2, i+1
127 q_moments_local = Sffull;
128 active_set_source_function(front_gs, q_moments_local,
129 phi_new_local,
132
133 frons_wgs_context->ApplyInverseTransportOperator(NO_FLAGS_SET);
134 lbs_solver.GSScopedCopyPrimarySTLvectors(front_gs, phi_new_local, phi_old_local);
135
136 //====================================== Non-Linear Acceleration solve
137 nl_diff_context->phi_lph_ip1_ = lbs_solver.WGSCopyOnlyPhi0(front_gs, phi_new_local);
138
139 nl_diff_context->kresid_func_context_.k_eff = k_eff; //sets mu_k
140 nl_diff_context->k_l = k_eff;
141
142 if (nit > 4)
143 {
144 nl_keigen_diff_solver.Setup();
145 nl_keigen_diff_solver.Solve();
146 k_eff = nl_diff_context->kresid_func_context_.k_eff;
147 }
148 else
149 {
150 double F_new = lbs_solver.ComputeFissionProduction(phi_new_local);
151 k_eff = F_new / F_prev * k_eff;
152 }
153
154 //======================================== Compute reactivity
155 double reactivity = (k_eff - 1.0) / k_eff;
156
157 //======================================== Check convergence, bookkeeping
158 k_eff_change = fabs(k_eff - k_eff_prev) / k_eff;
159 k_eff_prev = k_eff;
160 nit += 1;
161
162 if (k_eff_change < std::max(tolerance, 1.0e-12))
163 converged = true;
164
165 //======================================== Print iteration summary
166 if (lbs_solver.Options().verbose_outer_iterations)
167 {
168 std::stringstream k_iter_info;
169 k_iter_info
171 << " Iteration " << std::setw(5) << nit
172 << " k_eff " << std::setw(11) << std::setprecision(7) << k_eff
173 << " k_eff change " << std::setw(12) << k_eff_change
174 << " reactivity " << std::setw(10) << reactivity * 1e5;
175 if (converged) k_iter_info << " CONVERGED\n";
176
177 Chi::log.Log() << k_iter_info.str();
178 }
179
180 if (converged) break;
181 }//for k iterations
182
183 //================================================== Print summary
184 Chi::log.Log() << "\n";
185 Chi::log.Log()
186 << " Final k-eigenvalue : "
187 << std::setprecision(7) << k_eff;
188 Chi::log.Log()
189 << " Final change : "
190 << std::setprecision(6) << k_eff_change
191 << " (num_TrOps:" << frons_wgs_context->counter_applications_of_inv_op_ << ")"
192 << "\n";
193 Chi::log.Log() << "\n";
194}
195
196}//namespace lbs
static chi::Timer program_timer
Definition: chi_runtime.h:79
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
std::string GetTimeString() const
Definition: chi_timer.cc:38
NonLinearSolverOptions & ToleranceOptions()
BasicOptions & GetBasicOptions()
Definition: chi_solver.cc:118
AGSLinSolverPtr GetPrimaryAGSSolver()
std::vector< double > & PhiNewLocal()
std::vector< double > & QMomentsLocal()
std::vector< LBSGroupset > & Groupsets()
double ComputeFissionProduction(const std::vector< double > &phi)
std::vector< LinSolvePtr > & GetWGSSolvers()
SetSourceFunction GetActiveSetSourceFunction() const
std::vector< double > WGSCopyOnlyPhi0(const LBSGroupset &groupset, const std::vector< double > &phi_in)
void InitWGDSA(LBSGroupset &groupset, bool vaccum_bcs_are_dirichlet=true)
lbs::Options & Options()
std::vector< double > & PhiOldLocal()
virtual void GSScopedCopyPrimarySTLvectors(LBSGroupset &groupset, const std::vector< double > &x_src, std::vector< double > &y)
void Scale(VecDbl &x, const double &val)
void Set(VecDbl &x, const double &val)
@ APPLY_AGS_FISSION_SOURCES
Definition: lbs_structs.h:94
@ NO_FLAGS_SET
Definition: lbs_structs.h:89
@ APPLY_WGS_FISSION_SOURCES
Definition: lbs_structs.h:93
@ APPLY_FIXED_SOURCES
Definition: lbs_structs.h:90
@ APPLY_WGS_SCATTER_SOURCES
Definition: lbs_structs.h:91
@ APPLY_AGS_SCATTER_SOURCES
Definition: lbs_structs.h:92
void PowerIterationKEigen2(LBSSolver &lbs_solver, double tolerance, int max_iterations, double &k_eff)
std::vector< double > VecDbl
Definition: lbs_structs.h:18
bool verbose_ags_iterations
Definition: lbs_structs.h:144
bool verbose_outer_iterations
Definition: lbs_structs.h:145