Chi-Tech
assemble_pwlc.cc
Go to the documentation of this file.
1#include "diffusion_solver.h"
2
4
5// ###################################################################
6/**Assembles PWLC matrix for general cells.*/
8 int group)
9{
10 auto pwl_sdm = std::static_pointer_cast<
12 const auto& fe_intgrl_values = unit_integrals_.at(cell.global_id_);
13
14 size_t num_nodes = fe_intgrl_values.NumNodes();
15
16 //======================================== Process material id
17 std::vector<double> D(num_nodes, 1.0);
18 std::vector<double> q(num_nodes, 1.0);
19 std::vector<double> siga(num_nodes, 0.0);
20
21 GetMaterialProperties(cell, num_nodes, D, q, siga, group);
22
23 //======================================== Init cell matrix info
24 typedef std::vector<double> Row;
25 typedef std::vector<Row> Matrix;
26
27 Matrix cell_matrix;
28 std::vector<double> cell_rhs;
29
30 cell_matrix.resize(num_nodes, Row(num_nodes, 0.0));
31 cell_rhs.resize(num_nodes, 0.0);
32
33 std::vector<int64_t> dof_global_row_ind(num_nodes, -1);
34 std::vector<int64_t> dof_global_col_ind(num_nodes, -1);
35
36 //========================================= Loop over DOFs
37 for (int i=0; i<num_nodes; i++)
38 {
39 dof_global_row_ind[i] = pwl_sdm->MapDOF(cell,i);
40
41 for (int j=0; j<num_nodes; j++)
42 {
43 double mat_entry =
44 D[j]* fe_intgrl_values.IntV_gradShapeI_gradShapeJ(i, j) +
45 siga[j]* fe_intgrl_values.IntV_shapeI_shapeJ(i, j);
46
47 cell_matrix[i][j] = mat_entry;
48 }//for j
49
50 //====================== Develop RHS entry
51 cell_rhs[i] = q[i]* fe_intgrl_values.IntV_shapeI(i);
52 }//for i
53 dof_global_col_ind = dof_global_row_ind;
54
55 //======================================== Apply Dirichlet,Vacuum, Neumann and
56 // Robin BCs
57 // Dirichlets are just collected
58 std::vector<int> dirichlet_count(num_nodes, 0);
59 std::vector<double> dirichlet_value(num_nodes, 0.0);
60 for (int f=0; f<cell.faces_.size(); f++)
61 {
62 if (not cell.faces_[f].has_neighbor_)
63 {
64 uint64_t ir_boundary_index = cell.faces_[f].neighbor_id_;
65 auto ir_boundary_type = boundaries_.at(ir_boundary_index)->type_;
66
67 if (ir_boundary_type == BoundaryType::Dirichlet)
68 {
69 auto& dirichlet_bndry =
70 (chi_diffusion::BoundaryDirichlet&)*boundaries_.at(ir_boundary_index);
71
72 int num_face_dofs = cell.faces_[f].vertex_ids_.size();
73 for (int fi=0; fi<num_face_dofs; fi++)
74 {
75 int i = fe_intgrl_values.FaceDofMapping(f,fi);
76 dirichlet_count[i] += 1;
77 dirichlet_value[i] += dirichlet_bndry.boundary_value;
78 }
79 }
80
81 if (ir_boundary_type == BoundaryType::Robin)
82 {
83 auto& robin_bndry =
84 (chi_diffusion::BoundaryRobin&)*boundaries_.at(ir_boundary_index);
85
86 std::cout << robin_bndry.a << " " << robin_bndry.b << " " << robin_bndry.f << std::endl;
87
88 int num_face_dofs = cell.faces_[f].vertex_ids_.size();
89 for (int fi=0; fi<num_face_dofs; fi++)
90 {
91 int i = fe_intgrl_values.FaceDofMapping(f,fi);
92
93 for (int fj=0; fj<num_face_dofs; fj++)
94 {
95 int j = fe_intgrl_values.FaceDofMapping(f,fj);
96
97 double aij = robin_bndry.a* fe_intgrl_values.IntS_shapeI_shapeJ(f, i, j);
98 aij /= robin_bndry.b;
99
100 cell_matrix[i][j] += aij;
101 }//for fj
102
103 double aii = robin_bndry.f* fe_intgrl_values.IntS_shapeI(f, i);
104 aii /= robin_bndry.b;
105
106 cell_matrix[i][i] += aii;
107 }//for fi
108 }//if robin
109
110 }//if boundary
111
112 }//for face
113
114 //======================================== Apply dirichlet BCs
115 //Compute average dirichlet value
116 for (int i=0; i<num_nodes; ++i)
117 dirichlet_value[i] /= (dirichlet_count[i] > 0)? dirichlet_count[i] : 1;
118
119 for (int i=0; i<num_nodes; ++i)
120 {
121 if (dirichlet_count[i] > 0)
122 {
123 cell_matrix[i].clear();
124 cell_matrix[i] = std::vector<double>(num_nodes, 0.0);
125 cell_matrix[i][i] = 1.0;
126 int ir = dof_global_col_ind[i];
127 MatSetValue(A_, ir, ir, 1.0, ADD_VALUES);
128 dof_global_col_ind[i] = -1;
129 cell_rhs[i] = dirichlet_value[i];
130 }
131 else
132 {
133 for (int j=0; j<num_nodes; ++j)
134 {
135 if (dirichlet_count[j] > 0)
136 {
137 cell_rhs[i] -= cell_matrix[i][j]*dirichlet_value[j];
138 cell_matrix[i][j] = 0.0;
139 }
140 }
141 }
142 }
143
144 //======================================== Make contiguous copy of matrix
145 std::vector<double> cell_matrix_cont(num_nodes * num_nodes, 0.0);
146 int n = 0;
147 for (int i=0; i<num_nodes; ++i)
148 for (int j=0; j<num_nodes; ++j)
149 cell_matrix_cont[n++] = cell_matrix[i][j];
150
151 //======================================== Add to global
152 MatSetValues(A_,
153 num_nodes, dof_global_row_ind.data(),
154 num_nodes, dof_global_col_ind.data(),
155 cell_matrix_cont.data(), ADD_VALUES);
156
157 VecSetValues(b_,
158 num_nodes, dof_global_row_ind.data(),
159 cell_rhs.data(), ADD_VALUES);
160
161 VecSetValues(x_,
162 num_nodes,
163 dof_global_row_ind.data(),
164 dirichlet_value.data(), INSERT_VALUES);
165
166}
std::map< uint64_t, UnitIntegralContainer > unit_integrals_
void CFEM_Assemble_A_and_b(chi_mesh::Cell &cell, int group=0)
Definition: assemble_pwlc.cc:7
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
std::map< uint64_t, chi_diffusion::Boundary * > boundaries_
std::shared_ptr< chi_math::SpatialDiscretization > discretization_
std::vector< CellFace > faces_
Definition: cell.h:82
uint64_t global_id_
Definition: cell.h:75