std::vector<std::vector<int>> primeFactor(int n, const std::set<int>& primes) { std::vector<std::vector<int>> facs(n+1); for (auto p:primes) { for(int i = 2*p; i <= n ; i += p) facs[i].emplace_back(p); } std::function<void(int,int,int,const std::vector<int>&,std::vector<int>&)> tranverse = [&tranverse](int l,int i,int m,const std::vector<int>& f, std::vector<int>& lf) { if(l == 0) { lf.emplace_back(m); return ; } else { for(int j = i+1 ; j <= f.size() - l ; ++ j) tranverse(l-1,j,m*f[j],f,lf); } }; long whole_count = 0; for (int i = 2 ; i <= n ; ++ i) { int count = i-1; int t = -1; for(int l = 1 ; l <= facs[i].size() ; ++ l) { std::vector<int> lf; tranverse(l,-1,1,facs[i],lf); for(auto f:lf) count += t*(i/f-1); t = -t; } whole_count+=count; } std::cout<<whole_count<<std::endl; return facs; }
void StrandBlockSolver::gradQa(const int& mglevel) { if (mglevel == 0 && gradient != 0 && gradQaFlag == 0){ // compute nodal values nodalQa(mglevel); // initialize gradients for (int n=0; n<nFaces+nBedges; n++) for (int j=0; j<nPstr+2; j++) for (int k=0; k<ndim; k++) for (int m=0; m<nqa; m++) qax(m,k,j,n) = 0.; // loop through unstructured edges int c1,c2,n1,n2,jm,jp,k; double Ax,Ay,sqa; for (int n=0; n<nEdges; n++){ c1 = edge(0,n); c2 = edge(1,n); n1 = edgn(n); for (int j=1; j<nPstr+1; j++){ jm = j-1; Ax = facs(0,j,n); Ay = facs(1,j,n); for (int kk=0; kk<nqaGradQa; kk++){ k = iqagrad(kk); sqa = qap(k,jm,n1)+qap(k,j,n1); qax(k,0,j,c1) += Ax*sqa; qax(k,1,j,c1) += Ay*sqa; qax(k,0,j,c2) -= Ax*sqa; qax(k,1,j,c2) -= Ay*sqa; }}} // loop through structured edges for (int n=0; n<nFaces-nGfaces; n++){ n1 = face(0,n); n2 = face(1,n); for (int j=0; j<nPstr+1; j++){ jp = j+1; Ax = facu(0,j,n); Ay = facu(1,j,n); for (int kk=0; kk<nqaGradQa; kk++){ k = iqagrad(kk); sqa = qap(k,j,n1)+qap(k,j,n2); qax(k,0,j ,n) += Ax*sqa; qax(k,1,j ,n) += Ay*sqa; qax(k,0,jp,n) -= Ax*sqa; qax(k,1,jp,n) -= Ay*sqa; }}} // divide by twice the volume for the interior cells for (int n=0; n<nFaces-nGfaces; n++) for (int j=1; j<nPstr+1; j++) for (int m=0; m<ndim; m++) for (int kk=0; kk<nqaGradQa; kk++){ k = iqagrad(kk); qax(k,m,j,n) /= (2.*v(j,n)); } // surface, end, and boundary gradients double dx1,dy1,dx2,dy2,ds,l11,l12,l21,l22,sqa1,sqa2,eps=1.e-14; int j=0; jp = 1; for (int n=0; n<nFaces-nGfaces; n++){ n1 = face(0,n); n2 = face(1,n); dx1 = x (0,j ,n2)-x (0,j,n1); dy1 = x (1,j ,n2)-x (1,j,n1); dx2 = xc(0,jp,n )-xc(0,j,n ); dy2 = xc(1,jp,n )-xc(1,j,n ); ds = dx1*dy2-dx2*dy1; if (fabs(ds) < eps) ds = 0.; // on sharp corners qax = 0. else ds = 1./ds; l11 = ds*dy2; l12 =-ds*dy1; l21 =-ds*dx2; l22 = ds*dx1; for (int kk=0; kk<nqaGradQa; kk++){ k = iqagrad(kk); sqa1 = qap(k,j ,n2)-qap(k,j,n1); sqa2 = qa (k,jp,n )-qa (k,j,n ); qax(k,0,j,n) = l11*sqa1+l12*sqa2; qax(k,1,j,n) = l21*sqa1+l22*sqa2; }} j = nPstr+1; jm = nPstr; for (int n=0; n<nFaces-nGfaces; n++){ n1 = face(0,n); n2 = face(1,n); dx1 = x (0,j ,n2)-x (0,j,n1); dy1 = x (1,j ,n2)-x (1,j,n1); dx2 = xc(0,jm,n )-xc(0,j,n ); dy2 = xc(1,jm,n )-xc(1,j,n ); ds = dx1*dy2-dx2*dy1; if (fabs(ds) < eps) ds = 0.; else ds = 1./ds; l11 = ds*dy2; l12 =-ds*dy1; l21 =-ds*dx2; l22 = ds*dx1; for (int kk=0; kk<nqaGradQa; kk++){ k = iqagrad(kk); sqa1 = qap(k,j ,n2)-qap(k,j,n1); sqa2 = qa (k,jm,n )-qa (k,j,n ); qax(k,0,j,n) = l11*sqa1+l12*sqa2; qax(k,1,j,n) = l21*sqa1+l22*sqa2; }} for (int n=nEdges-nBedges; n<nEdges; n++){ c1 = edge(0,n); c2 = edge(1,n); n1 = edgn( n); for (int j=1; j<nPstr+1; j++){ jm = j-1; dx1 = x (0,j,n1)-x (0,jm,n1); dy1 = x (1,j,n1)-x (1,jm,n1); dx2 = xc(0,j,c1)-xc(0,j ,c2); dy2 = xc(1,j,c1)-xc(1,j ,c2); ds = dx1*dy2-dx2*dy1; if (fabs(ds) < eps) ds = 0.; else ds = 1./ds; l11 = ds*dy2; l12 =-ds*dy1; l21 =-ds*dx2; l22 = ds*dx1; for (int kk=0; kk<nqaGradQa; kk++){ k = iqagrad(kk); sqa1 = qap(k,j,n1)-qap(k,jm,n1); sqa2 = qa (k,j,c1)-qa (k,j ,c2); qax(k,0,j,c2) = l11*sqa1+l12*sqa2; qax(k,1,j,c2) = l21*sqa1+l22*sqa2; }}} gradQaFlag = 1; } }
void StrandBlockSolver::rhsViscousFine() { int c1,c2,n1,n2,fc,jm,jp,npts=1; double dx1,dy1,dx2,dy2,ds,dq1,dq2,eps=1.e-14, qxe[nq],qye[nq],qaxe[nqa],qaye[nqa],qe[nq],qae[nqa],fv[nq]; // unstructured faces for (int n=0; n<nEdges; n++){ c1 = edge(0,n); c2 = edge(1,n); n1 = edgn(n); fc = fClip(c1); if (fClip(c2) > fc) fc = fClip(c2); for (int j=1; j<fc+1; j++){ jm = j-1; dx1 = x (0,j,n1)-x (0,jm,n1); dy1 = x (1,j,n1)-x (1,jm,n1); dx2 = xc(0,j,c2)-xc(0,j ,c1); dy2 = xc(1,j,c2)-xc(1,j ,c1); ds = 1./(dx1*dy2-dx2*dy1); for (int k=0; k<nq; k++){ dq1 = qp(k,j,n1)-qp(k,jm,n1); dq2 = q (k,j,c2)-q (k,j ,c1); qxe[k] = ds*( dy2*dq1-dy1*dq2); qye[k] = ds*(-dx2*dq1+dx1*dq2); qe[k] = .5*(qp (k,j,n1)+qp (k,jm,n1)); } for (int k=0; k<nqa; k++){ dq1 = qap(k,j,n1)-qap(k,jm,n1); dq2 = qa (k,j,c2)-qa (k,j ,c1); qaxe[k] = ds*( dy2*dq1-dy1*dq2); qaye[k] = ds*(-dx2*dq1+dx1*dq2); qae[k] = .5*(qap(k,j,n1)+qap(k,jm,n1)); } sys->rhsVisFlux(npts,&facs(0,j,n),&qe[0],&qae[0],&qxe[0],&qye[0], &qaxe[0],&qaye[0],&fv[0]); for (int k=0; k<nq; k++){ r(k,j,c1) -= fv[k]; r(k,j,c2) += fv[k]; }}} // structured faces for (int n=0; n<nFaces-nGfaces; n++){ n1 = face(0,n); n2 = face(1,n); for (int j=0; j<fClip(n)+1; j++){ jp = j+1; dx1 = x (0,j ,n2)-x (0,j,n1); dy1 = x (1,j ,n2)-x (1,j,n1); dx2 = xc(0,jp,n )-xc(0,j,n ); dy2 = xc(1,jp,n )-xc(1,j,n ); ds = dx1*dy2-dx2*dy1; if (fabs(ds) < eps) for (int k=0; k<nq; k++) fv[k] = 0.; else{ ds = 1./ds; for (int k=0; k<nq; k++){ dq1 = qp(k,j ,n2)-qp(k,j,n1); dq2 = q (k,jp,n )-q (k,j,n ); qxe[k] = ds*( dy2*dq1-dy1*dq2); qye[k] = ds*(-dx2*dq1+dx1*dq2); qe[k] = .5*(qp (k,j,n1)+qp (k,j,n2)); } for (int k=0; k<nqa; k++){ dq1 = qap(k,j ,n2)-qap(k,j,n1); dq2 = qa (k,jp,n )-qa (k,j,n ); qaxe[k] = ds*( dy2*dq1-dy1*dq2); qaye[k] = ds*(-dx2*dq1+dx1*dq2); qae[k] = .5*(qap(k,j,n1)+qap(k,j,n2)); } sys->rhsVisFlux(npts,&facu(0,j,n),&qe[0],&qae[0],&qxe[0],&qye[0], &qaxe[0],&qaye[0],&fv[0]); } for (int k=0; k<nq; k++){ r(k,j ,n) -= fv[k]; r(k,jp,n) += fv[k]; }}} }
void StrandBlockSolver::lhsTime(const int& step, const int& pseudoStep) { // compute inviscid and viscous spectral radius specRadi(); specRadv(); // add physical time derivative to LHS if (step > 0){ int jj=1,m; double tj[nq*nq],a=1.5/dtUnsteady,b; for (int n=0; n<nFaces-nGfaces; n++) for (int j=1; j<fClip(n)+1; j++){ b = a*v(j,n); sys->lhsConsVarJacobian(jj,&q(0,j,n),&qa(0,j,n),&tj[0]); for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++) dd(l,k,j,n) = tj[m+l]*b; }}} // compute the pseudo time step using sum of face areas around a cell // in place of volume, and add to LHS int j=nPstr+2,k=nFaces+nBedges,c1,c2,m; double Ax,Ay,A; Array2D<double> ll(j,k); for (int n=0; n<nFaces+nBedges; n++) for (int j=0; j<nPstr+2; j++) ll(j,n) = 0.; for (int n=0; n<nEdges; n++){ c1 = edge(0,n); c2 = edge(1,n); m = fClip(c1); if (fClip(c2) > m) m = fClip(c2); for (int j=1; j<m+1; j++){ Ax = facs(0,j,n); Ay = facs(1,j,n); A = Ax*Ax+Ay*Ay; ll(j,c1)+= A; ll(j,c2)+= A; }} int jp; for (int n=0; n<nFaces-nGfaces; n++){ for (int j=0; j<fClip(n)+1; j++){ jp = j+1; Ax = facu(0,j,n); Ay = facu(1,j,n); A = Ax*Ax+Ay*Ay; ll(j ,n)+= A; ll(jp,n)+= A; }} // CFL and VNN ramping double cflT,vnnT; if (pseudoStep > nRamp){ cflT = cfl; vnnT = vnn; } else{ cflT = cfl0+(cfl-cfl0)/((double)nRamp)*((double)pseudoStep); vnnT = vnn0+(vnn-vnn0)/((double)nRamp)*((double)pseudoStep); } for (int n=0; n<nFaces+nBedges; n++) for (int j=0; j<nPstr+2; j++) dt(j,n) = 0; if (inviscid == 1){ for (int n=0; n<nFaces-nGfaces; n++) for (int j=0; j<fClip(n)+1; j++) dt(j,n) = radi(j,n)/cflT; } if (viscous == 1){ double a; for (int n=0; n<nFaces-nGfaces; n++) for (int j=0; j<fClip(n)+1; j++){ a = radv(j,n)/vnnT; if (a > dt(j,n)) dt(j,n) = a; } } for (int n=0; n<nFaces-nGfaces; n++) //for (int j=0; j<fClip(n)+1; j++) dt(j,n) = ll(j,n)/dt(j,n); for (int j=0; j<fClip(n)+1; j++) dt(j,n) = v(j,n)/dt(j,n); int jj=1; double pj[nq*nq],a; for (int n=0; n<nFaces-nGfaces; n++) for (int j=0; j<fClip(n)+1; j++){ sys->lhsPreconJacobian(jj,&q(0,j,n),&qa(0,j,n),&pj[0]); a = v(j,n)/dt(j,n); for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++) dd(l,k,j,n) += pj[m+l]*a; }} ll.deallocate(); }
void StrandBlockSolver::shiftTime(const int& step, const int& mglevel) { if (mglevel == 0){ // fine MG level cout << "\n*** Preparing to solve step " << step << " ***" << endl; cout << "physical time " << double(step)*dtUnsteady << endl; cout << "time step " << dtUnsteady << endl; // advance q, v, and x if (step == 1){ for (int n=0; n<nFaces+nBedges; n++) for (int j=0; j<nPstr+2; j++){ for (int k=0; k<nq; k++){ q1(k,j,n) = q(k,j,n); q2(k,j,n) = q(k,j,n); } v2(j,n) = v(j,n); v1(j,n) = v(j,n); } for (int n=0; n<nNodes; n++) for (int j=0; j<nPstr+1; j++){ for (int k=0; k<ndim; k++){ x0(k,j,n) = x(k,j,n); x1(k,j,n) = x(k,j,n); x2(k,j,n) = x(k,j,n); }} } else{ for (int n=0; n<nFaces+nBedges; n++) for (int j=0; j<nPstr+2; j++){ for (int k=0; k<nq; k++){ q2(k,j,n) = q1(k,j,n); q1(k,j,n) = q(k,j,n); } v2(j,n) = v1(j,n); v1(j,n) = v(j,n); } for (int n=0; n<nNodes; n++) for (int j=0; j<nPstr+1; j++){ for (int k=0; k<ndim; k++){ x2(k,j,n) = x1(k,j,n); x1(k,j,n) = x(k,j,n); //x(k,j,n) = ?; }} } // compute face areas, cell-centers, and volumes facearea_(pid, ndim, nFaces, nGfaces, nNodes, nGnodes, nEdges, nBedges, nPstr, &face(0,0), &edge(0,0), &edgn(0), &x(0,0,0), &facs(0,0,0), &facu(0,0,0)); cellcoord_(pid, ndim, nFaces, nGfaces, nNodes, nGnodes, nEdges, nBedges, nPstr, &face(0,0), &edge(0,0), &edgn(0), &x(0,0,0), &facs(0,0,0), &facu(0,0,0), &xc(0,0,0)); volume_(pid, ndim, nFaces, nGfaces, nNodes, nGnodes, nEdges, nBedges, nPstr, &face(0,0), &edge(0,0), &edgn(0), &fClip(0), &x(0,0,0), &facs(0,0,0), &facu(0,0,0), &xc(0,0,0), &v(0,0)); // compute least squares coefficients if (nodeVal == 1) lspVol(); else if (nodeVal == 2) lspLS(); else if (nodeVal == 3) lspMap(); else{ cout << "\nvalue of nodeVal not recognized" << endl; exit(0); } } else{ // coarse MG level // compute coarse level face areas and volumes coarseMetrics(); } // face velocities cout << "\n*** face velocity computation not yet implemented ***" << endl; }
void StrandBlockSolver::lhsDissipation() { int jj=nPstr+2,nn=nFaces+nBedges; Array4D<double> aa(nq,nq,jj,nn); for (int n=0; n<nFaces+nBedges; n++) for (int j=0; j<nPstr+2; j++) for (int k=0; k<nq; k++) for (int l=0; l<nq; l++) aa(l,k,j,n) = 0.; // unstructured faces int c1,c2,n1,n2,jp,fc,m,mm,m1l,m1u,m2l,m2u,npts=1; double a[nq*nq]; for (int n=0; n<nEdges; n++){ c1 = edge(0,n); c2 = edge(1,n); m1l = ncsc(c1 ); m1u = ncsc(c1+1); m2l = ncsc(c2 ); m2u = ncsc(c2+1); fc = fClip(c1); if (fClip(c2) > fc) fc = fClip(c2); for (int j=1; j<fc+1; j++){ sys->lhsDisFluxJacobian(npts,&facs(0,j,n),&xvs(j,n), &q(0,j,c1),&q(0,j,c2),&a[0]); for (int k=0; k<nq*nq; k++) a[k] *= .5; // diagonal contributions for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++){ dd(l,k,j,c1) += a[m+l]; dd(l,k,j,c2) += a[m+l]; }} // off-diagonal contributions for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++){ aa(l,k,j,c1) = a[m+l]; aa(l,k,j,c2) = a[m+l]; }} for (int mm=m1l; mm<m1u; mm++){ nn = csc(mm); for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++) bu(l,k,j,mm) -= aa(l,k,j,nn); }} for (int mm=m2l; mm<m2u; mm++){ nn = csc(mm); for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++) bu(l,k,j,mm) -= aa(l,k,j,nn); }} // reset working array to zero for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++){ aa(l,k,j,c1) = 0.; aa(l,k,j,c2) = 0.; }} }} aa.deallocate(); // structured faces double Ax,Ay,ds,eps=1.e-14; for (int n=0; n<nFaces-nGfaces; n++){ n1 = face(0,n); n2 = face(1,n); for (int j=0; j<fClip(n)+1; j++){ jp = j+1; Ax = facu(0,j,n); Ay = facu(1,j,n); ds = Ax*Ax+Ay*Ay; if (fabs(ds) < eps){ for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++) a[m+l] = 0.; }} else sys->lhsDisFluxJacobian(npts,&facu(0,j,n),&xvu(j,n), &q(0,j,n),&q(0,jp,n),&a[0]); for (int k=0; k<nq; k++){ m = k*nq; for (int l=0; l<nq; l++){ dd(l,k,j ,n) += (a[m+l]*.5); dp(l,k,j ,n) -= (a[m+l]*.5); dd(l,k,jp,n) += (a[m+l]*.5); dm(l,k,jp,n) -= (a[m+l]*.5); }}}} }