xref: /libCEED/examples/ceed/ex2-surface.h (revision c0b5abf0f23b15c4f0ada76f8abe9f8d2b6fa247)
15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
366087c08SValeria Barra //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
566087c08SValeria Barra //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
766087c08SValeria Barra 
8*c0b5abf0SJeremy L Thompson #include <ceed/types.h>
9c9c2c079SJeremy L Thompson 
1066087c08SValeria Barra /// A structure used to pass additional data to f_build_diff
112b730f8bSJeremy L Thompson struct BuildContext {
122b730f8bSJeremy L Thompson   CeedInt dim, space_dim;
132b730f8bSJeremy L Thompson };
1466087c08SValeria Barra 
1566087c08SValeria Barra /// libCEED Q-function for building quadrature data for a diffusion operator
16d37d859eSJeremy L Thompson CEED_QFUNCTION(build_diff)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
17d37d859eSJeremy L Thompson   struct BuildContext *build_data = (struct BuildContext *)ctx;
1866087c08SValeria Barra   // in[0] is Jacobians with shape [dim, nc=dim, Q]
1966087c08SValeria Barra   // in[1] is quadrature weights, size (Q)
2066087c08SValeria Barra   //
2166087c08SValeria Barra   // At every quadrature point, compute w/det(J).adj(J).adj(J)^T and store
2266087c08SValeria Barra   // the symmetric part of the result.
2366087c08SValeria Barra   const CeedScalar *J = in[0], *w = in[1];
24d1d35e2fSjeremylt   CeedScalar       *q_data = out[0];
2566087c08SValeria Barra 
26d37d859eSJeremy L Thompson   switch (build_data->dim + 10 * build_data->space_dim) {
2766087c08SValeria Barra     case 11:
282b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { q_data[i] = w[i] / J[i]; }  // End of Quadrature Point Loop
2966087c08SValeria Barra       break;
3066087c08SValeria Barra     case 22:
312b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
32d1d35e2fSjeremylt         // J: 0 2   q_data: 0 2   adj(J):  J22 -J12
3366087c08SValeria Barra         //    1 3          2 1           -J21  J11
3466087c08SValeria Barra         const CeedScalar J11 = J[i + Q * 0];
3566087c08SValeria Barra         const CeedScalar J21 = J[i + Q * 1];
3666087c08SValeria Barra         const CeedScalar J12 = J[i + Q * 2];
3766087c08SValeria Barra         const CeedScalar J22 = J[i + Q * 3];
3866087c08SValeria Barra         const CeedScalar qw  = w[i] / (J11 * J22 - J21 * J12);
39d1d35e2fSjeremylt         q_data[i + Q * 0]    = qw * (J12 * J12 + J22 * J22);
40d1d35e2fSjeremylt         q_data[i + Q * 1]    = qw * (J11 * J11 + J21 * J21);
41d1d35e2fSjeremylt         q_data[i + Q * 2]    = -qw * (J11 * J12 + J21 * J22);
4266087c08SValeria Barra       }  // End of Quadrature Point Loop
4366087c08SValeria Barra       break;
4466087c08SValeria Barra     case 33:
452b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
4666087c08SValeria Barra         // Compute the adjoint
4766087c08SValeria Barra         CeedScalar A[3][3];
4866087c08SValeria Barra         for (CeedInt j = 0; j < 3; j++)
4966087c08SValeria Barra           for (CeedInt k = 0; k < 3; k++)
5066087c08SValeria Barra             // Equivalent code with J as a VLA and no mod operations:
5166087c08SValeria Barra             // A[k][j] = J[j+1][k+1]*J[j+2][k+2] - J[j+1][k+2]*J[j+2][k+1]
5266087c08SValeria Barra             A[k][j] = J[i + Q * ((j + 1) % 3 + 3 * ((k + 1) % 3))] * J[i + Q * ((j + 2) % 3 + 3 * ((k + 2) % 3))] -
5366087c08SValeria Barra                       J[i + Q * ((j + 1) % 3 + 3 * ((k + 2) % 3))] * J[i + Q * ((j + 2) % 3 + 3 * ((k + 1) % 3))];
5466087c08SValeria Barra 
5566087c08SValeria Barra         // Compute quadrature weight / det(J)
562b730f8bSJeremy L Thompson         const CeedScalar qw = w[i] / (J[i + Q * 0] * A[0][0] + J[i + Q * 1] * A[0][1] + J[i + Q * 2] * A[0][2]);
5766087c08SValeria Barra 
5866087c08SValeria Barra         // Compute geometric factors
5966087c08SValeria Barra         // Stored in Voigt convention
6066087c08SValeria Barra         // 0 5 4
6166087c08SValeria Barra         // 5 1 3
6266087c08SValeria Barra         // 4 3 2
63d1d35e2fSjeremylt         q_data[i + Q * 0] = qw * (A[0][0] * A[0][0] + A[0][1] * A[0][1] + A[0][2] * A[0][2]);
64d1d35e2fSjeremylt         q_data[i + Q * 1] = qw * (A[1][0] * A[1][0] + A[1][1] * A[1][1] + A[1][2] * A[1][2]);
65d1d35e2fSjeremylt         q_data[i + Q * 2] = qw * (A[2][0] * A[2][0] + A[2][1] * A[2][1] + A[2][2] * A[2][2]);
66d1d35e2fSjeremylt         q_data[i + Q * 3] = qw * (A[1][0] * A[2][0] + A[1][1] * A[2][1] + A[1][2] * A[2][2]);
67d1d35e2fSjeremylt         q_data[i + Q * 4] = qw * (A[0][0] * A[2][0] + A[0][1] * A[2][1] + A[0][2] * A[2][2]);
68d1d35e2fSjeremylt         q_data[i + Q * 5] = qw * (A[0][0] * A[1][0] + A[0][1] * A[1][1] + A[0][2] * A[1][2]);
6966087c08SValeria Barra       }  // End of Quadrature Point Loop
7066087c08SValeria Barra       break;
7166087c08SValeria Barra   }
7266087c08SValeria Barra   return 0;
7366087c08SValeria Barra }
7466087c08SValeria Barra 
7566087c08SValeria Barra /// libCEED Q-function for applying a diff operator
76d37d859eSJeremy L Thompson CEED_QFUNCTION(apply_diff)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
77d37d859eSJeremy L Thompson   struct BuildContext *build_data = (struct BuildContext *)ctx;
7866087c08SValeria Barra   // in[0], out[0] have shape [dim, nc=1, Q]
79d1d35e2fSjeremylt   const CeedScalar *ug = in[0], *q_data = in[1];
8066087c08SValeria Barra   CeedScalar       *vg = out[0];
8166087c08SValeria Barra 
82d37d859eSJeremy L Thompson   switch (build_data->dim) {
8366087c08SValeria Barra     case 1:
842b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { vg[i] = ug[i] * q_data[i]; }  // End of Quadrature Point Loop
8566087c08SValeria Barra       break;
8666087c08SValeria Barra     case 2:
872b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
8866087c08SValeria Barra         // Read spatial derivatives of u
892b730f8bSJeremy L Thompson         const CeedScalar du[2] = {ug[i + Q * 0], ug[i + Q * 1]};
9066087c08SValeria Barra 
91d1d35e2fSjeremylt         // Read q_data (dXdxdXdx_T symmetric matrix)
9266087c08SValeria Barra         // Stored in Voigt convention
9366087c08SValeria Barra         // 0 2
9466087c08SValeria Barra         // 2 1
952b730f8bSJeremy L Thompson         const CeedScalar dXdxdXdx_T[2][2] = {
962b730f8bSJeremy L Thompson             {q_data[i + 0 * Q], q_data[i + 2 * Q]},
972b730f8bSJeremy L Thompson             {q_data[i + 2 * Q], q_data[i + 1 * Q]}
982b730f8bSJeremy L Thompson         };
9966087c08SValeria Barra         // j = direction of vg
1002b730f8bSJeremy L Thompson         for (int j = 0; j < 2; j++) vg[i + j * Q] = (du[0] * dXdxdXdx_T[0][j] + du[1] * dXdxdXdx_T[1][j]);
10166087c08SValeria Barra       }  // End of Quadrature Point Loop
10266087c08SValeria Barra       break;
10366087c08SValeria Barra     case 3:
1042b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
10566087c08SValeria Barra         // Read spatial derivatives of u
1062b730f8bSJeremy L Thompson         const CeedScalar du[3] = {ug[i + Q * 0], ug[i + Q * 1], ug[i + Q * 2]};
10766087c08SValeria Barra 
108d1d35e2fSjeremylt         // Read q_data (dXdxdXdx_T symmetric matrix)
10966087c08SValeria Barra         // Stored in Voigt convention
11066087c08SValeria Barra         // 0 5 4
11166087c08SValeria Barra         // 5 1 3
11266087c08SValeria Barra         // 4 3 2
1132b730f8bSJeremy L Thompson         const CeedScalar dXdxdXdx_T[3][3] = {
1142b730f8bSJeremy L Thompson             {q_data[i + 0 * Q], q_data[i + 5 * Q], q_data[i + 4 * Q]},
1152b730f8bSJeremy L Thompson             {q_data[i + 5 * Q], q_data[i + 1 * Q], q_data[i + 3 * Q]},
1162b730f8bSJeremy L Thompson             {q_data[i + 4 * Q], q_data[i + 3 * Q], q_data[i + 2 * Q]}
11766087c08SValeria Barra         };
11866087c08SValeria Barra         // j = direction of vg
1192b730f8bSJeremy L Thompson         for (int j = 0; j < 3; j++) vg[i + j * Q] = (du[0] * dXdxdXdx_T[0][j] + du[1] * dXdxdXdx_T[1][j] + du[2] * dXdxdXdx_T[2][j]);
12066087c08SValeria Barra       }  // End of Quadrature Point Loop
12166087c08SValeria Barra       break;
12266087c08SValeria Barra   }
12366087c08SValeria Barra   return 0;
12466087c08SValeria Barra }
125