xref: /libCEED/tests/t570-operator.c (revision 506b1a0c535297a01950817d4491440b9ddb5287)
17e2def38SSebastian Grimberg /// @file
2*506b1a0cSSebastian Grimberg /// Test full assembly of an identity operator (see t509)
3*506b1a0cSSebastian Grimberg /// \test Test full assembly of an identity operator
47e2def38SSebastian Grimberg #include <ceed.h>
57e2def38SSebastian Grimberg #include <math.h>
67e2def38SSebastian Grimberg #include <stdio.h>
77e2def38SSebastian Grimberg #include <stdlib.h>
87e2def38SSebastian Grimberg 
main(int argc,char ** argv)97e2def38SSebastian Grimberg int main(int argc, char **argv) {
107e2def38SSebastian Grimberg   Ceed                ceed;
11*506b1a0cSSebastian Grimberg   CeedElemRestriction elem_restriction_u, elem_restriction_u_i;
12*506b1a0cSSebastian Grimberg   CeedBasis           basis_u;
13*506b1a0cSSebastian Grimberg   CeedQFunction       qf_identity;
14*506b1a0cSSebastian Grimberg   CeedOperator        op_identity;
15*506b1a0cSSebastian Grimberg   CeedVector          u, v;
16*506b1a0cSSebastian Grimberg   CeedInt             num_elem = 15, p = 5, q = 8;
17*506b1a0cSSebastian Grimberg   CeedInt             num_nodes = num_elem * (p - 1) + 1;
18*506b1a0cSSebastian Grimberg   CeedInt             ind_u[num_elem * p];
19*506b1a0cSSebastian Grimberg   CeedScalar          assembled_values[num_nodes * q * num_elem];
20*506b1a0cSSebastian Grimberg   CeedScalar          assembled_true[num_nodes * q * num_elem];
217e2def38SSebastian Grimberg 
227e2def38SSebastian Grimberg   CeedInit(argv[1], &ceed);
237e2def38SSebastian Grimberg 
24*506b1a0cSSebastian Grimberg   CeedVectorCreate(ceed, num_nodes, &u);
25*506b1a0cSSebastian Grimberg   CeedVectorCreate(ceed, q * num_elem, &v);
267e2def38SSebastian Grimberg 
277e2def38SSebastian Grimberg   // Restrictions
287e2def38SSebastian Grimberg   for (CeedInt i = 0; i < num_elem; i++) {
29*506b1a0cSSebastian Grimberg     for (CeedInt j = 0; j < p; j++) {
30*506b1a0cSSebastian Grimberg       ind_u[p * i + j] = i * (p - 1) + j;
31*506b1a0cSSebastian Grimberg     }
32*506b1a0cSSebastian Grimberg   }
33*506b1a0cSSebastian Grimberg   CeedElemRestrictionCreate(ceed, num_elem, p, 1, 1, num_nodes, CEED_MEM_HOST, CEED_USE_POINTER, ind_u, &elem_restriction_u);
347e2def38SSebastian Grimberg 
35*506b1a0cSSebastian Grimberg   CeedInt strides_u_i[3] = {1, q, q};
36*506b1a0cSSebastian Grimberg   CeedElemRestrictionCreateStrided(ceed, num_elem, q, 1, q * num_elem, strides_u_i, &elem_restriction_u_i);
377e2def38SSebastian Grimberg 
387e2def38SSebastian Grimberg   // Bases
39*506b1a0cSSebastian Grimberg   CeedBasisCreateTensorH1Lagrange(ceed, 1, 1, p, q, CEED_GAUSS, &basis_u);
407e2def38SSebastian Grimberg 
41*506b1a0cSSebastian Grimberg   // QFunction
42*506b1a0cSSebastian Grimberg   CeedQFunctionCreateIdentity(ceed, 1, CEED_EVAL_INTERP, CEED_EVAL_NONE, &qf_identity);
437e2def38SSebastian Grimberg 
447e2def38SSebastian Grimberg   // Operators
45*506b1a0cSSebastian Grimberg   CeedOperatorCreate(ceed, qf_identity, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_identity);
46*506b1a0cSSebastian Grimberg   CeedOperatorSetField(op_identity, "input", elem_restriction_u, basis_u, CEED_VECTOR_ACTIVE);
47*506b1a0cSSebastian Grimberg   CeedOperatorSetField(op_identity, "output", elem_restriction_u_i, CEED_BASIS_NONE, CEED_VECTOR_ACTIVE);
487e2def38SSebastian Grimberg 
49*506b1a0cSSebastian Grimberg   // Fully assemble operator
50*506b1a0cSSebastian Grimberg   CeedSize   num_entries;
51*506b1a0cSSebastian Grimberg   CeedInt   *rows;
52*506b1a0cSSebastian Grimberg   CeedInt   *cols;
53*506b1a0cSSebastian Grimberg   CeedVector assembled;
547e2def38SSebastian Grimberg 
55*506b1a0cSSebastian Grimberg   for (CeedInt k = 0; k < num_nodes * q * num_elem; ++k) {
56*506b1a0cSSebastian Grimberg     assembled_values[k] = 0.0;
57*506b1a0cSSebastian Grimberg     assembled_true[k]   = 0.0;
58*506b1a0cSSebastian Grimberg   }
59*506b1a0cSSebastian Grimberg   CeedOperatorLinearAssembleSymbolic(op_identity, &num_entries, &rows, &cols);
60*506b1a0cSSebastian Grimberg   CeedVectorCreate(ceed, num_entries, &assembled);
61*506b1a0cSSebastian Grimberg   CeedOperatorLinearAssemble(op_identity, assembled);
62*506b1a0cSSebastian Grimberg   {
63*506b1a0cSSebastian Grimberg     const CeedScalar *assembled_array;
64*506b1a0cSSebastian Grimberg 
65*506b1a0cSSebastian Grimberg     CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembled_array);
66*506b1a0cSSebastian Grimberg     for (CeedInt k = 0; k < num_entries; ++k) {
67*506b1a0cSSebastian Grimberg       assembled_values[rows[k] * num_nodes + cols[k]] += assembled_array[k];
68*506b1a0cSSebastian Grimberg     }
69*506b1a0cSSebastian Grimberg     CeedVectorRestoreArrayRead(assembled, &assembled_array);
70*506b1a0cSSebastian Grimberg   }
71*506b1a0cSSebastian Grimberg 
72*506b1a0cSSebastian Grimberg   // Manually assemble operator
737e2def38SSebastian Grimberg   CeedVectorSetValue(u, 0.0);
74*506b1a0cSSebastian Grimberg   for (CeedInt j = 0; j < num_nodes; j++) {
757e2def38SSebastian Grimberg     CeedScalar       *u_array;
767e2def38SSebastian Grimberg     const CeedScalar *v_array;
777e2def38SSebastian Grimberg 
787e2def38SSebastian Grimberg     // Set input
797e2def38SSebastian Grimberg     CeedVectorGetArray(u, CEED_MEM_HOST, &u_array);
80*506b1a0cSSebastian Grimberg     u_array[j] = 1.0;
81*506b1a0cSSebastian Grimberg     if (j) u_array[j - 1] = 0.0;
827e2def38SSebastian Grimberg     CeedVectorRestoreArray(u, &u_array);
837e2def38SSebastian Grimberg 
84*506b1a0cSSebastian Grimberg     // Compute entries for column j
85*506b1a0cSSebastian Grimberg     CeedOperatorApply(op_identity, u, v, CEED_REQUEST_IMMEDIATE);
867e2def38SSebastian Grimberg 
877e2def38SSebastian Grimberg     CeedVectorGetArrayRead(v, CEED_MEM_HOST, &v_array);
88*506b1a0cSSebastian Grimberg     for (CeedInt i = 0; i < q * num_elem; i++) assembled_true[i * num_nodes + j] = v_array[i];
897e2def38SSebastian Grimberg     CeedVectorRestoreArrayRead(v, &v_array);
907e2def38SSebastian Grimberg   }
917e2def38SSebastian Grimberg 
927e2def38SSebastian Grimberg   // Check output
93*506b1a0cSSebastian Grimberg   for (CeedInt i = 0; i < q * num_elem; i++) {
94*506b1a0cSSebastian Grimberg     for (CeedInt j = 0; j < num_nodes; j++) {
95*506b1a0cSSebastian Grimberg       if (fabs(assembled_values[i * num_nodes + j] - assembled_true[i * num_nodes + j]) > 100. * CEED_EPSILON) {
967e2def38SSebastian Grimberg         // LCOV_EXCL_START
97*506b1a0cSSebastian Grimberg         printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] Error in assembly: %f != %f\n", i, j, assembled_values[i * num_nodes + j],
98*506b1a0cSSebastian Grimberg                assembled_true[i * num_nodes + j]);
997e2def38SSebastian Grimberg         // LCOV_EXCL_STOP
1007e2def38SSebastian Grimberg       }
1017e2def38SSebastian Grimberg     }
1027e2def38SSebastian Grimberg   }
1037e2def38SSebastian Grimberg 
1047e2def38SSebastian Grimberg   // Cleanup
105*506b1a0cSSebastian Grimberg   free(rows);
106*506b1a0cSSebastian Grimberg   free(cols);
1077e2def38SSebastian Grimberg   CeedVectorDestroy(&u);
1087e2def38SSebastian Grimberg   CeedVectorDestroy(&v);
109*506b1a0cSSebastian Grimberg   CeedVectorDestroy(&assembled);
1107e2def38SSebastian Grimberg   CeedElemRestrictionDestroy(&elem_restriction_u);
111*506b1a0cSSebastian Grimberg   CeedElemRestrictionDestroy(&elem_restriction_u_i);
1127e2def38SSebastian Grimberg   CeedBasisDestroy(&basis_u);
113*506b1a0cSSebastian Grimberg   CeedQFunctionDestroy(&qf_identity);
114*506b1a0cSSebastian Grimberg   CeedOperatorDestroy(&op_identity);
1157e2def38SSebastian Grimberg   CeedDestroy(&ceed);
1167e2def38SSebastian Grimberg   return 0;
1177e2def38SSebastian Grimberg }
118