1*d8f25ad8SToby Isaac const char help[] = "Tests PetscDTPTrimmedEvalJet()"; 2*d8f25ad8SToby Isaac 3*d8f25ad8SToby Isaac #include <petscdt.h> 4*d8f25ad8SToby Isaac #include <petscblaslapack.h> 5*d8f25ad8SToby Isaac #include <petscmat.h> 6*d8f25ad8SToby Isaac 7*d8f25ad8SToby Isaac static PetscErrorCode constructTabulationAndMass(PetscInt dim, PetscInt deg, PetscInt form, PetscInt jetDegree, PetscInt npoints, 8*d8f25ad8SToby Isaac const PetscReal *points, const PetscReal *weights, 9*d8f25ad8SToby Isaac PetscInt *_Nb, PetscInt *_Nf, PetscInt *_Nk, 10*d8f25ad8SToby Isaac PetscReal **B, PetscScalar **M) 11*d8f25ad8SToby Isaac { 12*d8f25ad8SToby Isaac PetscInt Nf; // Number of form components 13*d8f25ad8SToby Isaac PetscInt Nbpt; // number of trimmed polynomials 14*d8f25ad8SToby Isaac PetscInt Nk; // jet size 15*d8f25ad8SToby Isaac PetscReal *p_trimmed; 16*d8f25ad8SToby Isaac PetscErrorCode ierr; 17*d8f25ad8SToby Isaac 18*d8f25ad8SToby Isaac PetscFunctionBegin; 19*d8f25ad8SToby Isaac ierr = PetscDTBinomialInt(dim, PetscAbsInt(form), &Nf);CHKERRQ(ierr); 20*d8f25ad8SToby Isaac ierr = PetscDTPTrimmedSize(dim, deg, form, &Nbpt);CHKERRQ(ierr); 21*d8f25ad8SToby Isaac ierr = PetscDTBinomialInt(dim + jetDegree, dim, &Nk);CHKERRQ(ierr); 22*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbpt * Nf * Nk * npoints, &p_trimmed);CHKERRQ(ierr); 23*d8f25ad8SToby Isaac ierr = PetscDTPTrimmedEvalJet(dim, npoints, points, deg, form, jetDegree, p_trimmed);CHKERRQ(ierr); 24*d8f25ad8SToby Isaac 25*d8f25ad8SToby Isaac // compute the direct mass matrix 26*d8f25ad8SToby Isaac PetscScalar *M_trimmed; 27*d8f25ad8SToby Isaac ierr = PetscCalloc1(Nbpt * Nbpt, &M_trimmed);CHKERRQ(ierr); 28*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbpt; i++) { 29*d8f25ad8SToby Isaac for (PetscInt j = 0; j < Nbpt; j++) { 30*d8f25ad8SToby Isaac PetscReal v = 0.; 31*d8f25ad8SToby Isaac 32*d8f25ad8SToby Isaac for (PetscInt f = 0; f < Nf; f++) { 33*d8f25ad8SToby Isaac const PetscReal *p_i = &p_trimmed[(i * Nf + f) * Nk * npoints]; 34*d8f25ad8SToby Isaac const PetscReal *p_j = &p_trimmed[(j * Nf + f) * Nk * npoints]; 35*d8f25ad8SToby Isaac 36*d8f25ad8SToby Isaac for (PetscInt pt = 0; pt < npoints; pt++) { 37*d8f25ad8SToby Isaac v += p_i[pt] * p_j[pt] * weights[pt]; 38*d8f25ad8SToby Isaac } 39*d8f25ad8SToby Isaac } 40*d8f25ad8SToby Isaac M_trimmed[i * Nbpt + j] += v; 41*d8f25ad8SToby Isaac } 42*d8f25ad8SToby Isaac } 43*d8f25ad8SToby Isaac *_Nb = Nbpt; 44*d8f25ad8SToby Isaac *_Nf = Nf; 45*d8f25ad8SToby Isaac *_Nk = Nk; 46*d8f25ad8SToby Isaac *B = p_trimmed; 47*d8f25ad8SToby Isaac *M = M_trimmed; 48*d8f25ad8SToby Isaac PetscFunctionReturn(0); 49*d8f25ad8SToby Isaac } 50*d8f25ad8SToby Isaac 51*d8f25ad8SToby Isaac static PetscErrorCode test(PetscInt dim, PetscInt deg, PetscInt form, PetscInt jetDegree, PetscBool cond) 52*d8f25ad8SToby Isaac { 53*d8f25ad8SToby Isaac PetscQuadrature q; 54*d8f25ad8SToby Isaac PetscInt npoints; 55*d8f25ad8SToby Isaac const PetscReal *points; 56*d8f25ad8SToby Isaac const PetscReal *weights; 57*d8f25ad8SToby Isaac PetscInt Nf; // Number of form components 58*d8f25ad8SToby Isaac PetscInt Nk; // jet size 59*d8f25ad8SToby Isaac PetscInt Nbpt; // number of trimmed polynomials 60*d8f25ad8SToby Isaac PetscReal *p_trimmed; 61*d8f25ad8SToby Isaac PetscScalar *M_trimmed; 62*d8f25ad8SToby Isaac PetscReal *p_scalar; 63*d8f25ad8SToby Isaac PetscInt Nbp; // number of scalar polynomials 64*d8f25ad8SToby Isaac PetscScalar *Mcopy; 65*d8f25ad8SToby Isaac PetscScalar *M_moments; 66*d8f25ad8SToby Isaac PetscReal frob_err = 0.; 67*d8f25ad8SToby Isaac Mat mat_trimmed; 68*d8f25ad8SToby Isaac Mat mat_moments_T; 69*d8f25ad8SToby Isaac Mat AinvB; 70*d8f25ad8SToby Isaac PetscInt Nbm1; 71*d8f25ad8SToby Isaac Mat Mm1; 72*d8f25ad8SToby Isaac PetscReal *p_trimmed_copy; 73*d8f25ad8SToby Isaac PetscReal *M_moment_real; 74*d8f25ad8SToby Isaac PetscErrorCode ierr; 75*d8f25ad8SToby Isaac 76*d8f25ad8SToby Isaac PetscFunctionBegin; 77*d8f25ad8SToby Isaac // Construct an appropriate quadrature 78*d8f25ad8SToby Isaac ierr = PetscDTStroudConicalQuadrature(dim, 1, deg + 2, -1., 1., &q);CHKERRQ(ierr); 79*d8f25ad8SToby Isaac ierr = PetscQuadratureGetData(q, NULL, NULL, &npoints, &points, &weights);CHKERRQ(ierr); 80*d8f25ad8SToby Isaac 81*d8f25ad8SToby Isaac ierr = constructTabulationAndMass(dim, deg, form, jetDegree, npoints, points, weights, &Nbpt, &Nf, &Nk, &p_trimmed, &M_trimmed);CHKERRQ(ierr); 82*d8f25ad8SToby Isaac 83*d8f25ad8SToby Isaac ierr = PetscDTBinomialInt(dim + deg, dim, &Nbp);CHKERRQ(ierr); 84*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbp * Nk * npoints, &p_scalar);CHKERRQ(ierr); 85*d8f25ad8SToby Isaac ierr = PetscDTPKDEvalJet(dim, npoints, points, deg, jetDegree, p_scalar);CHKERRQ(ierr); 86*d8f25ad8SToby Isaac 87*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbpt * Nbpt, &Mcopy);CHKERRQ(ierr); 88*d8f25ad8SToby Isaac // Print the condition numbers (useful for testing out different bases internally in PetscDTPTrimmedEvalJet()) 89*d8f25ad8SToby Isaac #if !defined(PETSC_USE_COMPLEX) 90*d8f25ad8SToby Isaac if (cond) { 91*d8f25ad8SToby Isaac PetscReal *S; 92*d8f25ad8SToby Isaac PetscScalar *work; 93*d8f25ad8SToby Isaac PetscBLASInt n = Nbpt; 94*d8f25ad8SToby Isaac PetscBLASInt lwork = 5 * Nbpt; 95*d8f25ad8SToby Isaac PetscBLASInt lierr; 96*d8f25ad8SToby Isaac 97*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbpt, &S);CHKERRQ(ierr); 98*d8f25ad8SToby Isaac ierr = PetscMalloc1(5*Nbpt, &work);CHKERRQ(ierr); 99*d8f25ad8SToby Isaac ierr = PetscArraycpy(Mcopy, M_trimmed, Nbpt * Nbpt);CHKERRQ(ierr); 100*d8f25ad8SToby Isaac 101*d8f25ad8SToby Isaac PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("N","N",&n,&n,Mcopy,&n,S,NULL,&n,NULL,&n,work,&lwork,&lierr)); 102*d8f25ad8SToby Isaac PetscReal cond = S[0] / S[Nbpt - 1]; 103*d8f25ad8SToby Isaac ierr = PetscPrintf(PETSC_COMM_WORLD, "dimension %D, degree %D, form %D: condition number %g\n", dim, deg, form, (double) cond); 104*d8f25ad8SToby Isaac ierr = PetscFree(work);CHKERRQ(ierr); 105*d8f25ad8SToby Isaac ierr = PetscFree(S);CHKERRQ(ierr); 106*d8f25ad8SToby Isaac } 107*d8f25ad8SToby Isaac #endif 108*d8f25ad8SToby Isaac 109*d8f25ad8SToby Isaac // compute the moments with the orthonormal polynomials 110*d8f25ad8SToby Isaac ierr = PetscCalloc1(Nbpt * Nbp * Nf, &M_moments);CHKERRQ(ierr); 111*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbp; i++) { 112*d8f25ad8SToby Isaac for (PetscInt j = 0; j < Nbpt; j++) { 113*d8f25ad8SToby Isaac for (PetscInt f = 0; f < Nf; f++) { 114*d8f25ad8SToby Isaac PetscReal v = 0.; 115*d8f25ad8SToby Isaac const PetscReal *p_i = &p_scalar[i * Nk * npoints]; 116*d8f25ad8SToby Isaac const PetscReal *p_j = &p_trimmed[(j * Nf + f) * Nk * npoints]; 117*d8f25ad8SToby Isaac 118*d8f25ad8SToby Isaac for (PetscInt pt = 0; pt < npoints; pt++) { 119*d8f25ad8SToby Isaac v += p_i[pt] * p_j[pt] * weights[pt]; 120*d8f25ad8SToby Isaac } 121*d8f25ad8SToby Isaac M_moments[(i * Nf + f) * Nbpt + j] += v; 122*d8f25ad8SToby Isaac } 123*d8f25ad8SToby Isaac } 124*d8f25ad8SToby Isaac } 125*d8f25ad8SToby Isaac 126*d8f25ad8SToby Isaac // subtract M_moments^T * M_moments from M_trimmed: because the trimmed polynomials should be contained in 127*d8f25ad8SToby Isaac // the full polynomials, the result should be zero 128*d8f25ad8SToby Isaac ierr = PetscArraycpy(Mcopy, M_trimmed, Nbpt * Nbpt);CHKERRQ(ierr); 129*d8f25ad8SToby Isaac { 130*d8f25ad8SToby Isaac PetscBLASInt m = Nbpt; 131*d8f25ad8SToby Isaac PetscBLASInt n = Nbpt; 132*d8f25ad8SToby Isaac PetscBLASInt k = Nbp * Nf; 133*d8f25ad8SToby Isaac PetscScalar mone = -1.; 134*d8f25ad8SToby Isaac PetscScalar one = 1.; 135*d8f25ad8SToby Isaac 136*d8f25ad8SToby Isaac PetscStackCallBLAS("BLASgemm",BLASgemm_("N","T",&m,&n,&k,&mone,M_moments,&m,M_moments,&m,&one,Mcopy,&m)); 137*d8f25ad8SToby Isaac } 138*d8f25ad8SToby Isaac 139*d8f25ad8SToby Isaac frob_err = 0.; 140*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbpt * Nbpt; i++) frob_err += PetscRealPart(Mcopy[i]) * PetscRealPart(Mcopy[i]); 141*d8f25ad8SToby Isaac frob_err = PetscSqrtReal(frob_err); 142*d8f25ad8SToby Isaac 143*d8f25ad8SToby Isaac if (frob_err > PETSC_SMALL) { 144*d8f25ad8SToby Isaac SETERRQ4(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "dimension %D, degree %D, form %D: trimmed projection error %g\n", dim, deg, form, (double) frob_err); 145*d8f25ad8SToby Isaac } 146*d8f25ad8SToby Isaac 147*d8f25ad8SToby Isaac // P trimmed is also supposed to contain the polynomials of one degree less: construction M_moment[0:sub,:] * M_trimmed^{-1} * M_moments[0:sub,:]^T should be the identity matrix 148*d8f25ad8SToby Isaac ierr = MatCreateSeqDense(PETSC_COMM_SELF, Nbpt, Nbpt, M_trimmed, &mat_trimmed);CHKERRQ(ierr); 149*d8f25ad8SToby Isaac ierr = PetscDTBinomialInt(dim + deg - 1, dim, &Nbm1);CHKERRQ(ierr); 150*d8f25ad8SToby Isaac ierr = MatCreateSeqDense(PETSC_COMM_SELF, Nbpt, Nbm1 * Nf, M_moments, &mat_moments_T);CHKERRQ(ierr); 151*d8f25ad8SToby Isaac ierr = MatDuplicate(mat_moments_T, MAT_DO_NOT_COPY_VALUES, &AinvB);CHKERRQ(ierr); 152*d8f25ad8SToby Isaac ierr = MatLUFactor(mat_trimmed, NULL, NULL, NULL);CHKERRQ(ierr); 153*d8f25ad8SToby Isaac ierr = MatMatSolve(mat_trimmed, mat_moments_T, AinvB);CHKERRQ(ierr); 154*d8f25ad8SToby Isaac ierr = MatTransposeMatMult(mat_moments_T, AinvB, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Mm1);CHKERRQ(ierr); 155*d8f25ad8SToby Isaac ierr = MatShift(Mm1, -1.);CHKERRQ(ierr); 156*d8f25ad8SToby Isaac ierr = MatNorm(Mm1, NORM_FROBENIUS, &frob_err);CHKERRQ(ierr); 157*d8f25ad8SToby Isaac if (frob_err > PETSC_SMALL) { 158*d8f25ad8SToby Isaac SETERRQ4(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "dimension %D, degree %D, form %D: trimmed reverse projection error %g\n", dim, deg, form, (double) frob_err); 159*d8f25ad8SToby Isaac } 160*d8f25ad8SToby Isaac ierr = MatDestroy(&Mm1);CHKERRQ(ierr); 161*d8f25ad8SToby Isaac ierr = MatDestroy(&AinvB);CHKERRQ(ierr); 162*d8f25ad8SToby Isaac ierr = MatDestroy(&mat_moments_T);CHKERRQ(ierr); 163*d8f25ad8SToby Isaac 164*d8f25ad8SToby Isaac // The Koszul differential applied to P trimmed (Lambda k+1) should be contained in P trimmed (Lambda k) 165*d8f25ad8SToby Isaac if (PetscAbsInt(form) < dim) { 166*d8f25ad8SToby Isaac PetscInt Nf1, Nbpt1, Nk1; 167*d8f25ad8SToby Isaac PetscReal *p_trimmed1; 168*d8f25ad8SToby Isaac PetscScalar *M_trimmed1; 169*d8f25ad8SToby Isaac PetscInt (*pattern)[3]; 170*d8f25ad8SToby Isaac PetscReal *p_koszul; 171*d8f25ad8SToby Isaac PetscScalar *M_koszul; 172*d8f25ad8SToby Isaac PetscScalar *M_k_moment; 173*d8f25ad8SToby Isaac Mat mat_koszul; 174*d8f25ad8SToby Isaac Mat mat_k_moment_T; 175*d8f25ad8SToby Isaac Mat AinvB; 176*d8f25ad8SToby Isaac Mat prod; 177*d8f25ad8SToby Isaac 178*d8f25ad8SToby Isaac ierr = constructTabulationAndMass(dim, deg, form < 0 ? form - 1 : form + 1, 0, npoints, points, weights, &Nbpt1, &Nf1, &Nk1, 179*d8f25ad8SToby Isaac &p_trimmed1, &M_trimmed1);CHKERRQ(ierr); 180*d8f25ad8SToby Isaac 181*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nf1 * (PetscAbsInt(form) + 1), &pattern);CHKERRQ(ierr); 182*d8f25ad8SToby Isaac ierr = PetscDTAltVInteriorPattern(dim, PetscAbsInt(form) + 1, pattern);CHKERRQ(ierr); 183*d8f25ad8SToby Isaac 184*d8f25ad8SToby Isaac // apply the Koszul operator 185*d8f25ad8SToby Isaac ierr = PetscCalloc1(Nbpt1 * Nf * npoints, &p_koszul);CHKERRQ(ierr); 186*d8f25ad8SToby Isaac for (PetscInt b = 0; b < Nbpt1; b++) { 187*d8f25ad8SToby Isaac for (PetscInt a = 0; a < Nf1 * (PetscAbsInt(form) + 1); a++) { 188*d8f25ad8SToby Isaac PetscInt i,j,k; 189*d8f25ad8SToby Isaac PetscReal sign; 190*d8f25ad8SToby Isaac PetscReal *p_i; 191*d8f25ad8SToby Isaac const PetscReal *p_j; 192*d8f25ad8SToby Isaac 193*d8f25ad8SToby Isaac i = pattern[a][0]; 194*d8f25ad8SToby Isaac if (form < 0) { 195*d8f25ad8SToby Isaac i = Nf-1-i; 196*d8f25ad8SToby Isaac } 197*d8f25ad8SToby Isaac j = pattern[a][1]; 198*d8f25ad8SToby Isaac if (form < 0) { 199*d8f25ad8SToby Isaac j = Nf1-1-j; 200*d8f25ad8SToby Isaac } 201*d8f25ad8SToby Isaac k = pattern[a][2] < 0 ? -(pattern[a][2] + 1) : pattern[a][2]; 202*d8f25ad8SToby Isaac sign = pattern[a][2] < 0 ? -1 : 1; 203*d8f25ad8SToby Isaac if (form < 0 && (i & 1) ^ (j & 1)) { 204*d8f25ad8SToby Isaac sign = -sign; 205*d8f25ad8SToby Isaac } 206*d8f25ad8SToby Isaac 207*d8f25ad8SToby Isaac p_i = &p_koszul[(b * Nf + i) * npoints]; 208*d8f25ad8SToby Isaac p_j = &p_trimmed1[(b * Nf1 + j) * npoints]; 209*d8f25ad8SToby Isaac for (PetscInt pt = 0; pt < npoints; pt++) { 210*d8f25ad8SToby Isaac p_i[pt] += p_j[pt] * points[pt * dim + k] * sign; 211*d8f25ad8SToby Isaac } 212*d8f25ad8SToby Isaac } 213*d8f25ad8SToby Isaac } 214*d8f25ad8SToby Isaac 215*d8f25ad8SToby Isaac // mass matrix of the result 216*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbpt1 * Nbpt1, &M_koszul);CHKERRQ(ierr); 217*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbpt1; i++) { 218*d8f25ad8SToby Isaac for (PetscInt j = 0; j < Nbpt1; j++) { 219*d8f25ad8SToby Isaac PetscReal val = 0.; 220*d8f25ad8SToby Isaac 221*d8f25ad8SToby Isaac for (PetscInt v = 0; v < Nf; v++) { 222*d8f25ad8SToby Isaac const PetscReal *p_i = &p_koszul[(i * Nf + v) * npoints]; 223*d8f25ad8SToby Isaac const PetscReal *p_j = &p_koszul[(j * Nf + v) * npoints]; 224*d8f25ad8SToby Isaac 225*d8f25ad8SToby Isaac for (PetscInt pt = 0; pt < npoints; pt++) { 226*d8f25ad8SToby Isaac val += p_i[pt] * p_j[pt] * weights[pt]; 227*d8f25ad8SToby Isaac } 228*d8f25ad8SToby Isaac } 229*d8f25ad8SToby Isaac M_koszul[i * Nbpt1 + j] = val; 230*d8f25ad8SToby Isaac } 231*d8f25ad8SToby Isaac } 232*d8f25ad8SToby Isaac 233*d8f25ad8SToby Isaac // moment matrix between the result and P trimmed 234*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbpt * Nbpt1, &M_k_moment);CHKERRQ(ierr); 235*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbpt1; i++) { 236*d8f25ad8SToby Isaac for (PetscInt j = 0; j < Nbpt; j++) { 237*d8f25ad8SToby Isaac PetscReal val = 0.; 238*d8f25ad8SToby Isaac 239*d8f25ad8SToby Isaac for (PetscInt v = 0; v < Nf; v++) { 240*d8f25ad8SToby Isaac const PetscReal *p_i = &p_koszul[(i * Nf + v) * npoints]; 241*d8f25ad8SToby Isaac const PetscReal *p_j = &p_trimmed[(j * Nf + v) * Nk * npoints]; 242*d8f25ad8SToby Isaac 243*d8f25ad8SToby Isaac for (PetscInt pt = 0; pt < npoints; pt++) { 244*d8f25ad8SToby Isaac val += p_i[pt] * p_j[pt] * weights[pt]; 245*d8f25ad8SToby Isaac } 246*d8f25ad8SToby Isaac } 247*d8f25ad8SToby Isaac M_k_moment[i * Nbpt + j] = val; 248*d8f25ad8SToby Isaac } 249*d8f25ad8SToby Isaac } 250*d8f25ad8SToby Isaac 251*d8f25ad8SToby Isaac // M_k_moment M_trimmed^{-1} M_k_moment^T == M_koszul 252*d8f25ad8SToby Isaac ierr = MatCreateSeqDense(PETSC_COMM_SELF, Nbpt1, Nbpt1, M_koszul, &mat_koszul);CHKERRQ(ierr); 253*d8f25ad8SToby Isaac ierr = MatCreateSeqDense(PETSC_COMM_SELF, Nbpt, Nbpt1, M_k_moment, &mat_k_moment_T);CHKERRQ(ierr); 254*d8f25ad8SToby Isaac ierr = MatDuplicate(mat_k_moment_T, MAT_DO_NOT_COPY_VALUES, &AinvB);CHKERRQ(ierr); 255*d8f25ad8SToby Isaac ierr = MatMatSolve(mat_trimmed, mat_k_moment_T, AinvB);CHKERRQ(ierr); 256*d8f25ad8SToby Isaac ierr = MatTransposeMatMult(mat_k_moment_T, AinvB, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &prod);CHKERRQ(ierr); 257*d8f25ad8SToby Isaac ierr = MatAXPY(prod, -1., mat_koszul, SAME_NONZERO_PATTERN);CHKERRQ(ierr); 258*d8f25ad8SToby Isaac ierr = MatNorm(prod, NORM_FROBENIUS, &frob_err);CHKERRQ(ierr); 259*d8f25ad8SToby Isaac if (frob_err > PETSC_SMALL) { 260*d8f25ad8SToby Isaac SETERRQ5(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "dimension %D, degree %D, forms (%D, %D): koszul projection error %g\n", dim, deg, form, form < 0 ? (form-1):(form+1), (double) frob_err); 261*d8f25ad8SToby Isaac } 262*d8f25ad8SToby Isaac 263*d8f25ad8SToby Isaac ierr = MatDestroy(&prod);CHKERRQ(ierr); 264*d8f25ad8SToby Isaac ierr = MatDestroy(&AinvB);CHKERRQ(ierr); 265*d8f25ad8SToby Isaac ierr = MatDestroy(&mat_k_moment_T);CHKERRQ(ierr); 266*d8f25ad8SToby Isaac ierr = MatDestroy(&mat_koszul);CHKERRQ(ierr); 267*d8f25ad8SToby Isaac ierr = PetscFree(M_k_moment);CHKERRQ(ierr); 268*d8f25ad8SToby Isaac ierr = PetscFree(M_koszul);CHKERRQ(ierr); 269*d8f25ad8SToby Isaac ierr = PetscFree(p_koszul);CHKERRQ(ierr); 270*d8f25ad8SToby Isaac ierr = PetscFree(pattern);CHKERRQ(ierr); 271*d8f25ad8SToby Isaac ierr = PetscFree(p_trimmed1);CHKERRQ(ierr); 272*d8f25ad8SToby Isaac ierr = PetscFree(M_trimmed1);CHKERRQ(ierr); 273*d8f25ad8SToby Isaac } 274*d8f25ad8SToby Isaac 275*d8f25ad8SToby Isaac // M_moments has shape [Nbp][Nf][Nbpt] 276*d8f25ad8SToby Isaac // p_scalar has shape [Nbp][Nk][npoints] 277*d8f25ad8SToby Isaac // contracting on [Nbp] should be the same shape as 278*d8f25ad8SToby Isaac // p_trimmed, which is [Nbpt][Nf][Nk][npoints] 279*d8f25ad8SToby Isaac ierr = PetscCalloc1(Nbpt * Nf * Nk * npoints, &p_trimmed_copy);CHKERRQ(ierr); 280*d8f25ad8SToby Isaac ierr = PetscMalloc1(Nbp * Nf * Nbpt, &M_moment_real);CHKERRQ(ierr); 281*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbp * Nf * Nbpt; i++) { 282*d8f25ad8SToby Isaac M_moment_real[i] = PetscRealPart(M_moments[i]); 283*d8f25ad8SToby Isaac } 284*d8f25ad8SToby Isaac for (PetscInt f = 0; f < Nf; f++) { 285*d8f25ad8SToby Isaac PetscBLASInt m = Nk * npoints; 286*d8f25ad8SToby Isaac PetscBLASInt n = Nbpt; 287*d8f25ad8SToby Isaac PetscBLASInt k = Nbp; 288*d8f25ad8SToby Isaac PetscBLASInt lda = Nk * npoints; 289*d8f25ad8SToby Isaac PetscBLASInt ldb = Nf * Nbpt; 290*d8f25ad8SToby Isaac PetscBLASInt ldc = Nf * Nk * npoints; 291*d8f25ad8SToby Isaac PetscReal alpha = 1.0; 292*d8f25ad8SToby Isaac PetscReal beta = 1.0; 293*d8f25ad8SToby Isaac 294*d8f25ad8SToby Isaac PetscStackCallBLAS("BLASREALgemm",BLASREALgemm_("N","T",&m,&n,&k,&alpha,p_scalar,&lda,&M_moment_real[f * Nbpt],&ldb,&beta,&p_trimmed_copy[f * Nk * npoints],&ldc)); 295*d8f25ad8SToby Isaac } 296*d8f25ad8SToby Isaac frob_err = 0.; 297*d8f25ad8SToby Isaac for (PetscInt i = 0; i < Nbpt * Nf * Nk * npoints; i++) { 298*d8f25ad8SToby Isaac frob_err += (p_trimmed_copy[i] - p_trimmed[i]) * (p_trimmed_copy[i] - p_trimmed[i]); 299*d8f25ad8SToby Isaac } 300*d8f25ad8SToby Isaac frob_err = PetscSqrtReal(frob_err); 301*d8f25ad8SToby Isaac 302*d8f25ad8SToby Isaac if (frob_err > PETSC_SMALL) { 303*d8f25ad8SToby Isaac SETERRQ4(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "dimension %D, degree %D, form %D: jet error %g\n", dim, deg, form, (double) frob_err); 304*d8f25ad8SToby Isaac } 305*d8f25ad8SToby Isaac 306*d8f25ad8SToby Isaac ierr = PetscFree(M_moment_real);CHKERRQ(ierr); 307*d8f25ad8SToby Isaac ierr = PetscFree(p_trimmed_copy);CHKERRQ(ierr); 308*d8f25ad8SToby Isaac ierr = MatDestroy(&mat_trimmed);CHKERRQ(ierr); 309*d8f25ad8SToby Isaac ierr = PetscFree(Mcopy);CHKERRQ(ierr); 310*d8f25ad8SToby Isaac ierr = PetscFree(M_moments);CHKERRQ(ierr); 311*d8f25ad8SToby Isaac ierr = PetscFree(M_trimmed);CHKERRQ(ierr); 312*d8f25ad8SToby Isaac ierr = PetscFree(p_trimmed);CHKERRQ(ierr); 313*d8f25ad8SToby Isaac ierr = PetscFree(p_scalar);CHKERRQ(ierr); 314*d8f25ad8SToby Isaac ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr); 315*d8f25ad8SToby Isaac PetscFunctionReturn(0); 316*d8f25ad8SToby Isaac } 317*d8f25ad8SToby Isaac 318*d8f25ad8SToby Isaac int main(int argc, char **argv) 319*d8f25ad8SToby Isaac { 320*d8f25ad8SToby Isaac PetscInt max_dim = 3; 321*d8f25ad8SToby Isaac PetscInt max_deg = 4; 322*d8f25ad8SToby Isaac PetscInt k = 3; 323*d8f25ad8SToby Isaac PetscBool cond = PETSC_FALSE; 324*d8f25ad8SToby Isaac 325*d8f25ad8SToby Isaac PetscErrorCode ierr = PetscInitialize(&argc, &argv, NULL, help); if (ierr) return ierr; 326*d8f25ad8SToby Isaac ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"","Options for PetscDTPTrimmedEvalJet() tests","none");CHKERRQ(ierr); 327*d8f25ad8SToby Isaac ierr = PetscOptionsInt("-max_dim", "Maximum dimension of the simplex",__FILE__,max_dim,&max_dim,NULL);CHKERRQ(ierr); 328*d8f25ad8SToby Isaac ierr = PetscOptionsInt("-max_degree", "Maximum degree of the trimmed polynomial space",__FILE__,max_deg,&max_deg,NULL);CHKERRQ(ierr); 329*d8f25ad8SToby Isaac ierr = PetscOptionsInt("-max_jet", "The number of derivatives to test",__FILE__,k,&k,NULL);CHKERRQ(ierr); 330*d8f25ad8SToby Isaac ierr = PetscOptionsBool("-cond", "Compute the condition numbers of the mass matrices of the bases",__FILE__,cond,&cond,NULL);CHKERRQ(ierr); 331*d8f25ad8SToby Isaac ierr = PetscOptionsEnd();CHKERRQ(ierr); 332*d8f25ad8SToby Isaac for (PetscInt dim = 2; dim <= max_dim; dim++) { 333*d8f25ad8SToby Isaac for (PetscInt deg = 1; deg <= max_deg; deg++) { 334*d8f25ad8SToby Isaac for (PetscInt form = -dim+1; form <= dim; form++) { 335*d8f25ad8SToby Isaac ierr = test(dim, deg, form, PetscMax(1, k), cond);CHKERRQ(ierr); 336*d8f25ad8SToby Isaac } 337*d8f25ad8SToby Isaac } 338*d8f25ad8SToby Isaac } 339*d8f25ad8SToby Isaac ierr = PetscFinalize(); 340*d8f25ad8SToby Isaac return ierr; 341*d8f25ad8SToby Isaac } 342*d8f25ad8SToby Isaac 343*d8f25ad8SToby Isaac /*TEST 344*d8f25ad8SToby Isaac 345*d8f25ad8SToby Isaac test: 346*d8f25ad8SToby Isaac requires: !single 347*d8f25ad8SToby Isaac args: 348*d8f25ad8SToby Isaac 349*d8f25ad8SToby Isaac TEST*/ 350