11a989b97SToby Isaac #include <petsc/private/petscimpl.h> 2*28222859SToby Isaac #include <petsc/private/dtimpl.h> /*I "petscdt.h" I*/ 31a989b97SToby Isaac 4fad4db65SToby Isaac /*@ 5*28222859SToby Isaac PetscDTAltVApply - Apply an a k-form (an alternating k-linear map) to a set of k N-dimensional vectors 6fad4db65SToby Isaac 7fad4db65SToby Isaac Input Arguments: 8*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 9*28222859SToby Isaac . k - the degree k of the k-form w, 0 <= k <= N 10*28222859SToby Isaac . w - a k-form, size [N choose k] (each degree of freedom of a k-form is associated with a subset of k coordinates of the N-dimensional vectors: the degrees of freedom are ordered lexicographically by their associated subsets) 11*28222859SToby Isaac - v - a set of k vectors of size N, size [k x N], each vector stored contiguously 12fad4db65SToby Isaac 13fad4db65SToby Isaac Output Arguments: 14*28222859SToby Isaac . wv - w(v_1,...,v_k) = \sum_i w_i * det(V_i): the degree of freedom w_i is associated with coordinates [s_{i,1},...,s_{i,k}], and the square matrix V_i has entry (j,k) given by the s_{i,k}'th coordinate of v_j 15fad4db65SToby Isaac 16fad4db65SToby Isaac Level: intermediate 17fad4db65SToby Isaac 18fad4db65SToby Isaac .seealso: PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 19fad4db65SToby Isaac @*/ 201a989b97SToby Isaac PetscErrorCode PetscDTAltVApply(PetscInt N, PetscInt k, const PetscReal *w, const PetscReal *v, PetscReal *wv) 211a989b97SToby Isaac { 221a989b97SToby Isaac PetscErrorCode ierr; 231a989b97SToby Isaac 241a989b97SToby Isaac PetscFunctionBegin; 251a989b97SToby Isaac if (N < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid dimension"); 261a989b97SToby Isaac if (k < 0 || k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 271a989b97SToby Isaac if (N <= 3) { 281a989b97SToby Isaac if (!k) { 291a989b97SToby Isaac *wv = w[0]; 301a989b97SToby Isaac } else { 311a989b97SToby Isaac if (N == 1) {*wv = w[0] * v[0];} 321a989b97SToby Isaac else if (N == 2) { 331a989b97SToby Isaac if (k == 1) {*wv = w[0] * v[0] + w[1] * v[1];} 341a989b97SToby Isaac else {*wv = w[0] * (v[0] * v[3] - v[1] * v[2]);} 351a989b97SToby Isaac } else { 361a989b97SToby Isaac if (k == 1) {*wv = w[0] * v[0] + w[1] * v[1] + w[2] * v[2];} 371a989b97SToby Isaac else if (k == 2) { 381a989b97SToby Isaac *wv = w[0] * (v[0] * v[4] - v[1] * v[3]) + 391a989b97SToby Isaac w[1] * (v[0] * v[5] - v[2] * v[3]) + 401a989b97SToby Isaac w[2] * (v[1] * v[5] - v[2] * v[4]); 411a989b97SToby Isaac } else { 421a989b97SToby Isaac *wv = w[0] * (v[0] * (v[4] * v[8] - v[5] * v[7]) + 431a989b97SToby Isaac v[1] * (v[5] * v[6] - v[3] * v[8]) + 441a989b97SToby Isaac v[2] * (v[3] * v[7] - v[4] * v[6])); 451a989b97SToby Isaac } 461a989b97SToby Isaac } 471a989b97SToby Isaac } 481a989b97SToby Isaac } else { 491a989b97SToby Isaac PetscInt Nk, Nf; 50fad4db65SToby Isaac PetscInt *subset, *perm; 511a989b97SToby Isaac PetscInt i, j, l; 521a989b97SToby Isaac PetscReal sum = 0.; 531a989b97SToby Isaac 54fad4db65SToby Isaac ierr = PetscDTFactorialInt(k, &Nf);CHKERRQ(ierr); 55fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 56fad4db65SToby Isaac ierr = PetscMalloc2(k, &subset, k, &perm);CHKERRQ(ierr); 571a989b97SToby Isaac for (i = 0; i < Nk; i++) { 581a989b97SToby Isaac PetscReal subsum = 0.; 591a989b97SToby Isaac 601a989b97SToby Isaac ierr = PetscDTEnumSubset(N, k, i, subset);CHKERRQ(ierr); 611a989b97SToby Isaac for (j = 0; j < Nf; j++) { 621a989b97SToby Isaac PetscBool permOdd; 631a989b97SToby Isaac PetscReal prod; 641a989b97SToby Isaac 65fad4db65SToby Isaac ierr = PetscDTEnumPerm(k, j, perm, &permOdd);CHKERRQ(ierr); 661a989b97SToby Isaac prod = permOdd ? -1. : 1.; 671a989b97SToby Isaac for (l = 0; l < k; l++) { 681a989b97SToby Isaac prod *= v[perm[l] * N + subset[l]]; 691a989b97SToby Isaac } 701a989b97SToby Isaac subsum += prod; 711a989b97SToby Isaac } 721a989b97SToby Isaac sum += w[i] * subsum; 731a989b97SToby Isaac } 74fad4db65SToby Isaac ierr = PetscFree2(subset, perm);CHKERRQ(ierr); 751a989b97SToby Isaac *wv = sum; 761a989b97SToby Isaac } 771a989b97SToby Isaac PetscFunctionReturn(0); 781a989b97SToby Isaac } 791a989b97SToby Isaac 80fad4db65SToby Isaac /*@ 81*28222859SToby Isaac PetscDTAltVWedge - Compute the wedge product of a j-form and a k-form, giving a (j+k) form 82fad4db65SToby Isaac 83fad4db65SToby Isaac Input Arguments: 84*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 85*28222859SToby Isaac . j - the degree j of the j-form a, 0 <= j <= N 86*28222859SToby Isaac . k - the degree k of the k-form b, 0 <= k <= N and 0 <= j+k <= N 87*28222859SToby Isaac . a - a j-form, size [N choose j] 88*28222859SToby Isaac - b - a k-form, size [N choose k] 89fad4db65SToby Isaac 90fad4db65SToby Isaac Output Arguments: 91*28222859SToby Isaac . awedgeb - the (j+k)-form a wedge b, size [N choose (j+k)]: (a wedge b)(v_1,...,v_{j+k}) = \sum_{s} sign(s) a(v_{s_1},...,v_{s_j}) b(v_{s_{j+1}},...,v_{s_{j+k}}), 92*28222859SToby Isaac where the sum is over permutations s such that s_1 < s_2 < ... < s_j and s_{j+1} < s_{j+2} < ... < s_{j+k}. 93fad4db65SToby Isaac 94fad4db65SToby Isaac Level: intermediate 95fad4db65SToby Isaac 96fad4db65SToby Isaac .seealso: PetscDTAltVWedgeMatrix(), PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 97fad4db65SToby Isaac @*/ 981a989b97SToby Isaac PetscErrorCode PetscDTAltVWedge(PetscInt N, PetscInt j, PetscInt k, const PetscReal *a, const PetscReal *b, PetscReal *awedgeb) 991a989b97SToby Isaac { 1001a989b97SToby Isaac PetscInt i; 1011a989b97SToby Isaac PetscErrorCode ierr; 1021a989b97SToby Isaac 1031a989b97SToby Isaac PetscFunctionBegin; 1041a989b97SToby Isaac if (N < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid dimension"); 1051a989b97SToby Isaac if (j < 0 || k < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "negative form degree"); 1061a989b97SToby Isaac if (j + k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Wedge greater than dimension"); 1071a989b97SToby Isaac if (N <= 3) { 1081a989b97SToby Isaac PetscInt Njk; 1091a989b97SToby Isaac 110fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, j+k, &Njk);CHKERRQ(ierr); 1111a989b97SToby Isaac if (!j) {for (i = 0; i < Njk; i++) {awedgeb[i] = a[0] * b[i];}} 1121a989b97SToby Isaac else if (!k) {for (i = 0; i < Njk; i++) {awedgeb[i] = a[i] * b[0];}} 1131a989b97SToby Isaac else { 1141a989b97SToby Isaac if (N == 2) {awedgeb[0] = a[0] * b[1] - a[1] * b[0];} 1151a989b97SToby Isaac else { 1161a989b97SToby Isaac if (j+k == 2) { 1171a989b97SToby Isaac awedgeb[0] = a[0] * b[1] - a[1] * b[0]; 1181a989b97SToby Isaac awedgeb[1] = a[0] * b[2] - a[2] * b[0]; 1191a989b97SToby Isaac awedgeb[2] = a[1] * b[2] - a[2] * b[1]; 1201a989b97SToby Isaac } else { 1211a989b97SToby Isaac awedgeb[0] = a[0] * b[2] - a[1] * b[1] + a[2] * b[0]; 1221a989b97SToby Isaac } 1231a989b97SToby Isaac } 1241a989b97SToby Isaac } 1251a989b97SToby Isaac } else { 1261a989b97SToby Isaac PetscInt Njk; 1271a989b97SToby Isaac PetscInt JKj; 1281a989b97SToby Isaac PetscInt *subset, *subsetjk, *subsetj, *subsetk; 1291a989b97SToby Isaac PetscInt i; 1301a989b97SToby Isaac 131fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, j+k, &Njk);CHKERRQ(ierr); 132fad4db65SToby Isaac ierr = PetscDTBinomialInt(j+k, j, &JKj);CHKERRQ(ierr); 1331a989b97SToby Isaac ierr = PetscMalloc4(j+k, &subset, j+k, &subsetjk, j, &subsetj, k, &subsetk);CHKERRQ(ierr); 1341a989b97SToby Isaac for (i = 0; i < Njk; i++) { 1351a989b97SToby Isaac PetscReal sum = 0.; 1361a989b97SToby Isaac PetscInt l; 1371a989b97SToby Isaac 1381a989b97SToby Isaac ierr = PetscDTEnumSubset(N, j+k, i, subset);CHKERRQ(ierr); 1391a989b97SToby Isaac for (l = 0; l < JKj; l++) { 1401a989b97SToby Isaac PetscBool jkOdd; 1411a989b97SToby Isaac PetscInt m, jInd, kInd; 1421a989b97SToby Isaac 1431a989b97SToby Isaac ierr = PetscDTEnumSplit(j+k, j, l, subsetjk, &jkOdd);CHKERRQ(ierr); 1441a989b97SToby Isaac for (m = 0; m < j; m++) { 1451a989b97SToby Isaac subsetj[m] = subset[subsetjk[m]]; 1461a989b97SToby Isaac } 1471a989b97SToby Isaac for (m = 0; m < k; m++) { 1481a989b97SToby Isaac subsetk[m] = subset[subsetjk[j+m]]; 1491a989b97SToby Isaac } 1501a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, j, subsetj, &jInd);CHKERRQ(ierr); 1511a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, k, subsetk, &kInd);CHKERRQ(ierr); 1521a989b97SToby Isaac sum += jkOdd ? -(a[jInd] * b[kInd]) : (a[jInd] * b[kInd]); 1531a989b97SToby Isaac } 1541a989b97SToby Isaac awedgeb[i] = sum; 1551a989b97SToby Isaac } 1561a989b97SToby Isaac ierr = PetscFree4(subset, subsetjk, subsetj, subsetk);CHKERRQ(ierr); 1571a989b97SToby Isaac } 1581a989b97SToby Isaac PetscFunctionReturn(0); 1591a989b97SToby Isaac } 1601a989b97SToby Isaac 161fad4db65SToby Isaac /*@ 162*28222859SToby Isaac PetscDTAltVWedgeMatrix - Compute the matrix defined by the wedge product with a given j-form that maps k-forms to (j+k)-forms 163fad4db65SToby Isaac 164fad4db65SToby Isaac Input Arguments: 165*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 166*28222859SToby Isaac . j - the degree j of the j-form a, 0 <= j <= N 167*28222859SToby Isaac . k - the degree k of the k-forms that (a wedge) will be applied to, 0 <= k <= N and 0 <= j+k <= N 168*28222859SToby Isaac - a - a j-form, size [N choose j] 169fad4db65SToby Isaac 170fad4db65SToby Isaac Output Arguments: 171*28222859SToby Isaac . awedge - (a wedge), an [(N choose j+k) x (N choose k)] matrix in row-major order, such that (a wedge) * b = a wedge b 172fad4db65SToby Isaac 173fad4db65SToby Isaac Level: intermediate 174fad4db65SToby Isaac 175fad4db65SToby Isaac .seealso: PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 176fad4db65SToby Isaac @*/ 1771a989b97SToby Isaac PetscErrorCode PetscDTAltVWedgeMatrix(PetscInt N, PetscInt j, PetscInt k, const PetscReal *a, PetscReal *awedgeMat) 1781a989b97SToby Isaac { 1791a989b97SToby Isaac PetscInt i; 1801a989b97SToby Isaac PetscErrorCode ierr; 1811a989b97SToby Isaac 1821a989b97SToby Isaac PetscFunctionBegin; 1831a989b97SToby Isaac if (N < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid dimension"); 1841a989b97SToby Isaac if (j < 0 || k < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "negative form degree"); 1851a989b97SToby Isaac if (j + k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Wedge greater than dimension"); 1861a989b97SToby Isaac if (N <= 3) { 1871a989b97SToby Isaac PetscInt Njk; 1881a989b97SToby Isaac 189fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, j+k, &Njk);CHKERRQ(ierr); 1901a989b97SToby Isaac if (!j) { 1911a989b97SToby Isaac for (i = 0; i < Njk * Njk; i++) {awedgeMat[i] = 0.;} 1921a989b97SToby Isaac for (i = 0; i < Njk; i++) {awedgeMat[i * (Njk + 1)] = a[0];} 1931a989b97SToby Isaac } else if (!k) { 1941a989b97SToby Isaac for (i = 0; i < Njk; i++) {awedgeMat[i] = a[i];} 1951a989b97SToby Isaac } else { 1961a989b97SToby Isaac if (N == 2) { 1971a989b97SToby Isaac awedgeMat[0] = -a[1]; awedgeMat[1] = a[0]; 1981a989b97SToby Isaac } else { 1991a989b97SToby Isaac if (j+k == 2) { 2001a989b97SToby Isaac awedgeMat[0] = -a[1]; awedgeMat[1] = a[0]; awedgeMat[2] = 0.; 2011a989b97SToby Isaac awedgeMat[3] = -a[2]; awedgeMat[4] = 0.; awedgeMat[5] = a[0]; 2021a989b97SToby Isaac awedgeMat[6] = 0.; awedgeMat[7] = -a[2]; awedgeMat[8] = a[1]; 2031a989b97SToby Isaac } else { 2041a989b97SToby Isaac awedgeMat[0] = a[2]; awedgeMat[1] = -a[1]; awedgeMat[2] = a[0]; 2051a989b97SToby Isaac } 2061a989b97SToby Isaac } 2071a989b97SToby Isaac } 2081a989b97SToby Isaac } else { 2091a989b97SToby Isaac PetscInt Njk; 2101a989b97SToby Isaac PetscInt Nk; 2111a989b97SToby Isaac PetscInt JKj, i; 2121a989b97SToby Isaac PetscInt *subset, *subsetjk, *subsetj, *subsetk; 2131a989b97SToby Isaac 214fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 215fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, j+k, &Njk);CHKERRQ(ierr); 216fad4db65SToby Isaac ierr = PetscDTBinomialInt(j+k, j, &JKj);CHKERRQ(ierr); 2171a989b97SToby Isaac ierr = PetscMalloc4(j+k, &subset, j+k, &subsetjk, j, &subsetj, k, &subsetk);CHKERRQ(ierr); 2181a989b97SToby Isaac for (i = 0; i < Njk * Nk; i++) awedgeMat[i] = 0.; 2191a989b97SToby Isaac for (i = 0; i < Njk; i++) { 2201a989b97SToby Isaac PetscInt l; 2211a989b97SToby Isaac 2221a989b97SToby Isaac ierr = PetscDTEnumSubset(N, j+k, i, subset);CHKERRQ(ierr); 2231a989b97SToby Isaac for (l = 0; l < JKj; l++) { 2241a989b97SToby Isaac PetscBool jkOdd; 2251a989b97SToby Isaac PetscInt m, jInd, kInd; 2261a989b97SToby Isaac 2271a989b97SToby Isaac ierr = PetscDTEnumSplit(j+k, j, l, subsetjk, &jkOdd);CHKERRQ(ierr); 2281a989b97SToby Isaac for (m = 0; m < j; m++) { 2291a989b97SToby Isaac subsetj[m] = subset[subsetjk[m]]; 2301a989b97SToby Isaac } 2311a989b97SToby Isaac for (m = 0; m < k; m++) { 2321a989b97SToby Isaac subsetk[m] = subset[subsetjk[j+m]]; 2331a989b97SToby Isaac } 2341a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, j, subsetj, &jInd);CHKERRQ(ierr); 2351a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, k, subsetk, &kInd);CHKERRQ(ierr); 2361a989b97SToby Isaac awedgeMat[i * Nk + kInd] += jkOdd ? - a[jInd] : a[jInd]; 2371a989b97SToby Isaac } 2381a989b97SToby Isaac } 2391a989b97SToby Isaac ierr = PetscFree4(subset, subsetjk, subsetj, subsetk);CHKERRQ(ierr); 2401a989b97SToby Isaac } 2411a989b97SToby Isaac PetscFunctionReturn(0); 2421a989b97SToby Isaac } 2431a989b97SToby Isaac 244fad4db65SToby Isaac /*@ 245*28222859SToby Isaac PetscDTAltVPullback - Compute the pullback of a k-form under a linear transformation of the coordinate space 246fad4db65SToby Isaac 247fad4db65SToby Isaac Input Arguments: 248*28222859SToby Isaac + N - the dimension of the origin vector space of the linear transformation, M >= 0 249*28222859SToby Isaac . M - the dimension of the image vector space of the linear transformation, N >= 0 250*28222859SToby Isaac . L - a linear transformation, an [M x N] matrix in row-major format 251*28222859SToby Isaac . k - the *signed* degree k of the |k|-form w, -(min(M,N)) <= k <= min(M,N). A negative form degree indicates that the pullback should be conjugated by the Hodge star operator (see note). 252*28222859SToby Isaac - w - a |k|-form in the image space, size [M choose |k|] 253fad4db65SToby Isaac 254fad4db65SToby Isaac Output Arguments: 255*28222859SToby Isaac . Lstarw - the pullback of w to a |k|-form in the origin space, size [N choose |k|]: (Lstarw)(v_1,...v_k) = w(L*v_1,...,L*v_k). 256fad4db65SToby Isaac 257fad4db65SToby Isaac Level: intermediate 258fad4db65SToby Isaac 259fad4db65SToby Isaac Note: negative form degrees accomodate, e.g., H-div conforming vector fields. An H-div conforming vector field stores its degrees of freedom as (dx, dy, dz), like a 1-form, 260*28222859SToby Isaac but its normal trace is integrated on faces, like a 2-form. The correct pullback then is to apply the Hodge star transformation from (M-2)-form to 2-form, pullback as a 2-form, 261fad4db65SToby Isaac then the inverse Hodge star transformation. 262fad4db65SToby Isaac 263fad4db65SToby Isaac .seealso: PetscDTAltVPullbackMatrix(), PetscDTAltVStar() 264fad4db65SToby Isaac @*/ 2651a989b97SToby Isaac PetscErrorCode PetscDTAltVPullback(PetscInt N, PetscInt M, const PetscReal *L, PetscInt k, const PetscReal *w, PetscReal *Lstarw) 2661a989b97SToby Isaac { 2671a989b97SToby Isaac PetscInt i, j, Nk, Mk; 2681a989b97SToby Isaac PetscErrorCode ierr; 2691a989b97SToby Isaac 2701a989b97SToby Isaac PetscFunctionBegin; 2711a989b97SToby Isaac if (N < 0 || M < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid dimensions"); 2721a989b97SToby Isaac if (PetscAbsInt(k) > N || PetscAbsInt(k) > M) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 2731a989b97SToby Isaac if (N <= 3 && M <= 3) { 2741a989b97SToby Isaac 275fad4db65SToby Isaac ierr = PetscDTBinomialInt(M, PetscAbsInt(k), &Mk);CHKERRQ(ierr); 276fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, PetscAbsInt(k), &Nk);CHKERRQ(ierr); 2771a989b97SToby Isaac if (!k) { 2781a989b97SToby Isaac Lstarw[0] = w[0]; 2791a989b97SToby Isaac } else if (k == 1) { 2801a989b97SToby Isaac for (i = 0; i < Nk; i++) { 2811a989b97SToby Isaac PetscReal sum = 0.; 2821a989b97SToby Isaac 2831a989b97SToby Isaac for (j = 0; j < Mk; j++) {sum += L[j * Nk + i] * w[j];} 2841a989b97SToby Isaac Lstarw[i] = sum; 2851a989b97SToby Isaac } 2861a989b97SToby Isaac } else if (k == -1) { 2871a989b97SToby Isaac PetscReal mult[3] = {1., -1., 1.}; 2881a989b97SToby Isaac 2891a989b97SToby Isaac for (i = 0; i < Nk; i++) { 2901a989b97SToby Isaac PetscReal sum = 0.; 2911a989b97SToby Isaac 2921a989b97SToby Isaac for (j = 0; j < Mk; j++) { 2931a989b97SToby Isaac sum += L[(Mk - 1 - j) * Nk + (Nk - 1 - i)] * w[j] * mult[j]; 2941a989b97SToby Isaac } 2951a989b97SToby Isaac Lstarw[i] = mult[i] * sum; 2961a989b97SToby Isaac } 2971a989b97SToby Isaac } else if (k == 2) { 2981a989b97SToby Isaac PetscInt pairs[3][2] = {{0,1},{0,2},{1,2}}; 2991a989b97SToby Isaac 3001a989b97SToby Isaac for (i = 0; i < Nk; i++) { 3011a989b97SToby Isaac PetscReal sum = 0.; 3021a989b97SToby Isaac for (j = 0; j < Mk; j++) { 3031a989b97SToby Isaac sum += (L[pairs[j][0] * N + pairs[i][0]] * L[pairs[j][1] * N + pairs[i][1]] - 3041a989b97SToby Isaac L[pairs[j][1] * N + pairs[i][0]] * L[pairs[j][0] * N + pairs[i][1]]) * w[j]; 3051a989b97SToby Isaac } 3061a989b97SToby Isaac Lstarw[i] = sum; 3071a989b97SToby Isaac } 3081a989b97SToby Isaac } else if (k == -2) { 3091a989b97SToby Isaac PetscInt pairs[3][2] = {{1,2},{2,0},{0,1}}; 3101a989b97SToby Isaac PetscInt offi = (N == 2) ? 2 : 0; 3111a989b97SToby Isaac PetscInt offj = (M == 2) ? 2 : 0; 3121a989b97SToby Isaac 3131a989b97SToby Isaac for (i = 0; i < Nk; i++) { 3141a989b97SToby Isaac PetscReal sum = 0.; 3151a989b97SToby Isaac 3161a989b97SToby Isaac for (j = 0; j < Mk; j++) { 3171a989b97SToby Isaac sum += (L[pairs[offj + j][0] * N + pairs[offi + i][0]] * 3181a989b97SToby Isaac L[pairs[offj + j][1] * N + pairs[offi + i][1]] - 3191a989b97SToby Isaac L[pairs[offj + j][1] * N + pairs[offi + i][0]] * 3201a989b97SToby Isaac L[pairs[offj + j][0] * N + pairs[offi + i][1]]) * w[j]; 3211a989b97SToby Isaac 3221a989b97SToby Isaac } 3231a989b97SToby Isaac Lstarw[i] = sum; 3241a989b97SToby Isaac } 3251a989b97SToby Isaac } else { 3261a989b97SToby Isaac PetscReal detL = L[0] * (L[4] * L[8] - L[5] * L[7]) + 3271a989b97SToby Isaac L[1] * (L[5] * L[6] - L[3] * L[8]) + 3281a989b97SToby Isaac L[2] * (L[3] * L[7] - L[4] * L[6]); 3291a989b97SToby Isaac 3301a989b97SToby Isaac for (i = 0; i < Nk; i++) {Lstarw[i] = detL * w[i];} 3311a989b97SToby Isaac } 3321a989b97SToby Isaac } else { 3331a989b97SToby Isaac PetscInt Nf, l, p; 3341a989b97SToby Isaac PetscReal *Lw, *Lwv; 3351a989b97SToby Isaac PetscInt *subsetw, *subsetv; 336fad4db65SToby Isaac PetscInt *perm; 3371a989b97SToby Isaac PetscReal *walloc = NULL; 3381a989b97SToby Isaac const PetscReal *ww = NULL; 3391a989b97SToby Isaac PetscBool negative = PETSC_FALSE; 3401a989b97SToby Isaac 341fad4db65SToby Isaac ierr = PetscDTBinomialInt(M, PetscAbsInt(k), &Mk);CHKERRQ(ierr); 342fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, PetscAbsInt(k), &Nk);CHKERRQ(ierr); 343fad4db65SToby Isaac ierr = PetscDTFactorialInt(PetscAbsInt(k), &Nf);CHKERRQ(ierr); 3441a989b97SToby Isaac if (k < 0) { 3451a989b97SToby Isaac negative = PETSC_TRUE; 3461a989b97SToby Isaac k = -k; 3471a989b97SToby Isaac ierr = PetscMalloc1(Mk, &walloc);CHKERRQ(ierr); 3481a989b97SToby Isaac ierr = PetscDTAltVStar(M, M - k, 1, w, walloc);CHKERRQ(ierr); 3491a989b97SToby Isaac ww = walloc; 3501a989b97SToby Isaac } else { 3511a989b97SToby Isaac ww = w; 3521a989b97SToby Isaac } 353fad4db65SToby Isaac ierr = PetscMalloc5(k, &subsetw, k, &subsetv, k, &perm, N * k, &Lw, k * k, &Lwv);CHKERRQ(ierr); 3541a989b97SToby Isaac for (i = 0; i < Nk; i++) Lstarw[i] = 0.; 3551a989b97SToby Isaac for (i = 0; i < Mk; i++) { 3561a989b97SToby Isaac ierr = PetscDTEnumSubset(M, k, i, subsetw);CHKERRQ(ierr); 3571a989b97SToby Isaac for (j = 0; j < Nk; j++) { 3581a989b97SToby Isaac ierr = PetscDTEnumSubset(N, k, j, subsetv);CHKERRQ(ierr); 3591a989b97SToby Isaac for (p = 0; p < Nf; p++) { 3601a989b97SToby Isaac PetscReal prod; 3611a989b97SToby Isaac PetscBool isOdd; 3621a989b97SToby Isaac 363fad4db65SToby Isaac ierr = PetscDTEnumPerm(k, p, perm, &isOdd);CHKERRQ(ierr); 3641a989b97SToby Isaac prod = isOdd ? -ww[i] : ww[i]; 3651a989b97SToby Isaac for (l = 0; l < k; l++) { 3661a989b97SToby Isaac prod *= L[subsetw[perm[l]] * N + subsetv[l]]; 3671a989b97SToby Isaac } 3681a989b97SToby Isaac Lstarw[j] += prod; 3691a989b97SToby Isaac } 3701a989b97SToby Isaac } 3711a989b97SToby Isaac } 3721a989b97SToby Isaac if (negative) { 3731a989b97SToby Isaac PetscReal *sLsw; 3741a989b97SToby Isaac 3751a989b97SToby Isaac ierr = PetscMalloc1(Nk, &sLsw);CHKERRQ(ierr); 3761a989b97SToby Isaac ierr = PetscDTAltVStar(N, N - k, -1, Lstarw, sLsw);CHKERRQ(ierr); 3771a989b97SToby Isaac for (i = 0; i < Nk; i++) Lstarw[i] = sLsw[i]; 3781a989b97SToby Isaac ierr = PetscFree(sLsw);CHKERRQ(ierr); 3791a989b97SToby Isaac } 380fad4db65SToby Isaac ierr = PetscFree5(subsetw, subsetv, perm, Lw, Lwv);CHKERRQ(ierr); 3811a989b97SToby Isaac ierr = PetscFree(walloc);CHKERRQ(ierr); 3821a989b97SToby Isaac } 3831a989b97SToby Isaac PetscFunctionReturn(0); 3841a989b97SToby Isaac } 3851a989b97SToby Isaac 386fad4db65SToby Isaac /*@ 387fad4db65SToby Isaac PetscDTAltVPullbackMatrix - Compute the pullback matrix for k-forms under a linear transformation 388fad4db65SToby Isaac 389fad4db65SToby Isaac Input Arguments: 390*28222859SToby Isaac + N - the dimension of the origin vector space of the linear transformation, N >= 0 391*28222859SToby Isaac . M - the dimension of the image vector space of the linear transformation, M >= 0 392*28222859SToby Isaac . L - a linear transformation, an [M x N] matrix in row-major format 393*28222859SToby Isaac - k - the *signed* degree k of the |k|-forms on which Lstar acts, -(min(M,N)) <= k <= min(M,N). A negative form degree indicates that the pullback should be conjugated by the Hodge star operator (see note in PetscDTAltvPullback()) 394fad4db65SToby Isaac 395fad4db65SToby Isaac Output Arguments: 396*28222859SToby Isaac . Lstar - the pullback matrix, an [(N choose |k|) x (M choose |k|)] matrix in row-major format such that Lstar * w = L^* w 397fad4db65SToby Isaac 398fad4db65SToby Isaac Level: intermediate 399fad4db65SToby Isaac 400fad4db65SToby Isaac .seealso: PetscDTAltVPullback(), PetscDTAltVStar() 401fad4db65SToby Isaac @*/ 4021a989b97SToby Isaac PetscErrorCode PetscDTAltVPullbackMatrix(PetscInt N, PetscInt M, const PetscReal *L, PetscInt k, PetscReal *Lstar) 4031a989b97SToby Isaac { 4041a989b97SToby Isaac PetscInt Nk, Mk, Nf, i, j, l, p; 4051a989b97SToby Isaac PetscReal *Lw, *Lwv; 4061a989b97SToby Isaac PetscInt *subsetw, *subsetv; 407fad4db65SToby Isaac PetscInt *perm; 4081a989b97SToby Isaac PetscBool negative = PETSC_FALSE; 4091a989b97SToby Isaac PetscErrorCode ierr; 4101a989b97SToby Isaac 4111a989b97SToby Isaac PetscFunctionBegin; 4121a989b97SToby Isaac if (N < 0 || M < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid dimensions"); 4131a989b97SToby Isaac if (PetscAbsInt(k) > N || PetscAbsInt(k) > M) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 4141a989b97SToby Isaac if (N <= 3 && M <= 3) { 4151a989b97SToby Isaac PetscReal mult[3] = {1., -1., 1.}; 4161a989b97SToby Isaac 417fad4db65SToby Isaac ierr = PetscDTBinomialInt(M, PetscAbsInt(k), &Mk);CHKERRQ(ierr); 418fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, PetscAbsInt(k), &Nk);CHKERRQ(ierr); 4191a989b97SToby Isaac if (!k) { 4201a989b97SToby Isaac Lstar[0] = 1.; 4211a989b97SToby Isaac } else if (k == 1) { 4221a989b97SToby Isaac for (i = 0; i < Nk; i++) {for (j = 0; j < Mk; j++) {Lstar[i * Mk + j] = L[j * Nk + i];}} 4231a989b97SToby Isaac } else if (k == -1) { 4241a989b97SToby Isaac for (i = 0; i < Nk; i++) { 4251a989b97SToby Isaac for (j = 0; j < Mk; j++) { 4261a989b97SToby Isaac Lstar[i * Mk + j] = L[(Mk - 1 - j) * Nk + (Nk - 1 - i)] * mult[i] * mult[j]; 4271a989b97SToby Isaac } 4281a989b97SToby Isaac } 4291a989b97SToby Isaac } else if (k == 2) { 4301a989b97SToby Isaac PetscInt pairs[3][2] = {{0,1},{0,2},{1,2}}; 4311a989b97SToby Isaac 4321a989b97SToby Isaac for (i = 0; i < Nk; i++) { 4331a989b97SToby Isaac for (j = 0; j < Mk; j++) { 4341a989b97SToby Isaac Lstar[i * Mk + j] = L[pairs[j][0] * N + pairs[i][0]] * 4351a989b97SToby Isaac L[pairs[j][1] * N + pairs[i][1]] - 4361a989b97SToby Isaac L[pairs[j][1] * N + pairs[i][0]] * 4371a989b97SToby Isaac L[pairs[j][0] * N + pairs[i][1]]; 4381a989b97SToby Isaac } 4391a989b97SToby Isaac } 4401a989b97SToby Isaac } else if (k == -2) { 4411a989b97SToby Isaac PetscInt pairs[3][2] = {{1,2},{2,0},{0,1}}; 4421a989b97SToby Isaac PetscInt offi = (N == 2) ? 2 : 0; 4431a989b97SToby Isaac PetscInt offj = (M == 2) ? 2 : 0; 4441a989b97SToby Isaac 4451a989b97SToby Isaac for (i = 0; i < Nk; i++) { 4461a989b97SToby Isaac for (j = 0; j < Mk; j++) { 4471a989b97SToby Isaac Lstar[i * Mk + j] = L[pairs[offj + j][0] * N + pairs[offi + i][0]] * 4481a989b97SToby Isaac L[pairs[offj + j][1] * N + pairs[offi + i][1]] - 4491a989b97SToby Isaac L[pairs[offj + j][1] * N + pairs[offi + i][0]] * 4501a989b97SToby Isaac L[pairs[offj + j][0] * N + pairs[offi + i][1]]; 4511a989b97SToby Isaac } 4521a989b97SToby Isaac } 4531a989b97SToby Isaac } else { 4541a989b97SToby Isaac PetscReal detL = L[0] * (L[4] * L[8] - L[5] * L[7]) + 4551a989b97SToby Isaac L[1] * (L[5] * L[6] - L[3] * L[8]) + 4561a989b97SToby Isaac L[2] * (L[3] * L[7] - L[4] * L[6]); 4571a989b97SToby Isaac 4581a989b97SToby Isaac for (i = 0; i < Nk; i++) {Lstar[i] = detL;} 4591a989b97SToby Isaac } 4601a989b97SToby Isaac } else { 4611a989b97SToby Isaac if (k < 0) { 4621a989b97SToby Isaac negative = PETSC_TRUE; 4631a989b97SToby Isaac k = -k; 4641a989b97SToby Isaac } 465fad4db65SToby Isaac ierr = PetscDTBinomialInt(M, PetscAbsInt(k), &Mk);CHKERRQ(ierr); 466fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, PetscAbsInt(k), &Nk);CHKERRQ(ierr); 467fad4db65SToby Isaac ierr = PetscDTFactorialInt(PetscAbsInt(k), &Nf);CHKERRQ(ierr); 468fad4db65SToby Isaac ierr = PetscMalloc5(M, &subsetw, N, &subsetv, k, &perm, N * k, &Lw, k * k, &Lwv);CHKERRQ(ierr); 4691a989b97SToby Isaac for (i = 0; i < Nk * Mk; i++) Lstar[i] = 0.; 4701a989b97SToby Isaac for (i = 0; i < Mk; i++) { 4711a989b97SToby Isaac PetscBool iOdd; 4721a989b97SToby Isaac PetscInt iidx, jidx; 4731a989b97SToby Isaac 4741a989b97SToby Isaac ierr = PetscDTEnumSplit(M, k, i, subsetw, &iOdd);CHKERRQ(ierr); 4751a989b97SToby Isaac iidx = negative ? Mk - 1 - i : i; 476*28222859SToby Isaac iOdd = negative ? (PetscBool) (iOdd ^ ((k * (M-k)) & 1)) : PETSC_FALSE; 4771a989b97SToby Isaac for (j = 0; j < Nk; j++) { 4781a989b97SToby Isaac PetscBool jOdd; 4791a989b97SToby Isaac 4801a989b97SToby Isaac ierr = PetscDTEnumSplit(N, k, j, subsetv, &jOdd);CHKERRQ(ierr); 4811a989b97SToby Isaac jidx = negative ? Nk - 1 - j : j; 482*28222859SToby Isaac jOdd = negative ? (PetscBool) (iOdd ^ jOdd ^ ((k * (N-k)) & 1)) : PETSC_FALSE; 4831a989b97SToby Isaac for (p = 0; p < Nf; p++) { 4841a989b97SToby Isaac PetscReal prod; 4851a989b97SToby Isaac PetscBool isOdd; 4861a989b97SToby Isaac 487fad4db65SToby Isaac ierr = PetscDTEnumPerm(k, p, perm, &isOdd);CHKERRQ(ierr); 488*28222859SToby Isaac isOdd = (PetscBool) (isOdd ^ jOdd); 4891a989b97SToby Isaac prod = isOdd ? -1. : 1.; 4901a989b97SToby Isaac for (l = 0; l < k; l++) { 4911a989b97SToby Isaac prod *= L[subsetw[perm[l]] * N + subsetv[l]]; 4921a989b97SToby Isaac } 4931a989b97SToby Isaac Lstar[jidx * Mk + iidx] += prod; 4941a989b97SToby Isaac } 4951a989b97SToby Isaac } 4961a989b97SToby Isaac } 497fad4db65SToby Isaac ierr = PetscFree5(subsetw, subsetv, perm, Lw, Lwv);CHKERRQ(ierr); 4981a989b97SToby Isaac } 4991a989b97SToby Isaac PetscFunctionReturn(0); 5001a989b97SToby Isaac } 5011a989b97SToby Isaac 502fad4db65SToby Isaac /*@ 503*28222859SToby Isaac PetscDTAltVInterior - Compute the interior product of a k-form with a vector 504fad4db65SToby Isaac 505fad4db65SToby Isaac Input Arguments: 506*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 507*28222859SToby Isaac . k - the degree k of the k-form w, 0 <= k <= N 508*28222859SToby Isaac . w - a k-form, size [N choose k] 509*28222859SToby Isaac - v - an N dimensional vector 510fad4db65SToby Isaac 511fad4db65SToby Isaac Output Arguments: 512*28222859SToby Isaac . wIntv - the (k-1)-form (w int v), size [N choose (k-1)]: (w int v) is defined by its action on (k-1) vectors {v_1, ..., v_{k-1}} as (w inv v)(v_1, ..., v_{k-1}) = w(v, v_1, ..., v_{k-1}). 513fad4db65SToby Isaac 514fad4db65SToby Isaac Level: intermediate 515fad4db65SToby Isaac 516fad4db65SToby Isaac .seealso: PetscDTAltVInteriorMatrix(), PetscDTAltVInteriorPattern(), PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 517fad4db65SToby Isaac @*/ 5181a989b97SToby Isaac PetscErrorCode PetscDTAltVInterior(PetscInt N, PetscInt k, const PetscReal *w, const PetscReal *v, PetscReal *wIntv) 5191a989b97SToby Isaac { 5201a989b97SToby Isaac PetscInt i, Nk, Nkm; 5211a989b97SToby Isaac PetscErrorCode ierr; 5221a989b97SToby Isaac 5231a989b97SToby Isaac PetscFunctionBegin; 5241a989b97SToby Isaac if (k <= 0 || k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 525fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 526fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k-1, &Nkm);CHKERRQ(ierr); 5271a989b97SToby Isaac if (N <= 3) { 5281a989b97SToby Isaac if (k == 1) { 5291a989b97SToby Isaac PetscReal sum = 0.; 5301a989b97SToby Isaac 5311a989b97SToby Isaac for (i = 0; i < N; i++) { 5321a989b97SToby Isaac sum += w[i] * v[i]; 5331a989b97SToby Isaac } 5341a989b97SToby Isaac wIntv[0] = sum; 5351a989b97SToby Isaac } else if (k == N) { 5361a989b97SToby Isaac PetscReal mult[3] = {1., -1., 1.}; 5371a989b97SToby Isaac 5381a989b97SToby Isaac for (i = 0; i < N; i++) { 5391a989b97SToby Isaac wIntv[N - 1 - i] = w[0] * v[i] * mult[i]; 5401a989b97SToby Isaac } 5411a989b97SToby Isaac } else { 5421a989b97SToby Isaac wIntv[0] = - w[0]*v[1] - w[1]*v[2]; 5431a989b97SToby Isaac wIntv[1] = w[0]*v[0] - w[2]*v[2]; 5441a989b97SToby Isaac wIntv[2] = w[1]*v[0] + w[2]*v[1]; 5451a989b97SToby Isaac } 5461a989b97SToby Isaac } else { 5471a989b97SToby Isaac PetscInt *subset, *work; 5481a989b97SToby Isaac 5491a989b97SToby Isaac ierr = PetscMalloc2(k, &subset, k, &work);CHKERRQ(ierr); 5501a989b97SToby Isaac for (i = 0; i < Nkm; i++) wIntv[i] = 0.; 5511a989b97SToby Isaac for (i = 0; i < Nk; i++) { 5521a989b97SToby Isaac PetscInt j, l, m; 5531a989b97SToby Isaac 5541a989b97SToby Isaac ierr = PetscDTEnumSubset(N, k, i, subset);CHKERRQ(ierr); 5551a989b97SToby Isaac for (j = 0; j < k; j++) { 5561a989b97SToby Isaac PetscInt idx; 557*28222859SToby Isaac PetscBool flip = (PetscBool) (j & 1); 5581a989b97SToby Isaac 5591a989b97SToby Isaac for (l = 0, m = 0; l < k; l++) { 5601a989b97SToby Isaac if (l != j) work[m++] = subset[l]; 5611a989b97SToby Isaac } 5621a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, k - 1, work, &idx);CHKERRQ(ierr); 5631a989b97SToby Isaac wIntv[idx] += flip ? -(w[i] * v[subset[j]]) : (w[i] * v[subset[j]]); 5641a989b97SToby Isaac } 5651a989b97SToby Isaac } 5661a989b97SToby Isaac ierr = PetscFree2(subset, work);CHKERRQ(ierr); 5671a989b97SToby Isaac } 5681a989b97SToby Isaac PetscFunctionReturn(0); 5691a989b97SToby Isaac } 5701a989b97SToby Isaac 571fad4db65SToby Isaac /*@ 572*28222859SToby Isaac PetscDTAltVInteriorMatrix - Compute the matrix of the linear transformation induced on a k-form by the interior product with a vector 573fad4db65SToby Isaac 574fad4db65SToby Isaac Input Arguments: 575*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 576*28222859SToby Isaac . k - the degree k of the k-forms on which intvMat acts, 0 <= k <= N 577*28222859SToby Isaac - v - an N dimensional vector 578fad4db65SToby Isaac 579fad4db65SToby Isaac Output Arguments: 580fad4db65SToby Isaac . intvMat - an [(N choose (k-1)) x (N choose k)] matrix, row-major: (intvMat) * w = (w int v) 581fad4db65SToby Isaac 582fad4db65SToby Isaac Level: intermediate 583fad4db65SToby Isaac 584fad4db65SToby Isaac .seealso: PetscDTAltVInterior(), PetscDTAltVInteriorPattern(), PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 585fad4db65SToby Isaac @*/ 5861a989b97SToby Isaac PetscErrorCode PetscDTAltVInteriorMatrix(PetscInt N, PetscInt k, const PetscReal *v, PetscReal *intvMat) 5871a989b97SToby Isaac { 5881a989b97SToby Isaac PetscInt i, Nk, Nkm; 5891a989b97SToby Isaac PetscErrorCode ierr; 5901a989b97SToby Isaac 5911a989b97SToby Isaac PetscFunctionBegin; 5921a989b97SToby Isaac if (k <= 0 || k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 593fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 594fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k-1, &Nkm);CHKERRQ(ierr); 5951a989b97SToby Isaac if (N <= 3) { 5961a989b97SToby Isaac if (k == 1) { 5971a989b97SToby Isaac for (i = 0; i < N; i++) intvMat[i] = v[i]; 5981a989b97SToby Isaac } else if (k == N) { 5991a989b97SToby Isaac PetscReal mult[3] = {1., -1., 1.}; 6001a989b97SToby Isaac 6011a989b97SToby Isaac for (i = 0; i < N; i++) intvMat[N - 1 - i] = v[i] * mult[i]; 6021a989b97SToby Isaac } else { 6031a989b97SToby Isaac intvMat[0] = -v[1]; intvMat[1] = -v[2]; intvMat[2] = 0.; 6041a989b97SToby Isaac intvMat[3] = v[0]; intvMat[4] = 0.; intvMat[5] = -v[2]; 6051a989b97SToby Isaac intvMat[6] = 0.; intvMat[7] = v[0]; intvMat[8] = v[1]; 6061a989b97SToby Isaac } 6071a989b97SToby Isaac } else { 6081a989b97SToby Isaac PetscInt *subset, *work; 6091a989b97SToby Isaac 6101a989b97SToby Isaac ierr = PetscMalloc2(k, &subset, k, &work);CHKERRQ(ierr); 6111a989b97SToby Isaac for (i = 0; i < Nk * Nkm; i++) intvMat[i] = 0.; 6121a989b97SToby Isaac for (i = 0; i < Nk; i++) { 6131a989b97SToby Isaac PetscInt j, l, m; 6141a989b97SToby Isaac 6151a989b97SToby Isaac ierr = PetscDTEnumSubset(N, k, i, subset);CHKERRQ(ierr); 6161a989b97SToby Isaac for (j = 0; j < k; j++) { 6171a989b97SToby Isaac PetscInt idx; 618*28222859SToby Isaac PetscBool flip = (PetscBool) (j & 1); 6191a989b97SToby Isaac 6201a989b97SToby Isaac for (l = 0, m = 0; l < k; l++) { 6211a989b97SToby Isaac if (l != j) work[m++] = subset[l]; 6221a989b97SToby Isaac } 6231a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, k - 1, work, &idx);CHKERRQ(ierr); 6241a989b97SToby Isaac intvMat[idx * Nk + i] += flip ? -v[subset[j]] : v[subset[j]]; 6251a989b97SToby Isaac } 6261a989b97SToby Isaac } 6271a989b97SToby Isaac ierr = PetscFree2(subset, work);CHKERRQ(ierr); 6281a989b97SToby Isaac } 6291a989b97SToby Isaac PetscFunctionReturn(0); 6301a989b97SToby Isaac } 6311a989b97SToby Isaac 632fad4db65SToby Isaac /*@ 633fad4db65SToby Isaac PetscDTAltVInteriorPattern - compute the sparsity and sign pattern of the interior product matrix computed in PetscDTAltVInteriorMatrix() 634fad4db65SToby Isaac 635fad4db65SToby Isaac Input Arguments: 636*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 637*28222859SToby Isaac - k - the degree of the k-forms on which intvMat from PetscDTAltVInteriorMatrix() acts, 0 <= k <= N. 638fad4db65SToby Isaac 639fad4db65SToby Isaac Output Arguments: 640*28222859SToby Isaac . indices - The interior product matrix intvMat has size [(N choose (k-1)) x (N choose k)] and has (N choose k) * k 641*28222859SToby Isaac non-zeros. indices[i][0] and indices[i][1] are the row and column of a non-zero, and its value is equal to the vector 642*28222859SToby Isaac coordinate v[j] if indices[i][2] = j, or -v[j] if indices[i][2] = -(j+1) 643fad4db65SToby Isaac 644fad4db65SToby Isaac Level: intermediate 645fad4db65SToby Isaac 646*28222859SToby Isaac Note: this function is useful when the interior product needs to be computed at multiple locations, as when computing the Koszul differential 647fad4db65SToby Isaac 648fad4db65SToby Isaac .seealso: PetscDTAltVInterior(), PetscDTAltVInteriorMatrix(), PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 649fad4db65SToby Isaac @*/ 650dda711d0SToby Isaac PetscErrorCode PetscDTAltVInteriorPattern(PetscInt N, PetscInt k, PetscInt (*indices)[3]) 651dda711d0SToby Isaac { 652dda711d0SToby Isaac PetscInt i, Nk, Nkm; 653dda711d0SToby Isaac PetscErrorCode ierr; 654dda711d0SToby Isaac 655dda711d0SToby Isaac PetscFunctionBegin; 656dda711d0SToby Isaac if (k <= 0 || k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 657fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 658fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k-1, &Nkm);CHKERRQ(ierr); 659dda711d0SToby Isaac if (N <= 3) { 660dda711d0SToby Isaac if (k == 1) { 661dda711d0SToby Isaac for (i = 0; i < N; i++) { 662dda711d0SToby Isaac indices[i][0] = 0; 663dda711d0SToby Isaac indices[i][1] = i; 664dda711d0SToby Isaac indices[i][2] = i; 665dda711d0SToby Isaac } 666dda711d0SToby Isaac } else if (k == N) { 667dda711d0SToby Isaac PetscInt val[3] = {0, -2, 2}; 668dda711d0SToby Isaac 669dda711d0SToby Isaac for (i = 0; i < N; i++) { 670dda711d0SToby Isaac indices[i][0] = N - 1 - i; 671dda711d0SToby Isaac indices[i][1] = 0; 672dda711d0SToby Isaac indices[i][2] = val[i]; 673dda711d0SToby Isaac } 674dda711d0SToby Isaac } else { 675dda711d0SToby Isaac indices[0][0] = 0; indices[0][1] = 0; indices[0][2] = -(1 + 1); 676dda711d0SToby Isaac indices[1][0] = 0; indices[1][1] = 1; indices[1][2] = -(2 + 1); 677dda711d0SToby Isaac indices[2][0] = 1; indices[2][1] = 0; indices[2][2] = 0; 678dda711d0SToby Isaac indices[3][0] = 1; indices[3][1] = 2; indices[3][2] = -(2 + 1); 679dda711d0SToby Isaac indices[4][0] = 2; indices[4][1] = 1; indices[4][2] = 0; 680dda711d0SToby Isaac indices[5][0] = 2; indices[5][1] = 2; indices[5][2] = 1; 681dda711d0SToby Isaac } 682dda711d0SToby Isaac } else { 683dda711d0SToby Isaac PetscInt *subset, *work; 684dda711d0SToby Isaac 685dda711d0SToby Isaac ierr = PetscMalloc2(k, &subset, k, &work);CHKERRQ(ierr); 686dda711d0SToby Isaac for (i = 0; i < Nk; i++) { 687dda711d0SToby Isaac PetscInt j, l, m; 688dda711d0SToby Isaac 689dda711d0SToby Isaac ierr = PetscDTEnumSubset(N, k, i, subset);CHKERRQ(ierr); 690dda711d0SToby Isaac for (j = 0; j < k; j++) { 691dda711d0SToby Isaac PetscInt idx; 692*28222859SToby Isaac PetscBool flip = (PetscBool) (j & 1); 693dda711d0SToby Isaac 694dda711d0SToby Isaac for (l = 0, m = 0; l < k; l++) { 695dda711d0SToby Isaac if (l != j) work[m++] = subset[l]; 696dda711d0SToby Isaac } 697dda711d0SToby Isaac ierr = PetscDTSubsetIndex(N, k - 1, work, &idx);CHKERRQ(ierr); 698dda711d0SToby Isaac indices[i * k + j][0] = idx; 699dda711d0SToby Isaac indices[i * k + j][1] = i; 700dda711d0SToby Isaac indices[i * k + j][2] = flip ? -(subset[j] + 1) : subset[j]; 701dda711d0SToby Isaac } 702dda711d0SToby Isaac } 703dda711d0SToby Isaac ierr = PetscFree2(subset, work);CHKERRQ(ierr); 704dda711d0SToby Isaac } 705dda711d0SToby Isaac PetscFunctionReturn(0); 706dda711d0SToby Isaac } 707dda711d0SToby Isaac 708fad4db65SToby Isaac /*@ 709*28222859SToby Isaac PetscDTAltVStar - Apply a power of the Hodge star operator, which maps k-forms to (N-k) forms, to a k-form 710fad4db65SToby Isaac 711fad4db65SToby Isaac Input Arguments: 712*28222859SToby Isaac + N - the dimension of the vector space, N >= 0 713*28222859SToby Isaac . k - the degree k of the k-form w, 0 <= k <= N 714*28222859SToby Isaac . pow - the number of times to apply the Hodge star operator: pow < 0 indicates that the inverse of the Hodge star operator should be applied |pow| times. 715*28222859SToby Isaac - w - a k-form, size [N choose k] 716fad4db65SToby Isaac 717fad4db65SToby Isaac Output Arguments: 718*28222859SToby Isaac . starw = (star)^pow w. Each degree of freedom of a k-form is associated with a subset S of k coordinates of the N dimensional vector space: the Hodge start operator (star) maps that degree of freedom to the degree of freedom associated with S', the complement of S, with a sign change if the permutation of coordinates {S[0], ... S[k-1], S'[0], ... S'[N-k- 1]} is an odd permutation. This implies (star)^2 w = (-1)^{k(N-k)} w, and (star)^4 w = w. 719fad4db65SToby Isaac 720fad4db65SToby Isaac Level: intermediate 721fad4db65SToby Isaac 722fad4db65SToby Isaac .seealso: PetscDTAltVPullback(), PetscDTAltVPullbackMatrix() 723fad4db65SToby Isaac @*/ 7241a989b97SToby Isaac PetscErrorCode PetscDTAltVStar(PetscInt N, PetscInt k, PetscInt pow, const PetscReal *w, PetscReal *starw) 7251a989b97SToby Isaac { 7261a989b97SToby Isaac PetscInt Nk, i; 7271a989b97SToby Isaac PetscErrorCode ierr; 7281a989b97SToby Isaac 7291a989b97SToby Isaac PetscFunctionBegin; 7301a989b97SToby Isaac if (k < 0 || k > N) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "invalid form degree"); 731fad4db65SToby Isaac ierr = PetscDTBinomialInt(N, k, &Nk);CHKERRQ(ierr); 7321a989b97SToby Isaac pow = pow % 4; 7331a989b97SToby Isaac pow = (pow + 4) % 4; /* make non-negative */ 7341a989b97SToby Isaac /* pow is now 0, 1, 2, 3 */ 7351a989b97SToby Isaac if (N <= 3) { 7361a989b97SToby Isaac if (pow & 1) { 7371a989b97SToby Isaac PetscReal mult[3] = {1., -1., 1.}; 7381a989b97SToby Isaac 7391a989b97SToby Isaac for (i = 0; i < Nk; i++) starw[Nk - 1 - i] = w[i] * mult[i]; 7401a989b97SToby Isaac } else { 7411a989b97SToby Isaac for (i = 0; i < Nk; i++) starw[i] = w[i]; 7421a989b97SToby Isaac } 7431a989b97SToby Isaac if (pow > 1 && ((k * (N - k)) & 1)) { 7441a989b97SToby Isaac for (i = 0; i < Nk; i++) starw[i] = -starw[i]; 7451a989b97SToby Isaac } 7461a989b97SToby Isaac } else { 7471a989b97SToby Isaac PetscInt *subset; 7481a989b97SToby Isaac 7491a989b97SToby Isaac ierr = PetscMalloc1(N, &subset);CHKERRQ(ierr); 7501a989b97SToby Isaac if (pow % 2) { 7511a989b97SToby Isaac PetscInt l = (pow == 1) ? k : N - k; 7521a989b97SToby Isaac for (i = 0; i < Nk; i++) { 7531a989b97SToby Isaac PetscBool sOdd; 7541a989b97SToby Isaac PetscInt j, idx; 7551a989b97SToby Isaac 7561a989b97SToby Isaac ierr = PetscDTEnumSplit(N, l, i, subset, &sOdd);CHKERRQ(ierr); 7571a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, l, subset, &idx);CHKERRQ(ierr); 7581a989b97SToby Isaac ierr = PetscDTSubsetIndex(N, N-l, &subset[l], &j);CHKERRQ(ierr); 7591a989b97SToby Isaac starw[j] = sOdd ? -w[idx] : w[idx]; 7601a989b97SToby Isaac } 7611a989b97SToby Isaac } else { 7621a989b97SToby Isaac for (i = 0; i < Nk; i++) starw[i] = w[i]; 7631a989b97SToby Isaac } 7641a989b97SToby Isaac /* star^2 = -1^(k * (N - k)) */ 7651a989b97SToby Isaac if (pow > 1 && (k * (N - k)) % 2) { 7661a989b97SToby Isaac for (i = 0; i < Nk; i++) starw[i] = -starw[i]; 7671a989b97SToby Isaac } 7681a989b97SToby Isaac ierr = PetscFree(subset);CHKERRQ(ierr); 7691a989b97SToby Isaac } 7701a989b97SToby Isaac PetscFunctionReturn(0); 7711a989b97SToby Isaac } 772