PolyFEM
Loading...
Searching...
No Matches
p_n_bases.cpp
Go to the documentation of this file.
1#include "p_n_bases.hpp"
2#include <cmath>
3#include <cassert>
4
5namespace polyfem
6{
7 namespace autogen
8 {
9 Eigen::Vector3i convert_local_index_to_ijk(const int local_index, const int p)
10 {
11 assert(p > 1);
12 Eigen::Vector3i ijk;
13 ijk.setZero();
14 if (local_index < 3)
15 { // vertices
16 ijk((local_index + 2) % 3) = p;
17 }
18 else if (local_index >= 3 && local_index < 3 * p) // edges
19 {
20 int a = (local_index - 3) / (p - 1); // which edge
21 int b = (local_index - 3) % (p - 1); // location on the edge
22 ijk(a) = b + 1;
23 ijk((a + 2) % 3) = p - b - 1;
24 }
25 else
26 { // interior
27 int t0 = local_index - 3 * p + 1;
28 int t1 = p - 2;
29 ijk(0) = 1;
30 while (t0 > t1)
31 {
32 t0 -= t1;
33 t1 -= 1;
34 ijk(0) += 1;
35 }
36 ijk(1) = t0;
37 ijk(2) = p - ijk(0) - ijk(1);
38 }
39 return ijk;
40 }
41
42 Eigen::ArrayXd P(const int m, const int p, const Eigen::ArrayXd &z)
43 {
44 Eigen::ArrayXd result;
45 result.resize(z.size());
46 result.setConstant(1);
47 if (m >= 1)
48 {
49 for (int i = 1; i <= m; ++i)
50 {
51 result *= (p * z - i + 1) / double(i);
52 }
53 }
54 return result;
55 }
56
57 Eigen::ArrayXd P_prime(const int m, const int p, const Eigen::ArrayXd &z)
58 {
59 Eigen::ArrayXd result, tmp;
60 result.resize(z.size());
61 tmp.resize(z.size());
62 result.setZero();
63 if (m >= 1)
64 {
65 for (int i = 1; i <= m; ++i)
66 {
67 tmp.setConstant(1);
68 for (int j = 1; j <= m; ++j)
69 {
70 if (j != i)
71 {
72 tmp *= (p * z - j + 1) / double(j);
73 }
74 }
75 result += tmp * p / double(i);
76 }
77 }
78 return result;
79 }
80
81 void p_n_nodes_3d(const int p, Eigen::MatrixXd &val)
82 {
83 int size = ((p + 3) * (p + 2) * (p + 1)) / 6;
84 val.resize(size, 3);
85 val.setZero();
86 val.topRows(4) << 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1;
87 if (p > 1)
88 {
89 for (int i = 1; i < p; i++)
90 {
91 double x = i / (double)p;
92 double y = 1 - x;
93 val.row(i + 3 + (p - 1) * 0) << x, 0, 0;
94 val.row(i + 3 + (p - 1) * 1) << y, x, 0;
95 val.row(i + 3 + (p - 1) * 2) << 0, y, 0;
96 val.row(i + 3 + (p - 1) * 3) << 0, 0, x;
97 val.row(i + 3 + (p - 1) * 4) << y, 0, x;
98 val.row(i + 3 + (p - 1) * 5) << 0, y, x;
99 }
100 }
101 if (p > 2)
102 {
103 int start_id = 4 + 6 * (p - 1);
104 int n_face_nodes = ((p - 1) * (p - 2)) / 2;
105 for (int i = 1, idx = 0; i < p; i++)
106 for (int j = 1; i + j < p; j++)
107 {
108 double x = i / (double)p, y = j / (double)p;
109 double z = 1 - x - y;
110 val.row(start_id + idx + n_face_nodes * 0) << x, y, 0;
111 val.row(start_id + idx + n_face_nodes * 1) << x, 0, y;
112 val.row(start_id + idx + n_face_nodes * 2) << z, x, y;
113 val.row(start_id + idx + n_face_nodes * 3) << 0, z, y;
114 idx++;
115 }
116 }
117 if (p > 3)
118 {
119 int start_id = 4 + 6 * (p - 1) + 2 * (p - 1) * (p - 2);
120 for (int i = 1, idx = 0; i < p; i++)
121 for (int j = 1; i + j < p; j++)
122 for (int k = 1; i + j + k < p; k++)
123 {
124 val.row(start_id + idx) << i / (double)p, j / (double)p, k / (double)p;
125 idx++;
126 }
127 }
128 }
129
130 void p_n_nodes_2d(const int p, Eigen::MatrixXd &val)
131 {
132 int size = (p + 1) * (p + 2) / 2;
133 val.resize(size, 2);
134 val.setZero();
135 val.topRows(3) << 0, 0, 1, 0, 0, 1;
136 if (p > 1)
137 {
138 for (int i = 0; i < p - 1; i++)
139 {
140 val.row(i + 3) << (i + 1) / double(p), 0; // 3+i
141 val.row(i + p + 2) << 1.0 - (i + 1) / double(p), (i + 1) / double(p); // 3+(p-1)+i
142 val.row(i + p * 2 + 1) << 0, 1.0 - (i + 1) / double(p); // 3+2(p-1)+i
143 }
144 }
145 if (p > 2)
146 {
147 int inner_node_id = 3 * p;
148 for (int i = 0; i < p - 2; i++)
149 for (int j = 0; j < p - i - 2; j++)
150 {
151 val.row(inner_node_id) << (i + 1) / double(p), (j + 1) / double(p);
152 inner_node_id++;
153 }
154 }
155 }
156
157 void p_n_basis_value_3d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
158 {
159 auto x = uv.col(0).array();
160 auto y = uv.col(1).array();
161 auto z = uv.col(2).array();
162 p_n_nodes_3d(p, val);
163 int i = round(val(local_index, 0) * p), j = round(val(local_index, 1) * p), k = round(val(local_index, 2) * p);
164 val = P(i, p, x) * P(j, p, y) * P(k, p, z) * P(p - i - j - k, p, 1 - x - y - z);
165 }
166
167 void p_n_basis_value_2d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
168 {
169 auto x = uv.col(0).array();
170 auto y = uv.col(1).array();
171 Eigen::Vector3i ijk;
172 ijk = convert_local_index_to_ijk(local_index, p);
173 val = P(ijk(0), p, x) * P(ijk(1), p, y) * P(ijk(2), p, 1 - x - y);
174 }
175
176 void p_n_basis_grad_value_3d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
177 {
178 auto x = uv.col(0).array();
179 auto y = uv.col(1).array();
180 auto z = uv.col(2).array();
181 auto w = 1 - x - y - z;
182 p_n_nodes_3d(p, val);
183 int i = round(val(local_index, 0) * p), j = round(val(local_index, 1) * p), k = round(val(local_index, 2) * p);
184 int l = p - i - j - k;
185 val.resize(uv.rows(), uv.cols());
186 auto value_x = P(i, p, x), value_y = P(j, p, y), value_z = P(k, p, z);
187 auto value_w = P(l, p, w), derivative_w = P_prime(l, p, w);
188 val.col(0) = value_y * value_z * (P_prime(i, p, x) * value_w - value_x * derivative_w);
189 val.col(1) = value_x * value_z * (P_prime(j, p, y) * value_w - value_y * derivative_w);
190 val.col(2) = value_x * value_y * (P_prime(k, p, z) * value_w - value_z * derivative_w);
191 }
192
193 void p_n_basis_grad_value_2d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
194 {
195 auto x = uv.col(0).array();
196 auto y = uv.col(1).array();
197 Eigen::Vector3i ijk;
198 ijk = convert_local_index_to_ijk(local_index, p);
199 val.resize(uv.rows(), uv.cols());
200 val.col(0) = P(ijk(1), p, y) * (P_prime(ijk(0), p, x) * P(ijk(2), p, 1 - x - y) - P(ijk(0), p, x) * P_prime(ijk(2), p, 1 - x - y));
201 val.col(1) = P(ijk(0), p, x) * (P_prime(ijk(1), p, y) * P(ijk(2), p, 1 - x - y) - P(ijk(1), p, y) * P_prime(ijk(2), p, 1 - x - y));
202 }
203 } // namespace autogen
204} // namespace polyfem
double val
Definition Assembler.cpp:86
int y
int z
int x
void p_n_nodes_3d(const int p, Eigen::MatrixXd &val)
Definition p_n_bases.cpp:81
void p_n_basis_grad_value_2d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
void p_n_basis_grad_value_3d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
Eigen::ArrayXd P(const int m, const int p, const Eigen::ArrayXd &z)
Definition p_n_bases.cpp:42
void p_n_basis_value_3d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
void p_n_basis_value_2d(const int p, const int local_index, const Eigen::MatrixXd &uv, Eigen::MatrixXd &val)
Eigen::Vector3i convert_local_index_to_ijk(const int local_index, const int p)
Definition p_n_bases.cpp:9
void p_n_nodes_2d(const int p, Eigen::MatrixXd &val)
Eigen::ArrayXd P_prime(const int m, const int p, const Eigen::ArrayXd &z)
Definition p_n_bases.cpp:57