xref: /libCEED/examples/ceed/ex2-surface.h (revision 5aed82e4fa97acf4ba24a7f10a35f5303a6798e0)
1*5aed82e4SJeremy 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 
8e3bad73bSvaleriabarra #ifndef ex2_surface_h
9e3bad73bSvaleriabarra #define ex2_surface_h
10e3bad73bSvaleriabarra 
11c9c2c079SJeremy L Thompson #include <ceed.h>
12c9c2c079SJeremy L Thompson 
1366087c08SValeria Barra /// A structure used to pass additional data to f_build_diff
142b730f8bSJeremy L Thompson struct BuildContext {
152b730f8bSJeremy L Thompson   CeedInt dim, space_dim;
162b730f8bSJeremy L Thompson };
1766087c08SValeria Barra 
1866087c08SValeria Barra /// libCEED Q-function for building quadrature data for a diffusion operator
19d37d859eSJeremy L Thompson CEED_QFUNCTION(build_diff)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
20d37d859eSJeremy L Thompson   struct BuildContext *build_data = (struct BuildContext *)ctx;
2166087c08SValeria Barra   // in[0] is Jacobians with shape [dim, nc=dim, Q]
2266087c08SValeria Barra   // in[1] is quadrature weights, size (Q)
2366087c08SValeria Barra   //
2466087c08SValeria Barra   // At every quadrature point, compute w/det(J).adj(J).adj(J)^T and store
2566087c08SValeria Barra   // the symmetric part of the result.
2666087c08SValeria Barra   const CeedScalar *J = in[0], *w = in[1];
27d1d35e2fSjeremylt   CeedScalar       *q_data = out[0];
2866087c08SValeria Barra 
29d37d859eSJeremy L Thompson   switch (build_data->dim + 10 * build_data->space_dim) {
3066087c08SValeria Barra     case 11:
312b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { q_data[i] = w[i] / J[i]; }  // End of Quadrature Point Loop
3266087c08SValeria Barra       break;
3366087c08SValeria Barra     case 22:
342b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
35d1d35e2fSjeremylt         // J: 0 2   q_data: 0 2   adj(J):  J22 -J12
3666087c08SValeria Barra         //    1 3          2 1           -J21  J11
3766087c08SValeria Barra         const CeedScalar J11 = J[i + Q * 0];
3866087c08SValeria Barra         const CeedScalar J21 = J[i + Q * 1];
3966087c08SValeria Barra         const CeedScalar J12 = J[i + Q * 2];
4066087c08SValeria Barra         const CeedScalar J22 = J[i + Q * 3];
4166087c08SValeria Barra         const CeedScalar qw  = w[i] / (J11 * J22 - J21 * J12);
42d1d35e2fSjeremylt         q_data[i + Q * 0]    = qw * (J12 * J12 + J22 * J22);
43d1d35e2fSjeremylt         q_data[i + Q * 1]    = qw * (J11 * J11 + J21 * J21);
44d1d35e2fSjeremylt         q_data[i + Q * 2]    = -qw * (J11 * J12 + J21 * J22);
4566087c08SValeria Barra       }  // End of Quadrature Point Loop
4666087c08SValeria Barra       break;
4766087c08SValeria Barra     case 33:
482b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
4966087c08SValeria Barra         // Compute the adjoint
5066087c08SValeria Barra         CeedScalar A[3][3];
5166087c08SValeria Barra         for (CeedInt j = 0; j < 3; j++)
5266087c08SValeria Barra           for (CeedInt k = 0; k < 3; k++)
5366087c08SValeria Barra             // Equivalent code with J as a VLA and no mod operations:
5466087c08SValeria Barra             // A[k][j] = J[j+1][k+1]*J[j+2][k+2] - J[j+1][k+2]*J[j+2][k+1]
5566087c08SValeria Barra             A[k][j] = J[i + Q * ((j + 1) % 3 + 3 * ((k + 1) % 3))] * J[i + Q * ((j + 2) % 3 + 3 * ((k + 2) % 3))] -
5666087c08SValeria Barra                       J[i + Q * ((j + 1) % 3 + 3 * ((k + 2) % 3))] * J[i + Q * ((j + 2) % 3 + 3 * ((k + 1) % 3))];
5766087c08SValeria Barra 
5866087c08SValeria Barra         // Compute quadrature weight / det(J)
592b730f8bSJeremy 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]);
6066087c08SValeria Barra 
6166087c08SValeria Barra         // Compute geometric factors
6266087c08SValeria Barra         // Stored in Voigt convention
6366087c08SValeria Barra         // 0 5 4
6466087c08SValeria Barra         // 5 1 3
6566087c08SValeria Barra         // 4 3 2
66d1d35e2fSjeremylt         q_data[i + Q * 0] = qw * (A[0][0] * A[0][0] + A[0][1] * A[0][1] + A[0][2] * A[0][2]);
67d1d35e2fSjeremylt         q_data[i + Q * 1] = qw * (A[1][0] * A[1][0] + A[1][1] * A[1][1] + A[1][2] * A[1][2]);
68d1d35e2fSjeremylt         q_data[i + Q * 2] = qw * (A[2][0] * A[2][0] + A[2][1] * A[2][1] + A[2][2] * A[2][2]);
69d1d35e2fSjeremylt         q_data[i + Q * 3] = qw * (A[1][0] * A[2][0] + A[1][1] * A[2][1] + A[1][2] * A[2][2]);
70d1d35e2fSjeremylt         q_data[i + Q * 4] = qw * (A[0][0] * A[2][0] + A[0][1] * A[2][1] + A[0][2] * A[2][2]);
71d1d35e2fSjeremylt         q_data[i + Q * 5] = qw * (A[0][0] * A[1][0] + A[0][1] * A[1][1] + A[0][2] * A[1][2]);
7266087c08SValeria Barra       }  // End of Quadrature Point Loop
7366087c08SValeria Barra       break;
7466087c08SValeria Barra   }
7566087c08SValeria Barra   return 0;
7666087c08SValeria Barra }
7766087c08SValeria Barra 
7866087c08SValeria Barra /// libCEED Q-function for applying a diff operator
79d37d859eSJeremy L Thompson CEED_QFUNCTION(apply_diff)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
80d37d859eSJeremy L Thompson   struct BuildContext *build_data = (struct BuildContext *)ctx;
8166087c08SValeria Barra   // in[0], out[0] have shape [dim, nc=1, Q]
82d1d35e2fSjeremylt   const CeedScalar *ug = in[0], *q_data = in[1];
8366087c08SValeria Barra   CeedScalar       *vg = out[0];
8466087c08SValeria Barra 
85d37d859eSJeremy L Thompson   switch (build_data->dim) {
8666087c08SValeria Barra     case 1:
872b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { vg[i] = ug[i] * q_data[i]; }  // End of Quadrature Point Loop
8866087c08SValeria Barra       break;
8966087c08SValeria Barra     case 2:
902b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
9166087c08SValeria Barra         // Read spatial derivatives of u
922b730f8bSJeremy L Thompson         const CeedScalar du[2] = {ug[i + Q * 0], ug[i + Q * 1]};
9366087c08SValeria Barra 
94d1d35e2fSjeremylt         // Read q_data (dXdxdXdx_T symmetric matrix)
9566087c08SValeria Barra         // Stored in Voigt convention
9666087c08SValeria Barra         // 0 2
9766087c08SValeria Barra         // 2 1
982b730f8bSJeremy L Thompson         const CeedScalar dXdxdXdx_T[2][2] = {
992b730f8bSJeremy L Thompson             {q_data[i + 0 * Q], q_data[i + 2 * Q]},
1002b730f8bSJeremy L Thompson             {q_data[i + 2 * Q], q_data[i + 1 * Q]}
1012b730f8bSJeremy L Thompson         };
10266087c08SValeria Barra         // j = direction of vg
1032b730f8bSJeremy 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]);
10466087c08SValeria Barra       }  // End of Quadrature Point Loop
10566087c08SValeria Barra       break;
10666087c08SValeria Barra     case 3:
1072b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
10866087c08SValeria Barra         // Read spatial derivatives of u
1092b730f8bSJeremy L Thompson         const CeedScalar du[3] = {ug[i + Q * 0], ug[i + Q * 1], ug[i + Q * 2]};
11066087c08SValeria Barra 
111d1d35e2fSjeremylt         // Read q_data (dXdxdXdx_T symmetric matrix)
11266087c08SValeria Barra         // Stored in Voigt convention
11366087c08SValeria Barra         // 0 5 4
11466087c08SValeria Barra         // 5 1 3
11566087c08SValeria Barra         // 4 3 2
1162b730f8bSJeremy L Thompson         const CeedScalar dXdxdXdx_T[3][3] = {
1172b730f8bSJeremy L Thompson             {q_data[i + 0 * Q], q_data[i + 5 * Q], q_data[i + 4 * Q]},
1182b730f8bSJeremy L Thompson             {q_data[i + 5 * Q], q_data[i + 1 * Q], q_data[i + 3 * Q]},
1192b730f8bSJeremy L Thompson             {q_data[i + 4 * Q], q_data[i + 3 * Q], q_data[i + 2 * Q]}
12066087c08SValeria Barra         };
12166087c08SValeria Barra         // j = direction of vg
1222b730f8bSJeremy 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]);
12366087c08SValeria Barra       }  // End of Quadrature Point Loop
12466087c08SValeria Barra       break;
12566087c08SValeria Barra   }
12666087c08SValeria Barra   return 0;
12766087c08SValeria Barra }
128e3bad73bSvaleriabarra 
129e3bad73bSvaleriabarra #endif  // ex2_surface_h
130