1250756a7Sjeremylt /// @file 26227f746SJeremy L Thompson /// Test CeedOperatorApplyAdd for composite operator 36227f746SJeremy L Thompson /// \test CeedOperatorApplyAdd for composite operator 4250756a7Sjeremylt #include <ceed.h> 5250756a7Sjeremylt #include <math.h> 6*49aac155SJeremy L Thompson #include <stdio.h> 72b730f8bSJeremy L Thompson #include <stdlib.h> 82b730f8bSJeremy L Thompson 9250756a7Sjeremylt #include "t320-basis.h" 10250756a7Sjeremylt #include "t510-operator.h" 11250756a7Sjeremylt 124fee36f0SJeremy L Thompson /* The mesh comprises of two rows of 3 quadrilaterals followed by one row 13250756a7Sjeremylt of 6 triangles: 14250756a7Sjeremylt _ _ _ 15250756a7Sjeremylt |_|_|_| 16250756a7Sjeremylt |_|_|_| 17250756a7Sjeremylt |/|/|/| 18250756a7Sjeremylt 19250756a7Sjeremylt */ 20250756a7Sjeremylt 21250756a7Sjeremylt int main(int argc, char **argv) { 22250756a7Sjeremylt Ceed ceed; 234fee36f0SJeremy L Thompson CeedElemRestriction elem_restriction_x_tet, elem_restriction_u_tet, elem_restriction_q_data_tet, elem_restriction_x_hex, elem_restriction_u_hex, 244fee36f0SJeremy L Thompson elem_restriction_q_data_hex; 252b730f8bSJeremy L Thompson CeedBasis basis_x_tet, basis_u_tet, basis_x_hex, basis_u_hex; 262b730f8bSJeremy L Thompson CeedQFunction qf_setup_tet, qf_mass_tet, qf_setup_hex, qf_mass_hex; 272b730f8bSJeremy L Thompson CeedOperator op_setup_tet, op_mass_tet, op_setup_hex, op_mass_hex, op_setup, op_mass; 284fee36f0SJeremy L Thompson CeedVector q_data_tet, q_data_hex, x, u, v; 294fee36f0SJeremy L Thompson CeedInt num_elem_tet = 6, p_tet = 6, q_tet = 4, num_elem_hex = 6, p_hex = 3, q_hex = 4, dim = 2; 302b730f8bSJeremy L Thompson CeedInt nx = 3, ny = 3, nx_tet = 3, ny_tet = 1, nx_hex = 3; 31250756a7Sjeremylt CeedInt row, col, offset; 324fee36f0SJeremy L Thompson CeedInt num_dofs = (nx * 2 + 1) * (ny * 2 + 1), num_qpts_tet = num_elem_tet * q_tet, num_qpts_hex = num_elem_hex * q_hex * q_hex; 334fee36f0SJeremy L Thompson CeedInt ind_x_tet[num_elem_tet * p_tet], ind_x_hex[num_elem_hex * p_hex * p_hex]; 344fee36f0SJeremy L Thompson CeedScalar q_ref[dim * q_tet], q_weight[q_tet]; 354fee36f0SJeremy L Thompson CeedScalar interp[p_tet * q_tet], grad[dim * p_tet * q_tet]; 36250756a7Sjeremylt 37250756a7Sjeremylt CeedInit(argv[1], &ceed); 38250756a7Sjeremylt 394fee36f0SJeremy L Thompson // Vectors 404fee36f0SJeremy L Thompson CeedVectorCreate(ceed, dim * num_dofs, &x); 414fee36f0SJeremy L Thompson { 424fee36f0SJeremy L Thompson CeedScalar x_array[dim * num_dofs]; 432b730f8bSJeremy L Thompson for (CeedInt i = 0; i < ny * 2 + 1; i++) { 44250756a7Sjeremylt for (CeedInt j = 0; j < nx * 2 + 1; j++) { 454fee36f0SJeremy L Thompson x_array[i + j * (ny * 2 + 1) + 0 * num_dofs] = (CeedScalar)i / (2 * ny); 464fee36f0SJeremy L Thompson x_array[i + j * (ny * 2 + 1) + 1 * num_dofs] = (CeedScalar)j / (2 * nx); 47250756a7Sjeremylt } 482b730f8bSJeremy L Thompson } 494fee36f0SJeremy L Thompson CeedVectorSetArray(x, CEED_MEM_HOST, CEED_COPY_VALUES, x_array); 504fee36f0SJeremy L Thompson } 514fee36f0SJeremy L Thompson CeedVectorCreate(ceed, num_dofs, &u); 524fee36f0SJeremy L Thompson CeedVectorCreate(ceed, num_dofs, &v); 53d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts_tet, &q_data_tet); 54d1d35e2fSjeremylt CeedVectorCreate(ceed, num_qpts_hex, &q_data_hex); 55250756a7Sjeremylt 564fee36f0SJeremy L Thompson // Tet Elements 574fee36f0SJeremy L Thompson // -- Restrictions 584fee36f0SJeremy L Thompson for (CeedInt i = 0; i < num_elem_tet / 2; i++) { 59d1d35e2fSjeremylt col = i % nx_tet; 60d1d35e2fSjeremylt row = i / nx_tet; 61d1d35e2fSjeremylt offset = col * 2 + row * (nx_tet * 2 + 1) * 2; 62250756a7Sjeremylt 634fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 0] = 2 + offset; 644fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 1] = 9 + offset; 654fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 2] = 16 + offset; 664fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 3] = 1 + offset; 674fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 4] = 8 + offset; 684fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 5] = 0 + offset; 69250756a7Sjeremylt 704fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 6] = 14 + offset; 714fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 7] = 7 + offset; 724fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 8] = 0 + offset; 734fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 9] = 15 + offset; 744fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 10] = 8 + offset; 754fee36f0SJeremy L Thompson ind_x_tet[i * 2 * p_tet + 11] = 16 + offset; 76250756a7Sjeremylt } 774fee36f0SJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem_tet, p_tet, dim, num_dofs, dim * num_dofs, CEED_MEM_HOST, CEED_USE_POINTER, ind_x_tet, 784fee36f0SJeremy L Thompson &elem_restriction_x_tet); 794fee36f0SJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem_tet, p_tet, 1, 1, num_dofs, CEED_MEM_HOST, CEED_USE_POINTER, ind_x_tet, &elem_restriction_u_tet); 80250756a7Sjeremylt 814fee36f0SJeremy L Thompson CeedInt strides_q_data_tet[3] = {1, q_tet, q_tet}; 824fee36f0SJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem_tet, q_tet, 1, num_qpts_tet, strides_q_data_tet, &elem_restriction_q_data_tet); 83250756a7Sjeremylt 84250756a7Sjeremylt // -- Bases 854fee36f0SJeremy L Thompson Build2DSimplex(q_ref, q_weight, interp, grad); 864fee36f0SJeremy L Thompson CeedBasisCreateH1(ceed, CEED_TOPOLOGY_TRIANGLE, dim, p_tet, q_tet, interp, grad, q_ref, q_weight, &basis_x_tet); 87250756a7Sjeremylt 884fee36f0SJeremy L Thompson Build2DSimplex(q_ref, q_weight, interp, grad); 894fee36f0SJeremy L Thompson CeedBasisCreateH1(ceed, CEED_TOPOLOGY_TRIANGLE, 1, p_tet, q_tet, interp, grad, q_ref, q_weight, &basis_u_tet); 90250756a7Sjeremylt 91250756a7Sjeremylt // -- QFunctions 92d1d35e2fSjeremylt CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup_tet); 93a61c78d6SJeremy L Thompson CeedQFunctionAddInput(qf_setup_tet, "weight", 1, CEED_EVAL_WEIGHT); 94d1d35e2fSjeremylt CeedQFunctionAddInput(qf_setup_tet, "dx", dim * dim, CEED_EVAL_GRAD); 95d1d35e2fSjeremylt CeedQFunctionAddOutput(qf_setup_tet, "rho", 1, CEED_EVAL_NONE); 96250756a7Sjeremylt 97d1d35e2fSjeremylt CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass_tet); 98d1d35e2fSjeremylt CeedQFunctionAddInput(qf_mass_tet, "rho", 1, CEED_EVAL_NONE); 99d1d35e2fSjeremylt CeedQFunctionAddInput(qf_mass_tet, "u", 1, CEED_EVAL_INTERP); 100d1d35e2fSjeremylt CeedQFunctionAddOutput(qf_mass_tet, "v", 1, CEED_EVAL_INTERP); 101250756a7Sjeremylt 102250756a7Sjeremylt // -- Operators 103d1d35e2fSjeremylt // ---- Setup _tet 1042b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_setup_tet, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_setup_tet); 1052b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_tet, "weight", CEED_ELEMRESTRICTION_NONE, basis_x_tet, CEED_VECTOR_NONE); 1064fee36f0SJeremy L Thompson CeedOperatorSetField(op_setup_tet, "dx", elem_restriction_x_tet, basis_x_tet, CEED_VECTOR_ACTIVE); 1074fee36f0SJeremy L Thompson CeedOperatorSetField(op_setup_tet, "rho", elem_restriction_q_data_tet, CEED_BASIS_COLLOCATED, q_data_tet); 108d1d35e2fSjeremylt // ---- Mass _tet 1092b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_mass_tet, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_mass_tet); 1104fee36f0SJeremy L Thompson CeedOperatorSetField(op_mass_tet, "rho", elem_restriction_q_data_tet, CEED_BASIS_COLLOCATED, q_data_tet); 1114fee36f0SJeremy L Thompson CeedOperatorSetField(op_mass_tet, "u", elem_restriction_u_tet, basis_u_tet, CEED_VECTOR_ACTIVE); 1124fee36f0SJeremy L Thompson CeedOperatorSetField(op_mass_tet, "v", elem_restriction_u_tet, basis_u_tet, CEED_VECTOR_ACTIVE); 113250756a7Sjeremylt 1144fee36f0SJeremy L Thompson // Hex Elements 1154fee36f0SJeremy L Thompson // -- Restrictions 1164fee36f0SJeremy L Thompson for (CeedInt i = 0; i < num_elem_hex; i++) { 117d1d35e2fSjeremylt col = i % nx_hex; 118d1d35e2fSjeremylt row = i / nx_hex; 119d1d35e2fSjeremylt offset = (nx_tet * 2 + 1) * (ny_tet * 2) * (1 + row) + col * 2; 1204fee36f0SJeremy L Thompson for (CeedInt j = 0; j < p_hex; j++) { 1214fee36f0SJeremy L Thompson for (CeedInt k = 0; k < p_hex; k++) ind_x_hex[p_hex * (p_hex * i + k) + j] = offset + k * (nx_hex * 2 + 1) + j; 1222b730f8bSJeremy L Thompson } 123250756a7Sjeremylt } 1244fee36f0SJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem_hex, p_hex * p_hex, dim, num_dofs, dim * num_dofs, CEED_MEM_HOST, CEED_USE_POINTER, ind_x_hex, 1254fee36f0SJeremy L Thompson &elem_restriction_x_hex); 1264fee36f0SJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem_hex, p_hex * p_hex, 1, 1, num_dofs, CEED_MEM_HOST, CEED_USE_POINTER, ind_x_hex, &elem_restriction_u_hex); 127250756a7Sjeremylt 1284fee36f0SJeremy L Thompson CeedInt strides_q_data_hex[3] = {1, q_hex * q_hex, q_hex * q_hex}; 1294fee36f0SJeremy L Thompson CeedElemRestrictionCreateStrided(ceed, num_elem_hex, q_hex * q_hex, 1, num_qpts_hex, strides_q_data_hex, &elem_restriction_q_data_hex); 130250756a7Sjeremylt 131250756a7Sjeremylt // -- Bases 1324fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, dim, p_hex, q_hex, CEED_GAUSS, &basis_x_hex); 1334fee36f0SJeremy L Thompson CeedBasisCreateTensorH1Lagrange(ceed, dim, 1, p_hex, q_hex, CEED_GAUSS, &basis_u_hex); 134250756a7Sjeremylt 135250756a7Sjeremylt // -- QFunctions 136d1d35e2fSjeremylt CeedQFunctionCreateInterior(ceed, 1, setup, setup_loc, &qf_setup_hex); 137a61c78d6SJeremy L Thompson CeedQFunctionAddInput(qf_setup_hex, "weight", 1, CEED_EVAL_WEIGHT); 138d1d35e2fSjeremylt CeedQFunctionAddInput(qf_setup_hex, "dx", dim * dim, CEED_EVAL_GRAD); 139d1d35e2fSjeremylt CeedQFunctionAddOutput(qf_setup_hex, "rho", 1, CEED_EVAL_NONE); 140250756a7Sjeremylt 141d1d35e2fSjeremylt CeedQFunctionCreateInterior(ceed, 1, mass, mass_loc, &qf_mass_hex); 142d1d35e2fSjeremylt CeedQFunctionAddInput(qf_mass_hex, "rho", 1, CEED_EVAL_NONE); 143d1d35e2fSjeremylt CeedQFunctionAddInput(qf_mass_hex, "u", 1, CEED_EVAL_INTERP); 144d1d35e2fSjeremylt CeedQFunctionAddOutput(qf_mass_hex, "v", 1, CEED_EVAL_INTERP); 145250756a7Sjeremylt 146250756a7Sjeremylt // -- Operators 1472b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_setup_hex, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_setup_hex); 1482b730f8bSJeremy L Thompson CeedOperatorSetField(op_setup_hex, "weight", CEED_ELEMRESTRICTION_NONE, basis_x_hex, CEED_VECTOR_NONE); 1494fee36f0SJeremy L Thompson CeedOperatorSetField(op_setup_hex, "dx", elem_restriction_x_hex, basis_x_hex, CEED_VECTOR_ACTIVE); 1504fee36f0SJeremy L Thompson CeedOperatorSetField(op_setup_hex, "rho", elem_restriction_q_data_hex, CEED_BASIS_COLLOCATED, q_data_hex); 151250756a7Sjeremylt 1522b730f8bSJeremy L Thompson CeedOperatorCreate(ceed, qf_mass_hex, CEED_QFUNCTION_NONE, CEED_QFUNCTION_NONE, &op_mass_hex); 1534fee36f0SJeremy L Thompson CeedOperatorSetField(op_mass_hex, "rho", elem_restriction_q_data_hex, CEED_BASIS_COLLOCATED, q_data_hex); 1544fee36f0SJeremy L Thompson CeedOperatorSetField(op_mass_hex, "u", elem_restriction_u_hex, basis_u_hex, CEED_VECTOR_ACTIVE); 1554fee36f0SJeremy L Thompson CeedOperatorSetField(op_mass_hex, "v", elem_restriction_u_hex, basis_u_hex, CEED_VECTOR_ACTIVE); 156250756a7Sjeremylt 157250756a7Sjeremylt // Composite Operators 158250756a7Sjeremylt CeedCompositeOperatorCreate(ceed, &op_setup); 159d1d35e2fSjeremylt CeedCompositeOperatorAddSub(op_setup, op_setup_tet); 160d1d35e2fSjeremylt CeedCompositeOperatorAddSub(op_setup, op_setup_hex); 161250756a7Sjeremylt 162250756a7Sjeremylt CeedCompositeOperatorCreate(ceed, &op_mass); 163d1d35e2fSjeremylt CeedCompositeOperatorAddSub(op_mass, op_mass_tet); 164d1d35e2fSjeremylt CeedCompositeOperatorAddSub(op_mass, op_mass_hex); 165250756a7Sjeremylt 166250756a7Sjeremylt // Apply Setup Operator 1674fee36f0SJeremy L Thompson CeedOperatorApply(op_setup, x, CEED_VECTOR_NONE, CEED_REQUEST_IMMEDIATE); 168250756a7Sjeremylt 169250756a7Sjeremylt // Apply Mass Operator 1704fee36f0SJeremy L Thompson CeedVectorSetValue(u, 1.0); 1714fee36f0SJeremy L Thompson CeedVectorSetValue(v, 0.0); 1724fee36f0SJeremy L Thompson CeedOperatorApplyAdd(op_mass, u, v, CEED_REQUEST_IMMEDIATE); 173250756a7Sjeremylt 174250756a7Sjeremylt // Check output 1754fee36f0SJeremy L Thompson { 1764fee36f0SJeremy L Thompson const CeedScalar *v_array; 1774fee36f0SJeremy L Thompson CeedScalar sum = 0.; 1784fee36f0SJeremy L Thompson 1794fee36f0SJeremy L Thompson CeedVectorGetArrayRead(v, CEED_MEM_HOST, &v_array); 1804fee36f0SJeremy L Thompson for (CeedInt i = 0; i < num_dofs; i++) sum += v_array[i]; 1814fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(v, &v_array); 1822b730f8bSJeremy L Thompson if (fabs(sum - 1.) > 1000. * CEED_EPSILON) printf("Computed Area: %f != True Area: 1.0\n", sum); 1834fee36f0SJeremy L Thompson } 184250756a7Sjeremylt 185250756a7Sjeremylt // Apply Add 1864fee36f0SJeremy L Thompson CeedVectorSetValue(v, 1.0); 1874fee36f0SJeremy L Thompson CeedOperatorApplyAdd(op_mass, u, v, CEED_REQUEST_IMMEDIATE); 188250756a7Sjeremylt 189250756a7Sjeremylt // Check output 1904fee36f0SJeremy L Thompson { 1914fee36f0SJeremy L Thompson const CeedScalar *v_array; 1924fee36f0SJeremy L Thompson CeedScalar sum = -num_dofs; 1934fee36f0SJeremy L Thompson 1944fee36f0SJeremy L Thompson CeedVectorGetArrayRead(v, CEED_MEM_HOST, &v_array); 1954fee36f0SJeremy L Thompson for (CeedInt i = 0; i < num_dofs; i++) sum += v_array[i]; 1964fee36f0SJeremy L Thompson CeedVectorRestoreArrayRead(v, &v_array); 1972b730f8bSJeremy L Thompson if (fabs(sum - 1.) > 1000. * CEED_EPSILON) printf("Computed Area: %f != True Area: 1.0\n", sum); 1984fee36f0SJeremy L Thompson } 199250756a7Sjeremylt 200250756a7Sjeremylt // Cleanup 2014fee36f0SJeremy L Thompson CeedVectorDestroy(&x); 2024fee36f0SJeremy L Thompson CeedVectorDestroy(&u); 2034fee36f0SJeremy L Thompson CeedVectorDestroy(&v); 2044fee36f0SJeremy L Thompson CeedVectorDestroy(&q_data_tet); 2054fee36f0SJeremy L Thompson CeedVectorDestroy(&q_data_hex); 2064fee36f0SJeremy L Thompson CeedElemRestrictionDestroy(&elem_restriction_u_tet); 2074fee36f0SJeremy L Thompson CeedElemRestrictionDestroy(&elem_restriction_x_tet); 2084fee36f0SJeremy L Thompson CeedElemRestrictionDestroy(&elem_restriction_q_data_tet); 2094fee36f0SJeremy L Thompson CeedElemRestrictionDestroy(&elem_restriction_u_hex); 2104fee36f0SJeremy L Thompson CeedElemRestrictionDestroy(&elem_restriction_x_hex); 2114fee36f0SJeremy L Thompson CeedElemRestrictionDestroy(&elem_restriction_q_data_hex); 2124fee36f0SJeremy L Thompson CeedBasisDestroy(&basis_u_tet); 2134fee36f0SJeremy L Thompson CeedBasisDestroy(&basis_x_tet); 2144fee36f0SJeremy L Thompson CeedBasisDestroy(&basis_u_hex); 2154fee36f0SJeremy L Thompson CeedBasisDestroy(&basis_x_hex); 216d1d35e2fSjeremylt CeedQFunctionDestroy(&qf_setup_tet); 217d1d35e2fSjeremylt CeedQFunctionDestroy(&qf_mass_tet); 218d1d35e2fSjeremylt CeedOperatorDestroy(&op_setup_tet); 219d1d35e2fSjeremylt CeedOperatorDestroy(&op_mass_tet); 220d1d35e2fSjeremylt CeedQFunctionDestroy(&qf_setup_hex); 221d1d35e2fSjeremylt CeedQFunctionDestroy(&qf_mass_hex); 222d1d35e2fSjeremylt CeedOperatorDestroy(&op_setup_hex); 223d1d35e2fSjeremylt CeedOperatorDestroy(&op_mass_hex); 224250756a7Sjeremylt CeedOperatorDestroy(&op_setup); 225250756a7Sjeremylt CeedOperatorDestroy(&op_mass); 226250756a7Sjeremylt CeedDestroy(&ceed); 227250756a7Sjeremylt return 0; 228250756a7Sjeremylt } 229