Chi-Tech
lbts_sweepchunk_pwl.cc
Go to the documentation of this file.
2
3#include "chi_runtime.h"
5
6#include "chi_log.h"
7
8//###################################################################
9/**Constructor.*/
12 std::shared_ptr<chi_mesh::MeshContinuum> grid_ptr,
13 chi_math::SpatialDiscretization& discretization,
14 const std::vector<UnitCellMatrices>& unit_cell_matrices,
15 std::vector<lbs::CellLBSView>& cell_transport_views,
16 std::vector<double>& destination_phi,
17 std::vector<double>& destination_psi,
18 const std::vector<double>& psi_prev_ref,
19 const double input_theta,
20 const double time_step,
21 const std::vector<double>& source_moments,
22 LBSGroupset& groupset,
23 const std::map<int, XSPtr>& xs,
24 const int num_moments,
25 const int max_num_cell_dofs)
26 : SweepChunk(destination_phi, destination_psi),
27 grid_view_(std::move(grid_ptr)),
28 grid_fe_view_(discretization),
29 unit_cell_matrices_(unit_cell_matrices),
30 grid_transport_view_(cell_transport_views),
31 q_moments_(source_moments),
32 groupset_(groupset),
33 xs_(xs),
34 num_moments_(num_moments),
35 num_groups_(groupset.groups_.size()),
36 max_num_cell_dofs_(max_num_cell_dofs),
37 save_angular_flux_(!destination_psi.empty()),
38 psi_prev_(psi_prev_ref),
39 theta_(input_theta),
40 dt_(time_step),
41 a_and_b_initialized_(false)
42{
43
44}
45
47GetUpwindPsi(int fj, bool local, bool boundary) const
48{
49 const double* psi;
50 if (local) psi = fluds.UpwindPsi(spls_index,
51 in_face_counter,
52 fj,0,angle_set_index);
53 else if (not boundary) psi = fluds.NLUpwindPsi(preloc_face_counter,
54 fj,0,angle_set_index);
55 else psi = angle_set->PsiBndry(bndry_id,
56 angle_num,
57 cell_local_id,
58 f, fj, gs_gi, gs_ss_begin,
59 surface_source_active);
60 return psi;
61}
62
64GetDownwindPsi(int fi, bool local, bool boundary, bool reflecting_bndry) const
65{
66 double* psi;
67 if (local) psi = fluds.
68 OutgoingPsi(spls_index,
69 out_face_counter,
70 fi, angle_set_index);
71 else if (not boundary) psi = fluds.
72 NLOutgoingPsi(deploc_face_counter,
73 fi, angle_set_index);
74 else if (reflecting_bndry) psi = angle_set->
75 ReflectingPsiOutBoundBndry(bndry_id, angle_num,
76 cell_local_id, f,
77 fi, gs_ss_begin);
78 else
79 psi = nullptr;
80
81 return psi;
82}
83
84//###################################################################
85/**Actual sweep function*/
88{
89 if (!a_and_b_initialized_)
90 {
91 Amat_.resize(max_num_cell_dofs_, std::vector<double>(max_num_cell_dofs_));
92 Atemp_.resize(max_num_cell_dofs_, std::vector<double>(max_num_cell_dofs_));
93 b_.resize(num_groups_, std::vector<double>(max_num_cell_dofs_, 0.0));
94 source_.resize(max_num_cell_dofs_, 0.0);
95 a_and_b_initialized_ = true;
96 }
97
98 const auto& spds = angle_set->GetSPDS();
99 const auto fluds = angle_set->fluds;
100 const bool surface_source_active = IsSurfaceSourceActive();
101 std::vector<double>& output_phi = GetDestinationPhi();
102 std::vector<double>& output_psi = GetDestinationPsi();
103
104 const SubSetInfo& grp_ss_info =
105 groupset_.grp_subset_infos_[angle_set->ref_subset];
106
107 const size_t gs_ss_size = grp_ss_info.ss_size;
108 const size_t gs_ss_begin = grp_ss_info.ss_begin;
109
110 // first groupset subset group
111 const int gs_gi = groupset_.groups_[gs_ss_begin].id_;
112
113 int deploc_face_counter = -1;
114 int preloc_face_counter = -1;
115
116 auto const& d2m_op = groupset_.quadrature_->GetDiscreteToMomentOperator();
117 auto const& m2d_op = groupset_.quadrature_->GetMomentToDiscreteOperator();
118
119 const auto& psi_uk_man = groupset_.psi_uk_man_;
120 typedef const int64_t cint64_t;
121
122 const bool fixed_src_active = surface_source_active;
123// const bool fixed_src_active = true;
124
125 // ========================================================== Loop over each cell
126 size_t num_loc_cells = spds.spls.item_id.size();
127 for (size_t spls_index = 0; spls_index < num_loc_cells; ++spls_index)
128 {
129 const int cell_local_id = spds.spls.item_id[spls_index];
130 const auto& cell = grid_view_->local_cells[cell_local_id];
131 const auto num_faces = cell.faces_.size();
132 const auto& cell_mapping = grid_fe_view_.GetCellMapping(cell);
133 const auto& fe_intgrl_values = unit_cell_matrices_[cell_local_id];
134 const int num_nodes = static_cast<int>(cell_mapping.NumNodes());
135 auto& transport_view = grid_transport_view_[cell.local_id_];
136 const auto& sigma_tg = transport_view.XS().SigmaTotal();
137 std::vector<bool> face_incident_flags(num_faces, false);
138 std::vector<double> face_mu_values(num_faces, 0.0);
139
140 //time-dependent parameters
141 const auto& inv_velg = transport_view.XS().InverseVelocity();
142 const double inv_theta = 1.0 / theta_;
143 const double inv_dt = 1.0 / dt_;
144 std::vector<double> tau_gsg(gs_ss_size, 0.0);
145 for (size_t gsg = 0; gsg < gs_ss_size; ++gsg)
146 tau_gsg[gsg] = inv_velg[gs_gi+gsg]*inv_theta*inv_dt;
147
148 // =================================================== Get Cell matrices
149 const auto& G = fe_intgrl_values.G_matrix;
150 const auto& M = fe_intgrl_values.M_matrix;
151 const auto& M_surf = fe_intgrl_values.face_M_matrices;
152 const auto& IntS_shapeI = fe_intgrl_values.face_Si_vectors;
153
154 // =================================================== Loop over angles in set
155 const int ni_deploc_face_counter = deploc_face_counter;
156 const int ni_preloc_face_counter = preloc_face_counter;
157 const size_t as_num_angles = angle_set->angles.size();
158 for (size_t angle_set_index = 0; angle_set_index<as_num_angles; ++angle_set_index)
159 {
160 deploc_face_counter = ni_deploc_face_counter;
161 preloc_face_counter = ni_preloc_face_counter;
162 const int angle_num = angle_set->angles[angle_set_index];
163 const chi_mesh::Vector3& omega = groupset_.quadrature_->omegas_[angle_num];
164 const double wt = groupset_.quadrature_->weights_[angle_num];
165
166 // ============================================ Gradient matrix
167 for (int i = 0; i < num_nodes; ++i)
168 for (int j = 0; j < num_nodes; ++j)
169 Amat_[i][j] = omega.Dot(G[i][j]);
170
171 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
172 b_[gsg].assign(num_nodes, 0.0);
173
174 // ============================================ Upwinding structure
175 Upwinder upwind{*fluds, angle_set, spls_index, angle_set_index,
176 /*in_face_counter*/0,
177 /*preloc_face_counter*/0,
178 /*out_face_counter*/0,
179 /*deploc_face_counter*/0,
180 /*bndry_id*/0, angle_num, cell.local_id_,
181 /*f*/0,gs_gi, gs_ss_begin,
182 surface_source_active};
183
184 // ============================================ Surface integrals
185 int in_face_counter = -1;
186 for (int f = 0; f < num_faces; ++f)
187 {
188 const auto& face = cell.faces_[f];
189 const double mu = omega.Dot(face.normal_);
190 face_mu_values[f] = mu;
191
192 if (mu >= 0.0) continue;
193
194 face_incident_flags[f] = true;
195 const bool local = transport_view.IsFaceLocal(f);
196 const bool boundary = not face.has_neighbor_;
197 const uint64_t bndry_id = face.neighbor_id_;
198
199 if (local) ++in_face_counter;
200 else if (not boundary) ++preloc_face_counter;
201
202 upwind.in_face_counter = in_face_counter;
203 upwind.preloc_face_counter = preloc_face_counter;
204 upwind.bndry_id = bndry_id;
205 upwind.f = f;
206
207 const size_t num_face_indices = face.vertex_ids_.size();
208 for (int fi = 0; fi < num_face_indices; ++fi)
209 {
210 const int i = cell_mapping.MapFaceNode(f,fi);
211 for (int fj = 0; fj < num_face_indices; ++fj)
212 {
213 const int j = cell_mapping.MapFaceNode(f,fj);
214
215 const double* psi = upwind.GetUpwindPsi(fj, local, boundary);
216
217 const double mu_Nij = -mu * M_surf[f][i][j];
218 Amat_[i][j] += mu_Nij;
219 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
220 b_[gsg][i] += psi[gsg] * mu_Nij;
221
222 }//for face j
223 }//for face i
224 } // for f
225
226 // ========================================== Looping over groups
227 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
228 {
229 const int g = gs_gi+gsg;
230
231 // ============================= Contribute source moments
232 // q = M_n^T * q_moms
233 for (int i = 0; i < num_nodes; ++i)
234 {
235 double temp_src = 0.0;
236 for (int m = 0; m < num_moments_; ++m)
237 {
238 const size_t ir = transport_view.MapDOF(i, m, g);
239 temp_src += m2d_op[m][angle_num] * q_moments_[ir];
240 }//for m
241 cint64_t imap = grid_fe_view_.MapDOFLocal(cell, i, psi_uk_man, angle_num, 0);
242 if (fixed_src_active)
243 temp_src += tau_gsg[gsg] * psi_prev_[imap + gsg];
244 source_[i] = temp_src;
245 }//for i
246
247 // ============================= Mass Matrix and Source
248 // Atemp = Amat + sigma_tgr * M
249 // b += M * q
250 const double sigma_tgr = sigma_tg[g] + tau_gsg[gsg];
251 for (int i = 0; i < num_nodes; ++i)
252 {
253 double temp = 0.0;
254 for (int j = 0; j < num_nodes; ++j)
255 {
256 const double Mij = M[i][j];
257 Atemp_[i][j] = Amat_[i][j] + Mij * sigma_tgr;
258 temp += Mij * source_[j];
259 }//for j
260 b_[gsg][i] += temp;
261 }//for i
262
263 // ============================= Solve system
264 chi_math::GaussElimination(Atemp_, b_[gsg], num_nodes);
265 }
266
267 // ============================= Accumulate flux
268 for (int m = 0; m < num_moments_; ++m)
269 {
270 const double wn_d2m = d2m_op[m][angle_num];
271 for (int i = 0; i < num_nodes; ++i)
272 {
273 const size_t ir = transport_view.MapDOF(i, m, gs_gi);
274 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
275 output_phi[ir + gsg] += wn_d2m * b_[gsg][i];
276 }
277 }
278
279 for (auto& callback : moment_callbacks)
280 callback(this, angle_set);
281
282 // ============================= Save angular fluxes if needed
283 if (save_angular_flux_)
284 {
285 for (int i = 0; i < num_nodes; ++i)
286 {
287 cint64_t imap = grid_fe_view_.MapDOFLocal(cell, i, psi_uk_man,
288 angle_num, gs_ss_begin);
289 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
290 output_psi[imap + gsg] = b_[gsg][i];
291 //inv_theta*(b_[gsg][i] + (theta_ - 1.0) * psi_prev_[imap + gsg]);
292 }//for i
293 }//if save psi
294
295 int out_face_counter = -1;
296 for (int f = 0; f < num_faces; ++f)
297 {
298 if (face_incident_flags[f]) continue;
299 double mu = face_mu_values[f];
300
301 // ============================= Set flags and counters
302 out_face_counter++;
303 const auto& face = cell.faces_[f];
304 const bool local = transport_view.IsFaceLocal(f);
305 const bool boundary = not face.has_neighbor_;
306 const size_t num_face_indices = face.vertex_ids_.size();
307 const std::vector<double>& IntF_shapeI = IntS_shapeI[f];
308 const uint64_t bndry_id = face.neighbor_id_;
309
310 bool reflecting_bndry = false;
311 if (boundary)
312 if (angle_set->ref_boundaries[bndry_id]->IsReflecting())
313 reflecting_bndry = true;
314
315 if (not boundary and not local) ++deploc_face_counter;
316
317 upwind.out_face_counter = out_face_counter;
318 upwind.deploc_face_counter = deploc_face_counter;
319 upwind.bndry_id = bndry_id;
320 upwind.f = f;
321
322 for (int fi = 0; fi < num_face_indices; ++fi)
323 {
324 const int i = cell_mapping.MapFaceNode(f,fi);
325
326 double* psi = upwind.GetDownwindPsi(fi, local, boundary, reflecting_bndry);
327
328 if (not boundary or reflecting_bndry)
329 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
330 psi[gsg] = b_[gsg][i];
331 if (boundary and not reflecting_bndry)
332 for (int gsg = 0; gsg < gs_ss_size; ++gsg)
333 transport_view.AddOutflow(gs_gi + gsg,
334 wt * mu * b_[gsg][i] * IntF_shapeI[i]);
335 }//for fi
336 }//for face
337 } // for n
338 } // for cell
339}//Sweep
const SPDS & GetSPDS() const
Definition: AngleSet.cc:34
void Sweep(chi_mesh::sweep_management::AngleSet *angle_set) override
SweepChunkPWLTransientTheta(std::shared_ptr< chi_mesh::MeshContinuum > grid_ptr, chi_math::SpatialDiscretization &discretization, const std::vector< UnitCellMatrices > &unit_cell_matrices, std::vector< lbs::CellLBSView > &cell_transport_views, std::vector< double > &destination_phi, std::vector< double > &destination_psi, const std::vector< double > &psi_prev_ref, double input_theta, double time_step, const std::vector< double > &source_moments, LBSGroupset &groupset, const std::map< int, XSPtr > &xs, int num_moments, int max_num_cell_dofs)
void GaussElimination(MatDbl &A, VecDbl &b, int n)
Vector3 Dot(const chi_mesh::TensorRank2Dim3 &that) const
double * GetDownwindPsi(int fi, bool local, bool boundary, bool reflecting_bndry) const
const double * GetUpwindPsi(int fj, bool local, bool boundary) const