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