Chi-Tech
SpatialDiscretization.cc
Go to the documentation of this file.
2
5
6#include "chi_log.h"
7
8namespace chi_math
9{
10
12 const chi_mesh::MeshContinuum& grid,
14 SDMType sdm_type)
15 : UNITARY_UNKNOWN_MANAGER({std::make_pair(chi_math::UnknownType::SCALAR, 0)}),
16 ref_grid_(grid),
17 coord_sys_type_(cs_type),
18 type_(sdm_type)
19{
20}
21
22const CellMapping&
24{
25 constexpr std::string_view fname = "chi_math::SpatialDiscretization::"
26 "GetCellMapping";
27 try
28 {
29 if (Grid().IsCellLocal(cell.global_id_))
30 return *cell_mappings_.at(cell.local_id_);
31 else
32 return *nb_cell_mappings_.at(cell.global_id_);
33 }
34 catch (const std::out_of_range& oor)
35 {
36 throw std::out_of_range(std::string(fname) +
37 ": Failed to obtain cell mapping.");
38 }
39}
40
42
44{
45 return ref_grid_;
46}
47
49{
50 return coord_sys_type_;
51}
52
54 const UnknownManager& unknown_manager) const
55{
56 unsigned int N = unknown_manager.GetTotalUnknownStructureSize();
57
58 return local_base_block_size_ * N;
59}
60
62 const UnknownManager& unknown_manager) const
63{
64 unsigned int N = unknown_manager.GetTotalUnknownStructureSize();
65
66 return globl_base_block_size_ * N;
67}
68
70 const UnknownManager& unknown_manager) const
71{
72 return GetNumLocalDOFs(unknown_manager) + GetNumGhostDOFs(unknown_manager);
73}
74
76{
77 return GetCellMapping(cell).NumNodes();
78}
79
80const std::vector<chi_mesh::Vector3>&
82{
83 return GetCellMapping(cell).GetNodeLocations();
84}
85
86std::pair<std::set<uint32_t>, std::set<uint32_t>>
88 const chi_mesh::Cell& cell) const
89{
90 const auto& cell_mapping = GetCellMapping(cell);
91 const size_t num_faces = cell.faces_.size();
92 const size_t num_nodes = cell_mapping.NumNodes();
93
94 //====================================== Determine which nodes are on the
95 // boundary
96 std::set<uint32_t> boundary_nodes;
97 for (size_t f = 0; f < num_faces; ++f)
98 {
99 if (not cell.faces_[f].has_neighbor_)
100 {
101 const size_t num_face_nodes = cell_mapping.NumFaceNodes(f);
102 for (size_t fi = 0; fi < num_face_nodes; ++fi)
103 boundary_nodes.insert(cell_mapping.MapFaceNode(f, fi));
104 }
105 } // for f
106
107 //====================================== Determine non-boundary nodes
108 std::set<uint32_t> internal_nodes;
109 for (size_t i = 0; i < num_nodes; ++i)
110 if (boundary_nodes.find(i) == boundary_nodes.end())
111 internal_nodes.insert(i);
112
113 return {internal_nodes, boundary_nodes};
114}
115
116// ###################################################################
117/**For each cell, for each face of that cell, for each node on that face,
118 * maps to which local node on the adjacent cell that node position corresponds.
119 *
120\param tolerance double. Tolerance to use to determine if two node locations are
121 equal. [Default: 1.0e-12]
122 *
123 * For example consider two adjacent quadrilaterals.
124
125\verbatim
126o--------o--------o o--------o
127|3 2|3 2| | 2 |
128| 101 | 102 | , face ids for both: |3 1|
129|0 1|0 1| | 0 |
130o--------o--------o o--------o
131internal face for cell 101 is face-1, ccw orientated
132--o
133 1|
134 |
135 0|
136--o
137internal face for cell 102 is face-3, ccw orientated
138o-
139|0
140|
141|1
142o-
143
144mapping[101][1][0] = 0
145mapping[101][1][1] = 3
146
147mapping[102][3][0] = 2
148mapping[102][3][1] = 1
149\endverbatim
150
151*/
152std::vector<std::vector<std::vector<int>>>
154 const double tolerance /*=1.0e-12*/) const
155{
156 typedef std::vector<int> FaceAdjMapping;
157 typedef std::vector<FaceAdjMapping> PerFaceAdjMapping;
158 typedef std::vector<PerFaceAdjMapping> CellAdjMapping;
159
160 const auto& grid = this->ref_grid_;
161
162 CellAdjMapping cell_adj_mapping;
163 for (const auto& cell : grid.local_cells)
164 {
165 const auto& cell_mapping = this->GetCellMapping(cell);
166 const auto& node_locations = cell_mapping.GetNodeLocations();
167 const size_t num_faces = cell.faces_.size();
168
169 PerFaceAdjMapping per_face_adj_mapping;
170
171 for (size_t f = 0; f < num_faces; ++f)
172 {
173 const auto& face = cell.faces_[f];
174 const auto num_face_nodes = cell_mapping.NumFaceNodes(f);
175 FaceAdjMapping face_adj_mapping(num_face_nodes, -1);
176 if (face.has_neighbor_)
177 {
178 const auto& adj_cell = grid.cells[face.neighbor_id_];
179 const auto& adj_cell_mapping = this->GetCellMapping(adj_cell);
180 const auto& adj_node_locations = adj_cell_mapping.GetNodeLocations();
181 const size_t adj_num_nodes = adj_cell_mapping.NumNodes();
182
183 for (size_t fi = 0; fi < num_face_nodes; ++fi)
184 {
185 const int i = cell_mapping.MapFaceNode(f, fi);
186 const auto& ivec3 = node_locations[i];
187
188 for (size_t ai = 0; ai < adj_num_nodes; ++ai)
189 {
190 const auto& aivec3 = adj_node_locations[ai];
191 if ((ivec3 - aivec3).NormSquare() < tolerance)
192 {
193 face_adj_mapping[fi] = static_cast<int>(ai);
194 break;
195 }
196 } // for ai
197 if (face_adj_mapping[fi] < 0)
198 throw std::logic_error("Face node mapping failed");
199 } // for fi
200 } // if internal face
201
202 per_face_adj_mapping.push_back(std::move(face_adj_mapping));
203 } // for face
204
205 cell_adj_mapping.push_back(std::move(per_face_adj_mapping));
206 } // for cell
207
208 return cell_adj_mapping;
209}
210
211// ###################################################################
212/**Copy part of vector A to vector B. Suppose vector A's entries are
213 * managed `chi_math::UnknownManager` A (`uk_manA`) and that the
214 * entries of the vector B are managed by `chi_math::UnknownManager` B
215 * (`uk_manB`). This function copies the entries associated with an unknown with
216 * id `uk_id_A` in `uk_manA` from vector A to vector B such that the entries
217 * in vector B are aligned with the entries of an unknown with id `uk_id_B` in
218 * `uk_manB`. All the components are copied.
219 *
220\param from_vector Vector to copy from.
221\param to_vector Vector to copy to.
222\param from_vec_uk_structure Unknown manager for vector A.
223\param from_vec_uk_id Unknown-id in unknown manager A.
224\param to_vec_uk_structure Unknown manager for vector B.
225\param to_vec_uk_id Unknown-id in unknown manager B.
226 */
228 const std::vector<double>& from_vector,
229 std::vector<double>& to_vector,
230 const UnknownManager& from_vec_uk_structure,
231 const unsigned int from_vec_uk_id,
232 const UnknownManager& to_vec_uk_structure,
233 const unsigned int to_vec_uk_id) const
234{
235 const std::string fname = "chi_math::SpatialDiscretization::"
236 "CopyVectorWithUnknownScope";
237 const auto& ukmanF = from_vec_uk_structure;
238 const auto& ukmanT = to_vec_uk_structure;
239 const auto& ukidF = from_vec_uk_id;
240 const auto& ukidT = to_vec_uk_id;
241 try
242 {
243 const auto& ukA = from_vec_uk_structure.unknowns_.at(from_vec_uk_id);
244 const auto& ukB = to_vec_uk_structure.unknowns_.at(to_vec_uk_id);
245
246 if (ukA.num_components_ != ukB.num_components_)
247 throw std::logic_error(fname + " Unknowns do not have the "
248 "same number of components");
249
250 const size_t num_comps = ukA.num_components_;
251
252 for (const auto& cell : ref_grid_.local_cells)
253 {
254 const auto& cell_mapping = this->GetCellMapping(cell);
255 const size_t num_nodes = cell_mapping.NumNodes();
256
257 for (size_t i = 0; i < num_nodes; ++i)
258 {
259 for (size_t c = 0; c < num_comps; ++c)
260 {
261 const int64_t fmap = MapDOFLocal(cell, i, ukmanF, ukidF, c);
262 const int64_t imap = MapDOFLocal(cell, i, ukmanT, ukidT, c);
263
264 to_vector[imap] = from_vector[fmap];
265 } // for component c
266 } // for node i
267 } // for cell
268 }
269 catch (const std::out_of_range& oor)
270 {
271 throw std::out_of_range(fname +
272 ": either from_vec_uk_id or to_vec_uk_id is "
273 "out of range for its respective "
274 "unknown manager.");
275 }
276}
277
278// ###################################################################
279/**Develops a localized view of a petsc vector.*/
281 Vec petsc_vector,
282 std::vector<double>& local_vector,
283 const chi_math::UnknownManager& unknown_manager) const
284{
285 size_t num_local_dofs = GetNumLocalDOFs(unknown_manager);
286
288 petsc_vector, local_vector, num_local_dofs);
289}
290
291// ###################################################################
292/**Develops a localized view of a petsc vector.*/
294 Vec petsc_vector,
295 std::vector<double>& local_vector,
296 const chi_math::UnknownManager& unknown_manager) const
297{
298 size_t num_local_dofs = GetNumLocalAndGhostDOFs(unknown_manager);
299
301 petsc_vector, local_vector, num_local_dofs);
302}
303
305 const chi_mesh::Vector3& point)
306{
307 return 1.0;
308}
309
311 const chi_mesh::Vector3& point)
312{
313 return 2.0 * M_PI * point[0];
314}
315
317 const chi_mesh::Vector3& point)
318{
319 const double r = point[2];
320 return 4.0 * M_PI * r * r;
321}
322
325{
326 switch (coord_sys_type_)
327 {
335 default:
336 ChiLogicalError("Coordinate system undefined.");
337 }
338}
339
340} // namespace chi_math
#define ChiLogicalError(message)
size_t NumNodes() const
Definition: CellMapping.cc:34
const std::vector< chi_mesh::Vector3 > & GetNodeLocations() const
Definition: CellMapping.cc:156
std::function< double(const chi_mesh::Vector3 &)> SpatialWeightFunction
size_t GetNumLocalAndGhostDOFs(const UnknownManager &unknown_manager) const
SpatialDiscretizationType Type() const
const CellMapping & GetCellMapping(const chi_mesh::Cell &cell) const
static double CylindricalRZSpatialWeightFunction(const chi_mesh::Vector3 &point)
static double Spherical1DSpatialWeightFunction(const chi_mesh::Vector3 &point)
static double CartesianSpatialWeightFunction(const chi_mesh::Vector3 &point)
std::vector< std::unique_ptr< CellMapping > > cell_mappings_
size_t GetNumGlobalDOFs(const UnknownManager &unknown_manager) const
CoordinateSystemType GetCoordinateSystemType() const
const chi_mesh::MeshContinuum & Grid() const
void CopyVectorWithUnknownScope(const std::vector< double > &from_vector, std::vector< double > &to_vector, const UnknownManager &from_vec_uk_structure, unsigned int from_vec_uk_id, const UnknownManager &to_vec_uk_structure, unsigned int to_vec_uk_id) const
std::map< uint64_t, std::shared_ptr< CellMapping > > nb_cell_mappings_
size_t GetNumLocalDOFs(const UnknownManager &unknown_manager) const
SpatialWeightFunction GetSpatialWeightingFunction() const
const SpatialDiscretizationType type_
std::pair< std::set< uint32_t >, std::set< uint32_t > > MakeCellInternalAndBndryNodeIDs(const chi_mesh::Cell &cell) const
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
virtual void LocalizePETScVectorWithGhosts(Vec petsc_vector, std::vector< double > &local_vector, const UnknownManager &unknown_manager) const
virtual void LocalizePETScVector(Vec petsc_vector, std::vector< double > &local_vector, const UnknownManager &unknown_manager) const
const std::vector< chi_mesh::Vector3 > & GetCellNodeLocations(const chi_mesh::Cell &cell) const
size_t GetCellNumNodes(const chi_mesh::Cell &cell) const
std::vector< std::vector< std::vector< int > > > MakeInternalFaceNodeMappings(double tolerance=1.0e-12) const
For each local cell, for each face, for each face-node, provides a mapping to the adjacent cell's nod...
virtual size_t GetNumGhostDOFs(const UnknownManager &unknown_manager) const =0
const CoordinateSystemType coord_sys_type_
SpatialDiscretization(const chi_mesh::MeshContinuum &grid, CoordinateSystemType cs_type, SDMType sdm_type)
const chi_mesh::MeshContinuum & ref_grid_
std::vector< Unknown > unknowns_
unsigned int GetTotalUnknownStructureSize() const
std::vector< CellFace > faces_
Definition: cell.h:82
uint64_t local_id_
Definition: cell.h:76
uint64_t global_id_
Definition: cell.h:75
LocalCellHandler local_cells
void CopyVecToSTLvectorWithGhosts(Vec x, std::vector< double > &data, size_t N, bool resize_STL=true)
void CopyVecToSTLvector(Vec x, std::vector< double > &data, size_t N, bool resize_STL=true)
SpatialDiscretizationType
Definition: chi_math.h:37
CoordinateSystemType
Definition: chi_math.h:29
struct _p_Vec * Vec