1e2f04181SAndrew T. Barker /// @file 2e2f04181SAndrew T. Barker /// Test assembly of mass matrix operator (multi-component) see t537 3e2f04181SAndrew T. Barker /// \test Test assembly of mass matrix operator (multi-component) 4e2f04181SAndrew T. Barker #include <ceed.h> 5e2f04181SAndrew T. Barker #include <math.h> 6*2b730f8bSJeremy L Thompson #include <stdlib.h> 7*2b730f8bSJeremy L Thompson 8e2f04181SAndrew T. Barker #include "t537-operator.h" 9e2f04181SAndrew T. Barker 10e2f04181SAndrew T. Barker int main(int argc, char **argv) { 11e2f04181SAndrew T. Barker Ceed ceed; 12*2b730f8bSJeremy L Thompson CeedElemRestriction elem_restr_x, elem_restr_u, elem_restr_qd_i; 13d1d35e2fSjeremylt CeedBasis basis_x, basis_u; 14e2f04181SAndrew T. Barker CeedQFunction qf_setup, qf_mass; 15e2f04181SAndrew T. Barker CeedOperator op_setup, op_mass; 16d1d35e2fSjeremylt CeedVector q_data, X, U, V; 17d1d35e2fSjeremylt CeedInt P = 3, Q = 4, dim = 2, num_comp = 2; 18d1d35e2fSjeremylt CeedInt n_x = 1, n_y = 1; 19d1d35e2fSjeremylt CeedInt num_elem = n_x * n_y; 20d1d35e2fSjeremylt CeedInt num_dofs = (n_x * 2 + 1) * (n_y * 2 + 1), num_qpts = num_elem * Q * Q; 21d1d35e2fSjeremylt CeedInt ind_x[num_elem * P * P]; 22d1d35e2fSjeremylt CeedScalar assembled[num_comp * num_comp * num_dofs * num_dofs]; 23d1d35e2fSjeremylt CeedScalar x[dim * num_dofs], assembled_true[num_comp * num_comp * num_dofs * num_dofs]; 24e2f04181SAndrew T. Barker CeedScalar *u; 25e2f04181SAndrew T. Barker const CeedScalar *v; 26e2f04181SAndrew T. Barker 27e2f04181SAndrew T. Barker CeedInit(argv[1], &ceed); 28e2f04181SAndrew T. Barker 29e2f04181SAndrew T. Barker // DoF Coordinates 30*2b730f8bSJeremy L Thompson for (CeedInt i = 0; i < n_x * 2 + 1; i++) { 31d1d35e2fSjeremylt for (CeedInt j = 0; j < n_y * 2 + 1; j++) { 32d1d35e2fSjeremylt x[i + j * (n_x * 2 + 1) + 0 * num_dofs] = (CeedScalar)i / (2 * n_x); 33d1d35e2fSjeremylt x[i + j * (n_x * 2 + 1) + 1 * num_dofs] = (CeedScalar)j / (2 * n_y); 34e2f04181SAndrew T. Barker } 35*2b730f8bSJeremy L Thompson } 36d1d35e2fSjeremylt CeedVectorCreate(ceed, dim * num_dofs, &X); 37e2f04181SAndrew T. Barker CeedVectorSetArray(X, CEED_MEM_HOST, CEED_USE_POINTER, x); 38e2f04181SAndrew T. Barker 39e2f04181SAndrew T. Barker // Qdata Vector 40d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts, &q_data); 41e2f04181SAndrew T. Barker 42e2f04181SAndrew T. Barker // Element Setup 43d1d35e2fSjeremylt for (CeedInt i = 0; i < num_elem; i++) { 44e2f04181SAndrew T. Barker CeedInt col, row, offset; 45d1d35e2fSjeremylt col = i % n_x; 46d1d35e2fSjeremylt row = i / n_x; 47d1d35e2fSjeremylt offset = col * (P - 1) + row * (n_x * 2 + 1) * (P - 1); 48*2b730f8bSJeremy L Thompson for (CeedInt j = 0; j < P; j++) { 49*2b730f8bSJeremy L Thompson for (CeedInt k = 0; k < P; k++) ind_x[P * (P * i + k) + j] = offset + k * (n_x * 2 + 1) + j; 50*2b730f8bSJeremy L Thompson } 51e2f04181SAndrew T. Barker } 52e2f04181SAndrew T. Barker 53e2f04181SAndrew T. Barker // Restrictions 54*2b730f8bSJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem, P * P, dim, num_dofs, dim * num_dofs, CEED_MEM_HOST, CEED_USE_POINTER, ind_x, &elem_restr_x); 55*2b730f8bSJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem, P * P, num_comp, num_dofs, num_comp * num_dofs, CEED_MEM_HOST, CEED_USE_POINTER, ind_x, &elem_restr_u); 56d1d35e2fSjeremylt CeedInt strides_qd[3] = {1, Q * Q, Q * Q}; 57*2b730f8bSJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem, Q * Q, 1, num_qpts, strides_qd, &elem_restr_qd_i); 58e2f04181SAndrew T. Barker 59e2f04181SAndrew T. Barker // Bases 60d1d35e2fSjeremylt CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, P, Q, CEED_GAUSS, &basis_x); 61*2b730f8bSJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, num_comp, P, Q, CEED_GAUSS, &basis_u); 62e2f04181SAndrew T. Barker 63e2f04181SAndrew T. Barker // QFunctions 64e2f04181SAndrew T. Barker CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup); 65a61c78d6SJeremy L Thompson CeedQFunctionAddInput(qf_setup, "weight", 1, CEED_EVAL_WEIGHT); 66e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_setup, "dx", dim * dim, CEED_EVAL_GRAD); 67e2f04181SAndrew T. Barker CeedQFunctionAddOutput(qf_setup, "rho", 1, CEED_EVAL_NONE); 68e2f04181SAndrew T. Barker 69e2f04181SAndrew T. Barker CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass); 70e2f04181SAndrew T. Barker CeedQFunctionAddInput(qf_mass, "rho", 1, CEED_EVAL_NONE); 71d1d35e2fSjeremylt CeedQFunctionAddInput(qf_mass, "u", num_comp, CEED_EVAL_INTERP); 72d1d35e2fSjeremylt CeedQFunctionAddOutput(qf_mass, "v", num_comp, CEED_EVAL_INTERP); 73e2f04181SAndrew T. Barker 74e2f04181SAndrew T. Barker // Operators 75*2b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_setup, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_setup); 76*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup, "weight", CEED_ELEMRESTRICTION_NONE, basis_x, CEED_VECTOR_NONE); 77d1d35e2fSjeremylt CeedOperatorSetField(op_setup, "dx", elem_restr_x, basis_x, CEED_VECTOR_ACTIVE); 78*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup, "rho", elem_restr_qd_i, CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 79e2f04181SAndrew T. Barker 80*2b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_mass, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_mass); 81*2b730f8bSJeremy L Thompson CeedOperatorSetField(op_mass, "rho", elem_restr_qd_i, CEED_BASIS_COLLOCATED, q_data); 82d1d35e2fSjeremylt CeedOperatorSetField(op_mass, "u", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 83d1d35e2fSjeremylt CeedOperatorSetField(op_mass, "v", elem_restr_u, basis_u, CEED_VECTOR_ACTIVE); 84e2f04181SAndrew T. Barker 85e2f04181SAndrew T. Barker // Apply Setup Operator 86d1d35e2fSjeremylt CeedOperatorApply(op_setup, X, q_data, CEED_REQUEST_IMMEDIATE); 87e2f04181SAndrew T. Barker 88e2f04181SAndrew T. Barker // Fuly assemble operator 89b8edc0e7SJeremy L Thompson for (CeedInt k = 0; k < num_comp * num_comp * num_dofs * num_dofs; k++) { 90e2f04181SAndrew T. Barker assembled[k] = 0.0; 91d1d35e2fSjeremylt assembled_true[k] = 0.0; 92e2f04181SAndrew T. Barker } 93c30b7fbdSJeremy L Thompson CeedSize nentries; 94e2f04181SAndrew T. Barker CeedInt *rows; 95e2f04181SAndrew T. Barker CeedInt *cols; 96e2f04181SAndrew T. Barker CeedVector values; 97e2f04181SAndrew T. Barker CeedOperatorLinearAssembleSymbolic(op_mass, &nentries, &rows, &cols); 98e2f04181SAndrew T. Barker CeedVectorCreate(ceed, nentries, &values); 99e2f04181SAndrew T. Barker CeedOperatorLinearAssemble(op_mass, values); 100e2f04181SAndrew T. Barker const CeedScalar *vals; 101e2f04181SAndrew T. Barker CeedVectorGetArrayRead(values, CEED_MEM_HOST, &vals); 102*2b730f8bSJeremy L Thompson for (CeedInt k = 0; k < nentries; ++k) assembled[rows[k] * num_comp * num_dofs + cols[k]] += vals[k]; 103e2f04181SAndrew T. Barker CeedVectorRestoreArrayRead(values, &vals); 104e2f04181SAndrew T. Barker 105e2f04181SAndrew T. Barker // Manually assemble operator 106d1d35e2fSjeremylt CeedVectorCreate(ceed, num_comp * num_dofs, &U); 107e2f04181SAndrew T. Barker CeedVectorSetValue(U, 0.0); 108d1d35e2fSjeremylt CeedVectorCreate(ceed, num_comp * num_dofs, &V); 109e2f04181SAndrew T. Barker CeedInt indOld = -1; 110b8edc0e7SJeremy L Thompson for (CeedInt j = 0; j < num_dofs * num_comp; j++) { 111e2f04181SAndrew T. Barker // Set input 112e2f04181SAndrew T. Barker CeedVectorGetArray(U, CEED_MEM_HOST, &u); 113e2f04181SAndrew T. Barker CeedInt ind = j; 114e2f04181SAndrew T. Barker u[ind] = 1.0; 115*2b730f8bSJeremy L Thompson if (ind > 0) u[indOld] = 0.0; 116e2f04181SAndrew T. Barker indOld = ind; 117e2f04181SAndrew T. Barker CeedVectorRestoreArray(U, &u); 118e2f04181SAndrew T. Barker 119e2f04181SAndrew T. Barker // Compute effect of DoF j 120e2f04181SAndrew T. Barker CeedOperatorApply(op_mass, U, V, CEED_REQUEST_IMMEDIATE); 121e2f04181SAndrew T. Barker 122e2f04181SAndrew T. Barker CeedVectorGetArrayRead(V, CEED_MEM_HOST, &v); 123*2b730f8bSJeremy L Thompson for (CeedInt k = 0; k < num_dofs * num_comp; k++) assembled_true[j * num_dofs * num_comp + k] = v[k]; 124e2f04181SAndrew T. Barker CeedVectorRestoreArrayRead(V, &v); 125e2f04181SAndrew T. Barker } 126e2f04181SAndrew T. Barker 127e2f04181SAndrew T. Barker // Check output 128*2b730f8bSJeremy L Thompson for (CeedInt i = 0; i < num_comp * num_dofs; i++) { 129*2b730f8bSJeremy L Thompson for (CeedInt j = 0; j < num_comp * num_dofs; j++) { 130*2b730f8bSJeremy L Thompson if (fabs(assembled[j * num_dofs * num_comp + i] - assembled_true[j * num_dofs * num_comp + i]) > 100. * CEED_EPSILON) { 131e2f04181SAndrew T. Barker // LCOV_EXCL_START 132*2b730f8bSJeremy L Thompson printf("[%" CeedInt_FMT ", %" CeedInt_FMT "] Error in assembly: %f != %f\n", i, j, assembled[j * num_dofs * num_comp + i], 133*2b730f8bSJeremy L Thompson assembled_true[j * num_dofs * num_comp + i]); 134e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 135*2b730f8bSJeremy L Thompson } 136*2b730f8bSJeremy L Thompson } 137*2b730f8bSJeremy L Thompson } 138e2f04181SAndrew T. Barker 139e2f04181SAndrew T. Barker // Cleanup 140e2f04181SAndrew T. Barker free(rows); 141e2f04181SAndrew T. Barker free(cols); 142e2f04181SAndrew T. Barker CeedVectorDestroy(&values); 143e2f04181SAndrew T. Barker CeedQFunctionDestroy(&qf_setup); 144e2f04181SAndrew T. Barker CeedQFunctionDestroy(&qf_mass); 145e2f04181SAndrew T. Barker CeedOperatorDestroy(&op_setup); 146e2f04181SAndrew T. Barker CeedOperatorDestroy(&op_mass); 147d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_u); 148d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_x); 149d1d35e2fSjeremylt CeedElemRestrictionDestroy(&elem_restr_qd_i); 150d1d35e2fSjeremylt CeedBasisDestroy(&basis_u); 151d1d35e2fSjeremylt CeedBasisDestroy(&basis_x); 152e2f04181SAndrew T. Barker CeedVectorDestroy(&X); 153d1d35e2fSjeremylt CeedVectorDestroy(&q_data); 154e2f04181SAndrew T. Barker CeedVectorDestroy(&U); 155e2f04181SAndrew T. Barker CeedVectorDestroy(&V); 156e2f04181SAndrew T. Barker CeedDestroy(&ceed); 157e2f04181SAndrew T. Barker return 0; 158e2f04181SAndrew T. Barker } 159