12 std::shared_ptr<chi_mesh::MeshContinuum> grid_ptr,
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,
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),
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),
41 a_and_b_initialized_(false)
50 if (local) psi = fluds.UpwindPsi(spls_index,
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,
58 f, fj, gs_gi, gs_ss_begin,
59 surface_source_active);
64GetDownwindPsi(
int fi,
bool local,
bool boundary,
bool reflecting_bndry)
const
67 if (local) psi = fluds.
68 OutgoingPsi(spls_index,
71 else if (not boundary) psi = fluds.
72 NLOutgoingPsi(deploc_face_counter,
74 else if (reflecting_bndry) psi = angle_set->
75 ReflectingPsiOutBoundBndry(bndry_id, angle_num,
89 if (!a_and_b_initialized_)
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;
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();
104 const SubSetInfo& grp_ss_info =
105 groupset_.grp_subset_infos_[angle_set->ref_subset];
107 const size_t gs_ss_size = grp_ss_info.ss_size;
108 const size_t gs_ss_begin = grp_ss_info.ss_begin;
111 const int gs_gi = groupset_.groups_[gs_ss_begin].id_;
113 int deploc_face_counter = -1;
114 int preloc_face_counter = -1;
116 auto const& d2m_op = groupset_.quadrature_->GetDiscreteToMomentOperator();
117 auto const& m2d_op = groupset_.quadrature_->GetMomentToDiscreteOperator();
119 const auto& psi_uk_man = groupset_.psi_uk_man_;
120 typedef const int64_t cint64_t;
122 const bool fixed_src_active = surface_source_active;
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)
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);
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;
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;
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)
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];
164 const double wt = groupset_.quadrature_->weights_[angle_num];
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]);
171 for (
int gsg = 0; gsg < gs_ss_size; ++gsg)
172 b_[gsg].assign(num_nodes, 0.0);
175 Upwinder upwind{*fluds, angle_set, spls_index, angle_set_index,
180 0, angle_num, cell.local_id_,
181 0,gs_gi, gs_ss_begin,
182 surface_source_active};
185 int in_face_counter = -1;
186 for (
int f = 0; f < num_faces; ++f)
188 const auto& face = cell.faces_[f];
189 const double mu = omega.
Dot(face.normal_);
190 face_mu_values[f] = mu;
192 if (mu >= 0.0)
continue;
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_;
199 if (local) ++in_face_counter;
200 else if (not boundary) ++preloc_face_counter;
202 upwind.in_face_counter = in_face_counter;
203 upwind.preloc_face_counter = preloc_face_counter;
204 upwind.bndry_id = bndry_id;
207 const size_t num_face_indices = face.vertex_ids_.size();
208 for (
int fi = 0; fi < num_face_indices; ++fi)
210 const int i = cell_mapping.MapFaceNode(f,fi);
211 for (
int fj = 0; fj < num_face_indices; ++fj)
213 const int j = cell_mapping.MapFaceNode(f,fj);
215 const double* psi = upwind.GetUpwindPsi(fj, local, boundary);
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;
227 for (
int gsg = 0; gsg < gs_ss_size; ++gsg)
229 const int g = gs_gi+gsg;
233 for (
int i = 0; i < num_nodes; ++i)
235 double temp_src = 0.0;
236 for (
int m = 0; m < num_moments_; ++m)
238 const size_t ir = transport_view.MapDOF(i, m, g);
239 temp_src += m2d_op[m][angle_num] * q_moments_[ir];
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;
250 const double sigma_tgr = sigma_tg[g] + tau_gsg[gsg];
251 for (
int i = 0; i < num_nodes; ++i)
254 for (
int j = 0; j < num_nodes; ++j)
256 const double Mij = M[i][j];
257 Atemp_[i][j] = Amat_[i][j] + Mij * sigma_tgr;
258 temp += Mij * source_[j];
268 for (
int m = 0; m < num_moments_; ++m)
270 const double wn_d2m = d2m_op[m][angle_num];
271 for (
int i = 0; i < num_nodes; ++i)
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];
279 for (
auto& callback : moment_callbacks)
280 callback(
this, angle_set);
283 if (save_angular_flux_)
285 for (
int i = 0; i < num_nodes; ++i)
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];
295 int out_face_counter = -1;
296 for (
int f = 0; f < num_faces; ++f)
298 if (face_incident_flags[f])
continue;
299 double mu = face_mu_values[f];
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_;
310 bool reflecting_bndry =
false;
312 if (angle_set->ref_boundaries[bndry_id]->IsReflecting())
313 reflecting_bndry =
true;
315 if (not boundary and not local) ++deploc_face_counter;
317 upwind.out_face_counter = out_face_counter;
318 upwind.deploc_face_counter = deploc_face_counter;
319 upwind.bndry_id = bndry_id;
322 for (
int fi = 0; fi < num_face_indices; ++fi)
324 const int i = cell_mapping.MapFaceNode(f,fi);
326 double* psi = upwind.GetDownwindPsi(fi, local, boundary, reflecting_bndry);
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]);
const SPDS & GetSPDS() const
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