1c4762a1bSJed Brown static char help[] = "Tests 1D discretization tools.\n\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscdt.h> 4c4762a1bSJed Brown #include <petscviewer.h> 5c4762a1bSJed Brown #include <petsc/private/petscimpl.h> 6c4762a1bSJed Brown #include <petsc/private/dtimpl.h> 7c4762a1bSJed Brown 8c4762a1bSJed Brown static PetscErrorCode CheckPoints(const char *name,PetscInt npoints,const PetscReal *points,PetscInt ndegrees,const PetscInt *degrees) 9c4762a1bSJed Brown { 10c4762a1bSJed Brown PetscReal *B,*D,*D2; 11c4762a1bSJed Brown PetscInt i,j; 12c4762a1bSJed Brown 13c4762a1bSJed Brown PetscFunctionBegin; 145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(npoints*ndegrees,&B,npoints*ndegrees,&D,npoints*ndegrees,&D2)); 155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTLegendreEval(npoints,points,ndegrees,degrees,B,D,D2)); 165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"%s\n",name)); 17c4762a1bSJed Brown for (i=0; i<npoints; i++) { 18c4762a1bSJed Brown for (j=0; j<ndegrees; j++) { 19c4762a1bSJed Brown PetscReal b,d,d2; 20c4762a1bSJed Brown b = B[i*ndegrees+j]; 21c4762a1bSJed Brown d = D[i*ndegrees+j]; 22c4762a1bSJed Brown d2 = D2[i*ndegrees+j]; 23c4762a1bSJed Brown if (PetscAbsReal(b) < PETSC_SMALL) b = 0; 24c4762a1bSJed Brown if (PetscAbsReal(d) < PETSC_SMALL) d = 0; 25c4762a1bSJed Brown if (PetscAbsReal(d2) < PETSC_SMALL) d2 = 0; 265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"degree %D at %12.4g: B=%12.4g D=%12.4g D2=%12.4g\n",degrees[j],(double)points[i],(double)b,(double)d,(double)d2)); 27c4762a1bSJed Brown } 28c4762a1bSJed Brown } 295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(B,D,D2)); 30c4762a1bSJed Brown PetscFunctionReturn(0); 31c4762a1bSJed Brown } 32c4762a1bSJed Brown 33c4762a1bSJed Brown typedef PetscErrorCode(*quadratureFunc)(PetscInt,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal[],PetscReal[]); 34c4762a1bSJed Brown 35c4762a1bSJed Brown static PetscErrorCode CheckQuadrature_Basics(PetscInt npoints, PetscReal alpha, PetscReal beta, const PetscReal x[], const PetscReal w[]) 36c4762a1bSJed Brown { 37c4762a1bSJed Brown PetscInt i; 38c4762a1bSJed Brown 39c4762a1bSJed Brown PetscFunctionBegin; 40c4762a1bSJed Brown for (i = 1; i < npoints; i++) { 412c71b3e2SJacob Faibussowitsch PetscCheckFalse(x[i] <= x[i-1],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Quadrature points not monotonically increasing, %D points, alpha = %g, beta = %g, i = %D, x[i] = %g, x[i-1] = %g",npoints, (double) alpha, (double) beta, i, x[i], x[i-1]); 42c4762a1bSJed Brown } 43c4762a1bSJed Brown for (i = 0; i < npoints; i++) { 442c71b3e2SJacob Faibussowitsch PetscCheckFalse(w[i] <= 0.,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Quadrature weight not positive, %D points, alpha = %g, beta = %g, i = %D, w[i] = %g",npoints, (double) alpha, (double) beta, i, w[i]); 45c4762a1bSJed Brown } 46c4762a1bSJed Brown PetscFunctionReturn(0); 47c4762a1bSJed Brown } 48c4762a1bSJed Brown 49c4762a1bSJed Brown static PetscErrorCode CheckQuadrature(PetscInt npoints, PetscReal alpha, PetscReal beta, const PetscReal x[], const PetscReal w[], PetscInt nexact) 50c4762a1bSJed Brown { 51c4762a1bSJed Brown PetscInt i, j, k; 52c4762a1bSJed Brown PetscReal *Pi, *Pj; 53c4762a1bSJed Brown PetscReal eps; 54c4762a1bSJed Brown 55c4762a1bSJed Brown PetscFunctionBegin; 56c4762a1bSJed Brown eps = PETSC_SMALL; 575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(npoints, &Pi, npoints, &Pj)); 58c4762a1bSJed Brown for (i = 0; i <= nexact; i++) { 595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTJacobiEval(npoints, alpha, beta, x, 1, &i, Pi, NULL, NULL)); 60c4762a1bSJed Brown for (j = i; j <= nexact - i; j++) { 61c4762a1bSJed Brown PetscReal I_quad = 0.; 62c4762a1bSJed Brown PetscReal I_exact = 0.; 63c4762a1bSJed Brown PetscReal err, tol; 645f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTJacobiEval(npoints, alpha, beta, x, 1, &j, Pj, NULL, NULL)); 65c4762a1bSJed Brown 66c4762a1bSJed Brown tol = eps; 67c4762a1bSJed Brown if (i == j) { 68fbdc3dfeSToby Isaac PetscReal norm, norm2diff; 69fbdc3dfeSToby Isaac 70c4762a1bSJed Brown I_exact = PetscPowReal(2.0, alpha + beta + 1.) / (2.*i + alpha + beta + 1.); 71c4762a1bSJed Brown #if defined(PETSC_HAVE_LGAMMA) 72c4762a1bSJed Brown I_exact *= PetscExpReal(PetscLGamma(i + alpha + 1.) + PetscLGamma(i + beta + 1.) - (PetscLGamma(i + alpha + beta + 1.) + PetscLGamma(i + 1.))); 73c4762a1bSJed Brown #else 74c4762a1bSJed Brown { 75c4762a1bSJed Brown PetscInt ibeta = (PetscInt) beta; 76c4762a1bSJed Brown 772c71b3e2SJacob Faibussowitsch PetscCheckFalse((PetscReal) ibeta != beta,PETSC_COMM_SELF,PETSC_ERR_SUP,"lgamma() - math routine is unavailable."); 78c4762a1bSJed Brown for (k = 0; k < ibeta; k++) I_exact *= (i + 1. + k) / (i + alpha + 1. + k); 79c4762a1bSJed Brown } 80c4762a1bSJed Brown #endif 81fbdc3dfeSToby Isaac 825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTJacobiNorm(alpha, beta, i, &norm)); 83fbdc3dfeSToby Isaac norm2diff = PetscAbsReal(norm*norm - I_exact); 842c71b3e2SJacob Faibussowitsch PetscCheckFalse(norm2diff > eps * I_exact,PETSC_COMM_SELF,PETSC_ERR_PLIB, "Jacobi norm error %g", (double) norm2diff); 85fbdc3dfeSToby Isaac 86c4762a1bSJed Brown tol = eps * I_exact; 87c4762a1bSJed Brown } 88c4762a1bSJed Brown for (k = 0; k < npoints; k++) I_quad += w[k] * (Pi[k] * Pj[k]); 89c4762a1bSJed Brown err = PetscAbsReal(I_exact - I_quad); 905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"npoints %D, alpha %g, beta %g, i %D, j %D, exact %g, err %g\n", npoints, (double) alpha, (double) beta, i, j, (double) I_exact, (double) err)); 912c71b3e2SJacob Faibussowitsch PetscCheckFalse(err > tol,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Incorrectly integrated P_%D * P_%D using %D point rule with alpha = %g, beta = %g: exact %g, err %g", i, j, npoints, (double) alpha, (double) beta, (double) I_exact, (double) err); 92c4762a1bSJed Brown } 93c4762a1bSJed Brown } 945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(Pi, Pj)); 95c4762a1bSJed Brown PetscFunctionReturn(0); 96c4762a1bSJed Brown } 97c4762a1bSJed Brown 98c4762a1bSJed Brown static PetscErrorCode CheckJacobiQuadrature(PetscInt npoints, PetscReal alpha, PetscReal beta, quadratureFunc func, PetscInt nexact) 99c4762a1bSJed Brown { 100c4762a1bSJed Brown PetscReal *x, *w; 101c4762a1bSJed Brown 102c4762a1bSJed Brown PetscFunctionBegin; 1035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(npoints, &x, npoints, &w)); 1045f80ce2aSJacob Faibussowitsch CHKERRQ((*func)(npoints, -1., 1., alpha, beta, x, w)); 1055f80ce2aSJacob Faibussowitsch CHKERRQ(CheckQuadrature_Basics(npoints, alpha, beta, x, w)); 1065f80ce2aSJacob Faibussowitsch CHKERRQ(CheckQuadrature(npoints, alpha, beta, x, w, nexact)); 107c4762a1bSJed Brown #if defined(PETSCDTGAUSSIANQUADRATURE_EIG) 108c4762a1bSJed Brown /* compare methods of computing quadrature */ 109c4762a1bSJed Brown PetscDTGaussQuadratureNewton_Internal = (PetscBool) !PetscDTGaussQuadratureNewton_Internal; 110c4762a1bSJed Brown { 111c4762a1bSJed Brown PetscReal *x2, *w2; 112c4762a1bSJed Brown PetscReal eps; 113c4762a1bSJed Brown PetscInt i; 114c4762a1bSJed Brown 115c4762a1bSJed Brown eps = PETSC_SMALL; 1165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(npoints, &x2, npoints, &w2)); 1175f80ce2aSJacob Faibussowitsch CHKERRQ((*func)(npoints, -1., 1., alpha, beta, x2, w2)); 1185f80ce2aSJacob Faibussowitsch CHKERRQ(CheckQuadrature_Basics(npoints, alpha, beta, x2, w2)); 1195f80ce2aSJacob Faibussowitsch CHKERRQ(CheckQuadrature(npoints, alpha, beta, x2, w2, nexact)); 120c4762a1bSJed Brown for (i = 0; i < npoints; i++) { 121c4762a1bSJed Brown PetscReal xdiff, xtol, wdiff, wtol; 122c4762a1bSJed Brown 123c4762a1bSJed Brown xdiff = PetscAbsReal(x[i] - x2[i]); 124c4762a1bSJed Brown wdiff = PetscAbsReal(w[i] - w2[i]); 125c4762a1bSJed Brown xtol = eps * (1. + PetscMin(PetscAbsReal(x[i]),1. - PetscAbsReal(x[i]))); 126c4762a1bSJed Brown wtol = eps * (1. + w[i]); 1275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"npoints %D, alpha %g, beta %g, i %D, xdiff/xtol %g, wdiff/wtol %g\n", npoints, (double) alpha, (double) beta, i, (double) xdiff/xtol, (double) wdiff/wtol)); 1282c71b3e2SJacob Faibussowitsch PetscCheckFalse(xdiff > xtol,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatch quadrature point: %D points, alpha = %g, beta = %g, i = %D, xdiff = %g", npoints, (double) alpha, (double) beta, i, (double) xdiff); 1292c71b3e2SJacob Faibussowitsch PetscCheckFalse(wdiff > wtol,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mismatch quadrature weight: %D points, alpha = %g, beta = %g, i = %D, wdiff = %g", npoints, (double) alpha, (double) beta, i, (double) wdiff); 130c4762a1bSJed Brown } 1315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(x2, w2)); 132c4762a1bSJed Brown } 133c4762a1bSJed Brown /* restore */ 134c4762a1bSJed Brown PetscDTGaussQuadratureNewton_Internal = (PetscBool) !PetscDTGaussQuadratureNewton_Internal; 135c4762a1bSJed Brown #endif 1365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(x, w)); 137c4762a1bSJed Brown PetscFunctionReturn(0); 138c4762a1bSJed Brown } 139c4762a1bSJed Brown 140c4762a1bSJed Brown int main(int argc,char **argv) 141c4762a1bSJed Brown { 142c4762a1bSJed Brown PetscErrorCode ierr; 143c4762a1bSJed Brown PetscInt degrees[1000],ndegrees,npoints,two; 144c4762a1bSJed Brown PetscReal points[1000],weights[1000],interval[2]; 145c4762a1bSJed Brown PetscInt minpoints, maxpoints; 146c4762a1bSJed Brown PetscBool flg; 147c4762a1bSJed Brown 148*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc,&argv,(char*)0,help)); 149c4762a1bSJed Brown ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Discretization tools test options",NULL);CHKERRQ(ierr); 150c4762a1bSJed Brown { 151c4762a1bSJed Brown ndegrees = 1000; 152c4762a1bSJed Brown degrees[0] = 0; 153c4762a1bSJed Brown degrees[1] = 1; 154c4762a1bSJed Brown degrees[2] = 2; 1555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsIntArray("-degrees","list of degrees to evaluate","",degrees,&ndegrees,&flg)); 156c4762a1bSJed Brown 157c4762a1bSJed Brown if (!flg) ndegrees = 3; 158c4762a1bSJed Brown npoints = 1000; 159c4762a1bSJed Brown points[0] = 0.0; 160c4762a1bSJed Brown points[1] = -0.5; 161c4762a1bSJed Brown points[2] = 1.0; 1625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRealArray("-points","list of points at which to evaluate","",points,&npoints,&flg)); 163c4762a1bSJed Brown 164c4762a1bSJed Brown if (!flg) npoints = 3; 165c4762a1bSJed Brown two = 2; 166c4762a1bSJed Brown interval[0] = -1.; 167c4762a1bSJed Brown interval[1] = 1.; 1685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsRealArray("-interval","interval on which to construct quadrature","",interval,&two,NULL)); 169c4762a1bSJed Brown 170c4762a1bSJed Brown minpoints = 1; 1715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-minpoints","minimum points for thorough Gauss-Jacobi quadrature tests","",minpoints,&minpoints,NULL)); 172c4762a1bSJed Brown maxpoints = 30; 173c4762a1bSJed Brown #if defined(PETSC_USE_REAL_SINGLE) 174c4762a1bSJed Brown maxpoints = 5; 175c4762a1bSJed Brown #elif defined(PETSC_USE_REAL___FLOAT128) 176c4762a1bSJed Brown maxpoints = 20; /* just to make test faster */ 177c4762a1bSJed Brown #endif 1785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-maxpoints","maximum points for thorough Gauss-Jacobi quadrature tests","",maxpoints,&maxpoints,NULL)); 179c4762a1bSJed Brown } 180c4762a1bSJed Brown ierr = PetscOptionsEnd();CHKERRQ(ierr); 1815f80ce2aSJacob Faibussowitsch CHKERRQ(CheckPoints("User-provided points",npoints,points,ndegrees,degrees)); 182c4762a1bSJed Brown 1835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDTGaussQuadrature(npoints,interval[0],interval[1],points,weights)); 1845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Quadrature weights\n")); 1855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRealView(npoints,weights,PETSC_VIEWER_STDOUT_WORLD)); 186c4762a1bSJed Brown { 187c4762a1bSJed Brown PetscReal a = interval[0],b = interval[1],zeroth,first,second; 188c4762a1bSJed Brown PetscInt i; 189c4762a1bSJed Brown zeroth = b - a; 190c4762a1bSJed Brown first = (b*b - a*a)/2; 191c4762a1bSJed Brown second = (b*b*b - a*a*a)/3; 192c4762a1bSJed Brown for (i=0; i<npoints; i++) { 193c4762a1bSJed Brown zeroth -= weights[i]; 194c4762a1bSJed Brown first -= weights[i] * points[i]; 195c4762a1bSJed Brown second -= weights[i] * PetscSqr(points[i]); 196c4762a1bSJed Brown } 197c4762a1bSJed Brown if (PetscAbs(zeroth) < 1e-10) zeroth = 0.; 198c4762a1bSJed Brown if (PetscAbs(first) < 1e-10) first = 0.; 199c4762a1bSJed Brown if (PetscAbs(second) < 1e-10) second = 0.; 2005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"Moment error: zeroth=%g, first=%g, second=%g\n",(double)(-zeroth),(double)(-first),(double)(-second))); 201c4762a1bSJed Brown } 2025f80ce2aSJacob Faibussowitsch CHKERRQ(CheckPoints("Gauss points",npoints,points,ndegrees,degrees)); 203c4762a1bSJed Brown { 204c4762a1bSJed Brown PetscInt i; 205c4762a1bSJed Brown 206c4762a1bSJed Brown for (i = minpoints; i <= maxpoints; i++) { 207c4762a1bSJed Brown PetscReal a1, b1, a2, b2; 208c4762a1bSJed Brown 209c4762a1bSJed Brown #if defined(PETSC_HAVE_LGAMMA) 210c4762a1bSJed Brown a1 = -0.6; 211c4762a1bSJed Brown b1 = 1.1; 212c4762a1bSJed Brown a2 = 2.2; 213c4762a1bSJed Brown b2 = -0.6; 214c4762a1bSJed Brown #else 215c4762a1bSJed Brown a1 = 0.; 216c4762a1bSJed Brown b1 = 1.; 217c4762a1bSJed Brown a2 = 2.; 218c4762a1bSJed Brown b2 = 0.; 219c4762a1bSJed Brown #endif 2205f80ce2aSJacob Faibussowitsch CHKERRQ(CheckJacobiQuadrature(i, 0., 0., PetscDTGaussJacobiQuadrature, 2*i-1)); 2215f80ce2aSJacob Faibussowitsch CHKERRQ(CheckJacobiQuadrature(i, a1, b1, PetscDTGaussJacobiQuadrature, 2*i-1)); 2225f80ce2aSJacob Faibussowitsch CHKERRQ(CheckJacobiQuadrature(i, a2, b2, PetscDTGaussJacobiQuadrature, 2*i-1)); 223c4762a1bSJed Brown if (i >= 2) { 2245f80ce2aSJacob Faibussowitsch CHKERRQ(CheckJacobiQuadrature(i, 0., 0., PetscDTGaussLobattoJacobiQuadrature, 2*i-3)); 2255f80ce2aSJacob Faibussowitsch CHKERRQ(CheckJacobiQuadrature(i, a1, b1, PetscDTGaussLobattoJacobiQuadrature, 2*i-3)); 2265f80ce2aSJacob Faibussowitsch CHKERRQ(CheckJacobiQuadrature(i, a2, b2, PetscDTGaussLobattoJacobiQuadrature, 2*i-3)); 227c4762a1bSJed Brown } 228c4762a1bSJed Brown } 229c4762a1bSJed Brown } 230*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 231*b122ec5aSJacob Faibussowitsch return 0; 232c4762a1bSJed Brown } 233c4762a1bSJed Brown 234c4762a1bSJed Brown /*TEST 235c4762a1bSJed Brown test: 236c4762a1bSJed Brown suffix: 1 237c4762a1bSJed Brown args: -degrees 1,2,3,4,5 -points 0,.2,-.5,.8,.9,1 -interval -.5,1 238c4762a1bSJed Brown TEST*/ 239