Chi-Tech
assemble_pwld.cc
Go to the documentation of this file.
1#include "diffusion_solver.h"
2
5
6#include "chi_runtime.h"
7
8// ###################################################################
9/**Assembles PWLC matrix for polygon cells.*/
11 int component)
12{
13 auto pwl_sdm = std::static_pointer_cast<
15 const auto& fe_intgrl_values = unit_integrals_.at(cell.global_id_);
16
17 size_t num_nodes = fe_intgrl_values.NumNodes();
18
19 //====================================== Process material id
20 int mat_id = cell.material_id_;
21
22 std::vector<double> D(num_nodes, 1.0);
23 std::vector<double> q(num_nodes, 1.0);
24 std::vector<double> siga(num_nodes, 0.0);
25
26 GetMaterialProperties(cell, num_nodes, D, q, siga, component);
27
28 //========================================= Loop over DOFs
29 for (int i=0; i<num_nodes; i++)
30 {
31 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
32 double rhsvalue =0.0;
33
34 //====================== Develop matrix entry
35 for (int j=0; j<num_nodes; j++)
36 {
37 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
38
39 double jr_mat_entry =
40 D[j]* fe_intgrl_values.IntV_gradShapeI_gradShapeJ(i, j);
41
42 jr_mat_entry +=
43 siga[j]* fe_intgrl_values.IntV_shapeI_shapeJ(i, j);
44
45 MatSetValue(A_, ir, jr, jr_mat_entry, ADD_VALUES);
46
47 rhsvalue += q[j]* fe_intgrl_values.IntV_shapeI_shapeJ(i, j);
48 }//for j
49
50 //====================== Apply RHS entry
51 VecSetValue(b_, ir, rhsvalue, ADD_VALUES);
52
53 }//for i
54
55
56 //========================================= Loop over faces
57 int num_faces = cell.faces_.size();
58 for (unsigned int f=0; f<num_faces; f++)
59 {
60 auto& face = cell.faces_[f];
61
62 //================================== Get face normal
63 chi_mesh::Vector3 n = face.normal_;
64
65 int num_face_dofs = face.vertex_ids_.size();
66
67 if (face.has_neighbor_)
68 {
69 const auto& adj_cell = grid_ptr_->cells[face.neighbor_id_];
70 const auto& adj_fe_intgrl_values = unit_integrals_.at(adj_cell.global_id_);
71
72 //========================= Get the current map to the adj cell's face
73 unsigned int fmap = MapCellFace(cell,adj_cell,f);
74
75 //========================= Compute penalty coefficient
76 double hp = HPerpendicular(adj_cell, adj_fe_intgrl_values, fmap);
77 double hm = HPerpendicular(cell, fe_intgrl_values, f);
78
79 std::vector<double> adj_D,adj_Q,adj_sigma;
80
81 GetMaterialProperties(adj_cell,
82 adj_fe_intgrl_values.NumNodes(),
83 adj_D,
84 adj_Q,
85 adj_sigma,
86 component);
87
88 //========================= Compute surface average D
89 double D_avg = 0.0;
90 double intS = 0.0;
91 for (int fi=0; fi<num_face_dofs; fi++)
92 {
93 int i = fe_intgrl_values.FaceDofMapping(f,fi);
94 D_avg += D[i]* fe_intgrl_values.IntS_shapeI(f, i);
95 intS += fe_intgrl_values.IntS_shapeI(f, i);
96 }
97 D_avg /= intS;
98
99 //========================= Compute surface average D_adj
100 double adj_D_avg = 0.0;
101 double adj_intS = 0.0;
102 for (int fi=0; fi<num_face_dofs; fi++)
103 {
104 int i = fe_intgrl_values.FaceDofMapping(f,fi);
105 int imap = MapCellLocalNodeIDFromGlobalID(adj_cell, cell.vertex_ids_[i]);
106 adj_D_avg += adj_D[imap]* adj_fe_intgrl_values.IntS_shapeI(fmap, imap);
107 adj_intS += adj_fe_intgrl_values.IntS_shapeI(fmap, imap);
108 }
109 adj_D_avg /= adj_intS;
110
111 //========================= Compute kappa
112 double kappa = 1.0;
113 if (cell.Type() == chi_mesh::CellType::SLAB)
114 kappa = fmax(2.0*(adj_D_avg/hp + D_avg/hm),0.25);
115 if (cell.Type() == chi_mesh::CellType::POLYGON)
116 kappa = fmax(2.0*(adj_D_avg/hp + D_avg/hm),0.25);
118 kappa = fmax(4.0*(adj_D_avg/hp + D_avg/hm),0.25);
119
120 //========================= Assembly penalty terms
121 for (int fi=0; fi<num_face_dofs; fi++)
122 {
123 int i = fe_intgrl_values.FaceDofMapping(f,fi);
124 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
125
126 for (int fj=0; fj<num_face_dofs; fj++)
127 {
128 int j = fe_intgrl_values.FaceDofMapping(f,fj);
129 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
130 int jmap = MapCellLocalNodeIDFromGlobalID(adj_cell, face.vertex_ids_[fj]);
131 int jrmap = pwl_sdm->MapDOF(adj_cell, jmap, unknown_manager_, 0, component);
132
133 double aij = kappa* fe_intgrl_values.IntS_shapeI_shapeJ(f, i, j);
134
135 MatSetValue(A_, ir , jr , aij, ADD_VALUES);
136 MatSetValue(A_, ir , jrmap, -aij, ADD_VALUES);
137 }//for fj
138
139 }//for fi
140
141 //========================= Assemble gradient terms
142 // For the following comments we use the notation:
143 // Dk = 0.5* n dot nabla bk
144
145 // 0.5*D* n dot (b_j^+ - b_j^-)*nabla b_i^-
146 for (int i=0; i<fe_intgrl_values.NumNodes(); i++)
147 {
148 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
149
150 for (int fj=0; fj<num_face_dofs; fj++)
151 {
152 int j = fe_intgrl_values.FaceDofMapping(f,fj);
153 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
154 int jmap = MapCellLocalNodeIDFromGlobalID(adj_cell, face.vertex_ids_[fj]);
155 int jrmap = pwl_sdm->MapDOF(adj_cell, jmap, unknown_manager_, 0, component);
156
157 double aij =
158 -0.5*D_avg*n.Dot(fe_intgrl_values.IntS_shapeI_gradshapeJ(f, j, i));
159
160 MatSetValue(A_, ir, jr , aij, ADD_VALUES);
161 MatSetValue(A_, ir, jrmap, -aij, ADD_VALUES);
162 }//for fj
163 }//for i
164
165 // 0.5*D* n dot (b_i^+ - b_i^-)*nabla b_j^-
166 for (int fi=0; fi<num_face_dofs; fi++)
167 {
168 int i = fe_intgrl_values.FaceDofMapping(f,fi);
169 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
170 int imap = MapCellLocalNodeIDFromGlobalID(adj_cell, face.vertex_ids_[fi]);
171 int irmap = pwl_sdm->MapDOF(adj_cell, imap, unknown_manager_, 0, component);
172
173 for (int j=0; j<fe_intgrl_values.NumNodes(); j++)
174 {
175 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
176
177 double aij =
178 -0.5*D_avg*n.Dot(fe_intgrl_values.IntS_shapeI_gradshapeJ(f, i, j));
179
180 MatSetValue(A_, ir , jr, aij, ADD_VALUES);
181 MatSetValue(A_, irmap, jr, -aij, ADD_VALUES);
182 }//for j
183 }//for fi
184
185 }//if not bndry
186 else
187 {
188 uint64_t ir_boundary_index = face.neighbor_id_;
189 auto ir_boundary_type = boundaries_.at(ir_boundary_index)->type_;
190
191 if (ir_boundary_type == BoundaryType::Dirichlet)
192 {
193 auto dc_boundary =
194 (chi_diffusion::BoundaryDirichlet&)*boundaries_.at(ir_boundary_index);
195
196 //========================= Compute penalty coefficient
197 double hm = HPerpendicular(cell, fe_intgrl_values, f);
198
199 //========================= Compute surface average D
200 double D_avg = 0.0;
201 double intS = 0.0;
202 for (int fi=0; fi<num_face_dofs; fi++)
203 {
204 int i = fe_intgrl_values.FaceDofMapping(f,fi);
205 D_avg += D[i]* fe_intgrl_values.IntS_shapeI(f, i);
206 intS += fe_intgrl_values.IntS_shapeI(f, i);
207 }
208 D_avg /= intS;
209
210 double kappa = 1.0;
211 if (cell.Type() == chi_mesh::CellType::SLAB)
212 kappa = fmax(4.0*(D_avg/hm),0.25);
213 if (cell.Type() == chi_mesh::CellType::POLYGON)
214 kappa = fmax(4.0*(D_avg/hm),0.25);
216 kappa = fmax(8.0*(D_avg/hm),0.25);
217
218 //========================= Assembly penalty terms
219 for (int fi=0; fi<num_face_dofs; fi++)
220 {
221 int i = fe_intgrl_values.FaceDofMapping(f,fi);
222 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
223
224 for (int fj=0; fj<num_face_dofs; fj++)
225 {
226 int j = fe_intgrl_values.FaceDofMapping(f,fj);
227 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
228
229 double aij = kappa* fe_intgrl_values.IntS_shapeI_shapeJ(f, i, j);
230
231 MatSetValue(A_, ir , jr, aij, ADD_VALUES);
232 VecSetValue(b_, ir, aij * dc_boundary.boundary_value, ADD_VALUES);
233 }//for fj
234 }//for fi
235
236 // -Di^- bj^- and
237 // -Dj^- bi^-
238 for (int i=0; i<fe_intgrl_values.NumNodes(); i++)
239 {
240 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
241
242 for (int j=0; j<fe_intgrl_values.NumNodes(); j++)
243 {
244 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
245
246 double gij =
247 n.Dot(fe_intgrl_values.IntS_shapeI_gradshapeJ(f, i, j) +
248 fe_intgrl_values.IntS_shapeI_gradshapeJ(f, j, i));
249 double aij = -0.5*D_avg*gij;
250
251 MatSetValue(A_, ir, jr, aij, ADD_VALUES);
252 VecSetValue(b_, ir, aij * dc_boundary.boundary_value, ADD_VALUES);
253 }//for j
254 }//for i
255 }//Dirichlet
256 else if (ir_boundary_type == BoundaryType::Robin)
257 {
258 auto robin_bndry =
259 (chi_diffusion::BoundaryRobin&)*boundaries_.at(ir_boundary_index);
260
261 for (int fi=0; fi<num_face_dofs; fi++)
262 {
263 int i = fe_intgrl_values.FaceDofMapping(f,fi);
264 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
265
266 for (int fj=0; fj<num_face_dofs; fj++)
267 {
268 int j = fe_intgrl_values.FaceDofMapping(f,fj);
269 int jr = pwl_sdm->MapDOF(cell, j, unknown_manager_, 0, component);
270
271 double aij = robin_bndry.a* fe_intgrl_values.IntS_shapeI_shapeJ(f, i, j);
272 aij /= robin_bndry.b;
273
274 MatSetValue(A_, ir , jr, aij, ADD_VALUES);
275 }//for fj
276
277 double bi = robin_bndry.f* fe_intgrl_values.IntS_shapeI(f, i);
278 bi /= robin_bndry.b;
279
280 VecSetValue(b_, ir, bi, ADD_VALUES);
281 }//for fi
282 }//robin
283 }
284 }//for f
285}
286
287//###################################################################
288/**Assembles PWLC matrix for polygon cells.*/
290 int component)
291{
292 auto pwl_sdm = std::static_pointer_cast<
294 const auto& fe_intgrl_values = unit_integrals_.at(cell.global_id_);
295
296 size_t num_nodes = fe_intgrl_values.NumNodes();
297
298 //====================================== Process material id
299 int mat_id = cell.material_id_;
300
301 std::vector<double> D(num_nodes, 1.0);
302 std::vector<double> q(num_nodes, 1.0);
303 std::vector<double> siga(num_nodes, 1.0);
304
305 GetMaterialProperties(cell, num_nodes, D, q, siga, component);
306
307 //========================================= Loop over DOFs
308 for (int i=0; i<num_nodes; i++)
309 {
310 int ir = pwl_sdm->MapDOF(cell, i, unknown_manager_, 0, component);
311
312 //====================== Develop rhs entry
313 double rhsvalue =0.0;
314 for (int j=0; j<num_nodes; j++)
315 rhsvalue += q[j]* fe_intgrl_values.IntV_shapeI_shapeJ(i, j);
316
317 //====================== Apply RHS entry
318 VecSetValue(b_, ir, rhsvalue, ADD_VALUES);
319
320 }//for i
321
322
323}
std::map< uint64_t, UnitIntegralContainer > unit_integrals_
static uint64_t MapCellLocalNodeIDFromGlobalID(const chi_mesh::Cell &cell, uint64_t node_global_id)
void GetMaterialProperties(const chi_mesh::Cell &cell, int cell_dofs, std::vector< double > &diffCoeff, std::vector< double > &sourceQ, std::vector< double > &sigmaa, int group=0, int moment=0)
Definition: general.cc:16
void PWLD_Assemble_b(const chi_mesh::Cell &cell, int component=0)
static unsigned int MapCellFace(const chi_mesh::Cell &cur_cell, const chi_mesh::Cell &adj_cell, unsigned int f)
std::map< uint64_t, chi_diffusion::Boundary * > boundaries_
chi_mesh::MeshContinuumPtr grid_ptr_
std::shared_ptr< chi_math::SpatialDiscretization > discretization_
chi_math::UnknownManager unknown_manager_
double HPerpendicular(const chi_mesh::Cell &cell, const UnitIntegralContainer &fe_intgrl_values, unsigned int f)
void PWLD_Assemble_A_and_b(const chi_mesh::Cell &cell, int component=0)
std::vector< CellFace > faces_
Definition: cell.h:82
CellType Type() const
Definition: cell.h:98
int material_id_
Definition: cell.h:79
uint64_t global_id_
Definition: cell.h:75
std::vector< uint64_t > vertex_ids_
Definition: cell.h:81
Vector3 Dot(const chi_mesh::TensorRank2Dim3 &that) const