xref: /libCEED/tests/t305-basis.c (revision 2b730f8b5a9c809740a0b3b302db43a719c636b1)
14411cf47Sjeremylt /// @file
252bfb9bbSJeremy L Thompson /// Test Simultaneous Diagonalization
352bfb9bbSJeremy L Thompson /// \test Simultaneous Diagonalization
457c64913Sjeremylt #include <ceed.h>
5673160d7Sjeremylt #include <math.h>
657c64913Sjeremylt 
757c64913Sjeremylt int main(int argc, char **argv) {
857c64913Sjeremylt   Ceed       ceed;
9673160d7Sjeremylt   CeedInt    P = 4, Q = 4;
10673160d7Sjeremylt   CeedScalar M[P * P], K[P * P], X[P * P], lambda[P];
11673160d7Sjeremylt   CeedBasis  basis;
1257c64913Sjeremylt 
1357c64913Sjeremylt   CeedInit(argv[1], &ceed);
14aedaa0e5Sjeremylt 
15673160d7Sjeremylt   // Create mass, stiffness matrix
16673160d7Sjeremylt   CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, P, Q, CEED_GAUSS, &basis);
17673160d7Sjeremylt   const CeedScalar *interp, *grad, *quad_weights;
18673160d7Sjeremylt   CeedBasisGetInterp(basis, &interp);
19673160d7Sjeremylt   CeedBasisGetGrad(basis, &grad);
20673160d7Sjeremylt   CeedBasisGetQWeights(basis, &quad_weights);
21*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
22673160d7Sjeremylt     for (int j = 0; j < P; j++) {
23673160d7Sjeremylt       CeedScalar sum_m = 0, sum_k = 0;
24673160d7Sjeremylt       for (int k = 0; k < Q; k++) {
25673160d7Sjeremylt         sum_m += interp[P * k + i] * quad_weights[k] * interp[P * k + j];
26673160d7Sjeremylt         sum_k += grad[P * k + i] * quad_weights[k] * grad[P * k + j];
27673160d7Sjeremylt       }
28673160d7Sjeremylt       M[P * i + j] = sum_m;
29673160d7Sjeremylt       K[P * i + j] = sum_k;
30fb551037Sjeremylt     }
31*2b730f8bSJeremy L Thompson   }
32fb551037Sjeremylt 
33673160d7Sjeremylt   CeedSimultaneousDiagonalization(ceed, K, M, X, lambda, P);
34673160d7Sjeremylt 
35673160d7Sjeremylt   // Check X^T M X = I
36673160d7Sjeremylt   CeedScalar work[P * P];
37*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
38673160d7Sjeremylt     for (int j = 0; j < P; j++) {
39673160d7Sjeremylt       CeedScalar sum = 0;
40*2b730f8bSJeremy L Thompson       for (int k = 0; k < P; k++) sum += M[P * i + k] * X[P * k + j];
41673160d7Sjeremylt       work[P * i + j] = sum;
4252bfb9bbSJeremy L Thompson     }
43*2b730f8bSJeremy L Thompson   }
44*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
45673160d7Sjeremylt     for (int j = 0; j < P; j++) {
46673160d7Sjeremylt       CeedScalar sum = 0;
47*2b730f8bSJeremy L Thompson       for (int k = 0; k < P; k++) sum += X[P * k + i] * work[P * k + j];
48673160d7Sjeremylt       M[P * i + j] = sum;
4952bfb9bbSJeremy L Thompson     }
50*2b730f8bSJeremy L Thompson   }
51*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
52*2b730f8bSJeremy L Thompson     for (int j = 0; j < P; j++) {
53*2b730f8bSJeremy L Thompson       if (fabs(M[P * i + j] - (i == j ? 1.0 : 0.0)) > 100. * CEED_EPSILON) {
54673160d7Sjeremylt         // LCOV_EXCL_START
55*2b730f8bSJeremy L Thompson         printf("Error in diagonalization of M [%" CeedInt_FMT ", %" CeedInt_FMT "]: %f != %f\n", i, j, M[P * i + j], (i == j ? 1.0 : 0.0));
56673160d7Sjeremylt         // LCOV_EXCL_STOP
57*2b730f8bSJeremy L Thompson       }
58*2b730f8bSJeremy L Thompson     }
59*2b730f8bSJeremy L Thompson   }
60673160d7Sjeremylt 
61673160d7Sjeremylt   // Check X^T K X = Lamda
62*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
63673160d7Sjeremylt     for (int j = 0; j < P; j++) {
64673160d7Sjeremylt       CeedScalar sum = 0;
65*2b730f8bSJeremy L Thompson       for (int k = 0; k < P; k++) sum += K[P * i + k] * X[P * k + j];
66673160d7Sjeremylt       work[P * i + j] = sum;
6752bfb9bbSJeremy L Thompson     }
68*2b730f8bSJeremy L Thompson   }
69*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
70673160d7Sjeremylt     for (int j = 0; j < P; j++) {
71673160d7Sjeremylt       CeedScalar sum = 0;
72*2b730f8bSJeremy L Thompson       for (int k = 0; k < P; k++) sum += X[P * k + i] * work[P * k + j];
73673160d7Sjeremylt       K[P * i + j] = sum;
74673160d7Sjeremylt     }
75*2b730f8bSJeremy L Thompson   }
76*2b730f8bSJeremy L Thompson   for (int i = 0; i < P; i++) {
77*2b730f8bSJeremy L Thompson     for (int j = 0; j < P; j++) {
78*2b730f8bSJeremy L Thompson       if (fabs(K[P * i + j] - (i == j ? lambda[i] : 0.0)) > 100. * CEED_EPSILON) {
79673160d7Sjeremylt         // LCOV_EXCL_START
80*2b730f8bSJeremy L Thompson         printf("Error in diagonalization of K [%" CeedInt_FMT ", %" CeedInt_FMT "]: %f != %f\n", i, j, K[P * i + j], (i == j ? lambda[i] : 0.0));
81673160d7Sjeremylt         // LCOV_EXCL_STOP
82*2b730f8bSJeremy L Thompson       }
83*2b730f8bSJeremy L Thompson     }
84*2b730f8bSJeremy L Thompson   }
85673160d7Sjeremylt 
86673160d7Sjeremylt   CeedBasisDestroy(&basis);
8757c64913Sjeremylt   CeedDestroy(&ceed);
8857c64913Sjeremylt   return 0;
8957c64913Sjeremylt }
90