void PolyInterpMixin<time>::fas(time dt, shared_ptr<ISweeper<time>> dst, shared_ptr<const ISweeper<time>> src) { auto& crse = pfasst::encap::as_encap_sweeper(dst); auto& fine = pfasst::encap::as_encap_sweeper(src); auto const ncrse = crse.get_nodes().size(); assert(ncrse >= 1); auto const nfine = fine.get_nodes().size(); assert(nfine >= 1); auto crse_factory = crse.get_factory(); auto fine_factory = fine.get_factory(); EncapVecT crse_int(ncrse), fine_int(nfine), rstr_int(ncrse); for (size_t m = 0; m < ncrse; m++) { crse_int[m] = crse_factory->create(solution); } for (size_t m = 0; m < ncrse; m++) { rstr_int[m] = crse_factory->create(solution); } for (size_t m = 0; m < nfine; m++) { fine_int[m] = fine_factory->create(solution); } // compute '0 to node' integral on the coarse level crse.integrate(dt, crse_int); // compute '0 to node' integral on the fine level fine.integrate(dt, fine_int); // restrict '0 to node' fine integral int trat = (int(nfine) - 1) / (int(ncrse) - 1); for (size_t m = 0; m < ncrse; m++) { this->restrict(rstr_int[m], fine_int[m * trat]); } // compute 'node to node' tau correction EncapVecT tau(ncrse), rstr_and_crse(2 * ncrse); // Attention: tau is getting filled with pointers to the crse's member for (size_t m = 0; m < ncrse; m++) { tau[m] = crse.get_tau(m); } for (size_t m = 0; m < ncrse; m++) { rstr_and_crse[m] = rstr_int[m]; } for (size_t m = 0; m < ncrse; m++) { rstr_and_crse[ncrse + m] = crse_int[m]; } if (fmat.rows() == 0) { fmat.resize(ncrse, 2 * ncrse); fmat.fill(0.0); for (size_t m = 0; m < ncrse; m++) { fmat(m, m) = 1.0; fmat(m, ncrse + m) = -1.0; // subtract 0-to-(m-1) FAS so resulting FAS is (m-1)-to-m FAS, // which will be required in the sweeper logic for (size_t n = 0; n < m; n++) { fmat(m, n) = -1.0; fmat(m, ncrse + n) = 1.0; } } } tau[0]->mat_apply(tau, 1.0, fmat, rstr_and_crse, true); }
virtual void fas(time dt, shared_ptr<ISweeper<time>> dst, shared_ptr<const ISweeper<time>> src) override { auto& crse = pfasst::encap::as_encap_sweeper(dst); auto& fine = pfasst::encap::as_encap_sweeper(src); auto const ncrse = crse.get_nodes().size(); assert(ncrse >= 1); auto const nfine = fine.get_nodes().size(); assert(nfine >= 1); auto crse_factory = crse.get_factory(); auto fine_factory = fine.get_factory(); EncapVecT crse_int(ncrse), fine_int(nfine), rstr_int(ncrse); for (size_t m = 0; m < ncrse; m++) { crse_int[m] = crse_factory->create(solution); } for (size_t m = 0; m < ncrse; m++) { rstr_int[m] = crse_factory->create(solution); } for (size_t m = 0; m < nfine; m++) { fine_int[m] = fine_factory->create(solution); } // compute '0 to node' integral on the coarse level crse.integrate(dt, crse_int); // compute '0 to node' integral on the fine level fine.integrate(dt, fine_int); // restrict '0 to node' fine integral int trat = (int(nfine) - 1) / (int(ncrse) - 1); for (size_t m = 0; m < ncrse; m++) { this->restrict(rstr_int[m], fine_int[m * trat]); } // compute 'node to node' tau correction EncapVecT tau(ncrse), rstr_and_crse(2 * ncrse); for (size_t m = 0; m < ncrse; m++) { tau[m] = crse.get_tau(m); } for (size_t m = 0; m < ncrse; m++) { rstr_and_crse[m] = rstr_int[m]; } for (size_t m = 0; m < ncrse; m++) { rstr_and_crse[ncrse + m] = crse_int[m]; } if (fmat.rows() == 0) { fmat.resize(ncrse, 2 * ncrse); fmat.fill(0.0); for (size_t m = 0; m < ncrse; m++) { fmat(m, m) = 1.0; fmat(m, ncrse + m) = -1.0; for (size_t n = 0; n < m; n++) { fmat(m, n) = -1.0; fmat(m, ncrse + n) = 1.0; } } } tau[0]->mat_apply(tau, 1.0, fmat, rstr_and_crse, true); }