1*9ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, 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.
34d537eeaSYohann //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
54d537eeaSYohann //
63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed
74d537eeaSYohann
8c0b5abf0SJeremy L Thompson #include <ceed/types.h>
9c9c2c079SJeremy L Thompson
104d537eeaSYohann /// A structure used to pass additional data to f_build_diff and f_apply_diff
112b730f8bSJeremy L Thompson struct BuildContext {
122b730f8bSJeremy L Thompson CeedInt dim, space_dim;
132b730f8bSJeremy L Thompson };
144d537eeaSYohann
154d537eeaSYohann /// libCEED Q-function for building quadrature data for a diffusion operator
f_build_diff(void * ctx,const CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)162b730f8bSJeremy L Thompson CEED_QFUNCTION(f_build_diff)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
174d537eeaSYohann BuildContext *bc = (BuildContext *)ctx;
184d537eeaSYohann // in[0] is Jacobians with shape [dim, nc=dim, Q]
194d537eeaSYohann // in[1] is quadrature weights, size (Q)
204d537eeaSYohann //
21ea61e9acSJeremy L Thompson // At every quadrature point, compute w/det(J).adj(J).adj(J)^T and store the symmetric part of the result.
22a2fa7910SValeria Barra const CeedScalar *J = in[0], *w = in[1];
23a2fa7910SValeria Barra CeedScalar *qdata = out[0];
24ee07ded2SValeria Barra
254d537eeaSYohann switch (bc->dim + 10 * bc->space_dim) {
264d537eeaSYohann case 11:
27ee07ded2SValeria Barra // Quadrature Point Loop
282b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { qdata[i] = w[i] / J[i]; }
294d537eeaSYohann break;
304d537eeaSYohann case 22:
31ee07ded2SValeria Barra // Quadrature Point Loop
322b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
33a2fa7910SValeria Barra // J: 0 2 qdata: 0 2 adj(J): J22 -J12
34288c0443SJeremy L Thompson // 1 3 2 1 -J21 J11
354d537eeaSYohann const CeedScalar J11 = J[i + Q * 0];
364d537eeaSYohann const CeedScalar J21 = J[i + Q * 1];
374d537eeaSYohann const CeedScalar J12 = J[i + Q * 2];
384d537eeaSYohann const CeedScalar J22 = J[i + Q * 3];
39a2fa7910SValeria Barra const CeedScalar qw = w[i] / (J11 * J22 - J21 * J12);
40a2fa7910SValeria Barra qdata[i + Q * 0] = qw * (J12 * J12 + J22 * J22);
41a2fa7910SValeria Barra qdata[i + Q * 1] = qw * (J11 * J11 + J21 * J21);
42a2fa7910SValeria Barra qdata[i + Q * 2] = -qw * (J11 * J12 + J21 * J22);
434d537eeaSYohann }
444d537eeaSYohann break;
454d537eeaSYohann case 33:
46ee07ded2SValeria Barra // Quadrature Point Loop
472b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
48a2fa7910SValeria Barra // J: 0 3 6 qdata: 0 5 4
49288c0443SJeremy L Thompson // 1 4 7 5 1 3
50288c0443SJeremy L Thompson // 2 5 8 4 3 2
514d537eeaSYohann const CeedScalar J11 = J[i + Q * 0];
524d537eeaSYohann const CeedScalar J21 = J[i + Q * 1];
534d537eeaSYohann const CeedScalar J31 = J[i + Q * 2];
544d537eeaSYohann const CeedScalar J12 = J[i + Q * 3];
554d537eeaSYohann const CeedScalar J22 = J[i + Q * 4];
564d537eeaSYohann const CeedScalar J32 = J[i + Q * 5];
574d537eeaSYohann const CeedScalar J13 = J[i + Q * 6];
584d537eeaSYohann const CeedScalar J23 = J[i + Q * 7];
594d537eeaSYohann const CeedScalar J33 = J[i + Q * 8];
604d537eeaSYohann const CeedScalar A11 = J22 * J33 - J23 * J32;
614d537eeaSYohann const CeedScalar A12 = J13 * J32 - J12 * J33;
624d537eeaSYohann const CeedScalar A13 = J12 * J23 - J13 * J22;
634d537eeaSYohann const CeedScalar A21 = J23 * J31 - J21 * J33;
644d537eeaSYohann const CeedScalar A22 = J11 * J33 - J13 * J31;
654d537eeaSYohann const CeedScalar A23 = J13 * J21 - J11 * J23;
664d537eeaSYohann const CeedScalar A31 = J21 * J32 - J22 * J31;
674d537eeaSYohann const CeedScalar A32 = J12 * J31 - J11 * J32;
684d537eeaSYohann const CeedScalar A33 = J11 * J22 - J12 * J21;
69a2fa7910SValeria Barra const CeedScalar qw = w[i] / (J11 * A11 + J21 * A12 + J31 * A13);
70a2fa7910SValeria Barra qdata[i + Q * 0] = qw * (A11 * A11 + A12 * A12 + A13 * A13);
71a2fa7910SValeria Barra qdata[i + Q * 1] = qw * (A21 * A21 + A22 * A22 + A23 * A23);
72a2fa7910SValeria Barra qdata[i + Q * 2] = qw * (A31 * A31 + A32 * A32 + A33 * A33);
73a2fa7910SValeria Barra qdata[i + Q * 3] = qw * (A21 * A31 + A22 * A32 + A23 * A33);
74a2fa7910SValeria Barra qdata[i + Q * 4] = qw * (A11 * A31 + A12 * A32 + A13 * A33);
75a2fa7910SValeria Barra qdata[i + Q * 5] = qw * (A11 * A21 + A12 * A22 + A13 * A23);
764d537eeaSYohann }
774d537eeaSYohann break;
784d537eeaSYohann }
794d537eeaSYohann return 0;
804d537eeaSYohann }
814d537eeaSYohann
824d537eeaSYohann /// libCEED Q-function for applying a diff operator
f_apply_diff(void * ctx,const CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)832b730f8bSJeremy L Thompson CEED_QFUNCTION(f_apply_diff)(void *ctx, const CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
844d537eeaSYohann BuildContext *bc = (BuildContext *)ctx;
854d537eeaSYohann // in[0], out[0] have shape [dim, nc=1, Q]
86a2fa7910SValeria Barra const CeedScalar *ug = in[0], *qdata = in[1];
874d537eeaSYohann CeedScalar *vg = out[0];
88ee07ded2SValeria Barra
894d537eeaSYohann switch (bc->dim) {
904d537eeaSYohann case 1:
91ee07ded2SValeria Barra // Quadrature Point Loop
922b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { vg[i] = ug[i] * qdata[i]; }
934d537eeaSYohann break;
944d537eeaSYohann case 2:
95ee07ded2SValeria Barra // Quadrature Point Loop
962b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
974d537eeaSYohann const CeedScalar ug0 = ug[i + Q * 0];
984d537eeaSYohann const CeedScalar ug1 = ug[i + Q * 1];
99a2fa7910SValeria Barra vg[i + Q * 0] = qdata[i + Q * 0] * ug0 + qdata[i + Q * 2] * ug1;
100a2fa7910SValeria Barra vg[i + Q * 1] = qdata[i + Q * 2] * ug0 + qdata[i + Q * 1] * ug1;
1014d537eeaSYohann }
1024d537eeaSYohann break;
1034d537eeaSYohann case 3:
104ee07ded2SValeria Barra // Quadrature Point Loop
1052b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
1064d537eeaSYohann const CeedScalar ug0 = ug[i + Q * 0];
1074d537eeaSYohann const CeedScalar ug1 = ug[i + Q * 1];
1084d537eeaSYohann const CeedScalar ug2 = ug[i + Q * 2];
109a2fa7910SValeria Barra vg[i + Q * 0] = qdata[i + Q * 0] * ug0 + qdata[i + Q * 5] * ug1 + qdata[i + Q * 4] * ug2;
110a2fa7910SValeria Barra vg[i + Q * 1] = qdata[i + Q * 5] * ug0 + qdata[i + Q * 1] * ug1 + qdata[i + Q * 3] * ug2;
111a2fa7910SValeria Barra vg[i + Q * 2] = qdata[i + Q * 4] * ug0 + qdata[i + Q * 3] * ug1 + qdata[i + Q * 2] * ug2;
1124d537eeaSYohann }
1134d537eeaSYohann break;
1144d537eeaSYohann }
1154d537eeaSYohann return 0;
1164d537eeaSYohann }
117