int laplaceOrder4MatEntry(const pointSet& mesh, int pnb, Array& entries) { int nbEq = 15; int NP = mesh.getNIDX(pnb); double b[NP]; double A[nbEq*NP]; double weight[NP]; if (NP < nbEq) throw mfpmExcept(20); b[0] = 0.0; // const b[1] = 0.0; // h b[2] = 0.0; // k b[3] = 2.0; // hh b[4] = 2.0; // kk b[5] = 0.0; // hk b[6] = 0.0; // hhh b[7] = 0.0; // hhk b[8] = 0.0; // hkk b[9] = 0.0; // kkk b[10] = 0.0; // hhhh b[11] = 0.0; // kkkk b[12] = 0.0; // hhhk b[13] = 0.0; // hhkk b[14] = 0.0; // hkkk double maxLength = 0; for (int i=0; i<NP; i++) { int idx = mesh.getIDX(pnb,i); double dist = mesh.P(pnb).dist(mesh.P(idx)); if (dist>maxLength) maxLength=dist; } b[3] /= maxLength*maxLength; b[4] /= maxLength*maxLength; int diagEntry; int idx, mi; double h, k; double sl2 = pow(mesh.getSL(pnb),2); // Store matrix in Fortran format for (int i=0; i<NP; i++) { idx = mesh.getIDX(pnb,i); mi = nbEq*i; h = mesh.x(idx) - mesh.x(pnb); k = mesh.y(idx) - mesh.y(pnb); weight[i] = exp(-2.0 * (h*h+k*k)/sl2 ); h /= maxLength; k /= maxLength; A[mi+0] = 1.0 * weight[i]; A[mi+1] = h * weight[i]; A[mi+2] = k * weight[i]; A[mi+3] = h*h * weight[i]; A[mi+4] = k*k * weight[i]; A[mi+5] = h*k * weight[i]; double fac=1.0; A[mi+6] = fac*h*h*h * weight[i]; A[mi+7] = fac*h*h*k * weight[i]; A[mi+8] = fac*h*k*k * weight[i]; A[mi+9] = fac*k*k*k * weight[i]; A[mi+10] = h*h*h*h * weight[i]; A[mi+11] = k*k*k*k * weight[i]; A[mi+12] = h*h*h*k * weight[i]; A[mi+13] = h*h*k*k * weight[i]; A[mi+14] = h*k*k*k * weight[i]; } int n = nbEq; int lda = nbEq; int m = NP; int jpv[m+n]; int lwork = 3*(m+n); double work[lwork]; int info; int one = 1; int rank; char TN[] = "N"; dgels_(TN, &n, &m, &one, A, &lda, b, &m, work, &lwork, &info); if (info!=0) { cout << "Error solving least squares: laplaceMatEntry!" << endl; throw mfpmExcept(27); } for (int i=0; i<NP; i++) { entries(i) = b[i]*weight[i]; } // Test operator: double sum = 0; for (int i=0; i<NP; i++) { idx = mesh.getIDX(pnb,i); sum += entries(i)*(mesh.x(idx)*mesh.x(idx)+mesh.y(idx)*mesh.y(idx)); } if ( abs(sum - 4.0) > 1e-7 ) { //cout << pnb << " " << sum << endl; return -2; } return 0; }
double bgGridIntegration(const pointSet& mesh, const scalarField& data) { //cout << "Integrating over domain" << endl; // Get bounding box double xmin, ymin, xmax, ymax; mesh.getBoundingBox(xmin, xmax, ymin, ymax); // Get smoothing length double sl = mesh.getMinSL(); double h = 0.15*sl; // Calc dimensions int nx = (int) ((xmax-xmin)/h)+2; int ny = (int) ((ymax-ymin)/h)+2; // Build background grid #ifndef USE_STACK vector<point> P; P.reserve(nx*ny); #else point P[nx*ny]; #endif double val; for (int i=0; i<nx; i++) { for (int j=0; j<ny; j++) { #ifndef USE_STACK point pTmp; pTmp.X = xmin + i*h; pTmp.Y = ymin + j*h; P.push_back(pTmp); #else P[i*ny+j].X = xmin + i*h; P[i*ny+j].Y = ymin + j*h; #endif } } // Interpolate scalarField values onto bg grid int n = nx*ny; int ix, iy; double sum = 0; for (int i=0; i<n; i++) { mesh.getQuad(P[i], ix, iy); const vector<int>& bndquad = mesh.getQuad(ix, iy, false); int bqSize = bndquad.size(); // Point definitely in / out domain? if (bqSize == 0) { const vector<int>& quad = mesh.getQuad(ix, iy); if (quad.size() != 0) { sum += data.interpolateLS(P[i]); } } // No? Check in/out with normals else { // Find nearest bnd point double minDist = 1e100; int minPos = -1; for (int j=0; j<bqSize; j++) { if (minDist > mesh.P(bndquad[j]).dist(P[i])) { minDist = mesh.P(bndquad[j]).dist(P[i]); minPos = bndquad[j]; } } double vecX = P[i].X - mesh.P(minPos).X; double vecY = P[i].Y - mesh.P(minPos).Y; double nDir = mesh.P(minPos).Nx*vecX + mesh.P(minPos).Ny*vecY; if (nDir <= 0) { sum += data.interpolateLS(P[i]); } } } sum *= h*h; return sum; }