IdentifierModel<Adapter>::IdentifierModel( const RCP<const Adapter> &ia, const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, modelFlag_t &modelFlags): numGlobalIdentifiers_(), env_(env), comm_(comm), gids_(), nUserWeights_(0), weights_() { // Get the local and global problem size size_t nLocalIds = ia->getLocalNumIDs(); gno_t lsum = nLocalIds; reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_SUM, 1, &lsum, &numGlobalIdentifiers_); // Get the number of weights // Use max number of weights over all processes as nUserWeights_ int tmp = ia->getNumWeightsPerID(); Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, 1, &tmp, &nUserWeights_); // Prepare to store views from input adapter // TODO: Do we have to store these views, or can we get them on an // TODO: as-needed basis? Array<const scalar_t *> wgts(nUserWeights_, (const scalar_t *)NULL); Array<int> wgtStrides(nUserWeights_, 0); if (nUserWeights_ > 0){ input_t *w = new input_t [nUserWeights_]; weights_ = arcp<input_t>(w, 0, nUserWeights_); } const gno_t *gids=NULL; // Get the input adapter's views try{ ia->getIDsView(gids); for (int idx=0; idx < nUserWeights_; idx++) ia->getWeightsView(wgts[idx], wgtStrides[idx], idx); } Z2_FORWARD_EXCEPTIONS; if (nLocalIds){ gids_ = arcp(gids, 0, nLocalIds, false); if (nUserWeights_ > 0){ for (int idx=0; idx < nUserWeights_; idx++){ ArrayRCP<const scalar_t> wgtArray(wgts[idx], 0, nLocalIds*wgtStrides[idx], false); weights_[idx] = input_t(wgtArray, wgtStrides[idx]); } } } env_->memory("After construction of identifier model"); }
LDFE_quad::LDFE_quad(int param) { /* Calculate number of LDFE ranges */ order = param; // Quadrature order int num_LDFE = 2 * pow(2, order); // Number of LDFE regions /* Calculate quadrature directions */ double delta_gamma = (pi / num_LDFE) / 4.0; // Gamma from node to nearest LDFE edge double gamma_current = 0.0; mat gamma(num_LDFE, 2); for (int i=0; i<num_LDFE; i++) { gamma(i, 0) = gamma_current + delta_gamma; // Left node gamma gamma(i, 1) = gamma(i, 0) + 2.0 * delta_gamma; // Right node gamma gamma_current = gamma_current + 4.0 * delta_gamma; } /* Solve the basis functions of each LDFE range */ mat A = mat(2, 2); mat B = eye<mat>(2, 2); mat C = mat(3, 3); vec wgt = vec(2); wgts.set_size(num_LDFE, 2); // Resize matrix storing all LDFE range weights dirs.set_size(num_LDFE, 2); // Resize matrix storing all LDFE range directions basis.resize(num_LDFE); // Resize vector storing all LDFE basis functions for (int i=0; i<num_LDFE; i++){ for (int j=0; j<2; j++){ A(j, 0) = 1.0; A(j, 1) = cos(gamma(i, j)); } C = solve(A, B); // Solve for the basis functions /* Solve for the weights of each LDFE range */ double gamma_max = gamma(i, 1) + delta_gamma; double gamma_min = gamma(i, 0) - delta_gamma; for (int j=0; j<2; j++){ wgt(j) = C(0, j) * (gamma_max - gamma_min) + \ C(1, j) * (sin(gamma_max) - sin(gamma_min)); } /* Store quadrature directions, weights and basis functions */ for (int j=0; j<2; j++) { dirs(i, j) = cos(gamma(i, j)); wgts(i, j) = wgt(j) / pi * 2.0; } basis[i] = C; } }
LDFE_quad_eq::LDFE_quad_eq(int param) { /* Calculate number of LDFE ranges */ order = param; // Quadrature order int num_LDFE = 2 * pow(2, order); // Number of LDFE regions /* Calculate even quadrature weights */ double delta_gamma = pi / num_LDFE; double wgt_even = delta_gamma / 2.0; /* Initialize common parameters */ double gamma_current = 0.0; double gamma_min; double gamma_max; double gamma_center; vec dir = vec(2); mat A = mat(2, 2); mat B = eye<mat>(2, 2); mat C = mat(3, 3); vec wgt = vec(2); wgts.set_size(num_LDFE, 2); // Resize matrix storing all LDFE range weights dirs.set_size(num_LDFE, 2); // Resize matrix storing all LDFE range directions basis.resize(num_LDFE); // Resize vector storing all LDFE basis functions double RE_old; double RE_new; double ratio_old; double ratio_new; double ratio_temp; int converged; int iter_counter; double delta; for (int r=0; r<num_LDFE; r++) { /* First quadrature direction guess */ gamma_min = gamma_current; gamma_max = gamma_current + delta_gamma; gamma_current = gamma_max; gamma_center = (gamma_max + gamma_min) / 2.0; ratio_old = 0.5; dir(0) = gamma_center - ratio_old * delta_gamma / 2.0; dir(1) = gamma_center + ratio_old * delta_gamma / 2.0; /* Solve for basis functions */ for (int j=0; j<2; j++){ A(j, 0) = 1.0; A(j, 1) = cos(dir(j)); } C = solve(A, B); // Solve for the basis functions /* Solve for weights */ for (int j=0; j<2; j++){ wgt(j) = C(0, j) * (gamma_max - gamma_min) + \ C(1, j) * (sin(gamma_max) - sin(gamma_min)); } /* Calculate relative error using first direction guess */ RE_old = (wgt(0) - wgt_even) / wgt_even; /* Second ratio guess */ ratio_new = 0.75; /* Iterate until weights are equal */ converged = 0; iter_counter = 0; while (converged == 0 && iter_counter < 100) { /* New quadrature directions */ dir(0) = gamma_center - ratio_new * delta_gamma / 2.0; dir(1) = gamma_center + ratio_new * delta_gamma / 2.0; /* New quadrature basis functions */ for (int j=0; j<2; j++){ A(j, 0) = 1.0; A(j, 1) = cos(dir(j)); } C = solve(A, B); // Solve for the basis functions /* New quadrature weights */ for (int j=0; j<2; j++){ wgt(j) = C(0, j) * (gamma_max - gamma_min) + \ C(1, j) * (sin(gamma_max) - sin(gamma_min)); } /* Calculate new relative error */ RE_new = (wgt(0) - wgt_even) / wgt_even; /* Calculate next direction guess */ if (RE_old == RE_new && iter_counter == 1) { ratio_temp = ratio_new; ratio_new = (ratio_old + ratio_new) / 2.0; ratio_old = ratio_temp; iter_counter++; } else { delta = ((ratio_new - ratio_old) / (RE_new - RE_old)) * RE_new; /* Check for convergence */ if (abs(delta) < 1.e-12) { converged = 1; } else { RE_old = RE_new; ratio_old = ratio_new; ratio_new = ratio_new - delta; iter_counter++; } } } /* Store quadrature directions, weights and basis functions */ for (int j=0; j<2; j++) { dirs(r, j) = cos(dir(j)); wgts(r, j) = wgt(j) / pi * 2.0; } basis[r] = C; } }
IdentifierModel<IdentifierInput<User> >::IdentifierModel( const IdentifierInput<User> *ia, const RCP<const Environment> &env, const RCP<const Comm<int> > &comm, modelFlag_t &modelFlags): gnosAreGids_(false), numGlobalIdentifiers_(), env_(env), comm_(comm), gids_(), userWeightDim_(0), weights_(), gnos_(), gnosConst_() { userWeightDim_ = ia->getNumberOfWeights(); size_t nLocalIds = ia->getLocalNumberOfIdentifiers(); Model<IdentifierInput<User> >::maxCount(*comm, userWeightDim_); Array<const scalar_t *> wgts(userWeightDim_, (const scalar_t *)NULL); Array<int> wgtStrides(userWeightDim_, 0); Array<lno_t> weightArrayLengths(userWeightDim_, 0); if (userWeightDim_ > 0){ input_t *w = new input_t [userWeightDim_]; weights_ = arcp<input_t>(w, 0, userWeightDim_); } const gid_t *gids=NULL; try{ ia->getIdentifierList(gids); for (int dim=0; dim < userWeightDim_; dim++) ia->getIdentifierWeights(dim, wgts[dim], wgtStrides[dim]); } Z2_FORWARD_EXCEPTIONS; if (nLocalIds){ gids_ = arcp(gids, 0, nLocalIds, false); if (userWeightDim_ > 0){ for (int i=0; i < userWeightDim_; i++){ if (wgts[i] != NULL){ ArrayRCP<const scalar_t> wgtArray( wgts[i], 0, nLocalIds*wgtStrides[i], false); weights_[i] = input_t(wgtArray, wgtStrides[i]); weightArrayLengths[i] = nLocalIds; } } } } this->setWeightArrayLengths(weightArrayLengths, *comm_); RCP<const idmap_t> idMap; try{ if (modelFlags.test(IDS_MUST_BE_GLOBALLY_CONSECUTIVE)) idMap = rcp(new idmap_t(env_, comm_, gids_, true)); else idMap = rcp(new idmap_t(env_, comm_, gids_, false)); } Z2_FORWARD_EXCEPTIONS; gnosAreGids_ = idMap->gnosAreGids(); this->setIdentifierMap(idMap); gno_t lsum = nLocalIds; reduceAll<int, gno_t>(*comm_, Teuchos::REDUCE_SUM, 1, &lsum, &numGlobalIdentifiers_); if (!gnosAreGids_ && nLocalIds>0){ gno_t *tmpGno = new gno_t [nLocalIds]; env_->localMemoryAssertion(__FILE__, __LINE__, nLocalIds, tmpGno); gnos_ = arcp(tmpGno, 0, nLocalIds); try{ ArrayRCP<gid_t> gidsNonConst = arcp_const_cast<gid_t>(gids_); idMap->gidTranslate( gidsNonConst(0,nLocalIds), gnos_(0,nLocalIds), TRANSLATE_APP_TO_LIB); } Z2_FORWARD_EXCEPTIONS; }
// All-purpose routine for computing the L2-projection // of various functions onto the gradient of the Legendre basis // (Unstructured grid version) // void L2ProjectGrad_Unst( const dTensor2* vel_vec, const int istart, const int iend, const int QuadOrder, const int BasisOrder_qin, const int BasisOrder_auxin, const int BasisOrder_fout, const mesh& Mesh, const dTensor3* qin, const dTensor3* auxin, dTensor3* fout, void (*Func)(const dTensor2* vel_vec, const dTensor2&,const dTensor2&, const dTensor2&,dTensor3&)) { // starting and ending indeces const int NumElems = Mesh.get_NumElems(); assert_ge(istart,1); assert_le(iend,NumElems); // qin variable assert_eq(NumElems,qin->getsize(1)); const int meqn = qin->getsize(2); const int kmax_qin = qin->getsize(3); assert_eq(kmax_qin,(BasisOrder_qin*(BasisOrder_qin+1))/2); // auxin variable assert_eq(NumElems,auxin->getsize(1)); const int maux = auxin->getsize(2); const int kmax_auxin = auxin->getsize(3); assert_eq(kmax_auxin,(BasisOrder_auxin*(BasisOrder_auxin+1))/2); // fout variables assert_eq(NumElems,fout->getsize(1)); const int mcomps_out = fout->getsize(2); const int kmax_fout = fout->getsize(3); assert_eq(kmax_fout,(BasisOrder_fout*(BasisOrder_fout+1))/2); // number of quadrature points assert_ge(QuadOrder,1); assert_le(QuadOrder,5); int mpoints; switch ( QuadOrder ) { case 1: mpoints = 0; break; case 2: mpoints = 1; break; case 3: mpoints = 6; break; case 4: mpoints = 7; break; case 5: mpoints = 16; break; } // trivial case if ( QuadOrder==1 ) { for (int i=istart; i<=iend; i++) for (int m=1; m<=mcomps_out; m++) for (int k=1; k<=kmax_fout; k++) { fout->set(i,m,k, 0.0 ); } } else { const int kmax = iMax(iMax(kmax_qin,kmax_auxin),kmax_fout); dTensor2 spts(mpoints,2); dTensor1 wgts(mpoints); dTensor2 xpts(mpoints,2); dTensor2 qvals(mpoints,meqn); dTensor2 auxvals(mpoints,maux); dTensor3 fvals(mpoints,mcomps_out,2); dTensor2 mu(mpoints,kmax); // monomial basis (non-orthogonal) dTensor2 phi(mpoints,kmax); // Legendre basis (orthogonal) dTensor2 mu_xi(mpoints,kmax_fout); // xi-derivative of monomial basis (non-orthogonal) dTensor2 mu_eta(mpoints,kmax_fout); // eta-derivative of monomial basis (non-orthogonal) dTensor2 phi_xi(mpoints,kmax_fout); // xi-derivative of Legendre basis (orthogonal) dTensor2 phi_eta(mpoints,kmax_fout); // eta-derivative of Legendre basis (orthogonal) dTensor2 phi_x(mpoints,kmax_fout); // x-derivative of Legendre basis (orthogonal) dTensor2 phi_y(mpoints,kmax_fout); // y-derivative of Legendre basis (orthogonal) switch ( QuadOrder ) { case 2: spts.set(1,1, 0.0 ); spts.set(1,2, 0.0 ); wgts.set(1, 0.5 ); break; case 3: spts.set(1,1, 0.112615157582632 ); spts.set(1,2, 0.112615157582632 ); spts.set(2,1, -0.225230315165263 ); spts.set(2,2, 0.112615157582632 ); spts.set(3,1, 0.112615157582632 ); spts.set(3,2, -0.225230315165263 ); spts.set(4,1, -0.241757119823562 ); spts.set(4,2, -0.241757119823562 ); spts.set(5,1, 0.483514239647126 ); spts.set(5,2, -0.241757119823562 ); spts.set(6,1, -0.241757119823562 ); spts.set(6,2, 0.483514239647126 ); wgts.set(1, 0.1116907948390055 ); wgts.set(2, 0.1116907948390055 ); wgts.set(3, 0.1116907948390055 ); wgts.set(4, 0.0549758718276610 ); wgts.set(5, 0.0549758718276610 ); wgts.set(6, 0.0549758718276610 ); break; case 4: spts.set(1,1, 0.000000000000000 ); spts.set(1,2, 0.000000000000000 ); spts.set(2,1, 0.136808730771782 ); spts.set(2,2, 0.136808730771782 ); spts.set(3,1, -0.273617461543563 ); spts.set(3,2, 0.136808730771782 ); spts.set(4,1, 0.136808730771782 ); spts.set(4,2, -0.273617461543563 ); spts.set(5,1, -0.232046826009877 ); spts.set(5,2, -0.232046826009877 ); spts.set(6,1, 0.464093652019754 ); spts.set(6,2, -0.232046826009877 ); spts.set(7,1, -0.232046826009877 ); spts.set(7,2, 0.464093652019754 ); wgts.set(1, 0.1125000000000000 ); wgts.set(2, 0.0661970763942530 ); wgts.set(3, 0.0661970763942530 ); wgts.set(4, 0.0661970763942530 ); wgts.set(5, 0.0629695902724135 ); wgts.set(6, 0.0629695902724135 ); wgts.set(7, 0.0629695902724135 ); break; case 5: spts.set(1,1, 0.000000000000000 ); spts.set(1,2, 0.000000000000000 ); spts.set(2,1, 0.125959254959390 ); spts.set(2,2, 0.125959254959390 ); spts.set(3,1, -0.251918509918779 ); spts.set(3,2, 0.125959254959390 ); spts.set(4,1, 0.125959254959390 ); spts.set(4,2, -0.251918509918779 ); spts.set(5,1, -0.162764025581573 ); spts.set(5,2, -0.162764025581573 ); spts.set(6,1, 0.325528051163147 ); spts.set(6,2, -0.162764025581573 ); spts.set(7,1, -0.162764025581573 ); spts.set(7,2, 0.325528051163147 ); spts.set(8,1, -0.282786105016302 ); spts.set(8,2, -0.282786105016302 ); spts.set(9,1, 0.565572210032605 ); spts.set(9,2, -0.282786105016302 ); spts.set(10,1, -0.282786105016302 ); spts.set(10,2, 0.565572210032605 ); spts.set(11,1, -0.324938555923375 ); spts.set(11,2, -0.070220503698695 ); spts.set(12,1, -0.324938555923375 ); spts.set(12,2, 0.395159059622071 ); spts.set(13,1, -0.070220503698695 ); spts.set(13,2, -0.324938555923375 ); spts.set(14,1, -0.070220503698695 ); spts.set(14,2, 0.395159059622071 ); spts.set(15,1, 0.395159059622071 ); spts.set(15,2, -0.324938555923375 ); spts.set(16,1, 0.395159059622071 ); spts.set(16,2, -0.070220503698695 ); wgts.set(1, 0.0721578038388935 ); wgts.set(2, 0.0475458171336425 ); wgts.set(3, 0.0475458171336425 ); wgts.set(4, 0.0475458171336425 ); wgts.set(5, 0.0516086852673590 ); wgts.set(6, 0.0516086852673590 ); wgts.set(7, 0.0516086852673590 ); wgts.set(8, 0.0162292488115990 ); wgts.set(9, 0.0162292488115990 ); wgts.set(10, 0.0162292488115990 ); wgts.set(11, 0.0136151570872175 ); wgts.set(12, 0.0136151570872175 ); wgts.set(13, 0.0136151570872175 ); wgts.set(14, 0.0136151570872175 ); wgts.set(15, 0.0136151570872175 ); wgts.set(16, 0.0136151570872175 ); break; } // Loop over each quadrature point and construct monomial polys for (int m=1; m<=mpoints; m++) { // coordinates const double xi = spts.get(m,1); const double xi2 = xi*xi; const double xi3 = xi2*xi; const double xi4 = xi3*xi; const double eta = spts.get(m,2); const double eta2 = eta*eta; const double eta3 = eta2*eta; const double eta4 = eta3*eta; // monomial basis functions at each gaussian quadrature point switch( kmax ) { case 15: // fifth order mu.set(m, 15, eta4 ); mu.set(m, 14, xi4 ); mu.set(m, 13, xi2*eta2 ); mu.set(m, 12, eta3*xi ); mu.set(m, 11, xi3*eta ); case 10: // fourth order mu.set(m, 10, eta3 ); mu.set(m, 9, xi3 ); mu.set(m, 8, xi*eta2 ); mu.set(m, 7, eta*xi2 ); case 6: // third order mu.set(m, 6, eta2 ); mu.set(m, 5, xi2 ); mu.set(m, 4, xi*eta ); case 3: // second order mu.set(m, 3, eta ); mu.set(m, 2, xi ); case 1: // first order mu.set(m, 1, 1.0 ); break; } // Loop over each quadrature point and construct Legendre polys for (int i=1; i<=kmax; i++) { double tmp = 0.0; for (int j=1; j<=i; j++) { tmp = tmp + Mmat[i-1][j-1]*mu.get(m,j); } phi.set(m,i, tmp ); } // Gradient of monomial basis functions at each gaussian quadrature point switch( kmax_fout ) { case 15: // fifth order mu_xi.set( m,15, 0.0 ); mu_xi.set( m,14, 4.0*xi3 ); mu_xi.set( m,13, 2.0*xi*eta2 ); mu_xi.set( m,12, eta3 ); mu_xi.set( m,11, 3.0*xi2*eta ); mu_eta.set( m,15, 4.0*eta3 ); mu_eta.set( m,14, 0.0 ); mu_eta.set( m,13, 2.0*xi2*eta ); mu_eta.set( m,12, 3.0*eta2*xi ); mu_eta.set( m,11, xi3 ); case 10: // fourth order mu_xi.set( m,10, 0.0 ); mu_xi.set( m,9, 3.0*xi2 ); mu_xi.set( m,8, eta2 ); mu_xi.set( m,7, 2.0*eta*xi ); mu_eta.set( m,10, 3.0*eta2 ); mu_eta.set( m,9, 0.0 ); mu_eta.set( m,8, 2.0*eta*xi ); mu_eta.set( m,7, xi2 ); case 6: // third order mu_xi.set( m,6, 0.0 ); mu_xi.set( m,5, 2.0*xi ); mu_xi.set( m,4, eta ); mu_eta.set( m,6, 2.0*eta ); mu_eta.set( m,5, 0.0 ); mu_eta.set( m,4, xi ); case 3: // second order mu_xi.set( m,3, 0.0 ); mu_xi.set( m,2, 1.0 ); mu_eta.set( m,3, 1.0 ); mu_eta.set( m,2, 0.0 ); case 1: // first order mu_xi.set( m,1, 0.0 ); mu_eta.set( m,1, 0.0 ); break; } // Loop over each quadrature point and construct Legendre polys for (int i=1; i<=kmax_fout; i++) { double tmp1 = 0.0; double tmp2 = 0.0; for (int j=1; j<=i; j++) { tmp1 = tmp1 + Mmat[i-1][j-1]*mu_xi.get(m,j); tmp2 = tmp2 + Mmat[i-1][j-1]*mu_eta.get(m,j); } phi_xi.set(m,i, tmp1 ); phi_eta.set(m,i, tmp2 ); } } // ------------------------------------------------------------- // Loop over every grid cell indexed by user supplied parameters // described by istart...iend // ------------------------------------------------------------- #pragma omp parallel for for (int i=istart; i<=iend; i++) { // Find center of current cell const int i1 = Mesh.get_tnode(i,1); const int i2 = Mesh.get_tnode(i,2); const int i3 = Mesh.get_tnode(i,3); const double x1 = Mesh.get_node(i1,1); const double y1 = Mesh.get_node(i1,2); const double x2 = Mesh.get_node(i2,1); const double y2 = Mesh.get_node(i2,2); const double x3 = Mesh.get_node(i3,1); const double y3 = Mesh.get_node(i3,2); const double xc = (x1+x2+x3)/3.0; const double yc = (y1+y2+y3)/3.0; // Compute q, aux and fvals at each Gaussian Quadrature point // for this current cell indexed by (i,j) // Save results into dTensor2 qvals, auxvals and fvals. for (int m=1; m<=mpoints; m++) { // convert phi_xi and phi_eta derivatives // to phi_x and phi_y derivatives through Jacobian for (int k=1; k<=kmax_fout; k++) { phi_x.set(m,k, Mesh.get_jmat(i,1,1)*phi_xi.get(m,k) + Mesh.get_jmat(i,1,2)*phi_eta.get(m,k) ); phi_y.set(m,k, Mesh.get_jmat(i,2,1)*phi_xi.get(m,k) + Mesh.get_jmat(i,2,2)*phi_eta.get(m,k) ); } // point on the unit triangle const double s = spts.get(m,1); const double t = spts.get(m,2); // point on the physical triangle xpts.set(m,1, xc + (x2-x1)*s + (x3-x1)*t ); xpts.set(m,2, yc + (y2-y1)*s + (y3-y1)*t ); // Solution values (q) at each grid point for (int me=1; me<=meqn; me++) { qvals.set(m,me, 0.0 ); for (int k=1; k<=kmax_qin; k++) { qvals.set(m,me, qvals.get(m,me) + phi.get(m,k) * qin->get(i,me,k) ); } } // Auxiliary values (aux) at each grid point for (int ma=1; ma<=maux; ma++) { auxvals.set(m,ma, 0.0 ); for (int k=1; k<=kmax_auxin; k++) { auxvals.set(m,ma, auxvals.get(m,ma) + phi.get(m,k) * auxin->get(i,ma,k) ); } } } // Call user-supplied function to set fvals Func(vel_vec, xpts, qvals, auxvals, fvals); // Evaluate integral on current cell (project onto Legendre basis) // using Gaussian Quadrature for the integration for (int m1=1; m1<=mcomps_out; m1++) for (int m2=1; m2<=kmax_fout; m2++) { double tmp = 0.0; for (int k=1; k<=mpoints; k++) { tmp = tmp + wgts.get(k)* ( fvals.get(k,m1,1)*phi_x.get(k,m2) + fvals.get(k,m1,2)*phi_y.get(k,m2) ); } fout->set(i, m1, m2, 2.0*tmp ); } } } }
void ConstructA_CG2(const mesh& Mesh, FullMatrix& A) { const int NumPhysElems = Mesh.get_NumPhysElems(); const int NumBndNodes = Mesh.get_SubNumBndNodes(); const int Asize = Mesh.get_SubNumPhysNodes(); assert_eq(Asize,A.get_NumRows()); assert_eq(Asize,A.get_NumCols()); dTensor1 A1(6); dTensor1 A2(6); dTensor1 A3(6); dTensor1 A4(6); dTensor1 A5(6); dTensor1 A6(6); A1.set(1, -oneninth ); A1.set(2, 4.0*oneninth ); A1.set(3, -oneninth ); A1.set(4, 4.0*oneninth ); A1.set(5, 4.0*oneninth ); A1.set(6, -oneninth ); A2.set(1, -onethird ); A2.set(2, 0.0 ); A2.set(3, onethird ); A2.set(4, -4.0*onethird ); A2.set(5, 4.0*onethird ); A2.set(6, 0.0 ); A3.set(1, -onethird ); A3.set(2, -4.0*onethird ); A3.set(3, 0.0 ); A3.set(4, 0.0 ); A3.set(5, 4.0*onethird ); A3.set(6, onethird ); A4.set(1, 4.0 ); A4.set(2, -4.0 ); A4.set(3, 0.0 ); A4.set(4, -4.0 ); A4.set(5, 4.0 ); A4.set(6, 0.0 ); A5.set(1, 2.0 ); A5.set(2, -4.0 ); A5.set(3, 2.0 ); A5.set(4, 0.0 ); A5.set(5, 0.0 ); A5.set(6, 0.0 ); A6.set(1, 2.0 ); A6.set(2, 0.0 ); A6.set(3, 0.0 ); A6.set(4, -4.0 ); A6.set(5, 0.0 ); A6.set(6, 2.0 ); dTensor2 spts(3,2); spts.set(1,1, 1.0/3.0 ); spts.set(1,2, -1.0/6.0 ); spts.set(2,1, -1.0/6.0 ); spts.set(2,2, -1.0/6.0 ); spts.set(3,1, -1.0/6.0 ); spts.set(3,2, 1.0/3.0 ); dTensor1 wgts(3); wgts.set(1, 1.0/6.0 ); wgts.set(2, 1.0/6.0 ); wgts.set(3, 1.0/6.0 ); // Loop over all elements in the mesh for (int i=1; i<=NumPhysElems; i++) { // Information for element i iTensor1 tt(6); for (int k=1; k<=6; k++) { tt.set(k, Mesh.get_node_subs(i,k) ); } // Evaluate gradients of the Lagrange polynomials on Gauss quadrature points dTensor2 gpx(6,3); dTensor2 gpy(6,3); for (int m=1; m<=3; m++) { double xi = spts.get(m,1); double eta = spts.get(m,2); for (int k=1; k<=6; k++) { double gp_xi = A2.get(k) + 2.0*A5.get(k)*xi + A4.get(k)*eta; double gp_eta = A3.get(k) + A4.get(k)*xi + 2.0*A6.get(k)*eta; gpx.set(k,m, Mesh.get_jmat(i,1,1)*gp_xi + Mesh.get_jmat(i,1,2)*gp_eta ); gpy.set(k,m, Mesh.get_jmat(i,2,1)*gp_xi + Mesh.get_jmat(i,2,2)*gp_eta ); } } // Entries of the stiffness matrix A double Area = Mesh.get_area_prim(i); for (int j=1; j<=6; j++) for (int k=1; k<=6; k++) { double tmp = A.get(tt.get(j),tt.get(k)); for (int m=1; m<=3; m++) { tmp = tmp + 2.0*Area*wgts.get(m)*(gpx.get(j,m)*gpx.get(k,m)+gpy.get(j,m)*gpy.get(k,m)); } A.set(tt.get(j),tt.get(k), tmp ); } } // Replace boundary node equations by Dirichlet boundary condition enforcement for (int i=1; i<=NumBndNodes; i++) { const int j=Mesh.get_sub_bnd_node(i); for (int k=1; k<=A.get_NumCols(); k++) { A.set(j,k, 0.0 ); } for (int k=1; k<=A.get_NumRows(); k++) { A.set(k,j, 0.0 ); } A.set(j,j, 1.0 ); } // Get sparse structure representation A.Sparsify(); }
// Modified version of the all purpose routine L2Project specifically written // for projecting the "time-averaged" flux function onto the basis function. // // This routine also returns the coefficients of the Lax Wendroff Flux // Function when expanded with legendre basis functions, and therefore the // basis expansions produced by this routine can be used for all of the // Riemann solves. // // --------------------------------------------------------------------- // Inputs should have the following sizes: // TODO - document the inputs here // --------------------------------------------------------------------- void L2ProjectLxW_Unst( const int mterms, const double alpha, const double beta_dt, const double charlie_dt, const int istart, const int iend, // Start-stop indices const int QuadOrder, const int BasisOrder_qin, const int BasisOrder_auxin, const int BasisOrder_fout, const mesh& Mesh, const dTensor3* qin, const dTensor3* auxin, // state vector dTensor3* F, dTensor3* G, // time-averaged Flux function void FluxFunc (const dTensor2& xpts, const dTensor2& Q, const dTensor2& Aux, dTensor3& flux), void DFluxFunc (const dTensor2& xpts, const dTensor2& Q, const dTensor2& aux, dTensor4& Dflux), void D2FluxFunc (const dTensor2& xpts, const dTensor2& Q, const dTensor2& aux, dTensor5& D2flux) ) { if( fabs( alpha ) < 1e-14 && fabs( beta_dt ) < 1e-14 && fabs( charlie_dt ) < 1e-14 ) { F->setall(0.); G->setall(0.); return; } // starting and ending indices const int NumElems = Mesh.get_NumElems(); assert_ge(istart,1); assert_le(iend,NumElems); // qin variable assert_eq(NumElems,qin->getsize(1)); const int meqn = qin->getsize(2); const int kmax_qin = qin->getsize(3); assert_eq(kmax_qin,(BasisOrder_qin*(BasisOrder_qin+1))/2); // auxin variable assert_eq(NumElems,auxin->getsize(1)); const int maux = auxin->getsize(2); const int kmax_auxin = auxin->getsize(3); assert_eq(kmax_auxin,(BasisOrder_auxin*(BasisOrder_auxin+1))/2); // fout variables assert_eq(NumElems, F->getsize(1)); const int mcomps_out = F->getsize(2); const int kmax_fout = F->getsize(3); assert_eq(kmax_fout, (BasisOrder_fout*(BasisOrder_fout+1))/2 ); // number of quadrature points assert_ge(QuadOrder, 1); assert_le(QuadOrder, 5); // Number of quadrature points int mpoints; switch( QuadOrder ) { case 1: mpoints = 1; break; case 2: mpoints = 3; break; case 3: mpoints = 6; break; case 4: mpoints = 12; break; case 5: mpoints = 16; break; } const int kmax = iMax(iMax(kmax_qin, kmax_auxin), kmax_fout); dTensor2 phi(mpoints, kmax); // Legendre basis (orthogonal) dTensor2 spts(mpoints, 2); // List of quadrature points dTensor1 wgts(mpoints); // List of quadrature weights setQuadPoints_Unst( QuadOrder, wgts, spts ); // ---------------------------------------------------------------------- // // Evaluate the basis functions at each point SetLegendreAtPoints_Unst(spts, phi); // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- // // First-order derivatives dTensor2 phi_xi (mpoints, kmax ); dTensor2 phi_eta(mpoints, kmax ); SetLegendreGrad_Unst( spts, phi_xi, phi_eta ); // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- // // Second-order derivatives dTensor2 phi_xi2 (mpoints, kmax ); dTensor2 phi_xieta(mpoints, kmax ); dTensor2 phi_eta2 (mpoints, kmax ); LegendreDiff2_Unst(spts, &phi_xi2, &phi_xieta, &phi_eta2 ); // ---------------------------------------------------------------------- // // ------------------------------------------------------------- // // Loop over every grid cell indexed by user supplied parameters // // described by istart...iend, jstart...jend // // ------------------------------------------------------------- // #pragma omp parallel for for (int i=istart; i<=iend; i++) { // These need to be defined locally. Each mesh element carries its // own change of basis matrix, so these need to be recomputed for // each element. The canonical derivatives, phi_xi, and phi_eta can // be computed and shared for each element. // First-order derivatives dTensor2 phi_x(mpoints, kmax_fout); // x-derivative of Legendre basis (orthogonal) dTensor2 phi_y(mpoints, kmax_fout); // y-derivative of Legendre basis (orthogonal) // Second-order derivatives dTensor2 phi_xx(mpoints, kmax_fout); // xx-derivative of Legendre basis (orthogonal) dTensor2 phi_xy(mpoints, kmax_fout); // xy-derivative of Legendre basis (orthogonal) dTensor2 phi_yy(mpoints, kmax_fout); // yy-derivative of Legendre basis (orthogonal) //find center of current cell const int i1 = Mesh.get_tnode(i,1); const int i2 = Mesh.get_tnode(i,2); const int i3 = Mesh.get_tnode(i,3); // Corners: const double x1 = Mesh.get_node(i1,1); const double y1 = Mesh.get_node(i1,2); const double x2 = Mesh.get_node(i2,1); const double y2 = Mesh.get_node(i2,2); const double x3 = Mesh.get_node(i3,1); const double y3 = Mesh.get_node(i3,2); // Center of current cell: const double xc = (x1+x2+x3)/3.0; const double yc = (y1+y2+y3)/3.0; // Variables that need to be written to, and therefore are // created for each thread dTensor2 xpts (mpoints, 2); dTensor2 qvals (mpoints, meqn); dTensor2 auxvals(mpoints, maux); // local storage for Flux function its Jacobian, and the Hessian: dTensor3 fvals(mpoints, meqn, 2); // flux function (vector) dTensor4 A(mpoints, meqn, meqn, 2); // Jacobian of flux dTensor5 H(mpoints, meqn, meqn, meqn, 2); // Hessian of flux // Compute q, aux and fvals at each Gaussian Quadrature point // for this current cell indexed by (i,j) // Save results into dTensor2 qvals, auxvals and fvals. for (int m=1; m<= mpoints; m++) { // convert phi_xi and phi_eta derivatives // to phi_x and phi_y derivatives through Jacobian // // Note that: // // pd_x = J11 pd_xi + J12 pd_eta and // pd_y = J21 pd_xi + J22 pd_eta. // // Squaring these operators yields the second derivatives. for (int k=1; k<=kmax_fout; k++) { phi_x.set(m,k, Mesh.get_jmat(i,1,1)*phi_xi.get(m,k) + Mesh.get_jmat(i,1,2)*phi_eta.get(m,k) ); phi_y.set(m,k, Mesh.get_jmat(i,2,1)*phi_xi.get(m,k) + Mesh.get_jmat(i,2,2)*phi_eta.get(m,k) ); phi_xx.set(m,k, Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,1,1)*phi_xi2.get(m,k) + Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,1,2)*phi_xieta.get(m,k) + Mesh.get_jmat(i,1,2)*Mesh.get_jmat(i,1,2)*phi_eta2.get(m,k) ); phi_xy.set(m,k, Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,2,1)*phi_xi2.get(m,k) +(Mesh.get_jmat(i,1,2)*Mesh.get_jmat(i,2,1) + Mesh.get_jmat(i,1,1)*Mesh.get_jmat(i,2,2))*phi_xieta.get(m,k) + Mesh.get_jmat(i,1,2)*Mesh.get_jmat(i,2,2)*phi_eta2.get(m,k) ); phi_yy.set(m,k, Mesh.get_jmat(i,2,1)*Mesh.get_jmat(i,2,1)*phi_xi2.get(m,k) + Mesh.get_jmat(i,2,1)*Mesh.get_jmat(i,2,2)*phi_xieta.get(m,k) + Mesh.get_jmat(i,2,2)*Mesh.get_jmat(i,2,2)*phi_eta2.get(m,k) ); } // point on the unit triangle const double s = spts.get(m,1); const double t = spts.get(m,2); // point on the physical triangle xpts.set(m,1, xc + (x2-x1)*s + (x3-x1)*t ); xpts.set(m,2, yc + (y2-y1)*s + (y3-y1)*t ); // Solution values (q) at each grid point for (int me=1; me<=meqn; me++) { qvals.set(m,me, 0.0 ); for (int k=1; k<=kmax_qin; k++) { qvals.set(m,me, qvals.get(m,me) + phi.get(m,k) * qin->get(i,me,k) ); } } // Auxiliary values (aux) at each grid point for (int ma=1; ma<=maux; ma++) { auxvals.set(m,ma, 0.0 ); for (int k=1; k<=kmax_auxin; k++) { auxvals.set(m,ma, auxvals.get(m,ma) + phi.get(m,k) * auxin->get(i,ma,k) ); } } } // ----------------------------------------------------------------- // // // Part I: // // Project the flux function onto the basis // functions. This is the term of order O( 1 ) in the // "time-averaged" Taylor expansion of f and g. // // ----------------------------------------------------------------- // // Call user-supplied function to set fvals FluxFunc(xpts, qvals, auxvals, fvals); // Evaluate integral on current cell (project onto Legendre basis) // using Gaussian Quadrature for the integration // // TODO - do we want to optimize this by looking into using transposes, // as has been done in the 2d/cart code? (5/14/2014) -DS for (int me=1; me<=mcomps_out; me++) for (int k=1; k<=kmax; k++) { double tmp1 = 0.0; double tmp2 = 0.0; for (int mp=1; mp <= mpoints; mp++) { tmp1 += wgts.get(mp)*fvals.get(mp, me, 1)*phi.get(mp, k); tmp2 += wgts.get(mp)*fvals.get(mp, me, 2)*phi.get(mp, k); } F->set(i, me, k, 2.0*tmp1 ); G->set(i, me, k, 2.0*tmp2 ); } // ----------------------------------------------------------------- // // // Part II: // // Project the derivative of the flux function onto the basis // functions. This is the term of order O( \dt ) in the // "time-averaged" Taylor expansion of f and g. // // ----------------------------------------------------------------- // // ----------------------------------------------------------------- // // Compute pointwise values for fx+gy: // // We can't multiply fvals of f, and g, // by alpha, otherwise we compute the wrong derivative here! // dTensor2 fx_plus_gy( mpoints, meqn ); fx_plus_gy.setall(0.); for( int mp=1; mp <= mpoints; mp++ ) for( int me=1; me <= meqn; me++ ) { double tmp = 0.; for( int k=2; k <= kmax; k++ ) { tmp += F->get( i, me, k ) * phi_x.get( mp, k ); tmp += G->get( i, me, k ) * phi_y.get( mp, k ); } fx_plus_gy.set( mp, me, tmp ); } // Call user-supplied Jacobian to set f'(q) and g'(q): DFluxFunc( xpts, qvals, auxvals, A ); // place-holders for point values of // f'(q)( fx + gy ) and g'(q)( fx + gy ): dTensor2 dt_times_fdot( mpoints, meqn ); dTensor2 dt_times_gdot( mpoints, meqn ); // Compute point values for f'(q) * (fx+gy) and g'(q) * (fx+gy): for( int mp=1; mp <= mpoints; mp++ ) for( int m1=1; m1 <= meqn; m1++ ) { double tmp1 = 0.; double tmp2 = 0.; for( int m2=1; m2 <= meqn; m2++ ) { tmp1 += A.get(mp, m1, m2, 1 ) * fx_plus_gy.get(mp, m2); tmp2 += A.get(mp, m1, m2, 2 ) * fx_plus_gy.get(mp, m2); } dt_times_fdot.set( mp, m1, -beta_dt*tmp1 ); dt_times_gdot.set( mp, m1, -beta_dt*tmp2 ); } // --- Third-order terms --- // // // These are the terms that are O( \dt^2 ) in the "time-averaged" // flux function. dTensor2 f_tt( mpoints, meqn ); f_tt.setall(0.); dTensor2 g_tt( mpoints, meqn ); g_tt.setall(0.); if( mterms > 2 ) { // Construct the Hessian at each (quadrature) point D2FluxFunc( xpts, qvals, auxvals, H ); // Second-order derivative terms dTensor2 qx_vals (mpoints, meqn); qx_vals.setall(0.); dTensor2 qy_vals (mpoints, meqn); qy_vals.setall(0.); dTensor2 fxx_vals(mpoints, meqn); fxx_vals.setall(0.); dTensor2 gxx_vals(mpoints, meqn); gxx_vals.setall(0.); dTensor2 fxy_vals(mpoints, meqn); fxy_vals.setall(0.); dTensor2 gxy_vals(mpoints, meqn); gxy_vals.setall(0.); dTensor2 fyy_vals(mpoints, meqn); fyy_vals.setall(0.); dTensor2 gyy_vals(mpoints, meqn); gyy_vals.setall(0.); for( int m=1; m <= mpoints; m++ ) for( int me=1; me <= meqn; me++ ) { // Can start at k=1, because derivative of a constant is // zero. double tmp_qx = 0.; double tmp_qy = 0.; for( int k=2; k <= kmax; k++ ) { tmp_qx += phi_x.get(m,k) * qin->get(i,me,k); tmp_qy += phi_y.get(m,k) * qin->get(i,me,k); } qx_vals.set(m,me, tmp_qx ); qy_vals.set(m,me, tmp_qy ); // First non-zero terms start at third-order. for( int k=4; k <= kmax; k++ ) { fxx_vals.set(m,me, fxx_vals.get(m,me) + phi_xx.get(m,k)*F->get(i,me,k) ); gxx_vals.set(m,me, gxx_vals.get(m,me) + phi_xx.get(m,k)*G->get(i,me,k) ); fxy_vals.set(m,me, fxy_vals.get(m,me) + phi_xy.get(m,k)*F->get(i,me,k) ); gxy_vals.set(m,me, gxy_vals.get(m,me) + phi_xy.get(m,k)*G->get(i,me,k) ); fyy_vals.set(m,me, fyy_vals.get(m,me) + phi_yy.get(m,k)*F->get(i,me,k) ); gyy_vals.set(m,me, gyy_vals.get(m,me) + phi_yy.get(m,k)*G->get(i,me,k) ); } } // ----------------------------------- // // Part I: Compute (f_x + g_y)_{,t} // ----------------------------------- // // Compute terms that get multiplied by \pd2{ f }{ q } and \pd2{ g }{ q }. dTensor2 fx_plus_gy_t( mpoints, meqn ); for( int m = 1; m <= mpoints; m++ ) for( int me = 1; me <= meqn; me++ ) { double tmp = 0.; // Terms that get multiplied by the Hessian: for( int m1=1; m1 <= meqn; m1++ ) for( int m2=1; m2 <= meqn; m2++ ) { tmp += H.get(m,me,m1,m2,1)*qx_vals.get(m,m1)*fx_plus_gy.get(m,m2); tmp += H.get(m,me,m1,m2,2)*qy_vals.get(m,m1)*fx_plus_gy.get(m,m2); } // Terms that get multiplied by f'(q) and g'(q): for( int m1=1; m1 <= meqn; m1++ ) { tmp += A.get(m,me,m1,1)*( fxx_vals.get(m,m1)+gxy_vals.get(m,m1) ); tmp += A.get(m,me,m1,2)*( fxy_vals.get(m,m1)+gyy_vals.get(m,m1) ); } fx_plus_gy_t.set( m, me, tmp ); } // ----------------------------------- // // Part II: Compute // f'(q) * fx_plus_gy_t and // g'(q) * fx_plus_gy_t // ----------------------------------- // // Add in the third term that gets multiplied by A: for( int m=1; m <= mpoints; m++ ) for( int m1=1; m1 <= meqn; m1++ ) { double tmp1 = 0.; double tmp2 = 0.; for( int m2=1; m2 <= meqn; m2++ ) { tmp1 += A.get(m,m1,m2,1)*fx_plus_gy_t.get(m,m2); tmp2 += A.get(m,m1,m2,2)*fx_plus_gy_t.get(m,m2); } f_tt.set( m, m1, tmp1 ); g_tt.set( m, m1, tmp2 ); } // ----------------------------------------------- // // Part III: Add in contributions from // f''(q) * (fx_plus_gy, fx_plus_gy ) and // g''(q) * (fx_plus_gy, fx_plus_gy ). // ----------------------------------------------- // for( int m =1; m <= mpoints; m++ ) for( int me =1; me <= meqn; me++ ) { double tmp1 = 0.; double tmp2 = 0.; // Terms that get multiplied by the Hessian: for( int m1=1; m1 <= meqn; m1++ ) for( int m2=1; m2 <= meqn; m2++ ) { tmp1 += H.get(m,me,m1,m2,1)*fx_plus_gy.get(m,m1)*fx_plus_gy.get(m,m2); tmp2 += H.get(m,me,m1,m2,2)*fx_plus_gy.get(m,m1)*fx_plus_gy.get(m,m2); } f_tt.set( m, me, f_tt.get(m,me) + tmp1 ); g_tt.set( m, me, g_tt.get(m,me) + tmp2 ); } } // End of computing "third"-order terms // ---------------------------------------------------------- // // // Construct basis coefficients (integrate_on_current_cell) // // ---------------------------------------------------------- // for (int me=1; me<=mcomps_out; me++) for (int k=1; k<=kmax; k++) { double tmp1 = 0.0; double tmp2 = 0.0; for (int mp=1; mp<=mpoints; mp++) { tmp1 += wgts.get(mp)*phi.get(mp,k)*( dt_times_fdot.get(mp, me) + charlie_dt*f_tt.get(mp, me) ); tmp2 += wgts.get(mp)*phi.get(mp,k)*( dt_times_gdot.get(mp, me) + charlie_dt*g_tt.get(mp, me) ); } F->set(i,me,k, F->get(i,me,k) + 2.0*tmp1 ); G->set(i,me,k, G->get(i,me,k) + 2.0*tmp2 ); } } }
bool ParMetisPartitioner::partition(map<int, double>& elemWeights, PartitionMode mode) { FUNCNAME("ParMetisPartitioner::partition()"); int mpiSize = mpiComm->Get_size(); // === Create parmetis mesh === if (parMetisMesh) delete parMetisMesh; TEST_EXIT_DBG(elementInRank.size() != 0)("Should not happen!\n"); parMetisMesh = new ParMetisMesh(mesh, mpiComm, elementInRank, mapLocalGlobal); int nElements = parMetisMesh->getNumElements(); // === Create weight array === vector<int> wgts(nElements); vector<float> floatWgts(nElements); unsigned int floatWgtsPos = 0; float maxWgt = 0.0; TraverseStack stack; ElInfo* elInfo = stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { int index = elInfo->getElement()->getIndex(); if (elementInRank[index]) { // get weight float wgt = static_cast<float>(elemWeights[index]); maxWgt = std::max(wgt, maxWgt); // write float weight TEST_EXIT_DBG(floatWgtsPos < floatWgts.size())("Should not happen!\n"); floatWgts[floatWgtsPos++] = wgt; } elInfo = stack.traverseNext(elInfo); } TEST_EXIT_DBG(floatWgtsPos == floatWgts.size())("Should not happen!\n"); float tmp; mpiComm->Allreduce(&maxWgt, &tmp, 1, MPI_FLOAT, MPI_MAX); maxWgt = tmp; // === Create dual graph === ParMetisGraph parMetisGraph(parMetisMesh, mpiComm); // === Partitioning of dual graph === int wgtflag = 2; // weights at vertices only! int numflag = 0; // c numbering style! int ncon = 1; // one weight at each vertex! int nparts = mpiSize; // number of partitions vector<double> tpwgts(mpiSize); double ubvec = 1.05; int options[4] = {0, 0, 15, PARMETIS_PSR_COUPLED}; // default options int edgecut = -1; vector<int> part(nElements); // set tpwgts for (int i = 0; i < mpiSize; i++) tpwgts[i] = 1.0 / static_cast<double>(nparts); // float scale = 10000.0 / maxWgt; for (int i = 0; i < nElements; i++) wgts[i] = floatWgts[i]; // wgts[i] = static_cast<int>(floatWgts[i] * scale); // === Start ParMETIS. === MPI_Comm tmpComm = MPI_Comm(*mpiComm); switch (mode) { case INITIAL: ParMETIS_V3_PartKway(parMetisMesh->getElementDist(), parMetisGraph.getXAdj(), parMetisGraph.getAdjncy(), &(wgts[0]), NULL, &wgtflag, &numflag, &ncon, &nparts, &(tpwgts[0]), &ubvec, options, &edgecut, &(part[0]), &tmpComm); break; case ADAPTIVE_REPART: { vector<int> vsize(nElements); for (int i = 0; i < nElements; i++) vsize[i] = static_cast<int>(floatWgts[i]); ParMETIS_V3_AdaptiveRepart(parMetisMesh->getElementDist(), parMetisGraph.getXAdj(), parMetisGraph.getAdjncy(), &(wgts[0]), NULL, &(vsize[0]), &wgtflag, &numflag, &ncon, &nparts, &(tpwgts[0]), &ubvec, &itr, options, &edgecut, &(part[0]), &tmpComm); } break; case REFINE_PART: ParMETIS_V3_RefineKway(parMetisMesh->getElementDist(), parMetisGraph.getXAdj(), parMetisGraph.getAdjncy(), &(wgts[0]), NULL, &wgtflag, &numflag, &ncon, &nparts, &(tpwgts[0]), &ubvec, options, &edgecut, &(part[0]), &tmpComm); break; default: ERROR_EXIT("unknown partitioning mode\n"); } // === Distribute new partition data. === return distributePartitioning(&(part[0])); }
void CartCellDoubleQuadraticRefine::refine(Patch<NDIM>& fine, const Patch<NDIM>& coarse, const int dst_component, const int src_component, const Box<NDIM>& fine_box, const IntVector<NDIM>& ratio) const { // Get the patch data. Pointer<CellData<NDIM, double> > fdata = fine.getPatchData(dst_component); Pointer<CellData<NDIM, double> > cdata = coarse.getPatchData(src_component); #if !defined(NDEBUG) TBOX_ASSERT(fdata); TBOX_ASSERT(cdata); TBOX_ASSERT(fdata->getDepth() == cdata->getDepth()); #endif const int data_depth = fdata->getDepth(); const Box<NDIM>& patch_box_fine = fine.getBox(); const Index<NDIM>& patch_lower_fine = patch_box_fine.lower(); Pointer<CartesianPatchGeometry<NDIM> > pgeom_fine = fine.getPatchGeometry(); const double* const XLower_fine = pgeom_fine->getXLower(); const double* const dx_fine = pgeom_fine->getDx(); const Box<NDIM>& patch_box_crse = coarse.getBox(); const Index<NDIM>& patch_lower_crse = patch_box_crse.lower(); Pointer<CartesianPatchGeometry<NDIM> > pgeom_crse = coarse.getPatchGeometry(); const double* const XLower_crse = pgeom_crse->getXLower(); const double* const dx_crse = pgeom_crse->getDx(); // Set all values in the fine box via quadratic interpolation from the // overlying coarse grid data. for (Box<NDIM>::Iterator b(fine_box); b; b++) { const Index<NDIM>& i_fine = b(); const Index<NDIM> i_crse = coarsen(i_fine, ratio); // Determine the interpolation stencil in the coarse index space. Box<NDIM> stencil_box_crse(i_crse, i_crse); stencil_box_crse.grow(IntVector<NDIM>(1)); // Determine the interpolation weights. static const int degree = 2; boost::array<boost::array<double, degree + 1>, NDIM> wgts( array_constant<boost::array<double, degree + 1>, NDIM>( boost::array<double, degree + 1>(array_constant<double, degree + 1>(0.0)))); for (unsigned int axis = 0; axis < NDIM; ++axis) { const double X = XLower_fine[axis] + dx_fine[axis] * (static_cast<double>(i_fine(axis) - patch_lower_fine(axis)) + 0.5); std::vector<double> X_crse(degree + 1, 0.0); for (int i_crse = stencil_box_crse.lower()(axis), k = 0; i_crse <= stencil_box_crse.upper()(axis); ++i_crse, ++k) { X_crse[k] = XLower_crse[axis] + dx_crse[axis] * (static_cast<double>(i_crse - patch_lower_crse(axis)) + 0.5); } wgts[axis][0] = ((X - X_crse[1]) * (X - X_crse[2])) / ((X_crse[0] - X_crse[1]) * (X_crse[0] - X_crse[2])); wgts[axis][1] = ((X - X_crse[0]) * (X - X_crse[2])) / ((X_crse[1] - X_crse[0]) * (X_crse[1] - X_crse[2])); wgts[axis][2] = ((X - X_crse[0]) * (X - X_crse[1])) / ((X_crse[2] - X_crse[0]) * (X_crse[2] - X_crse[1])); } // Interpolate from the coarse grid to the fine grid. Index<NDIM> i_intrp; for (int d = 0; d < data_depth; ++d) { (*fdata)(i_fine, d) = 0.0; #if (NDIM > 2) for (int i2 = 0; i2 <= degree; ++i2) { const double& wgt2 = wgts[2][i2]; i_intrp(2) = stencil_box_crse.lower()(2) + i2; #else const double wgt2 = 1.0; #endif #if (NDIM > 1) for (int i1 = 0; i1 <= degree; ++i1) { const double& wgt1 = wgts[1][i1]; i_intrp(1) = stencil_box_crse.lower()(1) + i1; #else const double wgt1 = 1.0; #endif for (int i0 = 0; i0 <= degree; ++i0) { const double& wgt0 = wgts[0][i0]; i_intrp(0) = stencil_box_crse.lower()(0) + i0; (*fdata)(i_fine, d) += wgt0 * wgt1 * wgt2 * (*cdata)(i_intrp, d); } #if (NDIM > 1) } #endif #if (NDIM > 2) } #endif } } return; } // refine