14411cf47Sjeremylt /// @file
252bfb9bbSJeremy L Thompson /// Test Simultaneous Diagonalization
352bfb9bbSJeremy L Thompson /// \test Simultaneous Diagonalization
4f85e4a7bSJeremy L Thompson
5f85e4a7bSJeremy L Thompson //TESTARGS(only="cpu") {ceed_resource}
657c64913Sjeremylt #include <ceed.h>
7ba59ac12SSebastian Grimberg #include <ceed/backend.h>
8673160d7Sjeremylt #include <math.h>
949aac155SJeremy L Thompson #include <stdio.h>
1057c64913Sjeremylt
main(int argc,char ** argv)1157c64913Sjeremylt int main(int argc, char **argv) {
1257c64913Sjeremylt Ceed ceed;
134fee36f0SJeremy L Thompson CeedInt p = 4, q = 4;
144fee36f0SJeremy L Thompson CeedScalar M[p * p], K[p * p], X[p * p], lambda[p];
15673160d7Sjeremylt CeedBasis basis;
164fee36f0SJeremy L Thompson const CeedScalar *interpolation, *gradient, *quadrature_weights;
1757c64913Sjeremylt
1857c64913Sjeremylt CeedInit(argv[1], &ceed);
19aedaa0e5Sjeremylt
20673160d7Sjeremylt // Create mass, stiffness matrix
214fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, p, q, CEED_GAUSS, &basis);
224fee36f0SJeremy L Thompson CeedBasisGetInterp(basis, &interpolation);
234fee36f0SJeremy L Thompson CeedBasisGetGrad(basis, &gradient);
244fee36f0SJeremy L Thompson CeedBasisGetQWeights(basis, &quadrature_weights);
254fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
264fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
27673160d7Sjeremylt CeedScalar sum_m = 0, sum_k = 0;
284fee36f0SJeremy L Thompson for (int k = 0; k < q; k++) {
294fee36f0SJeremy L Thompson sum_m += interpolation[p * k + i] * quadrature_weights[k] * interpolation[p * k + j];
304fee36f0SJeremy L Thompson sum_k += gradient[p * k + i] * quadrature_weights[k] * gradient[p * k + j];
31673160d7Sjeremylt }
324fee36f0SJeremy L Thompson M[p * i + j] = sum_m;
334fee36f0SJeremy L Thompson K[p * i + j] = sum_k;
34fb551037Sjeremylt }
352b730f8bSJeremy L Thompson }
36fb551037Sjeremylt
374fee36f0SJeremy L Thompson CeedSimultaneousDiagonalization(ceed, K, M, X, lambda, p);
38673160d7Sjeremylt
39673160d7Sjeremylt // Check X^T M X = I
404fee36f0SJeremy L Thompson CeedScalar work_array[p * p];
414fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
424fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
43673160d7Sjeremylt CeedScalar sum = 0;
444fee36f0SJeremy L Thompson for (int k = 0; k < p; k++) sum += M[p * i + k] * X[p * k + j];
454fee36f0SJeremy L Thompson work_array[p * i + j] = sum;
4652bfb9bbSJeremy L Thompson }
472b730f8bSJeremy L Thompson }
484fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
494fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
50673160d7Sjeremylt CeedScalar sum = 0;
514fee36f0SJeremy L Thompson for (int k = 0; k < p; k++) sum += X[p * k + i] * work_array[p * k + j];
524fee36f0SJeremy L Thompson M[p * i + j] = sum;
5352bfb9bbSJeremy L Thompson }
542b730f8bSJeremy L Thompson }
554fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
564fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
574fee36f0SJeremy L Thompson if (fabs(M[p * i + j] - (i == j ? 1.0 : 0.0)) > 100. * CEED_EPSILON) {
58673160d7Sjeremylt // LCOV_EXCL_START
594fee36f0SJeremy 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));
60673160d7Sjeremylt // LCOV_EXCL_STOP
612b730f8bSJeremy L Thompson }
622b730f8bSJeremy L Thompson }
632b730f8bSJeremy L Thompson }
64673160d7Sjeremylt
654fee36f0SJeremy L Thompson // Check X^T K X = Lambda
664fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
674fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
68673160d7Sjeremylt CeedScalar sum = 0;
694fee36f0SJeremy L Thompson for (int k = 0; k < p; k++) sum += K[p * i + k] * X[p * k + j];
704fee36f0SJeremy L Thompson work_array[p * i + j] = sum;
7152bfb9bbSJeremy L Thompson }
722b730f8bSJeremy L Thompson }
734fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
744fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
75673160d7Sjeremylt CeedScalar sum = 0;
764fee36f0SJeremy L Thompson for (int k = 0; k < p; k++) sum += X[p * k + i] * work_array[p * k + j];
774fee36f0SJeremy L Thompson K[p * i + j] = sum;
78673160d7Sjeremylt }
792b730f8bSJeremy L Thompson }
804fee36f0SJeremy L Thompson for (int i = 0; i < p; i++) {
814fee36f0SJeremy L Thompson for (int j = 0; j < p; j++) {
82*17937fbfSZach Atkins if (fabs(K[p * i + j] - (i == j ? lambda[i] : 0.0)) > 1e3 * CEED_EPSILON) {
83673160d7Sjeremylt // LCOV_EXCL_START
844fee36f0SJeremy 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));
85673160d7Sjeremylt // LCOV_EXCL_STOP
862b730f8bSJeremy L Thompson }
872b730f8bSJeremy L Thompson }
882b730f8bSJeremy L Thompson }
89673160d7Sjeremylt
90673160d7Sjeremylt CeedBasisDestroy(&basis);
9157c64913Sjeremylt CeedDestroy(&ceed);
9257c64913Sjeremylt return 0;
9357c64913Sjeremylt }
94