1*c4762a1bSJed Brown static char help[] = "Test the PetscDTAltV interface for k-forms (alternating k-linear maps).\n\n"; 2*c4762a1bSJed Brown 3*c4762a1bSJed Brown #include <petscviewer.h> 4*c4762a1bSJed Brown #include <petscdt.h> 5*c4762a1bSJed Brown 6*c4762a1bSJed Brown static PetscErrorCode CheckPullback(PetscInt N, PetscInt M, const PetscReal *L, PetscInt k, 7*c4762a1bSJed Brown const PetscReal *w, PetscReal *x, PetscBool verbose, PetscViewer viewer) 8*c4762a1bSJed Brown { 9*c4762a1bSJed Brown PetscInt Nk, Mk, i, j, l; 10*c4762a1bSJed Brown PetscReal *Lstarw, *Lx, *Lstar, *Lstarwcheck, wLx, Lstarwx; 11*c4762a1bSJed Brown PetscReal diff, diffMat, normMat; 12*c4762a1bSJed Brown PetscReal *walloc = NULL; 13*c4762a1bSJed Brown const PetscReal *ww = NULL; 14*c4762a1bSJed Brown PetscBool negative = (PetscBool) (k < 0); 15*c4762a1bSJed Brown PetscErrorCode ierr; 16*c4762a1bSJed Brown 17*c4762a1bSJed Brown PetscFunctionBegin; 18*c4762a1bSJed Brown k = PetscAbsInt(k); 19*c4762a1bSJed Brown ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 20*c4762a1bSJed Brown ierr = PetscDTBinomialInt(M, k, &Mk);CHKERRQ(ierr); 21*c4762a1bSJed Brown if (negative) { 22*c4762a1bSJed Brown ierr = PetscMalloc1(Mk, &walloc);CHKERRQ(ierr); 23*c4762a1bSJed Brown ierr = PetscDTAltVStar(M, M - k, 1, w, walloc);CHKERRQ(ierr); 24*c4762a1bSJed Brown ww = walloc; 25*c4762a1bSJed Brown } else { 26*c4762a1bSJed Brown ww = w; 27*c4762a1bSJed Brown } 28*c4762a1bSJed Brown ierr = PetscMalloc2(Nk, &Lstarw, (M*k), &Lx);CHKERRQ(ierr); 29*c4762a1bSJed Brown ierr = PetscMalloc2(Nk * Mk, &Lstar, Nk, &Lstarwcheck);CHKERRQ(ierr); 30*c4762a1bSJed Brown ierr = PetscDTAltVPullback(N, M, L, negative ? -k : k, w, Lstarw);CHKERRQ(ierr); 31*c4762a1bSJed Brown ierr = PetscDTAltVPullbackMatrix(N, M, L, negative ? -k : k, Lstar);CHKERRQ(ierr); 32*c4762a1bSJed Brown if (negative) { 33*c4762a1bSJed Brown PetscReal *sLsw; 34*c4762a1bSJed Brown 35*c4762a1bSJed Brown ierr = PetscMalloc1(Nk, &sLsw);CHKERRQ(ierr); 36*c4762a1bSJed Brown ierr = PetscDTAltVStar(N, N - k, 1, Lstarw, sLsw);CHKERRQ(ierr); 37*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, sLsw, x, &Lstarwx);CHKERRQ(ierr); 38*c4762a1bSJed Brown ierr = PetscFree(sLsw);CHKERRQ(ierr); 39*c4762a1bSJed Brown } else { 40*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, Lstarw, x, &Lstarwx);CHKERRQ(ierr); 41*c4762a1bSJed Brown } 42*c4762a1bSJed Brown for (l = 0; l < k; l++) { 43*c4762a1bSJed Brown for (i = 0; i < M; i++) { 44*c4762a1bSJed Brown PetscReal sum = 0.; 45*c4762a1bSJed Brown 46*c4762a1bSJed Brown for (j = 0; j < N; j++) sum += L[i * N + j] * x[l * N + j]; 47*c4762a1bSJed Brown Lx[l * M + i] = sum; 48*c4762a1bSJed Brown } 49*c4762a1bSJed Brown } 50*c4762a1bSJed Brown diffMat = 0.; 51*c4762a1bSJed Brown normMat = 0.; 52*c4762a1bSJed Brown for (i = 0; i < Nk; i++) { 53*c4762a1bSJed Brown PetscReal sum = 0.; 54*c4762a1bSJed Brown for (j = 0; j < Mk; j++) { 55*c4762a1bSJed Brown sum += Lstar[i * Mk + j] * w[j]; 56*c4762a1bSJed Brown } 57*c4762a1bSJed Brown Lstarwcheck[i] = sum; 58*c4762a1bSJed Brown diffMat += PetscSqr(PetscAbsReal(Lstarwcheck[i] - Lstarw[i])); 59*c4762a1bSJed Brown normMat += PetscSqr(Lstarwcheck[i]) + PetscSqr(Lstarw[i]); 60*c4762a1bSJed Brown } 61*c4762a1bSJed Brown diffMat = PetscSqrtReal(diffMat); 62*c4762a1bSJed Brown normMat = PetscSqrtReal(normMat); 63*c4762a1bSJed Brown if (verbose) { 64*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "L:\n");CHKERRQ(ierr); 65*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 66*c4762a1bSJed Brown if (M*N > 0) {ierr = PetscRealView(M*N, L, viewer);CHKERRQ(ierr);} 67*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 68*c4762a1bSJed Brown 69*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "L*:\n");CHKERRQ(ierr); 70*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 71*c4762a1bSJed Brown if (Nk * Mk > 0) {ierr = PetscRealView(Nk * Mk, Lstar, viewer);CHKERRQ(ierr);} 72*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 73*c4762a1bSJed Brown 74*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "L*w:\n");CHKERRQ(ierr); 75*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 76*c4762a1bSJed Brown if (Nk > 0) {ierr = PetscRealView(Nk, Lstarw, viewer);CHKERRQ(ierr);} 77*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 78*c4762a1bSJed Brown } 79*c4762a1bSJed Brown ierr = PetscDTAltVApply(M, k, ww, Lx, &wLx);CHKERRQ(ierr); 80*c4762a1bSJed Brown diff = PetscAbsReal(wLx - Lstarwx); 81*c4762a1bSJed Brown if (diff > 10. * PETSC_SMALL * (PetscAbsReal(wLx) + PetscAbsReal(Lstarwx))) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "pullback check: pullback does not commute with application: w(Lx)(%g) != (L* w)(x)(%g)", wLx, Lstarwx); 82*c4762a1bSJed Brown if (diffMat > PETSC_SMALL * normMat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "pullback check: pullback matrix does match matrix free result"); 83*c4762a1bSJed Brown ierr = PetscFree2(Lstar, Lstarwcheck);CHKERRQ(ierr); 84*c4762a1bSJed Brown ierr = PetscFree2(Lstarw, Lx);CHKERRQ(ierr); 85*c4762a1bSJed Brown ierr = PetscFree(walloc);CHKERRQ(ierr); 86*c4762a1bSJed Brown PetscFunctionReturn(0); 87*c4762a1bSJed Brown } 88*c4762a1bSJed Brown 89*c4762a1bSJed Brown int main(int argc, char **argv) 90*c4762a1bSJed Brown { 91*c4762a1bSJed Brown PetscInt i, numTests = 5, n[5] = {0, 1, 2, 3, 4}; 92*c4762a1bSJed Brown PetscBool verbose = PETSC_FALSE; 93*c4762a1bSJed Brown PetscRandom rand; 94*c4762a1bSJed Brown PetscViewer viewer; 95*c4762a1bSJed Brown PetscErrorCode ierr; 96*c4762a1bSJed Brown 97*c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr; 98*c4762a1bSJed Brown ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"","Options for exterior algebra tests","none");CHKERRQ(ierr); 99*c4762a1bSJed Brown ierr = PetscOptionsIntArray("-N", "Up to 5 vector space dimensions to test","ex6.c",n,&numTests,NULL);CHKERRQ(ierr); 100*c4762a1bSJed Brown ierr = PetscOptionsBool("-verbose", "Verbose test output","ex6.c",verbose,&verbose,NULL);CHKERRQ(ierr); 101*c4762a1bSJed Brown ierr = PetscOptionsEnd(); 102*c4762a1bSJed Brown ierr = PetscRandomCreate(PETSC_COMM_SELF, &rand);CHKERRQ(ierr); 103*c4762a1bSJed Brown ierr = PetscRandomSetInterval(rand, -1., 1.);CHKERRQ(ierr); 104*c4762a1bSJed Brown ierr = PetscRandomSetFromOptions(rand);CHKERRQ(ierr); 105*c4762a1bSJed Brown if (!numTests) numTests = 5; 106*c4762a1bSJed Brown viewer = PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD); 107*c4762a1bSJed Brown for (i = 0; i < numTests; i++) { 108*c4762a1bSJed Brown PetscInt k, N = n[i]; 109*c4762a1bSJed Brown 110*c4762a1bSJed Brown if (verbose) {ierr = PetscViewerASCIIPrintf(viewer, "N = %D:\n", N);CHKERRQ(ierr);} 111*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 112*c4762a1bSJed Brown 113*c4762a1bSJed Brown if (verbose) { 114*c4762a1bSJed Brown PetscInt *perm; 115*c4762a1bSJed Brown PetscInt fac = 1; 116*c4762a1bSJed Brown 117*c4762a1bSJed Brown ierr = PetscMalloc1(N, &perm);CHKERRQ(ierr); 118*c4762a1bSJed Brown 119*c4762a1bSJed Brown for (k = 1; k <= N; k++) fac *= k; 120*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "Permutations of %D:\n", N);CHKERRQ(ierr); 121*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 122*c4762a1bSJed Brown for (k = 0; k < fac; k++) { 123*c4762a1bSJed Brown PetscBool isOdd, isOddCheck; 124*c4762a1bSJed Brown PetscInt j, kCheck; 125*c4762a1bSJed Brown 126*c4762a1bSJed Brown ierr = PetscDTEnumPerm(N, k, perm, &isOdd);CHKERRQ(ierr); 127*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "%D:", k);CHKERRQ(ierr); 128*c4762a1bSJed Brown for (j = 0; j < N; j++) { 129*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, " %D", perm[j]);CHKERRQ(ierr); 130*c4762a1bSJed Brown } 131*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, ", %s\n", isOdd ? "odd" : "even");CHKERRQ(ierr); 132*c4762a1bSJed Brown ierr = PetscDTPermIndex(N, perm, &kCheck, &isOddCheck);CHKERRQ(ierr); 133*c4762a1bSJed Brown if (kCheck != k || isOddCheck != isOdd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscDTEnumPerm / PetscDTPermIndex mismatch for (%D, %D)\n", N, k); 134*c4762a1bSJed Brown } 135*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 136*c4762a1bSJed Brown ierr = PetscFree(perm);CHKERRQ(ierr); 137*c4762a1bSJed Brown } 138*c4762a1bSJed Brown for (k = 0; k <= N; k++) { 139*c4762a1bSJed Brown PetscInt j, Nk, M; 140*c4762a1bSJed Brown PetscReal *w, *v, wv; 141*c4762a1bSJed Brown PetscInt *subset; 142*c4762a1bSJed Brown 143*c4762a1bSJed Brown ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 144*c4762a1bSJed Brown if (verbose) {ierr = PetscViewerASCIIPrintf(viewer, "k = %D:\n", k);CHKERRQ(ierr);} 145*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 146*c4762a1bSJed Brown if (verbose) {ierr = PetscViewerASCIIPrintf(viewer, "(%D choose %D): %D\n", N, k, Nk);CHKERRQ(ierr);} 147*c4762a1bSJed Brown 148*c4762a1bSJed Brown /* Test subset and complement enumeration */ 149*c4762a1bSJed Brown ierr = PetscMalloc1(N, &subset);CHKERRQ(ierr); 150*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 151*c4762a1bSJed Brown for (j = 0; j < Nk; j++) { 152*c4762a1bSJed Brown PetscBool isOdd, isOddCheck; 153*c4762a1bSJed Brown PetscInt jCheck, kCheck; 154*c4762a1bSJed Brown 155*c4762a1bSJed Brown ierr = PetscDTEnumSplit(N, k, j, subset, &isOdd);CHKERRQ(ierr); 156*c4762a1bSJed Brown ierr = PetscDTPermIndex(N, subset, &kCheck, &isOddCheck);CHKERRQ(ierr); 157*c4762a1bSJed Brown if (isOddCheck != isOdd) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscDTEnumSplit sign does not mmatch PetscDTPermIndex sign"); 158*c4762a1bSJed Brown if (verbose) { 159*c4762a1bSJed Brown PetscInt l; 160*c4762a1bSJed Brown 161*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "subset %D:", j);CHKERRQ(ierr); 162*c4762a1bSJed Brown for (l = 0; l < k; l++) { 163*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, " %D", subset[l]);CHKERRQ(ierr); 164*c4762a1bSJed Brown } 165*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, " |");CHKERRQ(ierr); 166*c4762a1bSJed Brown for (l = k; l < N; l++) { 167*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, " %D", subset[l]);CHKERRQ(ierr); 168*c4762a1bSJed Brown } 169*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, ", %s\n", isOdd ? "odd" : "even");CHKERRQ(ierr); 170*c4762a1bSJed Brown } 171*c4762a1bSJed Brown ierr = PetscDTSubsetIndex(N, k, subset, &jCheck);CHKERRQ(ierr); 172*c4762a1bSJed Brown if (jCheck != j) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "jCheck (%D) != j (%D)", jCheck, j); 173*c4762a1bSJed Brown } 174*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 175*c4762a1bSJed Brown ierr = PetscFree(subset);CHKERRQ(ierr); 176*c4762a1bSJed Brown 177*c4762a1bSJed Brown /* Make a random k form */ 178*c4762a1bSJed Brown ierr = PetscMalloc1(Nk, &w);CHKERRQ(ierr); 179*c4762a1bSJed Brown for (j = 0; j < Nk; j++) {ierr = PetscRandomGetValueReal(rand, &w[j]);CHKERRQ(ierr);} 180*c4762a1bSJed Brown /* Make a set of random vectors */ 181*c4762a1bSJed Brown ierr = PetscMalloc1(N*k, &v);CHKERRQ(ierr); 182*c4762a1bSJed Brown for (j = 0; j < N*k; j++) {ierr = PetscRandomGetValueReal(rand, &v[j]);CHKERRQ(ierr);} 183*c4762a1bSJed Brown 184*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, w, v, &wv);CHKERRQ(ierr); 185*c4762a1bSJed Brown 186*c4762a1bSJed Brown if (verbose) { 187*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "w:\n");CHKERRQ(ierr); 188*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 189*c4762a1bSJed Brown if (Nk) {ierr = PetscRealView(Nk, w, viewer);CHKERRQ(ierr);} 190*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 191*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "v:\n");CHKERRQ(ierr); 192*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 193*c4762a1bSJed Brown if (N*k > 0) {ierr = PetscRealView(N*k, v, viewer);CHKERRQ(ierr);} 194*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 195*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "w(v): %g\n", (double) wv);CHKERRQ(ierr); 196*c4762a1bSJed Brown } 197*c4762a1bSJed Brown 198*c4762a1bSJed Brown /* sanity checks */ 199*c4762a1bSJed Brown if (k == 1) { /* 1-forms are functionals (dot products) */ 200*c4762a1bSJed Brown PetscInt l; 201*c4762a1bSJed Brown PetscReal wvcheck = 0.; 202*c4762a1bSJed Brown PetscReal diff; 203*c4762a1bSJed Brown 204*c4762a1bSJed Brown for (l = 0; l < N; l++) wvcheck += w[l] * v[l]; 205*c4762a1bSJed Brown diff = PetscSqrtReal(PetscSqr(wvcheck - wv)); 206*c4762a1bSJed Brown if (diff >= PETSC_SMALL * (PetscAbsReal(wv) + PetscAbsReal(wvcheck))) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "1-form / dot product equivalence: wvcheck (%g) != wv (%g)", (double) wvcheck, (double) wv); 207*c4762a1bSJed Brown } 208*c4762a1bSJed Brown if (k == N && N < 5) { /* n-forms are scaled determinants */ 209*c4762a1bSJed Brown PetscReal det, wvcheck, diff; 210*c4762a1bSJed Brown 211*c4762a1bSJed Brown switch (k) { 212*c4762a1bSJed Brown case 0: 213*c4762a1bSJed Brown det = 1.; 214*c4762a1bSJed Brown break; 215*c4762a1bSJed Brown case 1: 216*c4762a1bSJed Brown det = v[0]; 217*c4762a1bSJed Brown break; 218*c4762a1bSJed Brown case 2: 219*c4762a1bSJed Brown det = v[0] * v[3] - v[1] * v[2]; 220*c4762a1bSJed Brown break; 221*c4762a1bSJed Brown case 3: 222*c4762a1bSJed Brown det = v[0] * (v[4] * v[8] - v[5] * v[7]) + 223*c4762a1bSJed Brown v[1] * (v[5] * v[6] - v[3] * v[8]) + 224*c4762a1bSJed Brown v[2] * (v[3] * v[7] - v[4] * v[6]); 225*c4762a1bSJed Brown break; 226*c4762a1bSJed Brown case 4: 227*c4762a1bSJed Brown det = v[0] * (v[5] * (v[10] * v[15] - v[11] * v[14]) + 228*c4762a1bSJed Brown v[6] * (v[11] * v[13] - v[ 9] * v[15]) + 229*c4762a1bSJed Brown v[7] * (v[ 9] * v[14] - v[10] * v[13])) - 230*c4762a1bSJed Brown v[1] * (v[4] * (v[10] * v[15] - v[11] * v[14]) + 231*c4762a1bSJed Brown v[6] * (v[11] * v[12] - v[ 8] * v[15]) + 232*c4762a1bSJed Brown v[7] * (v[ 8] * v[14] - v[10] * v[12])) + 233*c4762a1bSJed Brown v[2] * (v[4] * (v[ 9] * v[15] - v[11] * v[13]) + 234*c4762a1bSJed Brown v[5] * (v[11] * v[12] - v[ 8] * v[15]) + 235*c4762a1bSJed Brown v[7] * (v[ 8] * v[13] - v[ 9] * v[12])) - 236*c4762a1bSJed Brown v[3] * (v[4] * (v[ 9] * v[14] - v[10] * v[13]) + 237*c4762a1bSJed Brown v[5] * (v[10] * v[12] - v[ 8] * v[14]) + 238*c4762a1bSJed Brown v[6] * (v[ 8] * v[13] - v[ 9] * v[12])); 239*c4762a1bSJed Brown break; 240*c4762a1bSJed Brown default: 241*c4762a1bSJed Brown SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "invalid k"); 242*c4762a1bSJed Brown } 243*c4762a1bSJed Brown wvcheck = det * w[0]; 244*c4762a1bSJed Brown diff = PetscSqrtReal(PetscSqr(wvcheck - wv)); 245*c4762a1bSJed Brown if (diff >= PETSC_SMALL * (PetscAbsReal(wv) + PetscAbsReal(wvcheck))) SETERRQ3(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "n-form / determinant equivalence: wvcheck (%g) != wv (%g) %g", (double) wvcheck, (double) wv, (double) diff); 246*c4762a1bSJed Brown } 247*c4762a1bSJed Brown if (k > 0) { /* k-forms are linear in each component */ 248*c4762a1bSJed Brown PetscReal alpha; 249*c4762a1bSJed Brown PetscReal *x, *axv, wx, waxv, waxvcheck; 250*c4762a1bSJed Brown PetscReal diff; 251*c4762a1bSJed Brown PetscReal rj; 252*c4762a1bSJed Brown PetscInt l; 253*c4762a1bSJed Brown 254*c4762a1bSJed Brown ierr = PetscMalloc2(N * k, &x, N * k, &axv);CHKERRQ(ierr); 255*c4762a1bSJed Brown ierr = PetscRandomGetValueReal(rand, &alpha);CHKERRQ(ierr); 256*c4762a1bSJed Brown ierr = PetscRandomSetInterval(rand, 0, k);CHKERRQ(ierr); 257*c4762a1bSJed Brown ierr = PetscRandomGetValueReal(rand, &rj);CHKERRQ(ierr); 258*c4762a1bSJed Brown j = (PetscInt) rj; 259*c4762a1bSJed Brown ierr = PetscRandomSetInterval(rand, -1., 1.);CHKERRQ(ierr); 260*c4762a1bSJed Brown for (l = 0; l < N*k; l++) x[l] = v[l]; 261*c4762a1bSJed Brown for (l = 0; l < N*k; l++) axv[l] = v[l]; 262*c4762a1bSJed Brown for (l = 0; l < N; l++) { 263*c4762a1bSJed Brown PetscReal val; 264*c4762a1bSJed Brown 265*c4762a1bSJed Brown ierr = PetscRandomGetValueReal(rand, &val);CHKERRQ(ierr); 266*c4762a1bSJed Brown x[j * N + l] = val; 267*c4762a1bSJed Brown axv[j * N + l] += alpha * val; 268*c4762a1bSJed Brown } 269*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, w, x, &wx);CHKERRQ(ierr); 270*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, w, axv, &waxv);CHKERRQ(ierr); 271*c4762a1bSJed Brown waxvcheck = alpha * wx + wv; 272*c4762a1bSJed Brown diff = waxv - waxvcheck; 273*c4762a1bSJed Brown if (PetscAbsReal(diff) > 10. * PETSC_SMALL * (PetscAbsReal(waxv) + PetscAbsReal(waxvcheck))) SETERRQ3(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "linearity check: component %D, waxvcheck (%g) != waxv (%g)", j, (double) waxvcheck, (double) waxv); 274*c4762a1bSJed Brown ierr = PetscFree2(x,axv);CHKERRQ(ierr); 275*c4762a1bSJed Brown } 276*c4762a1bSJed Brown if (k > 1) { /* k-forms are antisymmetric */ 277*c4762a1bSJed Brown PetscReal rj, rl, *swapv, wswapv, diff; 278*c4762a1bSJed Brown PetscInt l, m; 279*c4762a1bSJed Brown 280*c4762a1bSJed Brown ierr = PetscRandomSetInterval(rand, 0, k);CHKERRQ(ierr); 281*c4762a1bSJed Brown ierr = PetscRandomGetValueReal(rand, &rj);CHKERRQ(ierr); 282*c4762a1bSJed Brown j = (PetscInt) rj; 283*c4762a1bSJed Brown l = j; 284*c4762a1bSJed Brown while (l == j) { 285*c4762a1bSJed Brown ierr = PetscRandomGetValueReal(rand, &rl);CHKERRQ(ierr); 286*c4762a1bSJed Brown l = (PetscInt) rl; 287*c4762a1bSJed Brown } 288*c4762a1bSJed Brown ierr = PetscRandomSetInterval(rand, -1., 1.);CHKERRQ(ierr); 289*c4762a1bSJed Brown ierr = PetscMalloc1(N * k, &swapv);CHKERRQ(ierr); 290*c4762a1bSJed Brown for (m = 0; m < N * k; m++) swapv[m] = v[m]; 291*c4762a1bSJed Brown for (m = 0; m < N; m++) { 292*c4762a1bSJed Brown swapv[j * N + m] = v[l * N + m]; 293*c4762a1bSJed Brown swapv[l * N + m] = v[j * N + m]; 294*c4762a1bSJed Brown } 295*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, w, swapv, &wswapv);CHKERRQ(ierr); 296*c4762a1bSJed Brown diff = PetscAbsReal(wswapv + wv); 297*c4762a1bSJed Brown if (diff > PETSC_SMALL * (PetscAbsReal(wswapv) + PetscAbsReal(wv))) SETERRQ4(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "antisymmetry check: components %D & %D, wswapv (%g) != -wv (%g)", j, l, (double) wswapv, (double) wv); 298*c4762a1bSJed Brown ierr = PetscFree(swapv);CHKERRQ(ierr); 299*c4762a1bSJed Brown } 300*c4762a1bSJed Brown for (j = 0; j <= k && j + k <= N; j++) { /* wedge product */ 301*c4762a1bSJed Brown PetscInt Nj, Njk, l, JKj; 302*c4762a1bSJed Brown PetscReal *u, *uWw, *uWwcheck, *uWwmat, *x, *xsplit, uWwx, uWwxcheck, diff, norm; 303*c4762a1bSJed Brown PetscInt *split; 304*c4762a1bSJed Brown 305*c4762a1bSJed Brown if (verbose) {ierr = PetscViewerASCIIPrintf(viewer, "wedge j = %D:\n", j);CHKERRQ(ierr);} 306*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 307*c4762a1bSJed Brown ierr = PetscDTBinomialInt(N, j, &Nj);CHKERRQ(ierr); 308*c4762a1bSJed Brown ierr = PetscDTBinomialInt(N, j+k, &Njk);CHKERRQ(ierr); 309*c4762a1bSJed Brown ierr = PetscMalloc4(Nj, &u, Njk, &uWw, N*(j+k), &x, N*(j+k), &xsplit);CHKERRQ(ierr); 310*c4762a1bSJed Brown ierr = PetscMalloc1(j+k,&split);CHKERRQ(ierr); 311*c4762a1bSJed Brown for (l = 0; l < Nj; l++) {ierr = PetscRandomGetValueReal(rand, &u[l]);CHKERRQ(ierr);} 312*c4762a1bSJed Brown for (l = 0; l < N*(j+k); l++) {ierr = PetscRandomGetValueReal(rand, &x[l]);CHKERRQ(ierr);} 313*c4762a1bSJed Brown ierr = PetscDTAltVWedge(N, j, k, u, w, uWw);CHKERRQ(ierr); 314*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, j+k, uWw, x, &uWwx);CHKERRQ(ierr); 315*c4762a1bSJed Brown if (verbose) { 316*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "u:\n");CHKERRQ(ierr); 317*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 318*c4762a1bSJed Brown if (Nj) {ierr = PetscRealView(Nj, u, viewer);CHKERRQ(ierr);} 319*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 320*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "u wedge w:\n");CHKERRQ(ierr); 321*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 322*c4762a1bSJed Brown if (Njk) {ierr = PetscRealView(Njk, uWw, viewer);CHKERRQ(ierr);} 323*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 324*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "x:\n");CHKERRQ(ierr); 325*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 326*c4762a1bSJed Brown if (N*(j+k) > 0) {ierr = PetscRealView(N*(j+k), x, viewer);CHKERRQ(ierr);} 327*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 328*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "u wedge w(x): %g\n", (double) uWwx);CHKERRQ(ierr); 329*c4762a1bSJed Brown } 330*c4762a1bSJed Brown /* verify wedge formula */ 331*c4762a1bSJed Brown uWwxcheck = 0.; 332*c4762a1bSJed Brown ierr = PetscDTBinomialInt(j+k, j, &JKj);CHKERRQ(ierr); 333*c4762a1bSJed Brown for (l = 0; l < JKj; l++) { 334*c4762a1bSJed Brown PetscBool isOdd; 335*c4762a1bSJed Brown PetscReal ux, wx; 336*c4762a1bSJed Brown PetscInt m, p; 337*c4762a1bSJed Brown 338*c4762a1bSJed Brown ierr = PetscDTEnumSplit(j+k, j, l, split, &isOdd);CHKERRQ(ierr); 339*c4762a1bSJed Brown for (m = 0; m < j+k; m++) {for (p = 0; p < N; p++) {xsplit[m * N + p] = x[split[m] * N + p];}} 340*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, j, u, xsplit, &ux);CHKERRQ(ierr); 341*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k, w, &xsplit[j*N], &wx);CHKERRQ(ierr); 342*c4762a1bSJed Brown uWwxcheck += isOdd ? -(ux * wx) : (ux * wx); 343*c4762a1bSJed Brown } 344*c4762a1bSJed Brown diff = PetscAbsReal(uWwx - uWwxcheck); 345*c4762a1bSJed Brown if (diff > 10. * PETSC_SMALL * (PetscAbsReal(uWwx) + PetscAbsReal(uWwxcheck))) SETERRQ4(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "wedge check: forms %D & %D, uWwxcheck (%g) != uWwx (%g)", j, k, (double) uWwxcheck, (double) uWwx); 346*c4762a1bSJed Brown ierr = PetscFree(split);CHKERRQ(ierr); 347*c4762a1bSJed Brown ierr = PetscMalloc2(Nk * Njk, &uWwmat, Njk, &uWwcheck);CHKERRQ(ierr); 348*c4762a1bSJed Brown ierr = PetscDTAltVWedgeMatrix(N, j, k, u, uWwmat);CHKERRQ(ierr); 349*c4762a1bSJed Brown if (verbose) { 350*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "(u wedge):\n");CHKERRQ(ierr); 351*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 352*c4762a1bSJed Brown if ((Nk * Njk) > 0) {ierr = PetscRealView(Nk * Njk, uWwmat, viewer);CHKERRQ(ierr);} 353*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 354*c4762a1bSJed Brown } 355*c4762a1bSJed Brown diff = 0.; 356*c4762a1bSJed Brown norm = 0.; 357*c4762a1bSJed Brown for (l = 0; l < Njk; l++) { 358*c4762a1bSJed Brown PetscInt m; 359*c4762a1bSJed Brown PetscReal sum = 0.; 360*c4762a1bSJed Brown 361*c4762a1bSJed Brown for (m = 0; m < Nk; m++) sum += uWwmat[l * Nk + m] * w[m]; 362*c4762a1bSJed Brown uWwcheck[l] = sum; 363*c4762a1bSJed Brown diff += PetscSqr(uWwcheck[l] - uWw[l]); 364*c4762a1bSJed Brown norm += PetscSqr(uWwcheck[l]) + PetscSqr(uWw[l]); 365*c4762a1bSJed Brown } 366*c4762a1bSJed Brown diff = PetscSqrtReal(diff); 367*c4762a1bSJed Brown norm = PetscSqrtReal(norm); 368*c4762a1bSJed Brown if (diff > PETSC_SMALL * norm) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "wedge matrix check: wedge matrix application does not match wedge direct application"); 369*c4762a1bSJed Brown ierr = PetscFree2(uWwmat, uWwcheck);CHKERRQ(ierr); 370*c4762a1bSJed Brown ierr = PetscFree4(u, uWw, x, xsplit);CHKERRQ(ierr); 371*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 372*c4762a1bSJed Brown } 373*c4762a1bSJed Brown for (M = PetscMax(1,k); M <= N; M++) { /* pullback */ 374*c4762a1bSJed Brown PetscReal *L, *u, *x; 375*c4762a1bSJed Brown PetscInt Mk, l; 376*c4762a1bSJed Brown 377*c4762a1bSJed Brown ierr = PetscDTBinomialInt(M, k, &Mk);CHKERRQ(ierr); 378*c4762a1bSJed Brown ierr = PetscMalloc3(M*N, &L, Mk, &u, M*k, &x);CHKERRQ(ierr); 379*c4762a1bSJed Brown for (l = 0; l < M*N; l++) {ierr = PetscRandomGetValueReal(rand, &L[l]);CHKERRQ(ierr);} 380*c4762a1bSJed Brown for (l = 0; l < Mk; l++) {ierr = PetscRandomGetValueReal(rand, &u[l]);CHKERRQ(ierr);} 381*c4762a1bSJed Brown for (l = 0; l < M*k; l++) {ierr = PetscRandomGetValueReal(rand, &x[l]);CHKERRQ(ierr);} 382*c4762a1bSJed Brown if (verbose) {ierr = PetscViewerASCIIPrintf(viewer, "pullback M = %D:\n", M);CHKERRQ(ierr);} 383*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 384*c4762a1bSJed Brown ierr = CheckPullback(M, N, L, k, w, x, verbose, viewer);CHKERRQ(ierr); 385*c4762a1bSJed Brown if (M != N) {ierr = CheckPullback(N, M, L, k, u, v, PETSC_FALSE, viewer);CHKERRQ(ierr);} 386*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 387*c4762a1bSJed Brown if ((k % N) && (N > 1)) { 388*c4762a1bSJed Brown if (verbose) {ierr = PetscViewerASCIIPrintf(viewer, "negative pullback M = %D:\n", M);CHKERRQ(ierr);} 389*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 390*c4762a1bSJed Brown ierr = CheckPullback(M, N, L, -k, w, x, verbose, viewer);CHKERRQ(ierr); 391*c4762a1bSJed Brown if (M != N) {ierr = CheckPullback(N, M, L, -k, u, v, PETSC_FALSE, viewer);CHKERRQ(ierr);} 392*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 393*c4762a1bSJed Brown } 394*c4762a1bSJed Brown ierr = PetscFree3(L, u, x);CHKERRQ(ierr); 395*c4762a1bSJed Brown } 396*c4762a1bSJed Brown if (k > 0) { /* Interior */ 397*c4762a1bSJed Brown PetscInt Nkm, l, m; 398*c4762a1bSJed Brown PetscReal *wIntv0, *wIntv0check, wvcheck, diff, diffMat, normMat; 399*c4762a1bSJed Brown PetscReal *intv0mat, *matcheck; 400*c4762a1bSJed Brown PetscInt (*indices)[3]; 401*c4762a1bSJed Brown 402*c4762a1bSJed Brown ierr = PetscDTBinomialInt(N, k-1, &Nkm);CHKERRQ(ierr); 403*c4762a1bSJed Brown ierr = PetscMalloc5(Nkm, &wIntv0, Nkm, &wIntv0check, Nk * Nkm, &intv0mat, Nk * Nkm, &matcheck, Nk * k, &indices);CHKERRQ(ierr); 404*c4762a1bSJed Brown ierr = PetscDTAltVInterior(N, k, w, v, wIntv0);CHKERRQ(ierr); 405*c4762a1bSJed Brown ierr = PetscDTAltVInteriorMatrix(N, k, v, intv0mat);CHKERRQ(ierr); 406*c4762a1bSJed Brown ierr = PetscDTAltVInteriorPattern(N, k, indices);CHKERRQ(ierr); 407*c4762a1bSJed Brown if (verbose) { 408*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "interior product matrix pattern:\n");CHKERRQ(ierr); 409*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 410*c4762a1bSJed Brown for (l = 0; l < Nk * k; l++) { 411*c4762a1bSJed Brown PetscInt row = indices[l][0]; 412*c4762a1bSJed Brown PetscInt col = indices[l][1]; 413*c4762a1bSJed Brown PetscInt x = indices[l][2]; 414*c4762a1bSJed Brown 415*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer,"intV[%D,%D] = %sV[%D]\n", row, col, x < 0 ? "-" : " ", x < 0 ? -(x + 1) : x);CHKERRQ(ierr); 416*c4762a1bSJed Brown } 417*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 418*c4762a1bSJed Brown } 419*c4762a1bSJed Brown for (l = 0; l < Nkm * Nk; l++) matcheck[l] = 0.; 420*c4762a1bSJed Brown for (l = 0; l < Nk * k; l++) { 421*c4762a1bSJed Brown PetscInt row = indices[l][0]; 422*c4762a1bSJed Brown PetscInt col = indices[l][1]; 423*c4762a1bSJed Brown PetscInt x = indices[l][2]; 424*c4762a1bSJed Brown 425*c4762a1bSJed Brown if (x < 0) { 426*c4762a1bSJed Brown matcheck[row * Nk + col] = -v[-(x+1)]; 427*c4762a1bSJed Brown } else { 428*c4762a1bSJed Brown matcheck[row * Nk + col] = v[x]; 429*c4762a1bSJed Brown } 430*c4762a1bSJed Brown } 431*c4762a1bSJed Brown diffMat = 0.; 432*c4762a1bSJed Brown normMat = 0.; 433*c4762a1bSJed Brown for (l = 0; l < Nkm * Nk; l++) { 434*c4762a1bSJed Brown diffMat += PetscSqr(PetscAbsReal(matcheck[l] - intv0mat[l])); 435*c4762a1bSJed Brown normMat += PetscSqr(matcheck[l]) + PetscSqr(intv0mat[l]); 436*c4762a1bSJed Brown } 437*c4762a1bSJed Brown diffMat = PetscSqrtReal(diffMat); 438*c4762a1bSJed Brown normMat = PetscSqrtReal(normMat); 439*c4762a1bSJed Brown if (diffMat > PETSC_SMALL * normMat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Interior product check: matrix pattern does not match matrix"); 440*c4762a1bSJed Brown diffMat = 0.; 441*c4762a1bSJed Brown normMat = 0.; 442*c4762a1bSJed Brown for (l = 0; l < Nkm; l++) { 443*c4762a1bSJed Brown PetscReal sum = 0.; 444*c4762a1bSJed Brown 445*c4762a1bSJed Brown for (m = 0; m < Nk; m++) sum += intv0mat[l * Nk + m] * w[m]; 446*c4762a1bSJed Brown wIntv0check[l] = sum; 447*c4762a1bSJed Brown 448*c4762a1bSJed Brown diffMat += PetscSqr(PetscAbsReal(wIntv0check[l] - wIntv0[l])); 449*c4762a1bSJed Brown normMat += PetscSqr(wIntv0check[l]) + PetscSqr(wIntv0[l]); 450*c4762a1bSJed Brown } 451*c4762a1bSJed Brown diffMat = PetscSqrtReal(diffMat); 452*c4762a1bSJed Brown normMat = PetscSqrtReal(normMat); 453*c4762a1bSJed Brown if (diffMat > PETSC_SMALL * normMat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Interior product check: application does not match matrix"); 454*c4762a1bSJed Brown if (verbose) { 455*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "(w int v_0):\n");CHKERRQ(ierr); 456*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 457*c4762a1bSJed Brown if (Nkm) {ierr = PetscRealView(Nkm, wIntv0, viewer);CHKERRQ(ierr);} 458*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 459*c4762a1bSJed Brown 460*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "(int v_0):\n");CHKERRQ(ierr); 461*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 462*c4762a1bSJed Brown if (Nk * Nkm > 0) {ierr = PetscRealView(Nk * Nkm, intv0mat, viewer);CHKERRQ(ierr);} 463*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 464*c4762a1bSJed Brown } 465*c4762a1bSJed Brown ierr = PetscDTAltVApply(N, k - 1, wIntv0, &v[N], &wvcheck);CHKERRQ(ierr); 466*c4762a1bSJed Brown diff = PetscSqrtReal(PetscSqr(wvcheck - wv)); 467*c4762a1bSJed Brown if (diff >= PETSC_SMALL * (PetscAbsReal(wv) + PetscAbsReal(wvcheck))) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Interior product check: (w Int v0)(v_rem) (%g) != w(v) (%g)", (double) wvcheck, (double) wv); 468*c4762a1bSJed Brown ierr = PetscFree5(wIntv0,wIntv0check,intv0mat,matcheck,indices);CHKERRQ(ierr); 469*c4762a1bSJed Brown } 470*c4762a1bSJed Brown if (k >= N - k) { /* Hodge star */ 471*c4762a1bSJed Brown PetscReal *u, *starw, *starstarw, wu, starwdotu; 472*c4762a1bSJed Brown PetscReal diff, norm; 473*c4762a1bSJed Brown PetscBool isOdd; 474*c4762a1bSJed Brown PetscInt l; 475*c4762a1bSJed Brown 476*c4762a1bSJed Brown isOdd = (PetscBool) ((k * (N - k)) & 1); 477*c4762a1bSJed Brown ierr = PetscMalloc3(Nk, &u, Nk, &starw, Nk, &starstarw);CHKERRQ(ierr); 478*c4762a1bSJed Brown ierr = PetscDTAltVStar(N, k, 1, w, starw);CHKERRQ(ierr); 479*c4762a1bSJed Brown ierr = PetscDTAltVStar(N, N-k, 1, starw, starstarw);CHKERRQ(ierr); 480*c4762a1bSJed Brown if (verbose) { 481*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "star w:\n");CHKERRQ(ierr); 482*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 483*c4762a1bSJed Brown if (Nk) {ierr = PetscRealView(Nk, starw, viewer);CHKERRQ(ierr);} 484*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 485*c4762a1bSJed Brown 486*c4762a1bSJed Brown ierr = PetscViewerASCIIPrintf(viewer, "star star w:\n");CHKERRQ(ierr); 487*c4762a1bSJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 488*c4762a1bSJed Brown if (Nk) {ierr = PetscRealView(Nk, starstarw, viewer);CHKERRQ(ierr);} 489*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 490*c4762a1bSJed Brown } 491*c4762a1bSJed Brown for (l = 0; l < Nk; l++) {ierr = PetscRandomGetValueReal(rand,&u[l]);CHKERRQ(ierr);} 492*c4762a1bSJed Brown ierr = PetscDTAltVWedge(N, k, N - k, w, u, &wu);CHKERRQ(ierr); 493*c4762a1bSJed Brown starwdotu = 0.; 494*c4762a1bSJed Brown for (l = 0; l < Nk; l++) starwdotu += starw[l] * u[l]; 495*c4762a1bSJed Brown diff = PetscAbsReal(wu - starwdotu); 496*c4762a1bSJed Brown if (diff > PETSC_SMALL * (PetscAbsReal(wu) + PetscAbsReal(starwdotu))) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Hodge star check: (star w, u) (%g) != (w wedge u) (%g)", (double) starwdotu, (double) wu); 497*c4762a1bSJed Brown 498*c4762a1bSJed Brown diff = 0.; 499*c4762a1bSJed Brown norm = 0.; 500*c4762a1bSJed Brown for (l = 0; l < Nk; l++) { 501*c4762a1bSJed Brown diff += PetscSqr(w[l] - (isOdd ? -starstarw[l] : starstarw[l])); 502*c4762a1bSJed Brown norm += PetscSqr(w[l]) + PetscSqr(starstarw[l]); 503*c4762a1bSJed Brown } 504*c4762a1bSJed Brown diff = PetscSqrtReal(diff); 505*c4762a1bSJed Brown norm = PetscSqrtReal(norm); 506*c4762a1bSJed Brown if (diff > PETSC_SMALL * norm) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Hodge star check: star(star(w)) != (-1)^(N*(N-k)) w"); 507*c4762a1bSJed Brown ierr = PetscFree3(u, starw, starstarw);CHKERRQ(ierr); 508*c4762a1bSJed Brown } 509*c4762a1bSJed Brown ierr = PetscFree(v);CHKERRQ(ierr); 510*c4762a1bSJed Brown ierr = PetscFree(w);CHKERRQ(ierr); 511*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 512*c4762a1bSJed Brown } 513*c4762a1bSJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 514*c4762a1bSJed Brown } 515*c4762a1bSJed Brown ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr); 516*c4762a1bSJed Brown ierr = PetscFinalize(); 517*c4762a1bSJed Brown return ierr; 518*c4762a1bSJed Brown } 519*c4762a1bSJed Brown 520*c4762a1bSJed Brown /*TEST 521*c4762a1bSJed Brown test: 522*c4762a1bSJed Brown suffix: 1234 523*c4762a1bSJed Brown args: -verbose 524*c4762a1bSJed Brown test: 525*c4762a1bSJed Brown suffix: 56 526*c4762a1bSJed Brown args: -N 5,6 527*c4762a1bSJed Brown TEST*/ 528