Skip to content

Commit 038a894

Browse files
authored
Add support for CEED_EVAL_GRADIENT and CEED_TRANSPOSE in CeedBasisApplyAtPoints (#1388)
1 parent 1d2a965 commit 038a894

2 files changed

Lines changed: 158 additions & 16 deletions

File tree

interface/ceed-basis.c

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,8 +1513,6 @@ int CeedBasisApplyAtPoints(CeedBasis basis, CeedInt num_points, CeedTransposeMod
15131513

15141514
// Default implementation
15151515
CeedCheck(basis->is_tensor_basis, basis->ceed, CEED_ERROR_UNSUPPORTED, "Evaluation at arbitrary points only supported for tensor product bases");
1516-
CeedCheck(eval_mode == CEED_EVAL_INTERP || t_mode == CEED_NOTRANSPOSE, basis->ceed, CEED_ERROR_UNSUPPORTED, "%s evaluation only supported for %s",
1517-
CeedEvalModes[eval_mode], CeedTransposeModes[CEED_NOTRANSPOSE]);
15181516
if (!basis->basis_chebyshev) {
15191517
// Build matrix mapping from quadrature point values to Chebyshev coefficients
15201518
CeedScalar *tau, *C, *I, *chebyshev_coeffs_1d;
@@ -1662,22 +1660,52 @@ int CeedBasisApplyAtPoints(CeedBasis basis, CeedInt num_points, CeedTransposeMod
16621660
CeedCall(CeedVectorGetArrayWrite(basis->vec_chebyshev, CEED_MEM_HOST, &chebyshev_coeffs));
16631661
CeedCall(CeedVectorGetArrayRead(x_ref, CEED_MEM_HOST, &x_array_read));
16641662
CeedCall(CeedVectorGetArrayRead(u, CEED_MEM_HOST, &u_array));
1665-
{
1666-
CeedScalar tmp[2][num_comp * CeedIntPow(Q_1d, dim)], chebyshev_x[Q_1d];
1667-
1668-
// ---- Values at point
1669-
for (CeedInt p = 0; p < num_points; p++) {
1670-
CeedInt pre = num_comp * 1, post = 1;
1671-
1672-
for (CeedInt d = 0; d < dim; d++) {
1673-
// ------ Tensor contract with current Chebyshev polynomial values
1674-
CeedCall(CeedChebyshevPolynomialsAtPoint(x_array_read[p * dim + d], Q_1d, chebyshev_x));
1675-
CeedCall(CeedTensorContractApply(basis->contract, pre, 1, post, Q_1d, chebyshev_x, t_mode, p > 0 && d == (dim - 1),
1676-
d == 0 ? &u_array[p * num_comp] : tmp[d % 2], d == (dim - 1) ? chebyshev_coeffs : tmp[(d + 1) % 2]));
1677-
pre /= 1;
1678-
post *= Q_1d;
1663+
1664+
switch (eval_mode) {
1665+
case CEED_EVAL_INTERP: {
1666+
CeedScalar tmp[2][num_comp * CeedIntPow(Q_1d, dim)], chebyshev_x[Q_1d];
1667+
1668+
// ---- Values at point
1669+
for (CeedInt p = 0; p < num_points; p++) {
1670+
CeedInt pre = num_comp * 1, post = 1;
1671+
1672+
for (CeedInt d = 0; d < dim; d++) {
1673+
// ------ Tensor contract with current Chebyshev polynomial values
1674+
CeedCall(CeedChebyshevPolynomialsAtPoint(x_array_read[p * dim + d], Q_1d, chebyshev_x));
1675+
CeedCall(CeedTensorContractApply(basis->contract, pre, 1, post, Q_1d, chebyshev_x, t_mode, p > 0 && d == (dim - 1),
1676+
d == 0 ? &u_array[p * num_comp] : tmp[d % 2], d == (dim - 1) ? chebyshev_coeffs : tmp[(d + 1) % 2]));
1677+
pre /= 1;
1678+
post *= Q_1d;
1679+
}
1680+
}
1681+
break;
1682+
}
1683+
case CEED_EVAL_GRAD: {
1684+
CeedScalar tmp[2][num_comp * CeedIntPow(Q_1d, dim)], chebyshev_x[Q_1d];
1685+
1686+
// ---- Values at point
1687+
for (CeedInt p = 0; p < num_points; p++) {
1688+
// Dim**2 contractions, apply grad when pass == dim
1689+
for (CeedInt pass = 0; pass < dim; pass++) {
1690+
CeedInt pre = num_comp * 1, post = 1;
1691+
1692+
for (CeedInt d = 0; d < dim; d++) {
1693+
// ------ Tensor contract with current Chebyshev polynomial values
1694+
if (pass == d) CeedCall(CeedChebyshevDerivativeAtPoint(x_array_read[p * dim + d], Q_1d, chebyshev_x));
1695+
else CeedCall(CeedChebyshevPolynomialsAtPoint(x_array_read[p * dim + d], Q_1d, chebyshev_x));
1696+
CeedCall(CeedTensorContractApply(
1697+
basis->contract, pre, 1, post, Q_1d, chebyshev_x, t_mode, (p > 0 || (p == 0 && pass > 0)) && d == (dim - 1),
1698+
d == 0 ? &u_array[p * num_comp * dim + pass] : tmp[d % 2], d == (dim - 1) ? chebyshev_coeffs : tmp[(d + 1) % 2]));
1699+
pre /= 1;
1700+
post *= Q_1d;
1701+
}
1702+
}
16791703
}
1704+
break;
16801705
}
1706+
default:
1707+
// Nothing to do, excluded above
1708+
break;
16811709
}
16821710
CeedCall(CeedVectorRestoreArray(basis->vec_chebyshev, &chebyshev_coeffs));
16831711
CeedCall(CeedVectorRestoreArrayRead(x_ref, &x_array_read));

tests/t357-basis.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/// @file
2+
/// Test gradient transpose in multiple dimensions at arbitrary points
3+
/// \test Test gradient transpose in multiple dimensions at arbitrary points
4+
#include <ceed.h>
5+
#include <math.h>
6+
#include <stdio.h>
7+
8+
static CeedScalar Eval(CeedInt dim, const CeedScalar x[]) {
9+
CeedScalar result = tanh(x[0] + 0.1);
10+
if (dim > 1) result += atan(x[1] + 0.2);
11+
if (dim > 2) result += exp(-(x[2] + 0.3) * (x[2] + 0.3));
12+
return result;
13+
}
14+
15+
static CeedScalar GetTolerance(CeedScalarType scalar_type, int dim) {
16+
CeedScalar tol;
17+
if (scalar_type == CEED_SCALAR_FP32) {
18+
if (dim == 3) tol = 0.005;
19+
else tol = 1.e-4;
20+
} else {
21+
tol = 1.e-11;
22+
}
23+
return tol;
24+
}
25+
26+
int main(int argc, char **argv) {
27+
Ceed ceed;
28+
29+
CeedInit(argv[1], &ceed);
30+
31+
for (CeedInt dim = 1; dim <= 3; dim++) {
32+
CeedVector x, x_nodes, x_points, u, u_points, v, ones;
33+
CeedBasis basis_x, basis_u;
34+
const CeedInt p = 9, q = 9, num_points = 4, x_dim = CeedIntPow(2, dim), p_dim = CeedIntPow(p, dim);
35+
CeedScalar sum_1 = 0, sum_2 = 0;
36+
37+
CeedVectorCreate(ceed, x_dim * dim, &x);
38+
CeedVectorCreate(ceed, p_dim * dim, &x_nodes);
39+
CeedVectorCreate(ceed, num_points * dim, &x_points);
40+
CeedVectorCreate(ceed, p_dim, &u);
41+
CeedVectorCreate(ceed, num_points * dim, &u_points);
42+
CeedVectorCreate(ceed, p_dim, &v);
43+
CeedVectorCreate(ceed, num_points * dim, &ones);
44+
45+
CeedVectorSetValue(ones, 1);
46+
CeedVectorSetValue(v, 0);
47+
48+
// Get nodal coordinates
49+
CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, 2, p, CEED_GAUSS_LOBATTO, &basis_x);
50+
{
51+
CeedScalar x_array[x_dim * dim];
52+
53+
for (CeedInt d = 0; d < dim; d++) {
54+
for (CeedInt i = 0; i < x_dim; i++) x_array[d * x_dim + i] = (i % CeedIntPow(2, d + 1)) / CeedIntPow(2, d) ? 1 : -1;
55+
}
56+
CeedVectorSetArray(x, CEED_MEM_HOST, CEED_COPY_VALUES, x_array);
57+
}
58+
CeedBasisApply(basis_x, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, x, x_nodes);
59+
60+
// Set values of u at nodes
61+
{
62+
const CeedScalar *x_array;
63+
CeedScalar u_array[p_dim];
64+
65+
CeedVectorGetArrayRead(x_nodes, CEED_MEM_HOST, &x_array);
66+
for (CeedInt i = 0; i < p_dim; i++) {
67+
CeedScalar coord[dim];
68+
69+
for (CeedInt d = 0; d < dim; d++) coord[d] = x_array[d * p_dim + i];
70+
u_array[i] = Eval(dim, coord);
71+
}
72+
CeedVectorRestoreArrayRead(x_nodes, &x_array);
73+
CeedVectorSetArray(u, CEED_MEM_HOST, CEED_COPY_VALUES, (CeedScalar *)&u_array);
74+
}
75+
76+
// Interpolate to arbitrary points
77+
CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p, q, CEED_GAUSS, &basis_u);
78+
{
79+
CeedScalar x_array[12] = {-0.33, -0.65, 0.16, 0.99, -0.65, 0.16, 0.99, -0.33, 0.16, 0.99, -0.33, -0.65};
80+
81+
CeedVectorSetArray(x_points, CEED_MEM_HOST, CEED_COPY_VALUES, x_array);
82+
}
83+
84+
// Calculate G u at arbitrary points, G' * 1 at dofs
85+
CeedBasisApplyAtPoints(basis_u, num_points, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, x_points, u, u_points);
86+
CeedBasisApplyAtPoints(basis_u, num_points, CEED_TRANSPOSE, CEED_EVAL_GRAD, x_points, ones, v);
87+
{
88+
const CeedScalar *u_array, *v_array, *u_points_array;
89+
90+
CeedVectorGetArrayRead(u, CEED_MEM_HOST, &u_array);
91+
CeedVectorGetArrayRead(v, CEED_MEM_HOST, &v_array);
92+
CeedVectorGetArrayRead(u_points, CEED_MEM_HOST, &u_points_array);
93+
for (CeedInt i = 0; i < p_dim; i++) sum_1 += v_array[i] * u_array[i];
94+
for (CeedInt i = 0; i < num_points * dim; i++) sum_2 += u_points_array[i];
95+
CeedVectorRestoreArrayRead(u, &u_array);
96+
CeedVectorRestoreArrayRead(v, &v_array);
97+
CeedVectorRestoreArrayRead(u_points, &u_points_array);
98+
}
99+
CeedScalar tol = GetTolerance(CEED_SCALAR_TYPE, dim);
100+
if (fabs(sum_1 - sum_2) > tol) printf("[%" CeedInt_FMT "] %f != %f\n", dim, sum_1, sum_2);
101+
102+
CeedVectorDestroy(&x);
103+
CeedVectorDestroy(&x_nodes);
104+
CeedVectorDestroy(&x_points);
105+
CeedVectorDestroy(&u);
106+
CeedVectorDestroy(&u_points);
107+
CeedVectorDestroy(&ones);
108+
CeedVectorDestroy(&v);
109+
CeedBasisDestroy(&basis_x);
110+
CeedBasisDestroy(&basis_u);
111+
}
112+
CeedDestroy(&ceed);
113+
return 0;
114+
}

0 commit comments

Comments
 (0)