xref: /libCEED/tests/t305-basis.c (revision 4fee36f0a30516a0b5ad51bf7eb3b32d83efd623)
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;
9*4fee36f0SJeremy L Thompson   CeedInt           p = 4, q = 4;
10*4fee36f0SJeremy L Thompson   CeedScalar        M[p * p], K[p * p], X[p * p], lambda[p];
11673160d7Sjeremylt   CeedBasis         basis;
12*4fee36f0SJeremy L Thompson   const CeedScalar *interpolation, *gradient, *quadrature_weights;
1357c64913Sjeremylt 
1457c64913Sjeremylt   CeedInit(argv[1], &ceed);
15aedaa0e5Sjeremylt 
16673160d7Sjeremylt   // Create mass, stiffness matrix
17*4fee36f0SJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, p, q, CEED_GAUSS, &basis);
18*4fee36f0SJeremy L Thompson   CeedBasisGetInterp(basis, &interpolation);
19*4fee36f0SJeremy L Thompson   CeedBasisGetGrad(basis, &gradient);
20*4fee36f0SJeremy L Thompson   CeedBasisGetQWeights(basis, &quadrature_weights);
21*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
22*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
23673160d7Sjeremylt       CeedScalar sum_m = 0, sum_k = 0;
24*4fee36f0SJeremy L Thompson       for (int k = 0; k < q; k++) {
25*4fee36f0SJeremy L Thompson         sum_m += interpolation[p * k + i] * quadrature_weights[k] * interpolation[p * k + j];
26*4fee36f0SJeremy L Thompson         sum_k += gradient[p * k + i] * quadrature_weights[k] * gradient[p * k + j];
27673160d7Sjeremylt       }
28*4fee36f0SJeremy L Thompson       M[p * i + j] = sum_m;
29*4fee36f0SJeremy L Thompson       K[p * i + j] = sum_k;
30fb551037Sjeremylt     }
312b730f8bSJeremy L Thompson   }
32fb551037Sjeremylt 
33*4fee36f0SJeremy L Thompson   CeedSimultaneousDiagonalization(ceed, K, M, X, lambda, p);
34673160d7Sjeremylt 
35673160d7Sjeremylt   // Check X^T M X = I
36*4fee36f0SJeremy L Thompson   CeedScalar work_array[p * p];
37*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
38*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
39673160d7Sjeremylt       CeedScalar sum = 0;
40*4fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += M[p * i + k] * X[p * k + j];
41*4fee36f0SJeremy L Thompson       work_array[p * i + j] = sum;
4252bfb9bbSJeremy L Thompson     }
432b730f8bSJeremy L Thompson   }
44*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
45*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
46673160d7Sjeremylt       CeedScalar sum = 0;
47*4fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += X[p * k + i] * work_array[p * k + j];
48*4fee36f0SJeremy L Thompson       M[p * i + j] = sum;
4952bfb9bbSJeremy L Thompson     }
502b730f8bSJeremy L Thompson   }
51*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
52*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
53*4fee36f0SJeremy L Thompson       if (fabs(M[p * i + j] - (i == j ? 1.0 : 0.0)) > 100. * CEED_EPSILON) {
54673160d7Sjeremylt         // LCOV_EXCL_START
55*4fee36f0SJeremy 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
572b730f8bSJeremy L Thompson       }
582b730f8bSJeremy L Thompson     }
592b730f8bSJeremy L Thompson   }
60673160d7Sjeremylt 
61*4fee36f0SJeremy L Thompson   // Check X^T K X = Lambda
62*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
63*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
64673160d7Sjeremylt       CeedScalar sum = 0;
65*4fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += K[p * i + k] * X[p * k + j];
66*4fee36f0SJeremy L Thompson       work_array[p * i + j] = sum;
6752bfb9bbSJeremy L Thompson     }
682b730f8bSJeremy L Thompson   }
69*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
70*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
71673160d7Sjeremylt       CeedScalar sum = 0;
72*4fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += X[p * k + i] * work_array[p * k + j];
73*4fee36f0SJeremy L Thompson       K[p * i + j] = sum;
74673160d7Sjeremylt     }
752b730f8bSJeremy L Thompson   }
76*4fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
77*4fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
78*4fee36f0SJeremy L Thompson       if (fabs(K[p * i + j] - (i == j ? lambda[i] : 0.0)) > 100. * CEED_EPSILON) {
79673160d7Sjeremylt         // LCOV_EXCL_START
80*4fee36f0SJeremy 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
822b730f8bSJeremy L Thompson       }
832b730f8bSJeremy L Thompson     }
842b730f8bSJeremy L Thompson   }
85673160d7Sjeremylt 
86673160d7Sjeremylt   CeedBasisDestroy(&basis);
8757c64913Sjeremylt   CeedDestroy(&ceed);
8857c64913Sjeremylt   return 0;
8957c64913Sjeremylt }
90