24 const std::string fname =
"lbs::PowerIterationKEigen";
28 auto context = wgs_solver->GetContext();
30 std::dynamic_pointer_cast<lbs::WGSContext<Mat,Vec,KSP>>(context);
32 if (not wgs_context)
throw std::logic_error(fname +
": Cast failed.");
40 throw std::invalid_argument(fname +
": The \"power1\" method can only "
41 "be used with a single groupset.");
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());
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());
61 front_gs.apply_wgdsa_ =
false;
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();
68 static_cast<int>(basic_options(
"PISA_PI_MAX_ITS").IntegerValue());
70 auto& diff_solver = *front_gs.wgdsa_solver_;
73 double k_eff_prev = 1.0;
74 double k_eff_change = 1.0;
77 auto SetLBSFissionSource = [&active_set_source_function,&front_gs,
79 (
const VecDbl& input,
const bool additive)
82 active_set_source_function(front_gs, q_moments_local,
89 auto SetLBSScatterSource = [&active_set_source_function,&front_gs,
91 (
const VecDbl& input,
const bool additive,
const bool suppress_wgs=
false)
94 active_set_source_function(front_gs, q_moments_local, input,
99 auto phi_temp = phi_old_local;
103 auto SetLBSScatterSourcePhi0 = [&lbs_solver,&front_gs,
104 &phi_temp, &SetLBSScatterSource]
105 (
const VecDbl& input,
const bool additive,
const bool suppress_wgs=
false)
108 SetLBSScatterSource(phi_temp, additive, suppress_wgs);
116 bool converged =
false;
117 while (nit < max_iterations)
121 SetLBSFissionSource(phi_old_local,
false);
122 Scale(q_moments_local, 1.0/k_eff);
124 auto Sf_all_moments = q_moments_local;
139 q_moments_local = Sf_all_moments;
140 SetLBSScatterSource(phi_new_local,
true);
142 frons_wgs_context->ApplyInverseTransportOperator(
NO_FLAGS_SET);
144 auto phi0_lph_ip1 = lbs_solver.
WGSCopyOnlyPhi0(front_gs, phi_new_local);
147 VecDbl epsilon_k(phi0_l.size(), 0.0);
148 auto epsilon_kp1 = epsilon_k;
150 double lambda_k = k_eff;
151 double lambda_kp1 = lambda_k;
153 for (
size_t k=0; k<pisa_pi_max_its; ++k)
160 SetLBSFissionSource(phi_temp,
false);
161 Scale(q_moments_local, 1.0 / lambda_k);
166 SetLBSScatterSourcePhi0(phi0_lph_ip1 - phi0_lph_i,
false);
172 for (
int i=0; i<1; ++i)
174 SetLBSScatterSourcePhi0(epsilon_k,
false,
180 diff_solver.Assemble_b(Ss + Sfaux + Ss_res - Sf);
181 diff_solver.Solve(epsilon_kp1,
true);
183 epsilon_k = epsilon_kp1;
190 lambda_kp1 = production_kp1 / (production_k / lambda_k);
192 const double lambda_change = std::fabs(1.0 - lambda_kp1 / lambda_k);
193 if (pisa_verbose_level >= 1)
195 <<
"PISA iteration " << k
196 <<
" lambda " << lambda_kp1 <<
" lambda change " << lambda_change;
198 if (lambda_change < pisa_pi_k_tol)
break;
200 lambda_k = lambda_kp1;
201 epsilon_k = epsilon_kp1;
214 double reactivity = (k_eff - 1.0) / k_eff;
217 k_eff_change = fabs(k_eff - k_eff_prev) / k_eff;
221 if (k_eff_change < std::max(tolerance, 1.0e-12))
227 std::stringstream 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";
239 if (converged)
break;
245 <<
" Final k-eigenvalue : "
246 << std::setprecision(7) << k_eff;
248 <<
" Final change : "
249 << std::setprecision(6) << k_eff_change
250 <<
" (num_TrOps:" << frons_wgs_context->counter_applications_of_inv_op_ <<
")"
static chi::Timer program_timer
LogStream Log(LOG_LVL level=LOG_0)
std::string GetTimeString() const
BasicOptions & GetBasicOptions()
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)
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
@ APPLY_WGS_FISSION_SOURCES
@ APPLY_WGS_SCATTER_SOURCES
@ APPLY_AGS_SCATTER_SOURCES
void PowerIterationKEigen1(LBSSolver &lbs_solver, double tolerance, int max_iterations, double &k_eff)
std::vector< double > VecDbl
bool verbose_ags_iterations
bool verbose_outer_iterations