Chi-Tech
LagrangeBaseMapping.cc
Go to the documentation of this file.
2
4
6
7#include "chi_runtime.h"
8#include "chi_log.h"
9
11{
12
14 const chi_mesh::MeshContinuum& grid,
15 const chi_mesh::Cell& cell,
16 size_t num_nodes,
17 std::vector<std::vector<int>> face_node_mappings,
18 const Quadrature& volume_quadrature,
19 const Quadrature& surface_quadrature)
20 : CellMapping(grid,
21 cell,
22 num_nodes,
23 GetVertexLocations(grid, cell),
24 std::move(face_node_mappings),
25 &CellMapping::ComputeCellVolumeAndAreas),
26 volume_quadrature_(volume_quadrature),
27 surface_quadrature_(surface_quadrature)
28{
29}
30
31/** This section just determines a mapping of face dofs
32to cell dofs. This is pretty simple since we can
33just loop over each face dof then subsequently
34loop over cell dofs, if the face dof node index equals
35the cell dof node index then the mapping is assigned.
36
37This mapping is not used by any of the methods in
38 this class but is used by methods requiring the
39 surface integrals of the shape functions.*/
40std::vector<std::vector<int>>
42{
43 const size_t num_faces = cell.faces_.size();
44 std::vector<std::vector<int>> mappings;
45 mappings.reserve(num_faces);
46 for (auto& face : cell.faces_)
47 {
48 std::vector<int> face_dof_mapping;
49 face_dof_mapping.reserve(face.vertex_ids_.size());
50 for (uint64_t fvid : face.vertex_ids_)
51 {
52 int mapping = -1;
53 for (size_t ci = 0; ci < cell.vertex_ids_.size(); ci++)
54 {
55 if (fvid == cell.vertex_ids_[ci])
56 {
57 mapping = static_cast<int>(ci);
58 break;
59 }
60 } // for cell i
61 if (mapping < 0)
62 {
63 Chi::log.LogAllError() << "Unknown face mapping encountered. "
64 "pwl_polyhedron.h";
65 Chi::Exit(EXIT_FAILURE);
66 }
67 face_dof_mapping.push_back(mapping);
68 } // for face i
69
70 mappings.push_back(face_dof_mapping);
71 }
72 return mappings;
73}
74
75std::vector<chi_mesh::Vector3>
77 const chi_mesh::Cell& cell)
78{
79 std::vector<chi_mesh::Vector3> verts;
80 verts.reserve(cell.vertex_ids_.size());
81
82 for (const auto vid : cell.vertex_ids_)
83 verts.push_back(grid.vertices[vid]);
84
85 return verts;
86}
87
90{
91 WorldXYZToNaturalMappingHelper helper(*this, world_xyz);
92
93 auto nat_xyz = chi_math::NewtonIteration(helper, {0.0, 0.0, 0.0}, 20, 1.0e-8);
94
95 return {nat_xyz[0], nat_xyz[1], nat_xyz[2]};
96}
97
99 const chi_mesh::Vector3& xyz) const
100{
101 const auto natural_xyz = MapWorldXYZToNaturalXYZ(xyz);
102 return RefShape(i, natural_xyz);
103}
104
106 std::vector<double>& shape_values) const
107{
108 const auto natural_xyz = MapWorldXYZToNaturalXYZ(xyz);
109
110 shape_values.clear();
111 for (int i = 0; i < num_nodes_; ++i)
112 shape_values.push_back(RefShape(i, natural_xyz));
113}
114
117{
118 const auto natural_xyz = MapWorldXYZToNaturalXYZ(xyz);
119 return RefGradShape(i, natural_xyz);
120}
121
123 const chi_mesh::Vector3& xyz,
124 std::vector<chi_mesh::Vector3>& gradshape_values) const
125{
126 const auto natural_xyz = MapWorldXYZToNaturalXYZ(xyz);
127
128 gradshape_values.clear();
129 for (int i = 0; i < num_nodes_; ++i)
130 gradshape_values.push_back(RefGradShape(i, natural_xyz));
131}
132
135{
136 typedef std::vector<Vec3> VecVec3;
137 const size_t num_qpoints = volume_quadrature_.qpoints_.size();
138
139 //=================================== Declare necessary vars
140 std::vector<unsigned int> quadrature_point_indices;
141 VecVec3 qpoints_xyz;
142 std::vector<VecDbl> shape_value;
143 std::vector<VecVec3> shape_grad;
144 VecDbl JxW;
145
146 quadrature_point_indices.reserve(num_qpoints);
147 for (unsigned int qp = 0; qp < num_qpoints; ++qp)
148 quadrature_point_indices.push_back(qp);
149
150 JxW.assign(num_qpoints, 0.0);
151 shape_value.assign(num_nodes_, VecDbl(num_qpoints, 0.0));
152 shape_grad.assign(num_nodes_, VecVec3(num_qpoints));
153 qpoints_xyz.assign(num_qpoints, Vec3{0.0, 0.0, 0.0});
154
155 for (uint32_t qp : quadrature_point_indices)
156 {
157 const Vec3& qpoint = volume_quadrature_.qpoints_[qp];
158 const auto J = RefJacobian(qpoint);
159 const auto JT = chi_math::Transpose(J);
160 const auto JTinv = chi_math::Inverse(JT);
161 const double detJ = Determinant(J);
162
163 JxW[qp] = detJ * volume_quadrature_.weights_[qp];
164
165 for (size_t i = 0; i < num_nodes_; ++i)
166 {
167 const double ref_shape_i = RefShape(i, qpoint);
168 shape_value[i][qp] = ref_shape_i;
169 const Vec3 ref_shape_grad = RefGradShape(i, qpoint);
170 const VecDbl b = {ref_shape_grad.x, ref_shape_grad.y, ref_shape_grad.z};
171 const VecDbl JTInv_b = MatMul(JTinv, b);
172
173 shape_grad[i][qp] = {JTInv_b[0], JTInv_b[1], JTInv_b[2]};
174
175 const auto& node_xyz = node_locations_[i];
176
177 qpoints_xyz[qp] += ref_shape_i * node_xyz;
178 } // for i
179 } // for qp
180
181 return finite_element::VolumetricQuadraturePointData(quadrature_point_indices,
182 qpoints_xyz,
183 shape_value,
184 shape_grad,
185 JxW,
187 num_nodes_);
188}
189
190const Quadrature&
192{
193 return surface_quadrature_;
194}
195
198{
199 const auto& surface_quadrature = GetSurfaceQuadrature(face_index);
200
201 typedef std::vector<Vec3> VecVec3;
202 const size_t num_qpoints = surface_quadrature.qpoints_.size();
203
204 //=================================== Declare necessary vars
205 std::vector<unsigned int> quadrature_point_indices;
206 VecVec3 qpoints_xyz;
207 std::vector<VecDbl> shape_value;
208 std::vector<VecVec3> shape_grad;
209 VecDbl JxW;
210 VecVec3 normals;
211
212 quadrature_point_indices.reserve(num_qpoints);
213 for (unsigned int qp = 0; qp < num_qpoints; ++qp)
214 quadrature_point_indices.push_back(qp);
215
216 JxW.assign(num_qpoints, 0.0);
217 normals.assign(num_qpoints, Vec3{0.0, 0.0, 0.0});
218 shape_value.assign(num_nodes_, VecDbl(num_qpoints, 0.0));
219 shape_grad.assign(num_nodes_, VecVec3(num_qpoints));
220 qpoints_xyz.assign(num_qpoints, Vec3{0.0, 0.0, 0.0});
221
222 const size_t f = face_index;
223 for (uint32_t qp : quadrature_point_indices)
224 {
225 const Vec3& qpoint_face = surface_quadrature.qpoints_[qp];
226 const auto qpoint = FaceToElementQPointConversion(f, qpoint_face);
227
228 const auto J = RefJacobian(qpoint);
229 const auto JT = chi_math::Transpose(J);
230 const auto JTinv = chi_math::Inverse(JT);
231 const auto [detJ, qp_normal] =
233
234 normals[qp] = qp_normal;
235
236 JxW[qp] = detJ * surface_quadrature.weights_[qp];
237
238 for (size_t i = 0; i < num_nodes_; ++i)
239 {
240 const double ref_shape_i = RefShape(i, qpoint);
241 shape_value[i][qp] = ref_shape_i;
242 const Vec3 ref_shape_grad = RefGradShape(i, qpoint);
243 const VecDbl b = {ref_shape_grad.x, ref_shape_grad.y, ref_shape_grad.z};
244 const VecDbl JTInv_b = MatMul(JTinv, b);
245
246 shape_grad[i][qp] = {JTInv_b[0], JTInv_b[1], JTInv_b[2]};
247
248 const auto& node_xyz = node_locations_[i];
249
250 qpoints_xyz[qp] += ref_shape_i * node_xyz;
251 } // for i
252 } // for qp
253
254 return finite_element::SurfaceQuadraturePointData(quadrature_point_indices,
255 qpoints_xyz,
256 shape_value,
257 shape_grad,
258 JxW,
259 normals,
261 num_nodes_);
262}
263
264std::pair<double, LagrangeBaseMapping::Vec3>
266 const Vec3& qpoint_face) const
267{
268 ChiLogicalError("Method not implemented");
269}
270
272 const LagrangeBaseMapping& cell_mapping, const Vec3& world_x)
273 : cell_mapping_(cell_mapping), world_x_(world_x)
274{
275 const auto& cell = cell_mapping.ReferenceCell();
276 const auto cell_type = cell.Type();
277 if (cell_type == chi_mesh::CellType::SLAB) dimension_ = 1;
278 else if (cell_type == chi_mesh::CellType::POLYGON)
279 dimension_ = 2;
280 else if (cell_type == chi_mesh::CellType::POLYHEDRON)
281 dimension_ = 3;
282 else
283 ChiLogicalError("Unsupported cell type.");
284}
285
287{
288 const size_t num_nodes = cell_mapping_.NumNodes();
289 const auto& node_x = cell_mapping_.GetNodeLocations();
290
291 Vec3 result_vec3 = world_x_;
292 if (dimension_ == 1)
293 for (uint32_t i = 0; i < num_nodes; ++i)
294 {
295 const double shape_i_val = cell_mapping_.RefShape(i, {x[0], x[1], x[2]});
296 result_vec3 -= Vec3(0.0, 0.0, shape_i_val * node_x[i].z);
297 }
298 else if (dimension_ == 2)
299 for (uint32_t i = 0; i < num_nodes; ++i)
300 {
301 const double shape_i_val = cell_mapping_.RefShape(i, {x[0], x[1], x[2]});
302 result_vec3 -=
303 Vec3(shape_i_val * node_x[i].x, shape_i_val * node_x[i].y, 0.0);
304 }
305 else if (dimension_ == 3)
306 for (uint32_t i = 0; i < num_nodes; ++i)
307 result_vec3 -= cell_mapping_.RefShape(i, {x[0], x[1], x[2]}) * node_x[i];
308
309 return {result_vec3.x, result_vec3.y, result_vec3.z};
310}
311
313{
314 return cell_mapping_.RefJacobian({x[0], x[1], x[2]});
315}
316
317} // namespace chi_math::cell_mapping
#define ChiLogicalError(message)
std::vector< VecDbl > MatDbl
Definition: chi_math.h:13
std::vector< double > VecDbl
Definition: chi_math.h:12
static void Exit(int error_code)
Definition: chi_runtime.cc:342
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream LogAllError()
Definition: chi_log.h:239
const std::vector< std::vector< int > > face_node_mappings_
Definition: CellMapping.h:130
size_t NumNodes() const
Definition: CellMapping.cc:34
const std::vector< chi_mesh::Vector3 > node_locations_
Definition: CellMapping.h:121
const size_t num_nodes_
Definition: CellMapping.h:120
const chi_mesh::Cell & ReferenceCell() const
Definition: CellMapping.cc:27
const std::vector< chi_mesh::Vector3 > & GetNodeLocations() const
Definition: CellMapping.cc:156
std::vector< chi_math::QuadraturePointXYZ > qpoints_
Definition: quadrature.h:37
std::vector< double > weights_
Definition: quadrature.h:38
virtual Vec3 RefGradShape(uint32_t i, const Vec3 &qpoint) const =0
static std::vector< chi_mesh::Vector3 > GetVertexLocations(const chi_mesh::MeshContinuum &grid, const chi_mesh::Cell &cell)
virtual double RefShape(uint32_t i, const Vec3 &qpoint) const =0
void GradShapeValues(const chi_mesh::Vector3 &xyz, std::vector< chi_mesh::Vector3 > &gradshape_values) const override
LagrangeBaseMapping(const chi_mesh::MeshContinuum &grid, const chi_mesh::Cell &cell, size_t num_nodes, std::vector< std::vector< int > > face_node_mappings, const Quadrature &volume_quadrature, const Quadrature &surface_quadrature)
finite_element::SurfaceQuadraturePointData MakeSurfaceQuadraturePointData(size_t face_index) const override
virtual const Quadrature & GetSurfaceQuadrature(size_t face_index) const
virtual std::pair< double, Vec3 > RefFaceJacobianDeterminantAndNormal(size_t face_index, const Vec3 &qpoint_face) const
static std::vector< std::vector< int > > MakeFaceNodeMapping(const chi_mesh::Cell &cell)
finite_element::VolumetricQuadraturePointData MakeVolumetricQuadraturePointData() const override
virtual MatDbl RefJacobian(const Vec3 &qpoint) const =0
void ShapeValues(const chi_mesh::Vector3 &xyz, std::vector< double > &shape_values) const override
double ShapeValue(int i, const chi_mesh::Vector3 &xyz) const override
chi_mesh::Vector3 GradShapeValue(int i, const chi_mesh::Vector3 &xyz) const override
virtual Vec3 FaceToElementQPointConversion(size_t face_index, const Vec3 &qpoint_face) const =0
Vec3 MapWorldXYZToNaturalXYZ(const Vec3 &world_xyz) const
WorldXYZToNaturalMappingHelper(const LagrangeBaseMapping &cell_mapping, const Vec3 &world_x)
std::vector< CellFace > faces_
Definition: cell.h:82
CellType Type() const
Definition: cell.h:98
std::vector< uint64_t > vertex_ids_
Definition: cell.h:81
std::vector< chi_mesh::Vector3 > VecVec3
MatDbl Inverse(const MatDbl &A)
double Determinant(const MatDbl &A)
VecDbl NewtonIteration(const NonLinearFunction &non_linear_function, const VecDbl &x_0, unsigned int max_iters, double epsilon, bool verbose=false)
MatDbl Transpose(const MatDbl &A)
MatDbl MatMul(const MatDbl &A, const double c)
double x
Element-0.
double y
Element-1.
double z
Element-2.