Chi-Tech
nl_keigen_ags_residual_func.cc
Go to the documentation of this file.
2#include "wgs_context.h"
4
5#include <petscsnes.h>
6
7namespace lbs
8{
9
10// ###################################################################
11/**This function evaluates the flux moments based k-eigenvalue transport
12 * residual of the form
13\f$ r(\phi) = DL^{-1} (\frac{1}{k} F\phi + MS \phi) - \phi \f$.*/
14PetscErrorCode NLKEigenResidualFunction(SNES snes, Vec phi, Vec r, void* ctx)
15{
16 const std::string fname = "lbs::SNESKResidualFunction";
17 auto& function_context = *((KResidualFunctionContext*)ctx);
18
19 NLKEigenAGSContext<Vec, SNES>* nl_context_ptr;
20 SNESGetApplicationContext(snes, &nl_context_ptr);
21
22 auto& lbs_solver = nl_context_ptr->lbs_solver_;
23 const auto& phi_old_local = lbs_solver.PhiOldLocal();
24 auto& q_moments_local = lbs_solver.QMomentsLocal();
25
26 auto active_set_source_function = lbs_solver.GetActiveSetSourceFunction();
27
28 std::vector<int> groupset_ids;
29 for (const auto& groupset : lbs_solver.Groupsets())
30 groupset_ids.push_back(groupset.id_);
31
32 //============================================= Disassemble phi vector
33 lbs_solver.SetPrimarySTLvectorFromMultiGSPETScVecFrom(
34 groupset_ids, phi, lbs::PhiSTLOption::PHI_OLD);
35
36 //============================================= Compute 1/k F phi
37 chi_math::Set(q_moments_local, 0.0);
38 for (auto& groupset : lbs_solver.Groupsets())
39 active_set_source_function(groupset,
40 q_moments_local,
41 phi_old_local,
44
45 const double k_eff = lbs_solver.ComputeFissionProduction(phi_old_local);
46 chi_math::Scale(q_moments_local, 1.0 / k_eff);
47
48 //============================================= Now add MS phi
49 for (auto& groupset : lbs_solver.Groupsets())
50 {
51 auto& wgs_context = lbs_solver.GetWGSContext(groupset.id_);
52 const bool supress_wgs =
53 wgs_context.lhs_src_scope_ & lbs::SUPPRESS_WG_SCATTER;
54 active_set_source_function(
55 groupset,
56 q_moments_local,
57 phi_old_local,
60 }
61
62 //============================================= Sweep all the groupsets
63 // After this phi_new = DLinv(MSD phi + 1/k FD phi)
64 for (auto& groupset : lbs_solver.Groupsets())
65 {
66 auto& wgs_context = lbs_solver.GetWGSContext(groupset.id_);
67 wgs_context.ApplyInverseTransportOperator(lbs::NO_FLAGS_SET);
68 }
69
70 //============================================= Reassemble PETSc vector
71 // We use r as a proxy for delta-phi here since
72 // we are anycase going to subtract phi from it.
73 lbs_solver.SetMultiGSPETScVecFromPrimarySTLvector(
74 groupset_ids, r, lbs::PhiSTLOption::PHI_NEW);
75
76 VecAXPY(r, -1.0, phi);
77
78 for (auto& groupset : lbs_solver.Groupsets())
79 {
80 if ((groupset.apply_wgdsa_ or groupset.apply_tgdsa_) and
81 lbs_solver.Groupsets().size() > 1)
82 throw std::logic_error(fname + ": Preconditioning currently only supports"
83 "single groupset simulations.");
84
85 auto& wgs_context = lbs_solver.GetWGSContext(groupset.id_);
86 lbs::WGDSA_TGDSA_PreConditionerMult2(wgs_context, r, r);
87 }
88
89 //============================================= Assign k to the context
90 // so monitors can work
91 function_context.k_eff = k_eff;
92
93 return 0;
94}
95
96} // namespace lbs
std::vector< double > & PhiOldLocal()
void Scale(VecDbl &x, const double &val)
void Set(VecDbl &x, const double &val)
PetscErrorCode NLKEigenResidualFunction(SNES snes, Vec phi, Vec r, void *ctx)
int WGDSA_TGDSA_PreConditionerMult2(lbs::WGSContext< Mat, Vec, KSP > &gs_context_ptr, Vec phi_input, Vec pc_output)
@ 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
@ 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
struct _p_Vec * Vec