1e2f04181SAndrew T. Barker /// @file 2e2f04181SAndrew T. Barker /// Test full assembly of mass and Poisson operator (see t536) 3e2f04181SAndrew T. Barker /// \test Test full assembly of mass and Poisson operator 4e2f04181SAndrew T. Barker #include <ceed.h> 5e2f04181SAndrew T. Barker #include <stdlib.h> 6e2f04181SAndrew T. Barker #include <math.h> 7e2f04181SAndrew T. Barker #include "t320-basis.h" 8e2f04181SAndrew T. Barker #include "t535-operator.h" 9e2f04181SAndrew T. Barker 10e2f04181SAndrew T. Barker int main(int argc, char **argv) { 11e2f04181SAndrew T. Barker Ceed ceed; 12*d1d35e2fSjeremylt CeedElemRestriction elem_restr_x, elem_restr_u, 13*d1d35e2fSjeremylt elem_restr_qd_mass_i, elem_restr_qd_diff_i; 14*d1d35e2fSjeremylt CeedBasis basis_x, basis_u; 15e2f04181SAndrew T. Barker CeedQFunction qf_setup_mass, qf_setup_diff, qf_apply; 16e2f04181SAndrew T. Barker CeedOperator op_setup_mass, op_setup_diff, op_apply; 17*d1d35e2fSjeremylt CeedVector q_data_mass, q_data_diff, X, U, V; 18*d1d35e2fSjeremylt CeedInt num_elem = 12, dim = 2, P = 6, Q = 4; 19*d1d35e2fSjeremylt CeedInt n_x = 3, n_y = 2; 20e2f04181SAndrew T. Barker CeedInt row, col, offset; 21*d1d35e2fSjeremylt CeedInt num_dofs = (n_x*2+1)*(n_y*2+1), num_qpts = num_elem*Q; 22*d1d35e2fSjeremylt CeedInt ind_x[num_elem*P*P]; 23*d1d35e2fSjeremylt CeedScalar assembled[num_dofs*num_dofs]; 24*d1d35e2fSjeremylt CeedScalar x[dim*num_dofs], assembled_true[num_dofs*num_dofs]; 25*d1d35e2fSjeremylt CeedScalar q_ref[dim*Q], q_weight[Q]; 26e2f04181SAndrew T. Barker CeedScalar interp[P*Q], grad[dim*P*Q]; 27e2f04181SAndrew T. Barker CeedScalar *u; 28e2f04181SAndrew T. Barker const CeedScalar *v; 29e2f04181SAndrew T. Barker 30e2f04181SAndrew T. Barker CeedInit(argv[1], &ceed); 31e2f04181SAndrew T. Barker 32e2f04181SAndrew T. Barker // DoF Coordinates 33*d1d35e2fSjeremylt for (CeedInt i=0; i<num_dofs; i++) { 34*d1d35e2fSjeremylt x[i] = (1. / (n_x*2)) * (CeedScalar) (i % (n_x*2+1)); 35*d1d35e2fSjeremylt x[i+num_dofs] = (1. / (n_y*2)) * (CeedScalar) (i / (n_x*2+1)); 36e2f04181SAndrew T. Barker } 37*d1d35e2fSjeremylt CeedVectorCreate(ceed, dim*num_dofs, &X); 38e2f04181SAndrew T. Barker CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x); 39e2f04181SAndrew T. Barker 40e2f04181SAndrew T. Barker // Qdata Vectors 41*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts, &q_data_mass); 42*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts*dim*(dim+1)/2, &q_data_diff); 43e2f04181SAndrew T. Barker 44e2f04181SAndrew T. Barker // Element Setup 45*d1d35e2fSjeremylt for (CeedInt i=0; i<num_elem/2; i++) { 46*d1d35e2fSjeremylt col = i % n_x; 47*d1d35e2fSjeremylt row = i / n_x; 48*d1d35e2fSjeremylt offset = col*2 + row*(n_x*2+1)*2; 49e2f04181SAndrew T. Barker 50*d1d35e2fSjeremylt ind_x[i*2*P + 0] = 2 + offset; 51*d1d35e2fSjeremylt ind_x[i*2*P + 1] = 9 + offset; 52*d1d35e2fSjeremylt ind_x[i*2*P + 2] = 16 + offset; 53*d1d35e2fSjeremylt ind_x[i*2*P + 3] = 1 + offset; 54*d1d35e2fSjeremylt ind_x[i*2*P + 4] = 8 + offset; 55*d1d35e2fSjeremylt ind_x[i*2*P + 5] = 0 + offset; 56e2f04181SAndrew T. Barker 57*d1d35e2fSjeremylt ind_x[i*2*P + 6] = 14 + offset; 58*d1d35e2fSjeremylt ind_x[i*2*P + 7] = 7 + offset; 59*d1d35e2fSjeremylt ind_x[i*2*P + 8] = 0 + offset; 60*d1d35e2fSjeremylt ind_x[i*2*P + 9] = 15 + offset; 61*d1d35e2fSjeremylt ind_x[i*2*P + 10] = 8 + offset; 62*d1d35e2fSjeremylt ind_x[i*2*P + 11] = 16 + offset; 63e2f04181SAndrew T. Barker } 64e2f04181SAndrew T. Barker 65e2f04181SAndrew T. Barker // Restrictions 66*d1d35e2fSjeremylt CeedElemRestrictionCreate(ceed, num_elem, P, dim, num_dofs, dim*num_dofs, 67*d1d35e2fSjeremylt CEED_MEM_HOST, CEED_USE_POINTER, ind_x, &elem_restr_x); 68e2f04181SAndrew T. Barker 69*d1d35e2fSjeremylt CeedElemRestrictionCreate(ceed, num_elem, P, 1, 1, num_dofs, CEED_MEM_HOST, 70*d1d35e2fSjeremylt CEED_USE_POINTER, ind_x, &elem_restr_u); 71*d1d35e2fSjeremylt CeedInt strides_qd_mass[3] = {1, Q, Q}; 72*d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, Q, 1, num_qpts, 73*d1d35e2fSjeremylt strides_qd_mass, 74*d1d35e2fSjeremylt &elem_restr_qd_mass_i); 75e2f04181SAndrew T. Barker 76*d1d35e2fSjeremylt CeedInt strides_qd_diff[3] = {1, Q, Q *dim *(dim+1)/2}; 77*d1d35e2fSjeremylt CeedElemRestrictionCreateStrided(ceed, num_elem, Q, dim*(dim+1)/2, 78*d1d35e2fSjeremylt dim*(dim+1)/2*num_qpts, 79*d1d35e2fSjeremylt strides_qd_diff, &elem_restr_qd_diff_i); 80e2f04181SAndrew T. Barker 81e2f04181SAndrew T. Barker // Bases 82*d1d35e2fSjeremylt buildmats(q_ref, q_weight, interp, grad); 83*d1d35e2fSjeremylt CeedBasisCreateH1(ceed, CEED_TRIANGLE, dim, P, Q, interp, grad, q_ref, 84*d1d35e2fSjeremylt q_weight, &basis_x); 85e2f04181SAndrew T. Barker 86*d1d35e2fSjeremylt buildmats(q_ref, q_weight, interp, grad); 87*d1d35e2fSjeremylt CeedBasisCreateH1(ceed, CEED_TRIANGLE, 1, P, Q, interp, grad, q_ref, 88*d1d35e2fSjeremylt q_weight, &basis_u); 89e2f04181SAndrew T. Barker 90e2f04181SAndrew T. Barker // QFunction - setup mass 91e2f04181SAndrew T. Barker CeedQFunctionCreateInterior(ceed, 1, setup_mass, setup_mass_loc, 92e2f04181SAndrew T. Barker &qf_setup_mass); 93e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_setup_mass, "dx", dim*dim, CEED_EVAL_GRAD); 94e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_setup_mass, "_weight", 1, CEED_EVAL_WEIGHT); 95e2f04181SAndrew T. Barker CeedQFunctionAddOutput(qf_setup_mass, "qdata", 1, CEED_EVAL_NONE); 96e2f04181SAndrew T. Barker 97e2f04181SAndrew T. Barker // Operator - setup mass 98e2f04181SAndrew T. Barker CeedOperatorCreate(ceed, qf_setup_mass, CEED_QFUNCTION_NONE, 99e2f04181SAndrew T. Barker CEED_QFUNCTION_NONE, &op_setup_mass); 100*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "dx", elem_restr_x, basis_x, 101*d1d35e2fSjeremylt CEED_VECTOR_ACTIVE); 102*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "_weight", CEED_ELEMRESTRICTION_NONE, 103*d1d35e2fSjeremylt basis_x, 104e2f04181SAndrew T. Barker CEED_VECTOR_NONE); 105*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_mass, "qdata", elem_restr_qd_mass_i, 106e2f04181SAndrew T. Barker CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 107e2f04181SAndrew T. Barker 108e2f04181SAndrew T. Barker // QFunction - setup diff 109e2f04181SAndrew T. Barker CeedQFunctionCreateInterior(ceed, 1, setup_diff, setup_diff_loc, 110e2f04181SAndrew T. Barker &qf_setup_diff); 111e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_setup_diff, "dx", dim*dim, CEED_EVAL_GRAD); 112e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_setup_diff, "_weight", 1, CEED_EVAL_WEIGHT); 113e2f04181SAndrew T. Barker CeedQFunctionAddOutput(qf_setup_diff, "qdata", dim*(dim+1)/2, CEED_EVAL_NONE); 114e2f04181SAndrew T. Barker 115e2f04181SAndrew T. Barker // Operator - setup diff 116e2f04181SAndrew T. Barker CeedOperatorCreate(ceed, qf_setup_diff, CEED_QFUNCTION_NONE, 117e2f04181SAndrew T. Barker CEED_QFUNCTION_NONE, &op_setup_diff); 118*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_diff, "dx", elem_restr_x, basis_x, 119*d1d35e2fSjeremylt CEED_VECTOR_ACTIVE); 120*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_diff, "_weight", CEED_ELEMRESTRICTION_NONE, 121*d1d35e2fSjeremylt basis_x, 122e2f04181SAndrew T. Barker CEED_VECTOR_NONE); 123*d1d35e2fSjeremylt CeedOperatorSetField(op_setup_diff, "qdata", elem_restr_qd_diff_i, 124e2f04181SAndrew T. Barker CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 125e2f04181SAndrew T. Barker 126e2f04181SAndrew T. Barker // Apply Setup Operators 127*d1d35e2fSjeremylt CeedOperatorApply(op_setup_mass, X, q_data_mass, CEED_REQUEST_IMMEDIATE); 128*d1d35e2fSjeremylt CeedOperatorApply(op_setup_diff, X, q_data_diff, CEED_REQUEST_IMMEDIATE); 129e2f04181SAndrew T. Barker 130e2f04181SAndrew T. Barker // QFunction - apply 131e2f04181SAndrew T. Barker CeedQFunctionCreateInterior(ceed, 1, apply, apply_loc, &qf_apply); 132e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_apply, "du", dim, CEED_EVAL_GRAD); 133e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_apply, "qdata_mass", 1, CEED_EVAL_NONE); 134e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_apply, "qdata_diff", dim*(dim+1)/2, CEED_EVAL_NONE); 135e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_apply, "u", 1, CEED_EVAL_INTERP); 136e2f04181SAndrew T. Barker CeedQFunctionAddOutput(qf_apply, "v", 1, CEED_EVAL_INTERP); 137e2f04181SAndrew T. Barker CeedQFunctionAddOutput(qf_apply, "dv", dim, CEED_EVAL_GRAD); 138e2f04181SAndrew T. Barker 139e2f04181SAndrew T. Barker // Operator - apply 140e2f04181SAndrew T. Barker CeedOperatorCreate(ceed, qf_apply, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, 141e2f04181SAndrew T. Barker &op_apply); 142*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "du", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 143*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "qdata_mass", elem_restr_qd_mass_i, 144*d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, q_data_mass); 145*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "qdata_diff", elem_restr_qd_diff_i, 146*d1d35e2fSjeremylt CEED_BASIS_COLLOCATED, q_data_diff); 147*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "u", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 148*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "v", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 149*d1d35e2fSjeremylt CeedOperatorSetField(op_apply, "dv", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 150e2f04181SAndrew T. Barker 151e2f04181SAndrew T. Barker // Fully assemble operator 152*d1d35e2fSjeremylt for (int k=0; k<num_dofs*num_dofs; ++k) { 153e2f04181SAndrew T. Barker assembled[k] = 0.0; 154*d1d35e2fSjeremylt assembled_true[k] = 0.0; 155e2f04181SAndrew T. Barker } 156*d1d35e2fSjeremylt CeedInt num_entries; 157e2f04181SAndrew T. Barker CeedInt *rows; 158e2f04181SAndrew T. Barker CeedInt *cols; 159e2f04181SAndrew T. Barker CeedVector values; 160*d1d35e2fSjeremylt CeedOperatorLinearAssembleSymbolic(op_apply, &num_entries, &rows, &cols); 161*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_entries, &values); 162e2f04181SAndrew T. Barker CeedOperatorLinearAssemble(op_apply, values); 163e2f04181SAndrew T. Barker const CeedScalar *vals; 164e2f04181SAndrew T. Barker CeedVectorGetArrayRead(values, CEED_MEM_HOST, &vals); 165*d1d35e2fSjeremylt for (int k=0; k<num_entries; ++k) { 166*d1d35e2fSjeremylt assembled[rows[k]*num_dofs + cols[k]] += vals[k]; 167e2f04181SAndrew T. Barker } 168e2f04181SAndrew T. Barker CeedVectorRestoreArrayRead(values, &vals); 169e2f04181SAndrew T. Barker 170e2f04181SAndrew T. Barker // Manually assemble operator 171*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &U); 172e2f04181SAndrew T. Barker CeedVectorSetValue(U, 0.0); 173*d1d35e2fSjeremylt CeedVectorCreate(ceed, num_dofs, &V); 174*d1d35e2fSjeremylt for (int i=0; i<num_dofs; i++) { 175e2f04181SAndrew T. Barker // Set input 176e2f04181SAndrew T. Barker CeedVectorGetArray(U, CEED_MEM_HOST, &u); 177e2f04181SAndrew T. Barker u[i] = 1.0; 178e2f04181SAndrew T. Barker if (i) 179e2f04181SAndrew T. Barker u[i-1] = 0.0; 180e2f04181SAndrew T. Barker CeedVectorRestoreArray(U, &u); 181e2f04181SAndrew T. Barker 182e2f04181SAndrew T. Barker // Compute entries for column i 183e2f04181SAndrew T. Barker CeedOperatorApply(op_apply, U, V, CEED_REQUEST_IMMEDIATE); 184e2f04181SAndrew T. Barker 185e2f04181SAndrew T. Barker CeedVectorGetArrayRead(V, CEED_MEM_HOST, &v); 186*d1d35e2fSjeremylt for (int k=0; k<num_dofs; k++) { 187*d1d35e2fSjeremylt assembled_true[i*num_dofs + k] = v[k]; 188e2f04181SAndrew T. Barker } 189e2f04181SAndrew T. Barker CeedVectorRestoreArrayRead(V, &v); 190e2f04181SAndrew T. Barker } 191e2f04181SAndrew T. Barker 192e2f04181SAndrew T. Barker // Check output 193*d1d35e2fSjeremylt for (int i=0; i<num_dofs; i++) 194*d1d35e2fSjeremylt for (int j=0; j<num_dofs; j++) 195*d1d35e2fSjeremylt if (fabs(assembled[j*num_dofs+i] - assembled_true[j*num_dofs+i]) > 1e-14) 196e2f04181SAndrew T. Barker // LCOV_EXCL_START 197e2f04181SAndrew T. Barker printf("[%d,%d] Error in assembly: %f != %f\n", i, j, 198*d1d35e2fSjeremylt assembled[j*num_dofs+i], assembled_true[j*num_dofs+i]); 199e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 200e2f04181SAndrew T. Barker 201e2f04181SAndrew T. Barker // Cleanup 202e2f04181SAndrew T. Barker free(rows); 203e2f04181SAndrew T. Barker free(cols); 204e2f04181SAndrew T. Barker CeedVectorDestroy(&values); 205e2f04181SAndrew T. Barker CeedQFunctionDestroy(&qf_setup_mass); 206e2f04181SAndrew T. Barker CeedQFunctionDestroy(&qf_setup_diff); 207e2f04181SAndrew T. Barker CeedQFunctionDestroy(&qf_apply); 208e2f04181SAndrew T. Barker CeedOperatorDestroy(&op_setup_mass); 209e2f04181SAndrew T. Barker CeedOperatorDestroy(&op_setup_diff); 210e2f04181SAndrew T. Barker CeedOperatorDestroy(&op_apply); 211*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_u); 212*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_x); 213*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_qd_mass_i); 214*d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_qd_diff_i); 215*d1d35e2fSjeremylt CeedBasisDestroy(&basis_u); 216*d1d35e2fSjeremylt CeedBasisDestroy(&basis_x); 217e2f04181SAndrew T. Barker CeedVectorDestroy(&X); 218*d1d35e2fSjeremylt CeedVectorDestroy(&q_data_mass); 219*d1d35e2fSjeremylt CeedVectorDestroy(&q_data_diff); 220e2f04181SAndrew T. Barker CeedVectorDestroy(&U); 221e2f04181SAndrew T. Barker CeedVectorDestroy(&V); 222e2f04181SAndrew T. Barker CeedDestroy(&ceed); 223e2f04181SAndrew T. Barker return 0; 224e2f04181SAndrew T. Barker } 225