xref: /libCEED/tests/t305-basis.c (revision 49aac155e7a09736f56fb3abac0f57dab29f7cbf)
14411cf47Sjeremylt /// @file
252bfb9bbSJeremy L Thompson /// Test Simultaneous Diagonalization
352bfb9bbSJeremy L Thompson /// \test Simultaneous Diagonalization
457c64913Sjeremylt #include <ceed.h>
5ba59ac12SSebastian Grimberg #include <ceed/backend.h>
6673160d7Sjeremylt #include <math.h>
7*49aac155SJeremy L Thompson #include <stdio.h>
857c64913Sjeremylt 
957c64913Sjeremylt int main(int argc, char **argv) {
1057c64913Sjeremylt   Ceed              ceed;
114fee36f0SJeremy L Thompson   CeedInt           p = 4, q = 4;
124fee36f0SJeremy L Thompson   CeedScalar        M[p * p], K[p * p], X[p * p], lambda[p];
13673160d7Sjeremylt   CeedBasis         basis;
144fee36f0SJeremy L Thompson   const CeedScalar *interpolation, *gradient, *quadrature_weights;
1557c64913Sjeremylt 
1657c64913Sjeremylt   CeedInit(argv[1], &ceed);
17aedaa0e5Sjeremylt 
18673160d7Sjeremylt   // Create mass, stiffness matrix
194fee36f0SJeremy L Thompson   CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, p, q, CEED_GAUSS, &basis);
204fee36f0SJeremy L Thompson   CeedBasisGetInterp(basis, &interpolation);
214fee36f0SJeremy L Thompson   CeedBasisGetGrad(basis, &gradient);
224fee36f0SJeremy L Thompson   CeedBasisGetQWeights(basis, &quadrature_weights);
234fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
244fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
25673160d7Sjeremylt       CeedScalar sum_m = 0, sum_k = 0;
264fee36f0SJeremy L Thompson       for (int k = 0; k < q; k++) {
274fee36f0SJeremy L Thompson         sum_m += interpolation[p * k + i] * quadrature_weights[k] * interpolation[p * k + j];
284fee36f0SJeremy L Thompson         sum_k += gradient[p * k + i] * quadrature_weights[k] * gradient[p * k + j];
29673160d7Sjeremylt       }
304fee36f0SJeremy L Thompson       M[p * i + j] = sum_m;
314fee36f0SJeremy L Thompson       K[p * i + j] = sum_k;
32fb551037Sjeremylt     }
332b730f8bSJeremy L Thompson   }
34fb551037Sjeremylt 
354fee36f0SJeremy L Thompson   CeedSimultaneousDiagonalization(ceed, K, M, X, lambda, p);
36673160d7Sjeremylt 
37673160d7Sjeremylt   // Check X^T M X = I
384fee36f0SJeremy L Thompson   CeedScalar work_array[p * p];
394fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
404fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
41673160d7Sjeremylt       CeedScalar sum = 0;
424fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += M[p * i + k] * X[p * k + j];
434fee36f0SJeremy L Thompson       work_array[p * i + j] = sum;
4452bfb9bbSJeremy L Thompson     }
452b730f8bSJeremy L Thompson   }
464fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
474fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
48673160d7Sjeremylt       CeedScalar sum = 0;
494fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += X[p * k + i] * work_array[p * k + j];
504fee36f0SJeremy L Thompson       M[p * i + j] = sum;
5152bfb9bbSJeremy L Thompson     }
522b730f8bSJeremy L Thompson   }
534fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
544fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
554fee36f0SJeremy L Thompson       if (fabs(M[p * i + j] - (i == j ? 1.0 : 0.0)) > 100. * CEED_EPSILON) {
56673160d7Sjeremylt         // LCOV_EXCL_START
574fee36f0SJeremy 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));
58673160d7Sjeremylt         // LCOV_EXCL_STOP
592b730f8bSJeremy L Thompson       }
602b730f8bSJeremy L Thompson     }
612b730f8bSJeremy L Thompson   }
62673160d7Sjeremylt 
634fee36f0SJeremy L Thompson   // Check X^T K X = Lambda
644fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
654fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
66673160d7Sjeremylt       CeedScalar sum = 0;
674fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += K[p * i + k] * X[p * k + j];
684fee36f0SJeremy L Thompson       work_array[p * i + j] = sum;
6952bfb9bbSJeremy L Thompson     }
702b730f8bSJeremy L Thompson   }
714fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
724fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
73673160d7Sjeremylt       CeedScalar sum = 0;
744fee36f0SJeremy L Thompson       for (int k = 0; k < p; k++) sum += X[p * k + i] * work_array[p * k + j];
754fee36f0SJeremy L Thompson       K[p * i + j] = sum;
76673160d7Sjeremylt     }
772b730f8bSJeremy L Thompson   }
784fee36f0SJeremy L Thompson   for (int i = 0; i < p; i++) {
794fee36f0SJeremy L Thompson     for (int j = 0; j < p; j++) {
804fee36f0SJeremy L Thompson       if (fabs(K[p * i + j] - (i == j ? lambda[i] : 0.0)) > 100. * CEED_EPSILON) {
81673160d7Sjeremylt         // LCOV_EXCL_START
824fee36f0SJeremy 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));
83673160d7Sjeremylt         // LCOV_EXCL_STOP
842b730f8bSJeremy L Thompson       }
852b730f8bSJeremy L Thompson     }
862b730f8bSJeremy L Thompson   }
87673160d7Sjeremylt 
88673160d7Sjeremylt   CeedBasisDestroy(&basis);
8957c64913Sjeremylt   CeedDestroy(&ceed);
9057c64913Sjeremylt   return 0;
9157c64913Sjeremylt }
92