18#define DefaultBCDirichlet \
21 BCType::DIRICHLET, { 0, 0, 0 } \
28 const std::vector<double>& q_vector)
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::"
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.");
42 <<
" Starting assembly";
49 const size_t num_faces = cell.faces_.size();
51 const size_t num_nodes = cell_mapping.
NumNodes();
52 const auto cc_nodes = cell_mapping.GetNodeLocations();
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;
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)
66 const auto& face = cell.faces_[f];
67 if (not face.has_neighbor_)
70 if (
bcs_.count(face.neighbor_id_) > 0) bc =
bcs_.at(face.neighbor_id_);
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,
81 for (
size_t g = 0; g < num_groups; ++g)
84 std::vector<double> qg(num_nodes, 0.0);
85 for (
size_t j = 0; j < num_nodes; j++)
89 const double Dg = xs.Dg[g];
90 const double sigr_g = xs.sigR[g];
92 for (
size_t i = 0; i < num_nodes; i++)
94 if (node_is_dirichlet[i].first)
continue;
96 double entry_rhs_i = 0.0;
97 for (
size_t j = 0; j < num_nodes; j++)
99 if (node_is_dirichlet[j].first)
101 const double entry_aij =
102 Dg * cell_K_matrix[i][j] + sigr_g * cell_M_matrix[i][j];
104 const double bcvalue = node_is_dirichlet[j].second;
105 VecSetValue(
rhs_, imap, -entry_aij * bcvalue, ADD_VALUES);
108 entry_rhs_i += qg[j] * cell_M_matrix[i][j];
111 VecSetValue(
rhs_, imap, entry_rhs_i, ADD_VALUES);
115 for (
size_t f = 0; f < num_faces; ++f)
117 const auto& face = cell.faces_[f];
118 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
120 const auto& face_Si = unit_cell_matrices.face_Si_vectors[f];
122 if (not face.has_neighbor_)
125 if (
bcs_.count(face.neighbor_id_) > 0)
126 bc =
bcs_.at(face.neighbor_id_);
130 const double bc_value = bc.values[0];
133 for (
size_t fi = 0; fi < num_face_nodes; ++fi)
135 const int i = cell_mapping.MapFaceNode(f, fi);
139 VecSetValue(
rhs_, imap, bc_value, ADD_VALUES);
145 const double bval = bc.values[1];
146 const double fval = bc.values[2];
148 if (std::fabs(bval) < 1.0e-12)
continue;
150 for (
size_t fi = 0; fi < num_face_nodes; fi++)
152 const int i = cell_mapping.MapFaceNode(f, fi);
155 if (std::fabs(fval) >= 1.0e-12)
157 const double rhs_val = (fval / bval) * face_Si[i];
159 VecSetValue(
rhs_, ir, rhs_val, ADD_VALUES);
168 VecAssemblyBegin(
rhs_);
169 VecAssemblyEnd(
rhs_);
173 <<
" Assembly completed";
181 const std::string fname =
"lbs::acceleration::DiffusionMIPSolver::"
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.");
188 <<
" Starting assembly";
190 const size_t num_groups = uk_man_.unknowns_.front().num_components_;
192 const double* q_vector;
193 VecGetArrayRead(petsc_q_vector, &q_vector);
196 for (
const auto& cell : grid_.local_cells)
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_];
204 const auto& cell_M_matrix = unit_cell_matrices.M_matrix;
205 const auto& cell_Vi = unit_cell_matrices.Vi_vectors;
208 std::vector<bool> node_is_dirichlet(num_nodes,
false);
209 for (
size_t f = 0; f < num_faces; ++f)
211 const auto& face = cell.faces_[f];
212 if (not face.has_neighbor_)
215 if (bcs_.count(face.neighbor_id_) > 0) bc = bcs_.at(face.neighbor_id_);
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;
225 for (
size_t g = 0; g < num_groups; ++g)
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)];
233 for (
size_t i = 0; i < num_nodes; i++)
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];
241 VecSetValue(rhs_, imap, entry_rhs_i, ADD_VALUES);
245 for (
size_t f = 0; f < num_faces; ++f)
247 const auto& face = cell.faces_[f];
248 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
250 const auto& face_Si = unit_cell_matrices.face_Si_vectors[f];
252 if (not face.has_neighbor_)
255 if (bcs_.count(face.neighbor_id_) > 0)
256 bc = bcs_.at(face.neighbor_id_);
260 const double bc_value = bc.values[0];
263 for (
size_t fi = 0; fi < num_face_nodes; ++fi)
265 const int i = cell_mapping.MapFaceNode(f, fi);
266 const int64_t imap = sdm_.MapDOF(cell, i, uk_man_, 0, g);
268 VecSetValue(rhs_, imap, bc_value * cell_Vi[i], ADD_VALUES);
274 const double bval = bc.values[1];
275 const double fval = bc.values[2];
277 if (std::fabs(bval) < 1.0e-12)
continue;
279 for (
size_t fi = 0; fi < num_face_nodes; fi++)
281 const int i = cell_mapping.MapFaceNode(f, fi);
282 const int64_t ir = sdm_.MapDOF(cell, i, uk_man_, 0, g);
284 if (std::fabs(fval) >= 1.0e-12)
286 const double rhs_val = (fval / bval) * face_Si[i];
288 VecSetValue(rhs_, ir, rhs_val, ADD_VALUES);
297 VecRestoreArrayRead(petsc_q_vector, &q_vector);
299 VecAssemblyBegin(rhs_);
300 VecAssemblyEnd(rhs_);
304 <<
" Assembly completed";
#define ChiInvalidArgumentIf(condition, message)
static chi::Timer program_timer
LogStream Log(LOG_LVL level=LOG_0)
std::string GetTimeString() const
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_
const chi_math::UnknownManager uk_man_
const chi_mesh::MeshContinuum & grid_
const std::map< uint64_t, BoundaryCondition > bcs_
const MatID2XSMap mat_id_2_xs_map_
const std::vector< UnitCellMatrices > & unit_cell_matrices_
#define DefaultBCDirichlet
bool verbose
Verbosity flag.