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