1*7e2def38SSebastian Grimberg /// @file 2*7e2def38SSebastian Grimberg /// Test assembly of H(div) mass matrix operator diagonal 3*7e2def38SSebastian Grimberg /// \test Test assembly of H(div) mass matrix operator diagonal 4*7e2def38SSebastian Grimberg #include <ceed.h> 5*7e2def38SSebastian Grimberg #include <math.h> 6*7e2def38SSebastian Grimberg #include <stdio.h> 7*7e2def38SSebastian Grimberg #include <stdlib.h> 8*7e2def38SSebastian Grimberg 9*7e2def38SSebastian Grimberg #include "t330-basis.h" 10*7e2def38SSebastian Grimberg #include "t570-operator.h" 11*7e2def38SSebastian Grimberg 12*7e2def38SSebastian Grimberg int main(int argc, char **argv) { 13*7e2def38SSebastian Grimberg Ceed ceed; 14*7e2def38SSebastian Grimberg CeedElemRestriction elem_restriction_x, elem_restriction_u; 15*7e2def38SSebastian Grimberg CeedBasis basis_x, basis_u; 16*7e2def38SSebastian Grimberg CeedQFunction qf_mass; 17*7e2def38SSebastian Grimberg CeedOperator op_mass; 18*7e2def38SSebastian Grimberg CeedVector x, assembled, u, v; 19*7e2def38SSebastian Grimberg CeedInt dim = 2, p = 8, q = 3, px = 2; 20*7e2def38SSebastian Grimberg CeedInt n_x = 1, n_y = 1; // Currently only implemented for single element 21*7e2def38SSebastian Grimberg CeedInt row, column, offset; 22*7e2def38SSebastian Grimberg CeedInt num_elem = n_x * n_y, num_faces = (n_x + 1) * n_y + (n_y + 1) * n_x; 23*7e2def38SSebastian Grimberg CeedInt num_dofs_x = (n_x + 1) * (n_y + 1), num_dofs_u = num_faces * 2, num_qpts = q * q; 24*7e2def38SSebastian Grimberg CeedInt ind_x[num_elem * px * px], ind_u[num_elem * p]; 25*7e2def38SSebastian Grimberg bool orient_u[num_elem * p]; 26*7e2def38SSebastian Grimberg CeedScalar assembled_true[num_dofs_u]; 27*7e2def38SSebastian Grimberg CeedScalar q_ref[dim * num_qpts], q_weight[num_qpts]; 28*7e2def38SSebastian Grimberg CeedScalar interp[dim * p * num_qpts], div[p * num_qpts]; 29*7e2def38SSebastian Grimberg 30*7e2def38SSebastian Grimberg CeedInit(argv[1], &ceed); 31*7e2def38SSebastian Grimberg 32*7e2def38SSebastian Grimberg // Vectors 33*7e2def38SSebastian Grimberg CeedVectorCreate(ceed, dim * num_dofs_x, &x); 34*7e2def38SSebastian Grimberg { 35*7e2def38SSebastian Grimberg CeedScalar x_array[dim * num_dofs_x]; 36*7e2def38SSebastian Grimberg 37*7e2def38SSebastian Grimberg for (CeedInt i = 0; i < n_x + 1; i++) { 38*7e2def38SSebastian Grimberg for (CeedInt j = 0; j < n_y + 1; j++) { 39*7e2def38SSebastian Grimberg x_array[i + j * (n_x + 1) + 0 * num_dofs_x] = i / (CeedScalar)n_x; 40*7e2def38SSebastian Grimberg x_array[i + j * (n_x + 1) + 1 * num_dofs_x] = j / (CeedScalar)n_y; 41*7e2def38SSebastian Grimberg } 42*7e2def38SSebastian Grimberg } 43*7e2def38SSebastian Grimberg CeedVectorSetArray(x, CEED_MEM_HOST, CEED_COPY_VALUES, x_array); 44*7e2def38SSebastian Grimberg } 45*7e2def38SSebastian Grimberg CeedVectorCreate(ceed, num_dofs_u, &u); 46*7e2def38SSebastian Grimberg CeedVectorCreate(ceed, num_dofs_u, &v); 47*7e2def38SSebastian Grimberg 48*7e2def38SSebastian Grimberg // Restrictions 49*7e2def38SSebastian Grimberg for (CeedInt i = 0; i < num_elem; i++) { 50*7e2def38SSebastian Grimberg column = i % n_x; 51*7e2def38SSebastian Grimberg row = i / n_x; 52*7e2def38SSebastian Grimberg offset = column * (px - 1) + row * (n_x + 1) * (px - 1); 53*7e2def38SSebastian Grimberg 54*7e2def38SSebastian Grimberg for (CeedInt j = 0; j < px; j++) { 55*7e2def38SSebastian Grimberg for (CeedInt k = 0; k < px; k++) { 56*7e2def38SSebastian Grimberg ind_x[px * (px * i + k) + j] = offset + k * (n_x + 1) + j; 57*7e2def38SSebastian Grimberg } 58*7e2def38SSebastian Grimberg } 59*7e2def38SSebastian Grimberg } 60*7e2def38SSebastian Grimberg bool orient_u_local[8] = {false, false, false, false, true, true, true, true}; 61*7e2def38SSebastian Grimberg CeedInt ind_u_local[8] = {0, 1, 6, 7, 2, 3, 4, 5}; 62*7e2def38SSebastian Grimberg for (CeedInt j = 0; j < n_y; j++) { 63*7e2def38SSebastian Grimberg for (CeedInt i = 0; i < n_x; i++) { 64*7e2def38SSebastian Grimberg for (CeedInt k = 0; k < p; k++) { 65*7e2def38SSebastian Grimberg ind_u[k] = ind_u_local[k]; 66*7e2def38SSebastian Grimberg orient_u[k] = orient_u_local[k]; 67*7e2def38SSebastian Grimberg } 68*7e2def38SSebastian Grimberg } 69*7e2def38SSebastian Grimberg } 70*7e2def38SSebastian Grimberg CeedElemRestrictionCreate(ceed, num_elem, px * px, dim, num_dofs_x, dim * num_dofs_x, CEED_MEM_HOST, CEED_USE_POINTER, ind_x, &elem_restriction_x); 71*7e2def38SSebastian Grimberg CeedElemRestrictionCreateOriented(ceed, num_elem, p, 1, 1, num_dofs_u, CEED_MEM_HOST, CEED_COPY_VALUES, ind_u, orient_u, &elem_restriction_u); 72*7e2def38SSebastian Grimberg 73*7e2def38SSebastian Grimberg // Bases 74*7e2def38SSebastian Grimberg CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, px, q, CEED_GAUSS, &basis_x); 75*7e2def38SSebastian Grimberg 76*7e2def38SSebastian Grimberg BuildHdivQuadrilateral(q, q_ref, q_weight, interp, div, CEED_GAUSS); 77*7e2def38SSebastian Grimberg CeedBasisCreateHdiv(ceed, CEED_TOPOLOGY_QUAD, 1, p, num_qpts, interp, div, q_ref, q_weight, &basis_u); 78*7e2def38SSebastian Grimberg 79*7e2def38SSebastian Grimberg // QFunctions 80*7e2def38SSebastian Grimberg CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass); 81*7e2def38SSebastian Grimberg CeedQFunctionAddInput(qf_mass, "weight", 1, CEED_EVAL_WEIGHT); 82*7e2def38SSebastian Grimberg CeedQFunctionAddInput(qf_mass, "dx", dim * dim, CEED_EVAL_GRAD); 83*7e2def38SSebastian Grimberg CeedQFunctionAddInput(qf_mass, "u", dim, CEED_EVAL_INTERP); 84*7e2def38SSebastian Grimberg CeedQFunctionAddOutput(qf_mass, "v", dim, CEED_EVAL_INTERP); 85*7e2def38SSebastian Grimberg 86*7e2def38SSebastian Grimberg // Operators 87*7e2def38SSebastian Grimberg CeedOperatorCreate(ceed, qf_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_mass); 88*7e2def38SSebastian Grimberg CeedOperatorSetField(op_mass, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE); 89*7e2def38SSebastian Grimberg CeedOperatorSetField(op_mass, "dx", elem_restriction_x, basis_x, x); 90*7e2def38SSebastian Grimberg CeedOperatorSetField(op_mass, "u", elem_restriction_u, basis_u, CEED_VECTOR_ACTIVE); 91*7e2def38SSebastian Grimberg CeedOperatorSetField(op_mass, "v", elem_restriction_u, basis_u, CEED_VECTOR_ACTIVE); 92*7e2def38SSebastian Grimberg 93*7e2def38SSebastian Grimberg // Assemble diagonal 94*7e2def38SSebastian Grimberg CeedVectorCreate(ceed, num_dofs_u, &assembled); 95*7e2def38SSebastian Grimberg CeedOperatorLinearAssembleDiagonal(op_mass, assembled, CEED_REQUEST_IMMEDIATE); 96*7e2def38SSebastian Grimberg 97*7e2def38SSebastian Grimberg // Manually assemble diagonal 98*7e2def38SSebastian Grimberg CeedVectorSetValue(u, 0.0); 99*7e2def38SSebastian Grimberg for (int i = 0; i < num_dofs_u; i++) { 100*7e2def38SSebastian Grimberg CeedScalar *u_array; 101*7e2def38SSebastian Grimberg const CeedScalar *v_array; 102*7e2def38SSebastian Grimberg 103*7e2def38SSebastian Grimberg // Set input 104*7e2def38SSebastian Grimberg CeedVectorGetArray(u, CEED_MEM_HOST, &u_array); 105*7e2def38SSebastian Grimberg u_array[i] = 1.0; 106*7e2def38SSebastian Grimberg if (i) u_array[i - 1] = 0.0; 107*7e2def38SSebastian Grimberg CeedVectorRestoreArray(u, &u_array); 108*7e2def38SSebastian Grimberg 109*7e2def38SSebastian Grimberg // Compute diag entry for DoF i 110*7e2def38SSebastian Grimberg CeedOperatorApply(op_mass, u, v, CEED_REQUEST_IMMEDIATE); 111*7e2def38SSebastian Grimberg 112*7e2def38SSebastian Grimberg // Retrieve entry 113*7e2def38SSebastian Grimberg CeedVectorGetArrayRead(v, CEED_MEM_HOST, &v_array); 114*7e2def38SSebastian Grimberg assembled_true[i] = v_array[i]; 115*7e2def38SSebastian Grimberg CeedVectorRestoreArrayRead(v, &v_array); 116*7e2def38SSebastian Grimberg } 117*7e2def38SSebastian Grimberg 118*7e2def38SSebastian Grimberg // Check output 119*7e2def38SSebastian Grimberg { 120*7e2def38SSebastian Grimberg const CeedScalar *assembled_array; 121*7e2def38SSebastian Grimberg 122*7e2def38SSebastian Grimberg CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembled_array); 123*7e2def38SSebastian Grimberg for (int i = 0; i < num_dofs_u; i++) { 124*7e2def38SSebastian Grimberg if (fabs(assembled_array[i] - assembled_true[i]) > 100. * CEED_EPSILON) { 125*7e2def38SSebastian Grimberg // LCOV_EXCL_START 126*7e2def38SSebastian Grimberg printf("[%" CeedInt_FMT "] Error in assembly: %f != %f\n", i, assembled_array[i], assembled_true[i]); 127*7e2def38SSebastian Grimberg // LCOV_EXCL_STOP 128*7e2def38SSebastian Grimberg } 129*7e2def38SSebastian Grimberg } 130*7e2def38SSebastian Grimberg CeedVectorRestoreArrayRead(assembled, &assembled_array); 131*7e2def38SSebastian Grimberg } 132*7e2def38SSebastian Grimberg 133*7e2def38SSebastian Grimberg // Cleanup 134*7e2def38SSebastian Grimberg CeedVectorDestroy(&x); 135*7e2def38SSebastian Grimberg CeedVectorDestroy(&assembled); 136*7e2def38SSebastian Grimberg CeedVectorDestroy(&u); 137*7e2def38SSebastian Grimberg CeedVectorDestroy(&v); 138*7e2def38SSebastian Grimberg CeedElemRestrictionDestroy(&elem_restriction_u); 139*7e2def38SSebastian Grimberg CeedElemRestrictionDestroy(&elem_restriction_x); 140*7e2def38SSebastian Grimberg CeedBasisDestroy(&basis_u); 141*7e2def38SSebastian Grimberg CeedBasisDestroy(&basis_x); 142*7e2def38SSebastian Grimberg CeedQFunctionDestroy(&qf_mass); 143*7e2def38SSebastian Grimberg CeedOperatorDestroy(&op_mass); 144*7e2def38SSebastian Grimberg CeedDestroy(&ceed); 145*7e2def38SSebastian Grimberg return 0; 146*7e2def38SSebastian Grimberg } 147