deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
grid_tools_nontemplates.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2020 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#include <deal.II/base/point.h>
14
16
18
19#include <vector>
20
21// GridTools functions that are template specializations (i.e., only compiled
22// once without expand_instantiations)
23
25
26
27namespace GridTools
28{
29 template <>
30 double
31 cell_measure<1>(const std::vector<Point<1>> &all_vertices,
33 {
35
36 return all_vertices[vertex_indices[1]][0] -
37 all_vertices[vertex_indices[0]][0];
38 }
39
40
41
42 template <>
43 double
44 cell_measure<2>(const std::vector<Point<2>> &all_vertices,
46 {
47 if (vertex_indices.size() == 3) // triangle
48 {
49 const double x[3] = {all_vertices[vertex_indices[0]][0],
50 all_vertices[vertex_indices[1]][0],
51 all_vertices[vertex_indices[2]][0]};
52
53 const double y[3] = {all_vertices[vertex_indices[0]][1],
54 all_vertices[vertex_indices[1]][1],
55 all_vertices[vertex_indices[2]][1]};
56
57 return 0.5 *
58 ((x[0] - x[2]) * (y[1] - y[0]) - (x[1] - x[0]) * (y[0] - y[2]));
59 }
60
62
63 /*
64 Get the computation of the measure by this little Maple script. We
65 use the blinear mapping of the unit quad to the real quad. However,
66 every transformation mapping the unit faces to straight lines should
67 do.
68
69 Remember that the area of the quad is given by
70 \int_K 1 dx dy = \int_{\hat K} |det J| d(xi) d(eta)
71
72 # x and y are arrays holding the x- and y-values of the four vertices
73 # of this cell in real space.
74 x := array(0..3);
75 y := array(0..3);
76 z := array(0..3);
77 tphi[0] := (1-xi)*(1-eta):
78 tphi[1] := xi*(1-eta):
79 tphi[2] := (1-xi)*eta:
80 tphi[3] := xi*eta:
81 x_real := sum(x[s]*tphi[s], s=0..3):
82 y_real := sum(y[s]*tphi[s], s=0..3):
83 z_real := sum(z[s]*tphi[s], s=0..3):
84
85 Jxi := <diff(x_real,xi) | diff(y_real,xi) | diff(z_real,xi)>;
86 Jeta := <diff(x_real,eta)| diff(y_real,eta)| diff(z_real,eta)>;
87 with(VectorCalculus):
88 J := CrossProduct(Jxi, Jeta);
89 detJ := sqrt(J[1]^2 + J[2]^2 +J[3]^2);
90
91 # measure := evalf (Int (Int (detJ, xi=0..1, method = _NCrule ) ,
92 eta=0..1, method = _NCrule ) ): # readlib(C):
93
94 # C(measure, optimized);
95
96 additional optimization: divide by 2 only one time
97 */
98
99 const double x[4] = {all_vertices[vertex_indices[0]][0],
100 all_vertices[vertex_indices[1]][0],
101 all_vertices[vertex_indices[2]][0],
102 all_vertices[vertex_indices[3]][0]};
103
104 const double y[4] = {all_vertices[vertex_indices[0]][1],
105 all_vertices[vertex_indices[1]][1],
106 all_vertices[vertex_indices[2]][1],
107 all_vertices[vertex_indices[3]][1]};
108
109 return (-x[1] * y[0] + x[1] * y[3] + y[0] * x[2] + x[0] * y[1] -
110 x[0] * y[2] - y[1] * x[3] - x[2] * y[3] + x[3] * y[2]) /
111 2;
112 }
113
114
115
116 template <>
117 double
118 cell_measure<3>(const std::vector<Point<3>> &all_vertices,
120 {
121 if (vertex_indices.size() == 4) // tetrahedron
122 {
123 const auto &a = all_vertices[vertex_indices[0]];
124 const auto &b = all_vertices[vertex_indices[1]];
125 const auto &c = all_vertices[vertex_indices[2]];
126 const auto &d = all_vertices[vertex_indices[3]];
127
128 return (1.0 / 6.0) * (d - a) * cross_product_3d(b - a, c - a);
129 }
130 else if (vertex_indices.size() == 5) // pyramid
131 {
132 // This remarkably simple formula comes from Equation 4 of
133 // "Calculation of the volume of a general hexahedron for flow
134 // predictions", Davies and Salmond, AIAA Journal vol. 23 no. 6.
135 const auto &x0 = all_vertices[vertex_indices[0]];
136 const auto &x1 = all_vertices[vertex_indices[1]];
137 const auto &x2 = all_vertices[vertex_indices[2]];
138 const auto &x3 = all_vertices[vertex_indices[3]];
139 const auto &x4 = all_vertices[vertex_indices[4]];
140
141 const auto v01 = x1 - x0;
142 const auto v02 = x2 - x0;
143 const auto v03 = x3 - x0;
144 const auto v04 = x4 - x0;
145 const auto v21 = x2 - x1;
146
147 // doing high - low consistently puts us off by -1 from the original
148 // paper in the first term
149 return -v04 * cross_product_3d(v21, v03) / 6.0 +
150 v03 * cross_product_3d(v01, v02) / 12.0;
151 }
152 else if (vertex_indices.size() == 6) // wedge
153 {
154 /* Script used to generate volume code:
155
156 #!/usr/bin/env python
157 # coding: utf-8
158 import sympy as sp
159 from sympy.simplify.cse_main import cse
160 n_vertices = 6
161 xs = list(sp.symbols(" ".join(["x{}".format(i)
162 for i in range(n_vertices)])))
163 ys = list(sp.symbols(" ".join(["y{}".format(i)
164 for i in range(n_vertices)])))
165 zs = list(sp.symbols(" ".join(["z{}".format(i)
166 for i in range(n_vertices)])))
167 xi, eta, zeta = sp.symbols("xi eta zeta")
168 tphi = [(1 - xi - eta)*(1 - zeta),
169 (xi)*(1 - zeta),
170 (eta)*(1 - zeta),
171 (1 - xi - eta)*(zeta),
172 (xi)*(zeta),
173 (eta)*(zeta)]
174 x_real = sum(xs[i]*tphi[i] for i in range(n_vertices))
175 y_real = sum(ys[i]*tphi[i] for i in range(n_vertices))
176 z_real = sum(zs[i]*tphi[i] for i in range(n_vertices))
177 J = sp.Matrix([[var.diff(v) for v in [xi, eta, zeta]]
178 for var in [x_real, y_real, z_real]])
179 detJ = J.det()
180 detJ2 = detJ.expand().collect(zeta).collect(eta).collect(xi)
181 for x in xs:
182 detJ2 = detJ2.collect(x)
183 for y in ys:
184 detJ2 = detJ2.collect(y)
185 for z in zs:
186 detJ2 = detJ2.collect(z)
187 measure = sp.integrate(sp.integrate(
188 sp.integrate(detJ2, (eta, 0, 1 - xi)),
189 (xi, 0, 1)), (zeta, 0, 1))
190 measure2 = measure
191 for vs in [xs, ys, zs]:
192 for v in vs:
193 measure2 = measure2.collect(v)
194
195 pairs, expression = cse(measure2)
196 for vertex_no in range(n_vertices):
197 for (coordinate, index) in [('x', 0), ('y', 1), ('z', 2)]:
198 print(
199 "const double {}{} = all_vertices[vertex_indices[{}]][{}];"
200 .format(coordinate, vertex_no, vertex_no, index))
201
202 for pair in pairs:
203 print("const double " + sp.ccode(pair[0]) + " = "
204 + sp.ccode(pair[1]) + ";")
205 print("const double result = " + sp.ccode(expression[0]) + ";")
206 print("return result;")
207 */
208 const double x0 = all_vertices[vertex_indices[0]][0];
209 const double y0 = all_vertices[vertex_indices[0]][1];
210 const double z0 = all_vertices[vertex_indices[0]][2];
211 const double x1 = all_vertices[vertex_indices[1]][0];
212 const double y1 = all_vertices[vertex_indices[1]][1];
213 const double z1 = all_vertices[vertex_indices[1]][2];
214 const double x2 = all_vertices[vertex_indices[2]][0];
215 const double y2 = all_vertices[vertex_indices[2]][1];
216 const double z2 = all_vertices[vertex_indices[2]][2];
217 const double x3 = all_vertices[vertex_indices[3]][0];
218 const double y3 = all_vertices[vertex_indices[3]][1];
219 const double z3 = all_vertices[vertex_indices[3]][2];
220 const double x4 = all_vertices[vertex_indices[4]][0];
221 const double y4 = all_vertices[vertex_indices[4]][1];
222 const double z4 = all_vertices[vertex_indices[4]][2];
223 const double x5 = all_vertices[vertex_indices[5]][0];
224 const double y5 = all_vertices[vertex_indices[5]][1];
225 const double z5 = all_vertices[vertex_indices[5]][2];
226 const double x6 = (1.0 / 12.0) * z1;
227 const double x7 = -x6;
228 const double x8 = (1.0 / 12.0) * z3;
229 const double x9 = x7 + x8;
230 const double x10 = (1.0 / 12.0) * z2;
231 const double x11 = -x8;
232 const double x12 = x10 + x11;
233 const double x13 = (1.0 / 6.0) * z2;
234 const double x14 = (1.0 / 12.0) * z4;
235 const double x15 = (1.0 / 6.0) * z1;
236 const double x16 = (1.0 / 12.0) * z5;
237 const double x17 = -x16;
238 const double x18 = x16 + x7;
239 const double x19 = -x14;
240 const double x20 = x10 + x19;
241 const double x21 = (1.0 / 12.0) * z0;
242 const double x22 = x19 + x21;
243 const double x23 = -x10;
244 const double x24 = x14 + x23;
245 const double x25 = (1.0 / 6.0) * z0;
246 const double x26 = x17 + x21;
247 const double x27 = x23 + x8;
248 const double x28 = -x21;
249 const double x29 = x16 + x28;
250 const double x30 = x17 + x6;
251 const double x31 = x14 + x28;
252 const double x32 = x11 + x6;
253 const double x33 = (1.0 / 6.0) * z5;
254 const double x34 = (1.0 / 6.0) * z4;
255 const double x35 = (1.0 / 6.0) * z3;
256 const double result =
257 x0 * (x12 * y5 + x9 * y4 + y1 * (-x13 + x14 + x8) +
258 y2 * (x11 + x15 + x17) + y3 * (x18 + x20)) +
259 x1 * (x22 * y3 + x24 * y5 + y0 * (x11 + x13 + x19) +
260 y2 * (x14 + x16 - x25) + y4 * (x26 + x27)) +
261 x2 * (x29 * y3 + x30 * y4 + y0 * (-x15 + x16 + x8) +
262 y1 * (x17 + x19 + x25) + y5 * (x31 + x32)) +
263 x3 * (x26 * y2 + x31 * y1 + y0 * (x24 + x30) + y4 * (x28 + x33 + x7) +
264 y5 * (x10 + x21 - x34)) +
265 x4 * (x18 * y2 + x32 * y0 + y1 * (x12 + x29) + y3 * (x21 - x33 + x6) +
266 y5 * (x23 + x35 + x7)) +
267 x5 * (x20 * y1 + x27 * y0 + y2 * (x22 + x9) + y3 * (x23 + x28 + x34) +
268 y4 * (x10 - x35 + x6));
269 return result;
270 }
271
273
274 const double x[8] = {all_vertices[vertex_indices[0]][0],
275 all_vertices[vertex_indices[1]][0],
276 all_vertices[vertex_indices[2]][0],
277 all_vertices[vertex_indices[3]][0],
278 all_vertices[vertex_indices[4]][0],
279 all_vertices[vertex_indices[5]][0],
280 all_vertices[vertex_indices[6]][0],
281 all_vertices[vertex_indices[7]][0]};
282 const double y[8] = {all_vertices[vertex_indices[0]][1],
283 all_vertices[vertex_indices[1]][1],
284 all_vertices[vertex_indices[2]][1],
285 all_vertices[vertex_indices[3]][1],
286 all_vertices[vertex_indices[4]][1],
287 all_vertices[vertex_indices[5]][1],
288 all_vertices[vertex_indices[6]][1],
289 all_vertices[vertex_indices[7]][1]};
290 const double z[8] = {all_vertices[vertex_indices[0]][2],
291 all_vertices[vertex_indices[1]][2],
292 all_vertices[vertex_indices[2]][2],
293 all_vertices[vertex_indices[3]][2],
294 all_vertices[vertex_indices[4]][2],
295 all_vertices[vertex_indices[5]][2],
296 all_vertices[vertex_indices[6]][2],
297 all_vertices[vertex_indices[7]][2]};
298
299 /*
300 This is the same Maple script as in the barycenter method above
301 except of that here the shape functions tphi[0]-tphi[7] are ordered
302 according to the lexicographic numbering.
303
304 x := array(0..7):
305 y := array(0..7):
306 z := array(0..7):
307 tphi[0] := (1-xi)*(1-eta)*(1-zeta):
308 tphi[1] := xi*(1-eta)*(1-zeta):
309 tphi[2] := (1-xi)* eta*(1-zeta):
310 tphi[3] := xi* eta*(1-zeta):
311 tphi[4] := (1-xi)*(1-eta)*zeta:
312 tphi[5] := xi*(1-eta)*zeta:
313 tphi[6] := (1-xi)* eta*zeta:
314 tphi[7] := xi* eta*zeta:
315 x_real := sum(x[s]*tphi[s], s=0..7):
316 y_real := sum(y[s]*tphi[s], s=0..7):
317 z_real := sum(z[s]*tphi[s], s=0..7):
318 with (linalg):
319 J := matrix(3,3, [[diff(x_real, xi), diff(x_real, eta), diff(x_real,
320 zeta)], [diff(y_real, xi), diff(y_real, eta), diff(y_real, zeta)],
321 [diff(z_real, xi), diff(z_real, eta), diff(z_real, zeta)]]):
322 detJ := det (J):
323
324 measure := simplify ( int ( int ( int (detJ, xi=0..1), eta=0..1),
325 zeta=0..1)):
326
327 readlib(C):
328
329 C(measure, optimized);
330
331 The C code produced by this maple script is further optimized by
332 hand. In particular, division by 12 is performed only once, not
333 hundred of times.
334 */
335
336 const double t3 = y[3] * x[2];
337 const double t5 = z[1] * x[5];
338 const double t9 = z[3] * x[2];
339 const double t11 = x[1] * y[0];
340 const double t14 = x[4] * y[0];
341 const double t18 = x[5] * y[7];
342 const double t20 = y[1] * x[3];
343 const double t22 = y[5] * x[4];
344 const double t26 = z[7] * x[6];
345 const double t28 = x[0] * y[4];
346 const double t34 =
347 z[3] * x[1] * y[2] + t3 * z[1] - t5 * y[7] + y[7] * x[4] * z[6] +
348 t9 * y[6] - t11 * z[4] - t5 * y[3] - t14 * z[2] + z[1] * x[4] * y[0] -
349 t18 * z[3] + t20 * z[0] - t22 * z[0] - y[0] * x[5] * z[4] - t26 * y[3] +
350 t28 * z[2] - t9 * y[1] - y[1] * x[4] * z[0] - t11 * z[5];
351 const double t37 = y[1] * x[0];
352 const double t44 = x[1] * y[5];
353 const double t46 = z[1] * x[0];
354 const double t49 = x[0] * y[2];
355 const double t52 = y[5] * x[7];
356 const double t54 = x[3] * y[7];
357 const double t56 = x[2] * z[0];
358 const double t58 = x[3] * y[2];
359 const double t64 = -x[6] * y[4] * z[2] - t37 * z[2] + t18 * z[6] -
360 x[3] * y[6] * z[2] + t11 * z[2] + t5 * y[0] +
361 t44 * z[4] - t46 * y[4] - t20 * z[7] - t49 * z[6] -
362 t22 * z[1] + t52 * z[3] - t54 * z[2] - t56 * y[4] -
363 t58 * z[0] + y[1] * x[2] * z[0] + t9 * y[7] + t37 * z[4];
364 const double t66 = x[1] * y[7];
365 const double t68 = y[0] * x[6];
366 const double t70 = x[7] * y[6];
367 const double t73 = z[5] * x[4];
368 const double t76 = x[6] * y[7];
369 const double t90 = x[4] * z[0];
370 const double t92 = x[1] * y[3];
371 const double t95 = -t66 * z[3] - t68 * z[2] - t70 * z[2] + t26 * y[5] -
372 t73 * y[6] - t14 * z[6] + t76 * z[2] - t3 * z[6] +
373 x[6] * y[2] * z[4] - z[3] * x[6] * y[2] + t26 * y[4] -
374 t44 * z[3] - x[1] * y[2] * z[0] + x[5] * y[6] * z[4] +
375 t54 * z[5] + t90 * y[2] - t92 * z[2] + t46 * y[2];
376 const double t102 = x[2] * y[0];
377 const double t107 = y[3] * x[7];
378 const double t114 = x[0] * y[6];
379 const double t125 =
380 y[0] * x[3] * z[2] - z[7] * x[5] * y[6] - x[2] * y[6] * z[4] +
381 t102 * z[6] - t52 * z[6] + x[2] * y[4] * z[6] - t107 * z[5] - t54 * z[6] +
382 t58 * z[6] - x[7] * y[4] * z[6] + t37 * z[5] - t114 * z[4] + t102 * z[4] -
383 z[1] * x[2] * y[0] + t28 * z[6] - y[5] * x[6] * z[4] -
384 z[5] * x[1] * y[4] - t73 * y[7];
385 const double t129 = z[0] * x[6];
386 const double t133 = y[1] * x[7];
387 const double t145 = y[1] * x[5];
388 const double t156 = t90 * y[6] - t129 * y[4] + z[7] * x[2] * y[6] -
389 t133 * z[5] + x[5] * y[3] * z[7] - t26 * y[2] -
390 t70 * z[3] + t46 * y[3] + z[5] * x[7] * y[4] +
391 z[7] * x[3] * y[6] - t49 * z[4] + t145 * z[7] -
392 x[2] * y[7] * z[6] + t70 * z[5] + t66 * z[5] -
393 z[7] * x[4] * y[6] + t18 * z[4] + x[1] * y[4] * z[0];
394 const double t160 = x[5] * y[4];
395 const double t165 = z[1] * x[7];
396 const double t178 = z[1] * x[3];
397 const double t181 =
398 t107 * z[6] + t22 * z[7] + t76 * z[3] + t160 * z[1] - x[4] * y[2] * z[6] +
399 t70 * z[4] + t165 * y[5] + x[7] * y[2] * z[6] - t76 * z[5] - t76 * z[4] +
400 t133 * z[3] - t58 * z[1] + y[5] * x[0] * z[4] + t114 * z[2] - t3 * z[7] +
401 t20 * z[2] + t178 * y[7] + t129 * y[2];
402 const double t207 = t92 * z[7] + t22 * z[6] + z[3] * x[0] * y[2] -
403 x[0] * y[3] * z[2] - z[3] * x[7] * y[2] - t165 * y[3] -
404 t9 * y[0] + t58 * z[7] + y[3] * x[6] * z[2] +
405 t107 * z[2] + t73 * y[0] - x[3] * y[5] * z[7] +
406 t3 * z[0] - t56 * y[6] - z[5] * x[0] * y[4] +
407 t73 * y[1] - t160 * z[6] + t160 * z[0];
408 const double t228 = -t44 * z[7] + z[5] * x[6] * y[4] - t52 * z[4] -
409 t145 * z[4] + t68 * z[4] + t92 * z[5] - t92 * z[0] +
410 t11 * z[3] + t44 * z[0] + t178 * y[5] - t46 * y[5] -
411 t178 * y[0] - t145 * z[0] - t20 * z[5] - t37 * z[3] -
412 t160 * z[7] + t145 * z[3] + x[4] * y[6] * z[2];
413
414 return (t34 + t64 + t95 + t125 + t156 + t181 + t207 + t228) / 12.;
415 }
416} /* namespace GridTools */
417
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
unsigned int vertex_indices[2]
#define AssertDimension(dim1, dim2)
double cell_measure< 2 >(const std::vector< Point< 2 > > &all_vertices, const ArrayView< const unsigned int > &vertex_indices)
double cell_measure< 1 >(const std::vector< Point< 1 > > &all_vertices, const ArrayView< const unsigned int > &vertex_indices)
double cell_measure< 3 >(const std::vector< Point< 3 > > &all_vertices, const ArrayView< const unsigned int > &vertex_indices)