| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (C) 2025 Tiago V. L. Amorim (@tiagovla) | ||
| 2 | // | ||
| 3 | // This file is part of oiseau (https://github.com/tiagovla/oiseau) | ||
| 4 | // | ||
| 5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 6 | |||
| 7 | #include "oiseau/dg/nodal/ref_tetrahedron.hpp" | ||
| 8 | |||
| 9 | #include <cmath> | ||
| 10 | #include <cstddef> | ||
| 11 | #include <numbers> | ||
| 12 | #include <xtensor-blas/xlinalg.hpp> | ||
| 13 | #include <xtensor/containers/xtensor.hpp> | ||
| 14 | #include <xtensor/core/xmath.hpp> | ||
| 15 | #include <xtensor/core/xoperation.hpp> | ||
| 16 | #include <xtensor/core/xshape.hpp> | ||
| 17 | #include <xtensor/core/xtensor_forward.hpp> | ||
| 18 | #include <xtensor/generators/xbuilder.hpp> | ||
| 19 | #include <xtensor/misc/xmanipulation.hpp> | ||
| 20 | #include <xtensor/views/xslice.hpp> | ||
| 21 | #include <xtensor/views/xview.hpp> | ||
| 22 | |||
| 23 | #include "oiseau/dg/nodal/ref_element.hpp" | ||
| 24 | #include "oiseau/dg/nodal/utils.hpp" | ||
| 25 | #include "oiseau/utils/math.hpp" | ||
| 26 | |||
| 27 | namespace oiseau::dg::nodal { | ||
| 28 | |||
| 29 | 16 | RefTetrahedron::RefTetrahedron(unsigned order) : RefElement(order) { | |
| 30 | 16 | this->m_np = ((order + 1) * (order + 2) * (order + 3)) / 6; | |
| 31 | 16 | this->m_nfp = ((order + 1) * (order + 2)) / 2; | |
| 32 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | this->m_r = detail::equilateral_xyz_to_rst(detail::generate_tetrahedron_nodes(this->m_order)); |
| 33 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | this->m_v = this->vandermonde(this->m_r); |
| 34 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | this->m_gv = this->grad_vandermonde(this->m_r); |
| 35 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | this->m_d = this->grad_operator(this->m_v, this->m_gv); |
| 36 | 16 | } | |
| 37 | |||
| 38 | 621 | xt::xarray<double> RefTetrahedron::basis_function(const xt::xarray<double> &abc, int i, int j, | |
| 39 | int k) const { | ||
| 40 |
2/4✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | xt::xarray<double> a = xt::col(abc, 0); |
| 41 |
2/4✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | xt::xarray<double> b = xt::col(abc, 1); |
| 42 |
2/4✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | xt::xarray<double> c = xt::col(abc, 2); |
| 43 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | auto h1 = oiseau::utils::jacobi_p(i, 0.0, 0.0, a); |
| 44 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | auto h2 = oiseau::utils::jacobi_p(j, 2.0 * i + 1.0, 0.0, b); |
| 45 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | auto h3 = oiseau::utils::jacobi_p(k, 2.0 * (i + j) + 2.0, 0.0, c); |
| 46 |
1/2✓ Branch 10 taken 621 times.
✗ Branch 11 not taken.
|
1242 | return 2 * std::numbers::sqrt2 * h1 * h2 * xt::pow(1 - b, i) * h3 * xt::pow(1 - c, i + j); |
| 47 | 621 | } | |
| 48 | |||
| 49 | 621 | xt::xarray<double> RefTetrahedron::grad_basis_function(const xt::xarray<double> &abc, int i, int j, | |
| 50 | int k) const { | ||
| 51 |
2/4✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | xt::xarray<double> a = xt::col(abc, 0); |
| 52 |
2/4✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | xt::xarray<double> b = xt::col(abc, 1); |
| 53 |
2/4✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | xt::xarray<double> c = xt::col(abc, 2); |
| 54 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | xt::xarray<double> fa = oiseau::utils::jacobi_p(i, 0.0, 0.0, a); |
| 55 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | xt::xarray<double> dfa = oiseau::utils::grad_jacobi_p(i, 0.0, 0.0, a); |
| 56 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | xt::xarray<double> gb = oiseau::utils::jacobi_p(j, 2.0 * i + 1.0, 0.0, b); |
| 57 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | xt::xarray<double> dgb = oiseau::utils::grad_jacobi_p(j, 2.0 * i + 1.0, 0.0, b); |
| 58 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | xt::xarray<double> hc = oiseau::utils::jacobi_p(k, 2.0 * (i + j) + 2.0, 0.0, c); |
| 59 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | xt::xarray<double> dhc = oiseau::utils::grad_jacobi_p(k, 2.0 * (i + j) + 2.0, 0.0, c); |
| 60 | |||
| 61 |
4/8✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 621 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 621 times.
✗ Branch 11 not taken.
|
621 | xt::xarray<double> v3dr, v3ds, v3dt, tmp; |
| 62 | |||
| 63 |
1/2✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
|
621 | v3dr = dfa * (gb * hc); |
| 64 |
3/4✓ Branch 0 taken 380 times.
✓ Branch 1 taken 241 times.
✓ Branch 7 taken 380 times.
✗ Branch 8 not taken.
|
621 | if (i > 0) v3dr = v3dr * xt::pow(0.5 * (1 - b), i - 1); |
| 65 |
3/4✓ Branch 0 taken 545 times.
✓ Branch 1 taken 76 times.
✓ Branch 7 taken 545 times.
✗ Branch 8 not taken.
|
621 | if (i + j > 0) v3dr = v3dr * xt::pow(0.5 * (1 - c), i + j - 1); |
| 66 | |||
| 67 |
1/2✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
|
621 | v3ds = 0.5 * (1 + a) * v3dr; |
| 68 |
1/2✓ Branch 5 taken 621 times.
✗ Branch 6 not taken.
|
621 | tmp = dgb * xt::pow(0.5 * (1 - b), i); |
| 69 |
3/4✓ Branch 0 taken 380 times.
✓ Branch 1 taken 241 times.
✓ Branch 9 taken 380 times.
✗ Branch 10 not taken.
|
621 | if (i > 0) tmp = tmp + (-0.5 * i) * gb * xt::pow(0.5 * (1 - b), i - 1); |
| 70 |
3/4✓ Branch 0 taken 545 times.
✓ Branch 1 taken 76 times.
✓ Branch 7 taken 545 times.
✗ Branch 8 not taken.
|
621 | if (i + j > 0) tmp = tmp * xt::pow(0.5 * (1 - c), i + j - 1); |
| 71 |
1/2✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
|
621 | tmp = fa * (tmp * hc); |
| 72 |
1/2✓ Branch 2 taken 621 times.
✗ Branch 3 not taken.
|
621 | v3ds = v3ds + tmp; |
| 73 | |||
| 74 |
1/2✓ Branch 8 taken 621 times.
✗ Branch 9 not taken.
|
621 | v3dt = 0.5 * (1 + a) * v3dr + 0.5 * (1 + b) * tmp; |
| 75 |
1/2✓ Branch 5 taken 621 times.
✗ Branch 6 not taken.
|
621 | tmp = dhc * xt::pow(0.5 * (1 - c), i + j); |
| 76 |
3/4✓ Branch 0 taken 545 times.
✓ Branch 1 taken 76 times.
✓ Branch 9 taken 545 times.
✗ Branch 10 not taken.
|
621 | if (i + j > 0) tmp = tmp - 0.5 * (i + j) * hc * xt::pow(0.5 * (1 - c), (i + j - 1)); |
| 77 |
1/2✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
|
621 | tmp = fa * gb * tmp; |
| 78 |
1/2✓ Branch 5 taken 621 times.
✗ Branch 6 not taken.
|
621 | tmp = tmp * xt::pow(0.5 * (1 - b), i); |
| 79 |
1/2✓ Branch 2 taken 621 times.
✗ Branch 3 not taken.
|
621 | v3dt = v3dt + tmp; |
| 80 | |||
| 81 |
1/2✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
|
621 | v3dr = v3dr * std::pow(2, 2 * i + j + 1.5); |
| 82 |
1/2✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
|
621 | v3ds = v3ds * std::pow(2, 2 * i + j + 1.5); |
| 83 |
1/2✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
|
621 | v3dt = v3dt * std::pow(2, 2 * i + j + 1.5); |
| 84 | |||
| 85 |
2/4✓ Branch 2 taken 621 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 621 times.
✗ Branch 6 not taken.
|
1242 | return xt::stack(xt::xtuple(v3dr, v3ds, v3dt), 1); |
| 86 | 621 | } | |
| 87 | |||
| 88 | 16 | xt::xarray<double> RefTetrahedron::vandermonde(const xt::xarray<double> &rst) const { | |
| 89 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | auto abc = detail::rst_to_abc(rst); |
| 90 | 16 | const std::size_t n_points = rst.shape()[0]; | |
| 91 | 16 | const std::size_t n_basis = this->m_np; // (order+1)(order+2)*(order+3)/6 | |
| 92 | // | ||
| 93 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | xt::xarray<double> output(xt::dynamic_shape<std::size_t>({n_points, n_basis})); |
| 94 | |||
| 95 | 16 | std::size_t index = 0; | |
| 96 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 16 times.
|
92 | for (unsigned i = 0; i <= this->m_order; ++i) { |
| 97 |
2/2✓ Branch 0 taken 241 times.
✓ Branch 1 taken 76 times.
|
317 | for (unsigned j = 0; j <= this->m_order - i; ++j) { |
| 98 |
2/2✓ Branch 0 taken 621 times.
✓ Branch 1 taken 241 times.
|
862 | for (unsigned k = 0; k <= this->m_order - i - j; ++k, ++index) { |
| 99 |
3/6✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 621 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 621 times.
✗ Branch 8 not taken.
|
621 | xt::col(output, index) = this->basis_function(abc, i, j, k); |
| 100 | } | ||
| 101 | } | ||
| 102 | } | ||
| 103 | 16 | return output; | |
| 104 | 16 | } | |
| 105 | |||
| 106 | 16 | xt::xarray<double> RefTetrahedron::grad_vandermonde(const xt::xarray<double> &rst) const { | |
| 107 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | auto abc = detail::rst_to_abc(rst); |
| 108 | 16 | const std::size_t n_points = rst.shape()[0]; | |
| 109 | 16 | const std::size_t n_basis = this->m_np; // (order+1)(order+2)*(order+3)/6 | |
| 110 | // | ||
| 111 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | xt::xarray<double> output(xt::dynamic_shape<std::size_t>({n_points, n_basis, 3})); |
| 112 | |||
| 113 | 16 | std::size_t index = 0; | |
| 114 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 16 times.
|
92 | for (unsigned i = 0; i <= this->m_order; ++i) { |
| 115 |
2/2✓ Branch 0 taken 241 times.
✓ Branch 1 taken 76 times.
|
317 | for (unsigned j = 0; j <= this->m_order - i; ++j) { |
| 116 |
2/2✓ Branch 0 taken 621 times.
✓ Branch 1 taken 241 times.
|
862 | for (unsigned k = 0; k <= this->m_order - i - j; ++k, ++index) { |
| 117 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | auto tmp = this->grad_basis_function(abc, i, j, k); |
| 118 |
2/4✓ Branch 3 taken 621 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 621 times.
✗ Branch 7 not taken.
|
621 | xt::view(output, xt::all(), index, xt::all()) = tmp; |
| 119 | 621 | } | |
| 120 | } | ||
| 121 | } | ||
| 122 | 16 | return output; | |
| 123 | 16 | } | |
| 124 | // | ||
| 125 | 16 | xt::xarray<double> RefTetrahedron::grad_operator(const xt::xarray<double> &v, | |
| 126 | const xt::xarray<double> &gv) const { | ||
| 127 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | auto gvr = xt::view(gv, xt::all(), xt::all(), 0); |
| 128 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | auto gvs = xt::view(gv, xt::all(), xt::all(), 1); |
| 129 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | auto gvt = xt::view(gv, xt::all(), xt::all(), 2); |
| 130 | |||
| 131 | 16 | const auto vt = xt::transpose(v); | |
| 132 | 16 | const auto dvt_dr = xt::transpose(gvr); | |
| 133 | 16 | const auto dvt_ds = xt::transpose(gvs); | |
| 134 | 16 | const auto dvt_dt = xt::transpose(gvt); | |
| 135 | |||
| 136 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | const auto dr = xt::transpose(xt::linalg::solve(vt, dvt_dr)); |
| 137 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | const auto ds = xt::transpose(xt::linalg::solve(vt, dvt_ds)); |
| 138 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | const auto dt = xt::transpose(xt::linalg::solve(vt, dvt_dt)); |
| 139 | |||
| 140 |
2/4✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
32 | return xt::stack(xt::xtuple(dr, ds, dt), 2); |
| 141 | 16 | } | |
| 142 | |||
| 143 | } // namespace oiseau::dg::nodal | ||
| 144 | |||
| 145 | namespace oiseau::dg::nodal::detail { | ||
| 146 | |||
| 147 | 32 | xt::xarray<double> rst_to_abc(const xt::xarray<double> &rst) { | |
| 148 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto abc = xt::zeros_like(rst); |
| 149 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto &&r = xt::col(rst, 0); |
| 150 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto &&s = xt::col(rst, 1); |
| 151 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto &&t = xt::col(rst, 2); |
| 152 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto &&a = xt::col(abc, 0); |
| 153 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto &&b = xt::col(abc, 1); |
| 154 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | auto &&c = xt::col(abc, 2); |
| 155 |
2/2✓ Branch 2 taken 1242 times.
✓ Branch 3 taken 32 times.
|
1274 | for (unsigned n = 0; n < rst.shape()[0]; ++n) { |
| 156 |
4/6✓ Branch 1 taken 1242 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1242 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1136 times.
✓ Branch 7 taken 106 times.
|
1242 | if ((s[n] + t[n]) != 0) { |
| 157 |
4/8✓ Branch 1 taken 1136 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1136 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1136 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1136 times.
✗ Branch 11 not taken.
|
1136 | a[n] = 2 * ((1 + r[n]) / (-s[n] - t[n])) - 1; |
| 158 | } else { | ||
| 159 |
1/2✓ Branch 1 taken 106 times.
✗ Branch 2 not taken.
|
106 | a[n] = -1; |
| 160 | } | ||
| 161 |
3/4✓ Branch 1 taken 1242 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1210 times.
✓ Branch 4 taken 32 times.
|
1242 | if (t[n] != 1) { |
| 162 |
3/6✓ Branch 1 taken 1210 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1210 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1210 times.
✗ Branch 8 not taken.
|
1210 | b[n] = 2 * (1 + s[n]) / (1 - t[n]) - 1; |
| 163 | } else { | ||
| 164 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | b[n] = -1; |
| 165 | } | ||
| 166 | } | ||
| 167 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | c = t; |
| 168 | 32 | return abc; | |
| 169 | 32 | } | |
| 170 | |||
| 171 | 192 | xt::xarray<double> eval_warp(int p, const xt::xarray<double> &xnodes, | |
| 172 | const xt::xarray<double> &xout) { | ||
| 173 |
1/2✓ Branch 1 taken 192 times.
✗ Branch 2 not taken.
|
192 | xt::xarray<double> warp = xt::zeros_like(xout); |
| 174 |
1/2✓ Branch 2 taken 192 times.
✗ Branch 3 not taken.
|
192 | xt::xarray<double> xeq = xt::zeros<double>({p + 1}); |
| 175 |
3/4✓ Branch 1 taken 912 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 912 times.
✓ Branch 4 taken 192 times.
|
1104 | for (int i = 0; i <= p; i++) xeq(i) = -1.0 + 2.0 * (p - i) / p; |
| 176 |
2/2✓ Branch 0 taken 912 times.
✓ Branch 1 taken 192 times.
|
1104 | for (int i = 0; i <= p; i++) { |
| 177 |
4/8✓ Branch 1 taken 912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 912 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 912 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 912 times.
✗ Branch 12 not taken.
|
912 | xt::xarray<double> d = xt::ones_like(xout) * (xnodes(i) - xeq(i)); |
| 178 |
2/2✓ Branch 0 taken 3048 times.
✓ Branch 1 taken 912 times.
|
3960 | for (int j = 1; j < p; j++) { |
| 179 |
6/10✓ Branch 0 taken 2520 times.
✓ Branch 1 taken 528 times.
✓ Branch 3 taken 2520 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2520 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2520 times.
✗ Branch 10 not taken.
✓ Branch 15 taken 2520 times.
✗ Branch 16 not taken.
|
3048 | if (i != j) d = d * (xout - xeq(j)) / (xeq(i) - xeq(j)); |
| 180 | } | ||
| 181 |
5/8✓ Branch 0 taken 720 times.
✓ Branch 1 taken 192 times.
✓ Branch 3 taken 720 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 720 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 720 times.
✗ Branch 12 not taken.
|
912 | if (i != 0) d = -d / (xeq(i) - xeq(0)); |
| 182 |
5/8✓ Branch 0 taken 720 times.
✓ Branch 1 taken 192 times.
✓ Branch 3 taken 720 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 720 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 720 times.
✗ Branch 11 not taken.
|
912 | if (i != p) d = d / (xeq(i) - xeq(p)); |
| 183 |
1/2✓ Branch 1 taken 912 times.
✗ Branch 2 not taken.
|
912 | warp += d; |
| 184 | 912 | } | |
| 185 | 192 | return warp; | |
| 186 | 192 | } | |
| 187 | |||
| 188 | 64 | xt::xarray<double> eval_shift(int p, double pval, const xt::xarray<double> &l1, | |
| 189 | const xt::xarray<double> &l2, const xt::xarray<double> &l3) { | ||
| 190 |
1/2✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
|
64 | auto gaussX = -oiseau::dg::nodal::utils::jacobi_gl(p, 0.0, 0.0); |
| 191 | 64 | auto blend1 = l2 * l3; | |
| 192 | 64 | auto blend2 = l1 * l3; | |
| 193 | 64 | auto blend3 = l1 * l2; | |
| 194 |
3/6✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
|
64 | auto warpfactor1 = 4 * eval_warp(p, gaussX, l3 - 1 * l2); |
| 195 |
3/6✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
|
64 | auto warpfactor2 = 4 * eval_warp(p, gaussX, l1 - 1 * l3); |
| 196 |
3/6✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
|
64 | auto warpfactor3 = 4 * eval_warp(p, gaussX, l2 - 1 * l1); |
| 197 | 64 | auto warp1 = blend1 * warpfactor1 * (1 + xt::pow(pval * l1, 2)); | |
| 198 | 64 | auto warp2 = blend2 * warpfactor2 * (1 + xt::pow(pval * l2, 2)); | |
| 199 | 64 | auto warp3 = blend3 * warpfactor3 * (1 + xt::pow(pval * l3, 2)); | |
| 200 | 64 | auto pi = xt::numeric_constants<double>::PI; | |
| 201 | 64 | auto dx = 1 * warp1 + cos(2.0 * pi / 3.0) * warp2 + cos(4.0 * pi / 3.0) * warp3; | |
| 202 | 64 | auto dy = 0 * warp1 + sin(2.0 * pi / 3.0) * warp2 + sin(4.0 * pi / 3.0) * warp3; | |
| 203 |
2/4✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
|
128 | return xt::stack(xt::xtuple(dx, dy), 1); |
| 204 | 64 | } | |
| 205 | |||
| 206 | 64 | xt::xarray<double> warp_shift_face_3d(int p, double pval, const xt::xarray<double> &l2, | |
| 207 | const xt::xarray<double> &l3, const xt::xarray<double> &l4) { | ||
| 208 | 64 | return eval_shift(p, pval, l2, l3, l4); | |
| 209 | } | ||
| 210 | |||
| 211 | 16 | xt::xarray<double> generate_tetrahedron_equidistant_nodes(unsigned n) { | |
| 212 | 16 | auto n_p = ((n + 1) * (n + 2) * (n + 3)) / 6; | |
| 213 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
32 | auto shape = xt::xarray<double>::shape_type{n_p, 3}; |
| 214 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | xt::xarray<double> output = xt::zeros<double>(shape); |
| 215 | 16 | std::size_t sk = 0; | |
| 216 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 16 times.
|
92 | for (std::size_t i = 0; i < n + 1; ++i) { |
| 217 |
2/2✓ Branch 0 taken 241 times.
✓ Branch 1 taken 76 times.
|
317 | for (std::size_t j = 0; j < n + 1 - i; ++j) { |
| 218 |
2/2✓ Branch 0 taken 621 times.
✓ Branch 1 taken 241 times.
|
862 | for (std::size_t k = 0; k < n + 1 - i - j; ++k, ++sk) { |
| 219 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | output(sk, 0) = -1 + k * 2.0 / n; |
| 220 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | output(sk, 1) = -1 + j * 2.0 / n; |
| 221 |
1/2✓ Branch 1 taken 621 times.
✗ Branch 2 not taken.
|
621 | output(sk, 2) = -1 + i * 2.0 / n; |
| 222 | } | ||
| 223 | } | ||
| 224 | } | ||
| 225 | 16 | return output; | |
| 226 | 16 | } | |
| 227 | |||
| 228 | 16 | xt::xarray<double> generate_tetrahedron_nodes(unsigned p) { | |
| 229 | xt::xarray<double> alphastore = { | ||
| 230 | 0, 0, 0, 0.1002, 1.1332, 1.5608, 1.3413, 1.2577, | ||
| 231 | 1.1603, 1.10153, 0.6080, 0.4523, 0.8856, 0.8717, 0.9655, | ||
| 232 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | }; |
| 233 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | double alpha = p > 14 ? 1 : alphastore[p]; |
| 234 | 16 | double tol = 1e-10; | |
| 235 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | auto rst = generate_tetrahedron_equidistant_nodes(p); |
| 236 |
3/6✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
16 | auto r = xt::col(rst, 0), s = xt::col(rst, 1), t = xt::col(rst, 2); |
| 237 |
3/6✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 20 taken 16 times.
✗ Branch 21 not taken.
|
16 | xt::xarray<double> l1 = (1 + t) / 2, l2 = (1 + s) / 2, l3 = -(1 + r + s + t) / 2, |
| 238 |
1/2✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
|
16 | l4 = (1 + r) / 2; |
| 239 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v1 = {-1.0, -1.0 / std::numbers::sqrt3, -1.0 / std::sqrt(6)}; |
| 240 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v2 = {1.0, -1.0 / std::numbers::sqrt3, -1.0 / std::sqrt(6)}; |
| 241 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v3 = {0.0, 2.0 / std::numbers::sqrt3, -1.0 / std::sqrt(6)}; |
| 242 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v4 = {0.0, 0.0, 3.0 / std::sqrt(6)}; |
| 243 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | xt::xtensor<double, 2> t1 = xt::zeros<double>({4, 3}); |
| 244 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | xt::xtensor<double, 2> t2 = xt::zeros<double>({4, 3}); |
| 245 |
2/4✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | xt::row(t1, 0) = v2 - 1 * v1; |
| 246 |
2/4✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | xt::row(t1, 1) = v2 - 1 * v1; |
| 247 |
2/4✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | xt::row(t1, 2) = v3 - 1 * v2; |
| 248 |
2/4✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | xt::row(t1, 3) = v3 - 1 * v1; |
| 249 |
2/4✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
16 | xt::row(t2, 0) = v3 - 0.5 * (v1 + v2); |
| 250 |
2/4✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
16 | xt::row(t2, 1) = v4 - 0.5 * (v1 + v2); |
| 251 |
2/4✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
16 | xt::row(t2, 2) = v4 - 0.5 * (v2 + v3); |
| 252 |
2/4✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
16 | xt::row(t2, 3) = v4 - 0.5 * (v1 + v3); |
| 253 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 16 times.
|
80 | for (int i = 0; i < 4; ++i) { |
| 254 |
4/8✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 64 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 64 times.
✗ Branch 11 not taken.
|
64 | xt::row(t1, i) /= xt::linalg::norm(xt::row(t1, i)); |
| 255 |
4/8✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 64 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 64 times.
✗ Branch 11 not taken.
|
64 | xt::row(t2, i) /= xt::linalg::norm(xt::row(t2, i)); |
| 256 | } | ||
| 257 |
3/6✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
32 | auto xyz = xt::linalg::outer(l3, v1) + xt::linalg::outer(l4, v2) + xt::linalg::outer(l2, v3) + |
| 258 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
48 | xt::linalg::outer(l1, v4); |
| 259 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | xt::xarray<double> shift = xt::zeros<double>(xyz.shape()); |
| 260 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 16 times.
|
80 | for (int face = 0; face < 4; ++face) { |
| 261 |
4/8✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 64 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 64 times.
✗ Branch 11 not taken.
|
64 | xt::xarray<double> la, lb, lc, ld; |
| 262 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 48 times.
|
64 | if (face == 0) { |
| 263 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | la = l1; |
| 264 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lb = l2; |
| 265 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lc = l3; |
| 266 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ld = l4; |
| 267 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
|
48 | } else if (face == 1) { |
| 268 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | la = l2; |
| 269 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lb = l1; |
| 270 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lc = l3; |
| 271 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ld = l4; |
| 272 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
32 | } else if (face == 2) { |
| 273 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | la = l3; |
| 274 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lb = l1; |
| 275 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lc = l4; |
| 276 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ld = l2; |
| 277 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | } else if (face == 3) { |
| 278 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | la = l4; |
| 279 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lb = l1; |
| 280 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | lc = l3; |
| 281 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | ld = l2; |
| 282 | } | ||
| 283 |
1/2✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
|
64 | auto warp = warp_shift_face_3d(p, alpha, lb, lc, ld); |
| 284 |
1/2✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
|
64 | auto warp1 = xt::col(warp, 0); |
| 285 |
1/2✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
|
64 | auto warp2 = xt::col(warp, 1); |
| 286 |
1/2✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
|
64 | xt::xarray<double> blend = lb * lc * ld; |
| 287 |
1/2✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
|
64 | xt::xarray<double> denom = (lb + 0.5 * la) * (lc + 0.5 * la) * (ld + 0.5 * la); |
| 288 |
2/4✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
|
64 | auto ids = xt::flatten_indices(xt::argwhere(denom > tol)); |
| 289 |
4/8✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 10 taken 64 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 64 times.
✗ Branch 14 not taken.
|
256 | xt::view(blend, xt::keep(ids)) = (1 + xt::pow(alpha * xt::view(la, xt::keep(ids)), 2)) * |
| 290 |
2/4✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
|
256 | xt::view(blend, xt::keep(ids)) / |
| 291 |
3/6✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 64 times.
✗ Branch 9 not taken.
|
256 | xt::view(denom, xt::keep(ids)); |
| 292 |
2/4✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
|
128 | shift = shift + xt::linalg::outer(blend * warp1, xt::row(t1, face)) + |
| 293 |
3/6✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 64 times.
✗ Branch 10 not taken.
|
192 | xt::linalg::outer(blend * warp2, xt::row(t2, face)); |
| 294 | 64 | auto mask = (la < tol) && (((lb > tol) + (lc > tol) + (ld > tol)) < 3); | |
| 295 |
2/4✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
|
64 | ids = xt::flatten_indices(xt::argwhere(mask)); |
| 296 |
2/4✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
|
128 | xt::view(shift, xt::keep(ids), xt::all()) = |
| 297 |
4/8✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 64 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 64 times.
✗ Branch 11 not taken.
|
128 | xt::linalg::outer(xt::view(warp1, xt::keep(ids)), xt::row(t1, face)) + |
| 298 |
5/10✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 64 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 64 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 64 times.
✗ Branch 15 not taken.
|
256 | xt::linalg::outer(xt::view(warp2, xt::keep(ids)), xt::row(t2, face)); |
| 299 | 64 | } | |
| 300 | 16 | xyz = xyz + shift; | |
| 301 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
32 | return xyz; |
| 302 | 16 | } | |
| 303 | |||
| 304 | 16 | xt::xarray<double> equilateral_xyz_to_rst(const xt::xarray<double> &coords) { | |
| 305 | 16 | const double sqrt3 = std::numbers::sqrt3; | |
| 306 | 16 | const double sqrt6 = std::sqrt(6.0); | |
| 307 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v1 = {-1, -1 / sqrt3, -1 / sqrt6}; |
| 308 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v2 = {1, -1 / sqrt3, -1 / sqrt6}; |
| 309 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v3 = {0, 2 / sqrt3, -1 / sqrt6}; |
| 310 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | xt::xtensor<double, 1> v4 = {0, 0 / sqrt3, 3 / sqrt6}; |
| 311 | 16 | auto rhs = xt::transpose(coords - 0.5 * (v2 + v3 + v4 - v1)); | |
| 312 |
1/2✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | auto lhs = 0.5 * xt::stack(xt::xtuple(v2 - v1, v3 - v1, v4 - v1), 1); |
| 313 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | auto rst = xt::linalg::solve(lhs, rhs); |
| 314 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
32 | return xt::transpose(rst); |
| 315 | 16 | } | |
| 316 | |||
| 317 | } // namespace oiseau::dg::nodal::detail | ||
| 318 |