// =========================================================================== // // Filename: bicgstab.h // // Description: // // Version: 0.0 // Created: 10/27/2009 03:15:06 PM // Revision: none // Compiler: g++ (c++) // // Author: Trevor Irons (ti) // // Organisation: Colorado School of Mines (CSM) // United States Geological Survey (USGS) // // Email: tirons@mines.edu, tirons@usgs.gov // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // =========================================================================== #pragma once #ifndef BICGSTAB_INC #define BICGSTAB_INC #include #include #ifdef CHOLMODPRECONDITION #include #endif // CHOLMODPRECONDITION //#include "unsupported/Eigen/IterativeSolvers" //#include #include #include #include #include #include #include "timer.h" using namespace Eigen; using namespace Lemma; typedef Eigen::SparseMatrix SparseMat; // Computes implicit calculation template < typename Solver > inline VectorXcr implicitDCInvBPhi3 ( const SparseMat& D, const Solver& solver, const Ref ioms, const Ref Phi, Real& tol, // not used int& max_it // not used ) { VectorXcr b = (ioms).asDiagonal() * (D.transpose()*Phi); VectorXcr y = solver.solve(b); //max_it = solver.iterations(); // actualy no need to pass this return D*y; //return y; } // // Simple extraction of indices in idx into reduceed array x1 // void vmap( const Ref x0, Ref x1, const std::vector& idx ) { // for (unsigned int ii=0; ii x0, const std::vector& idx ) { VectorXcr x1 = VectorXcr::Zero( idx.size() ); for (unsigned int ii=0; ii x0, const Ref x1, const std::vector& idx ) { for (unsigned int ii=0; ii int implicitbicgstab(//const SparseMat& D, //const SparseMat& C, const Ref< Eigen::SparseMatrix const > D, const std::vector& idx, const Ref< VectorXcr const > ioms, const Ref< VectorXcr const > rhs, Ref phi, CSolver& solver, int &max_it, const Real &tol, Real &errorn, int &iter_done, ofstream& logio) { logio << "using the preconditioned implicit solver" << std::endl; Complex omega, rho, rho_1, alpha, beta; Real tol2; int iter, max_it2, max_it1; // Look at reduced problem VectorXcr rhs2 = vmap(rhs, idx); VectorXcr phi2 = vmap(phi, idx); // Determine size of system and init vectors int n = idx.size(); // was phi.size(); std::cout << "BiCGStab SIZES " << n << "\t" << phi.size() << "\t" << ioms.size() << std::endl; VectorXcr r(n); VectorXcr r_tld(n); VectorXcr p(n); VectorXcr s(n); VectorXcr v = VectorXcr::Zero(ioms.size()); VectorXcr t = VectorXcr::Zero(ioms.size()); // VectorXcr vm1 = VectorXcr::Zero(ioms.size()); // VectorXcr tm1 = VectorXcr::Zero(ioms.size()); // TODO, refigure for implicit large system // std::cout << "Start BiCGStab, memory needed: " // << (sizeof(Complex)*(9+2)*n/(1024.*1024*1024)) << " [Gb]\n"; // Initialise iter_done = 0; Real eps = 1e-100; Real bnrm2 = rhs.norm(); if (bnrm2 == 0) { phi.setConstant(0.0); errorn = 0; std::cerr << "Trivial case of Ax = b, where b is 0\n"; return (0); } // If there is an initial guess if ( phi.norm() ) { tol2 = tol; max_it2 = 50000; //r = rhs - implicitDCInvBPhi3(D, solver, ioms, phi, tol2, max_it2); //r = rhs - implicitDCInvBPhi3(D, solver, ioms, phi, tol2, max_it2); r = rhs2 - vmap( implicitDCInvBPhi3(D, solver, ioms, phi, tol2, max_it2), idx ); } else { r = vmap(rhs, idx); } jsw_timer timer; errorn = r.norm() / bnrm2; omega = 1.; r_tld = r; Real errornold = 1e14; // Get down to business for (iter=0; iter 0) { beta = (rho/rho_1) * (alpha/omega); p = r.array() + beta*(p.array()-omega*v.array()).array(); } else { p = r; } tol2 = tol; max_it2 = 500000; ivmap(phi, p, idx); v = vmap(implicitDCInvBPhi3(D, solver, ioms, phi, tol2, max_it2), idx); alpha = rho / r_tld.dot(v); s = r.array() - alpha*v.array(); errorn = s.norm()/bnrm2; if (errorn < tol && iter > 1) { phi2.array() += alpha*p.array(); ivmap( phi, phi2, idx ); return (0); } tol2 = tol; max_it1 = 500000; //t = implicitDCInvBPhi2(D, C, ioms, solver, s, tol2, max_it1); //t = implicitDCInvBPhi3(D, solver, ioms, s, tol2, max_it1); ivmap(phi, s, idx); t = vmap(implicitDCInvBPhi3(D, solver, ioms, phi, tol2, max_it1), idx); omega = t.dot(s) / t.dot(t); r = s.array() - omega*t.array(); errorn = r.norm() / bnrm2; iter_done = iter; if (errorn <= tol) { ivmap( phi, phi2, idx ); return (0); } if (abs(omega) < eps) { ivmap( phi, phi2, idx ); return (0); } rho_1 = rho; logio << "iteration " << std::setw(3) << iter << " errorn " << std::setw(6) << std::setprecision(4) << std::scientific << errorn //<< "\timplicit iterations " << std::setw(5) << max_it1+max_it2 << " time " << std::setw(6) << std::fixed << std::setprecision(2) << timer.end()/60. << " [m] " << max_it2+max_it2 << " iterations " << std::endl; // Check to see how progress is going if (errornold - errorn < 0) { logio << "Irregular non-monotonic (negative) convergence. Recommend restart. \n"; ivmap( phi, phi2, idx ); return (2); } /* if (errornold - errorn < 1e-14) { logio << "not making any progress. Giving up\n"; return (1); } */ //std::cout << "|| p-s ||" << (alpha*p - omega*s).norm() << std::endl; // only update phi if good things are happening phi2.array() += alpha*p.array() + omega*s.array(); errornold = errorn; } ivmap( phi, phi2, idx ); return (0); } #endif // ----- #ifndef BICGSTAB_INC -----