Chi-Tech
poweriteration_keigen1.cc
Go to the documentation of this file.
2
5
7
8
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 bool pisa_verbose_level =
64 static_cast<int>(basic_options("PISA_VERBOSE_LEVEL").IntegerValue());
65 double pisa_pi_k_tol =
66 basic_options("PISA_PI_K_TOL").FloatValue();
67 int pisa_pi_max_its =
68 static_cast<int>(basic_options("PISA_PI_MAX_ITS").IntegerValue());
69
70 auto& diff_solver = *front_gs.wgdsa_solver_;
71
72 k_eff = 1.0;
73 double k_eff_prev = 1.0;
74 double k_eff_change = 1.0;
75
76 /**Lambda for the creation of fission sources.*/
77 auto SetLBSFissionSource = [&active_set_source_function,&front_gs,
78 &q_moments_local]
79 (const VecDbl& input, const bool additive)
80 {
81 if (not additive) chi_math::Set(q_moments_local, 0.0);
82 active_set_source_function(front_gs, q_moments_local,
83 input,
86 };
87
88 /**Lambda for the creation of scattering sources*/
89 auto SetLBSScatterSource = [&active_set_source_function,&front_gs,
90 &q_moments_local]
91 (const VecDbl& input, const bool additive,const bool suppress_wgs=false)
92 {
93 if (not additive) chi_math::Set(q_moments_local, 0.0);
94 active_set_source_function(front_gs, q_moments_local, input,
96 (suppress_wgs ? SUPPRESS_WG_SCATTER : NO_FLAGS_SET));
97 };
98
99 auto phi_temp = phi_old_local;
100
101 /**Lambda for the creation of scattering sources but the
102 * input vector is only the zeroth moment*/
103 auto SetLBSScatterSourcePhi0 = [&lbs_solver,&front_gs,
104 &phi_temp, &SetLBSScatterSource]
105 (const VecDbl& input, const bool additive,const bool suppress_wgs=false)
106 {
107 lbs_solver.GSProjectBackPhi0(front_gs, input, phi_temp);
108 SetLBSScatterSource(/*in*/phi_temp, additive, suppress_wgs);
109 };
110
111 using namespace chi_math;
112
113 //================================================== Start power iterations
114 primary_ags_solver->SetVerbosity(lbs_solver.Options().verbose_ags_iterations);
115 int nit = 0;
116 bool converged = false;
117 while (nit < max_iterations)
118 {
119 auto phi0_l = lbs_solver.WGSCopyOnlyPhi0(front_gs, phi_old_local);
120
121 SetLBSFissionSource(phi_old_local, /*additive=*/false);
122 Scale(q_moments_local, 1.0/k_eff);
123
124 auto Sf_all_moments = q_moments_local;
125 auto Sf = lbs_solver.WGSCopyOnlyPhi0(front_gs, q_moments_local);
126
127 //====================================== This solves the inners for transport
128 // produces phi at l+1/2
129 for (auto& wgs_solver : lbs_solver.GetWGSSolvers())
130 {
131 wgs_solver->Setup();
132 wgs_solver->Solve();
133 }
134
135 //lph_i = l + 1/2,i
136 auto phi0_lph_i = lbs_solver.WGSCopyOnlyPhi0(front_gs, phi_new_local);
137
138 // Now we produce lph_ip1 = l + 1/2, i+1
139 q_moments_local = Sf_all_moments; //Restore 1/k F phi_l
140 SetLBSScatterSource(phi_new_local, /*additive=*/true);
141
142 frons_wgs_context->ApplyInverseTransportOperator(NO_FLAGS_SET); //Sweep
143
144 auto phi0_lph_ip1 = lbs_solver.WGSCopyOnlyPhi0(front_gs, phi_new_local);
145
146 //====================================== Power Iteration Acceleration solve
147 VecDbl epsilon_k(phi0_l.size(), 0.0);
148 auto epsilon_kp1 = epsilon_k;
149
150 double lambda_k = k_eff;
151 double lambda_kp1 = lambda_k;
152
153 for (size_t k=0; k<pisa_pi_max_its; ++k)
154 {
155 lbs_solver.GSProjectBackPhi0(front_gs, /*in*/epsilon_k + phi0_lph_ip1,
156 /*out*/phi_temp);
157
158 double production_k = lbs_solver.ComputeFissionProduction(phi_temp);
159
160 SetLBSFissionSource(phi_temp, /*additive=*/false);
161 Scale(q_moments_local, 1.0 / lambda_k);
162
163 auto Sfaux = lbs_solver.WGSCopyOnlyPhi0(front_gs, q_moments_local);
164
165
166 SetLBSScatterSourcePhi0(phi0_lph_ip1 - phi0_lph_i, /*additive=*/false);
167
168 auto Ss_res = lbs_solver.WGSCopyOnlyPhi0(front_gs, q_moments_local);
169
170 // Inner iterations seems extremely wasteful therefore I
171 // am leaving this at 1 iteration here for further investigation.
172 for (int i=0; i<1; ++i)
173 {
174 SetLBSScatterSourcePhi0(epsilon_k, /*additive=*/false,
175 /*suppress_wgs=*/true);
176
177 auto Ss = lbs_solver.WGSCopyOnlyPhi0(front_gs, q_moments_local);
178
179 //Solve the diffusion system
180 diff_solver.Assemble_b(Ss + Sfaux + Ss_res - Sf);
181 diff_solver.Solve(epsilon_kp1, /*use_initial_guess=*/true);
182
183 epsilon_k = epsilon_kp1;
184 }
185
186 lbs_solver.GSProjectBackPhi0(front_gs, /*in*/epsilon_kp1 + phi0_lph_ip1,
187 /*out*/phi_old_local);
188 double production_kp1 = lbs_solver.ComputeFissionProduction(phi_old_local);
189
190 lambda_kp1 = production_kp1 / (production_k / lambda_k);
191
192 const double lambda_change = std::fabs(1.0 - lambda_kp1 / lambda_k);
193 if (pisa_verbose_level >= 1)
194 Chi::log.Log()
195 << "PISA iteration " << k
196 << " lambda " << lambda_kp1 << " lambda change " << lambda_change;
197
198 if (lambda_change < pisa_pi_k_tol) break;
199
200 lambda_k = lambda_kp1;
201 epsilon_k = epsilon_kp1;
202 }//acceleration
203
204 lbs_solver.GSProjectBackPhi0(front_gs, /*in*/epsilon_kp1 + phi0_lph_ip1,
205 /*out*/phi_new_local);
206 lbs_solver.GSScopedCopyPrimarySTLvectors(front_gs, /*in*/phi_new_local,
207 /*out*/phi_old_local);
208
209 const double production = lbs_solver.ComputeFissionProduction(phi_old_local);
210 lbs_solver.ScalePhiVector(PhiSTLOption::PHI_OLD, lambda_kp1 / production);
211
212 //======================================== Recompute k-eigenvalue
213 k_eff = lambda_kp1;
214 double reactivity = (k_eff - 1.0) / k_eff;
215
216 //======================================== Check convergence, bookkeeping
217 k_eff_change = fabs(k_eff - k_eff_prev) / k_eff;
218 k_eff_prev = k_eff;
219 nit += 1;
220
221 if (k_eff_change < std::max(tolerance, 1.0e-12))
222 converged = true;
223
224 //======================================== Print iteration summary
225 if (lbs_solver.Options().verbose_outer_iterations)
226 {
227 std::stringstream k_iter_info;
228 k_iter_info
230 << " Iteration " << std::setw(5) << nit
231 << " k_eff " << std::setw(11) << std::setprecision(7) << k_eff
232 << " k_eff change " << std::setw(12) << k_eff_change
233 << " reactivity " << std::setw(10) << reactivity * 1e5;
234 if (converged) k_iter_info << " CONVERGED\n";
235
236 Chi::log.Log() << k_iter_info.str();
237 }
238
239 if (converged) break;
240 }//for k iterations
241
242 //================================================== Print summary
243 Chi::log.Log() << "\n";
244 Chi::log.Log()
245 << " Final k-eigenvalue : "
246 << std::setprecision(7) << k_eff;
247 Chi::log.Log()
248 << " Final change : "
249 << std::setprecision(6) << k_eff_change
250 << " (num_TrOps:" << frons_wgs_context->counter_applications_of_inv_op_ << ")"
251 << "\n";
252 Chi::log.Log() << "\n";
253}
254
255}//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
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)
virtual void ScalePhiVector(PhiSTLOption which_phi, double value)
void GSProjectBackPhi0(const LBSGroupset &groupset, const std::vector< double > &input, std::vector< double > &output)
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
@ SUPPRESS_WG_SCATTER
Definition: lbs_structs.h:95
@ APPLY_WGS_SCATTER_SOURCES
Definition: lbs_structs.h:91
@ APPLY_AGS_SCATTER_SOURCES
Definition: lbs_structs.h:92
void PowerIterationKEigen1(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