1*d3c69ad0SToby Isaac const char help[] = "Test PetscDTSimplexQuadrature()"; 2*d3c69ad0SToby Isaac 3*d3c69ad0SToby Isaac #include <petscdt.h> 4*d3c69ad0SToby Isaac 5*d3c69ad0SToby Isaac // if we trust the PKD polynomials (tested in ex9), then we can see how well the quadrature integrates 6*d3c69ad0SToby Isaac // the mass matrix, which should be the identity 7*d3c69ad0SToby Isaac static PetscErrorCode testQuadrature(PetscInt dim, PetscInt degree, PetscDTSimplexQuadratureType type) 8*d3c69ad0SToby Isaac { 9*d3c69ad0SToby Isaac PetscInt num_points; 10*d3c69ad0SToby Isaac const PetscReal *points; 11*d3c69ad0SToby Isaac const PetscReal *weights; 12*d3c69ad0SToby Isaac PetscInt p_degree = (degree + 1) / 2; 13*d3c69ad0SToby Isaac PetscInt p_degree_min = degree - p_degree; 14*d3c69ad0SToby Isaac PetscInt Nb, Nb_min; 15*d3c69ad0SToby Isaac PetscReal *eval; 16*d3c69ad0SToby Isaac PetscQuadrature quad; 17*d3c69ad0SToby Isaac 18*d3c69ad0SToby Isaac PetscFunctionBegin; 19*d3c69ad0SToby Isaac PetscCall(PetscDTSimplexQuadrature(dim, degree, type, &quad)); 20*d3c69ad0SToby Isaac PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &num_points, &points, &weights)); 21*d3c69ad0SToby Isaac PetscCall(PetscDTBinomialInt(dim + p_degree, dim, &Nb)); 22*d3c69ad0SToby Isaac PetscCall(PetscDTBinomialInt(dim + p_degree_min, dim, &Nb_min)); 23*d3c69ad0SToby Isaac PetscCall(PetscMalloc1(num_points * Nb, &eval)); 24*d3c69ad0SToby Isaac PetscCall(PetscDTPKDEvalJet(dim, num_points, points, p_degree, 0, eval)); 25*d3c69ad0SToby Isaac for (PetscInt i = 0; i < Nb_min; i++) { 26*d3c69ad0SToby Isaac for (PetscInt j = i; j < Nb; j++) { 27*d3c69ad0SToby Isaac PetscReal I_exact = (i == j) ? 1.0 : 0.0; 28*d3c69ad0SToby Isaac PetscReal I_quad = 0.0; 29*d3c69ad0SToby Isaac PetscReal err; 30*d3c69ad0SToby Isaac 31*d3c69ad0SToby Isaac for (PetscInt q = 0; q < num_points; q++) { 32*d3c69ad0SToby Isaac I_quad += weights[q] * eval[i * num_points + q] * eval[j * num_points + q]; 33*d3c69ad0SToby Isaac } 34*d3c69ad0SToby Isaac err = PetscAbsReal(I_exact - I_quad); 35*d3c69ad0SToby Isaac PetscCall(PetscInfo(quad, "Dimension %d, degree %d, method %s, error in <P_PKD(%d),P_PKD(%d)> = %g\n", (int) dim, (int) degree, PetscDTSimplexQuadratureTypes[type], (int) i, (int) j, (double) err)); 36*d3c69ad0SToby Isaac PetscCheck(err < PETSC_SMALL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Dimension %d, degree %d, method %s, error in <P_PKD(%d),P_PKD(%d)> = %g", (int) dim, (int) degree, PetscDTSimplexQuadratureTypes[type], (int) i, (int) j, (double) err); 37*d3c69ad0SToby Isaac } 38*d3c69ad0SToby Isaac } 39*d3c69ad0SToby Isaac PetscCall(PetscFree(eval)); 40*d3c69ad0SToby Isaac PetscCall(PetscQuadratureDestroy(&quad)); 41*d3c69ad0SToby Isaac PetscFunctionReturn(0); 42*d3c69ad0SToby Isaac } 43*d3c69ad0SToby Isaac 44*d3c69ad0SToby Isaac int main(int argc, char **argv) 45*d3c69ad0SToby Isaac { 46*d3c69ad0SToby Isaac const PetscInt dimdeg[] = {0, 20, 20, 20}; 47*d3c69ad0SToby Isaac 48*d3c69ad0SToby Isaac PetscFunctionBeginUser; 49*d3c69ad0SToby Isaac PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 50*d3c69ad0SToby Isaac for (PetscInt dim = 0; dim <= 3; dim++) { 51*d3c69ad0SToby Isaac for (PetscInt deg = 0; deg <= dimdeg[dim]; deg++) { 52*d3c69ad0SToby Isaac const PetscDTSimplexQuadratureType types[] = {PETSCDTSIMPLEXQUAD_DEFAULT, PETSCDTSIMPLEXQUAD_CONIC, PETSCDTSIMPLEXQUAD_MINSYM}; 53*d3c69ad0SToby Isaac 54*d3c69ad0SToby Isaac for (PetscInt t = 0; t < 3; t++) { 55*d3c69ad0SToby Isaac PetscCall(testQuadrature(dim, deg, types[t])); 56*d3c69ad0SToby Isaac } 57*d3c69ad0SToby Isaac } 58*d3c69ad0SToby Isaac } 59*d3c69ad0SToby Isaac PetscCall(PetscFinalize()); 60*d3c69ad0SToby Isaac return 0; 61*d3c69ad0SToby Isaac } 62*d3c69ad0SToby Isaac 63*d3c69ad0SToby Isaac /*TEST 64*d3c69ad0SToby Isaac 65*d3c69ad0SToby Isaac test: 66*d3c69ad0SToby Isaac suffix: 0 67*d3c69ad0SToby Isaac 68*d3c69ad0SToby Isaac TEST*/ 69