Chi-Tech
diffusion_PWLC_02d_assemble_b.cc
Go to the documentation of this file.
1#include "diffusion_PWLC.h"
2#include "acceleration.h"
3
5
8
10
12
13#include "chi_runtime.h"
14#include "chi_log.h"
15#include "utils/chi_timer.h"
16#include "console/chi_console.h"
17
18#define DefaultBCDirichlet \
19 BoundaryCondition \
20 { \
21 BCType::DIRICHLET, { 0, 0, 0 } \
22 }
23
24// ###################################################################
25/**Assembles the RHS using unit cell-matrices. These are
26 * the routines used in the production versions.*/
28 const std::vector<double>& q_vector)
29{
30 const size_t num_local_dofs = sdm_.GetNumLocalAndGhostDOFs(uk_man_);
31 ChiInvalidArgumentIf(q_vector.size() != num_local_dofs,
32 std::string("q_vector size mismatch. ") +
33 std::to_string(q_vector.size()) + " vs " +
34 std::to_string(num_local_dofs));
35 const std::string fname = "lbs::acceleration::DiffusionMIPSolver::"
36 "Assemble_b";
37 if (A_ == nullptr or rhs_ == nullptr or ksp_ == nullptr)
38 throw std::logic_error(fname + ": Some or all PETSc elements are null. "
39 "Check that Initialize has been called.");
40 if (options.verbose)
42 << " Starting assembly";
43
44 const size_t num_groups = uk_man_.unknowns_.front().num_components_;
45
46 VecSet(rhs_, 0.0);
47 for (const auto& cell : grid_.local_cells)
48 {
49 const size_t num_faces = cell.faces_.size();
50 const auto& cell_mapping = sdm_.GetCellMapping(cell);
51 const size_t num_nodes = cell_mapping.NumNodes();
52 const auto cc_nodes = cell_mapping.GetNodeLocations();
53 const auto& unit_cell_matrices = unit_cell_matrices_[cell.local_id_];
54
55 const auto& cell_K_matrix = unit_cell_matrices.K_matrix;
56 const auto& cell_M_matrix = unit_cell_matrices.M_matrix;
57 const auto& cell_Vi = unit_cell_matrices.Vi_vectors;
58
59 const auto& xs = mat_id_2_xs_map_.at(cell.material_id_);
60
61 //=========================================== Mark dirichlet nodes
62 typedef std::pair<bool, double> DirichFlagVal;
63 std::vector<DirichFlagVal> node_is_dirichlet(num_nodes, {false, 0.0});
64 for (size_t f = 0; f < num_faces; ++f)
65 {
66 const auto& face = cell.faces_[f];
67 if (not face.has_neighbor_)
68 {
69 auto bc = DefaultBCDirichlet;
70 if (bcs_.count(face.neighbor_id_) > 0) bc = bcs_.at(face.neighbor_id_);
71
72 if (bc.type != BCType::DIRICHLET) continue;
73
74 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
75 for (size_t fi = 0; fi < num_face_nodes; ++fi)
76 node_is_dirichlet[cell_mapping.MapFaceNode(f, fi)] = {true,
77 bc.values[0]};
78 }
79 }
80
81 for (size_t g = 0; g < num_groups; ++g)
82 {
83 //==================================== Get coefficient and nodal src
84 std::vector<double> qg(num_nodes, 0.0);
85 for (size_t j = 0; j < num_nodes; j++)
86 qg[j] = q_vector[sdm_.MapDOFLocal(cell, j, uk_man_, 0, g)];
87
88 //==================================== Assemble continuous terms
89 const double Dg = xs.Dg[g];
90 const double sigr_g = xs.sigR[g];
91
92 for (size_t i = 0; i < num_nodes; i++)
93 {
94 if (node_is_dirichlet[i].first) continue;
95 const int64_t imap = sdm_.MapDOF(cell, i, uk_man_, 0, g);
96 double entry_rhs_i = 0.0;
97 for (size_t j = 0; j < num_nodes; j++)
98 {
99 if (node_is_dirichlet[j].first)
100 {
101 const double entry_aij =
102 Dg * cell_K_matrix[i][j] + sigr_g * cell_M_matrix[i][j];
103
104 const double bcvalue = node_is_dirichlet[j].second;
105 VecSetValue(rhs_, imap, -entry_aij * bcvalue, ADD_VALUES);
106 }
107
108 entry_rhs_i += qg[j] * cell_M_matrix[i][j];
109 } // for j
110
111 VecSetValue(rhs_, imap, entry_rhs_i, ADD_VALUES);
112 } // for i
113
114 //==================================== Assemble face terms
115 for (size_t f = 0; f < num_faces; ++f)
116 {
117 const auto& face = cell.faces_[f];
118 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
119
120 const auto& face_Si = unit_cell_matrices.face_Si_vectors[f];
121
122 if (not face.has_neighbor_)
123 {
124 auto bc = DefaultBCDirichlet;
125 if (bcs_.count(face.neighbor_id_) > 0)
126 bc = bcs_.at(face.neighbor_id_);
127
128 if (bc.type == BCType::DIRICHLET)
129 {
130 const double bc_value = bc.values[0];
131
132 //========================= Assembly penalty terms
133 for (size_t fi = 0; fi < num_face_nodes; ++fi)
134 {
135 const int i = cell_mapping.MapFaceNode(f, fi);
136 const int64_t imap = sdm_.MapDOF(cell, i, uk_man_, 0, g);
137
138 // VecSetValue(rhs_, imap, bc_value * cell_Vi[i], ADD_VALUES);
139 VecSetValue(rhs_, imap, bc_value, ADD_VALUES);
140 } // for fi
141
142 } // Dirichlet BC
143 else if (bc.type == BCType::ROBIN)
144 {
145 const double bval = bc.values[1];
146 const double fval = bc.values[2];
147
148 if (std::fabs(bval) < 1.0e-12) continue; // a and f assumed zero
149
150 for (size_t fi = 0; fi < num_face_nodes; fi++)
151 {
152 const int i = cell_mapping.MapFaceNode(f, fi);
153 const int64_t ir = sdm_.MapDOF(cell, i, uk_man_, 0, g);
154
155 if (std::fabs(fval) >= 1.0e-12)
156 {
157 const double rhs_val = (fval / bval) * face_Si[i];
158
159 VecSetValue(rhs_, ir, rhs_val, ADD_VALUES);
160 } // if f nonzero
161 } // for fi
162 } // Robin BC
163 } // boundary face
164 } // for face
165 } // for g
166 } // for cell
167
168 VecAssemblyBegin(rhs_);
169 VecAssemblyEnd(rhs_);
170
171 if (options.verbose)
173 << " Assembly completed";
174}
175
176// ###################################################################
177/**Assembles the RHS using unit cell-matrices. These are
178 * the routines used in the production versions.*/
180{
181 const std::string fname = "lbs::acceleration::DiffusionMIPSolver::"
182 "Assemble_b";
183 if (A_ == nullptr or rhs_ == nullptr or ksp_ == nullptr)
184 throw std::logic_error(fname + ": Some or all PETSc elements are null. "
185 "Check that Initialize has been called.");
186 if (options.verbose)
188 << " Starting assembly";
189
190 const size_t num_groups = uk_man_.unknowns_.front().num_components_;
191
192 const double* q_vector;
193 VecGetArrayRead(petsc_q_vector, &q_vector);
194
195 VecSet(rhs_, 0.0);
196 for (const auto& cell : grid_.local_cells)
197 {
198 const size_t num_faces = cell.faces_.size();
199 const auto& cell_mapping = sdm_.GetCellMapping(cell);
200 const size_t num_nodes = cell_mapping.NumNodes();
201 const auto cc_nodes = cell_mapping.GetNodeLocations();
202 const auto& unit_cell_matrices = unit_cell_matrices_[cell.local_id_];
203
204 const auto& cell_M_matrix = unit_cell_matrices.M_matrix;
205 const auto& cell_Vi = unit_cell_matrices.Vi_vectors;
206
207 //=========================================== Mark dirichlet nodes
208 std::vector<bool> node_is_dirichlet(num_nodes, false);
209 for (size_t f = 0; f < num_faces; ++f)
210 {
211 const auto& face = cell.faces_[f];
212 if (not face.has_neighbor_)
213 {
214 auto bc = DefaultBCDirichlet;
215 if (bcs_.count(face.neighbor_id_) > 0) bc = bcs_.at(face.neighbor_id_);
216
217 if (bc.type != BCType::DIRICHLET) continue;
218
219 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
220 for (size_t fi = 0; fi < num_face_nodes; ++fi)
221 node_is_dirichlet[cell_mapping.MapFaceNode(f, fi)] = true;
222 }
223 }
224
225 for (size_t g = 0; g < num_groups; ++g)
226 {
227 //==================================== Get coefficient and nodal src
228 std::vector<double> qg(num_nodes, 0.0);
229 for (size_t j = 0; j < num_nodes; j++)
230 qg[j] = q_vector[sdm_.MapDOFLocal(cell, j, uk_man_, 0, g)];
231
232 //==================================== Assemble continuous terms
233 for (size_t i = 0; i < num_nodes; i++)
234 {
235 if (node_is_dirichlet[i]) continue;
236 const int64_t imap = sdm_.MapDOF(cell, i, uk_man_, 0, g);
237 double entry_rhs_i = 0.0;
238 for (size_t j = 0; j < num_nodes; j++)
239 entry_rhs_i += qg[j] * cell_M_matrix[i][j];
240
241 VecSetValue(rhs_, imap, entry_rhs_i, ADD_VALUES);
242 } // for i
243
244 //==================================== Assemble face terms
245 for (size_t f = 0; f < num_faces; ++f)
246 {
247 const auto& face = cell.faces_[f];
248 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
249
250 const auto& face_Si = unit_cell_matrices.face_Si_vectors[f];
251
252 if (not face.has_neighbor_)
253 {
254 auto bc = DefaultBCDirichlet;
255 if (bcs_.count(face.neighbor_id_) > 0)
256 bc = bcs_.at(face.neighbor_id_);
257
258 if (bc.type == BCType::DIRICHLET)
259 {
260 const double bc_value = bc.values[0];
261
262 //========================= Assembly penalty terms
263 for (size_t fi = 0; fi < num_face_nodes; ++fi)
264 {
265 const int i = cell_mapping.MapFaceNode(f, fi);
266 const int64_t imap = sdm_.MapDOF(cell, i, uk_man_, 0, g);
267
268 VecSetValue(rhs_, imap, bc_value * cell_Vi[i], ADD_VALUES);
269 } // for fi
270
271 } // Dirichlet BC
272 else if (bc.type == BCType::ROBIN)
273 {
274 const double bval = bc.values[1];
275 const double fval = bc.values[2];
276
277 if (std::fabs(bval) < 1.0e-12) continue; // a and f assumed zero
278
279 for (size_t fi = 0; fi < num_face_nodes; fi++)
280 {
281 const int i = cell_mapping.MapFaceNode(f, fi);
282 const int64_t ir = sdm_.MapDOF(cell, i, uk_man_, 0, g);
283
284 if (std::fabs(fval) >= 1.0e-12)
285 {
286 const double rhs_val = (fval / bval) * face_Si[i];
287
288 VecSetValue(rhs_, ir, rhs_val, ADD_VALUES);
289 } // if f nonzero
290 } // for fi
291 } // Robin BC
292 } // boundary face
293 } // for face
294 } // for g
295 } // for cell
296
297 VecRestoreArrayRead(petsc_q_vector, &q_vector);
298
299 VecAssemblyBegin(rhs_);
300 VecAssemblyEnd(rhs_);
301
302 if (options.verbose)
304 << " Assembly completed";
305}
#define ChiInvalidArgumentIf(condition, message)
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
size_t NumNodes() const
Definition: CellMapping.cc:34
size_t GetNumLocalAndGhostDOFs(const UnknownManager &unknown_manager) const
const CellMapping & GetCellMapping(const chi_mesh::Cell &cell) const
virtual int64_t MapDOF(const chi_mesh::Cell &cell, unsigned int node, const UnknownManager &unknown_manager, unsigned int unknown_id, unsigned int component) const =0
virtual int64_t MapDOFLocal(const chi_mesh::Cell &cell, unsigned int node, const UnknownManager &unknown_manager, unsigned int unknown_id, unsigned int component) const =0
std::vector< Unknown > unknowns_
LocalCellHandler local_cells
void Assemble_b(const std::vector< double > &q_vector) override
struct lbs::acceleration::DiffusionSolver::Options options
const chi_math::SpatialDiscretization & sdm_
Definition: diffusion.h:39
const chi_math::UnknownManager uk_man_
Definition: diffusion.h:40
const chi_mesh::MeshContinuum & grid_
Definition: diffusion.h:38
const std::map< uint64_t, BoundaryCondition > bcs_
Definition: diffusion.h:42
const MatID2XSMap mat_id_2_xs_map_
Definition: diffusion.h:44
const std::vector< UnitCellMatrices > & unit_cell_matrices_
Definition: diffusion.h:46
#define DefaultBCDirichlet
struct _p_Vec * Vec