166 lines
6.7 KiB
C++
166 lines
6.7 KiB
C++
/********************************************************
|
|
* ██████╗ ██████╗████████╗██╗
|
|
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
|
* ██║ ███╗██║ ██║ ██║
|
|
* ██║ ██║██║ ██║ ██║
|
|
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
|
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
|
* Geophysical Computational Tools & Library (GCTL)
|
|
*
|
|
* Copyright (c) 2022 Yi Zhang (yizhang-geo@zju.edu.cn)
|
|
*
|
|
* GCTL is distributed under a dual licensing scheme. You can redistribute
|
|
* it and/or modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation, either version 2
|
|
* of the License, or (at your option) any later version. You should have
|
|
* received a copy of the GNU Lesser General Public License along with this
|
|
* program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* If the terms and conditions of the LGPL v.2. would prevent you from using
|
|
* the GCTL, please consider the option to obtain a commercial license for a
|
|
* fee. These licenses are offered by the GCTL's original author. As a rule,
|
|
* licenses are provided "as-is", unlimited in time for a one time fee. Please
|
|
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
|
|
* to include some description of your company and the realm of its activities.
|
|
* Also add information on how to contact you by electronic and paper mail.
|
|
******************************************************/
|
|
|
|
#ifndef _GCTL_CLCG_H
|
|
#define _GCTL_CLCG_H
|
|
|
|
#include "gctl/core.h"
|
|
#include "gctl/maths.h"
|
|
#include "gctl/algorithm.h"
|
|
|
|
#include "gctl_optimization_config.h"
|
|
#ifdef GCTL_OPTIMIZATION_TOML
|
|
#include "toml.hpp"
|
|
#endif // GCTL_OPTIMIZATION_TOML
|
|
|
|
#if defined _WINDOWS || __WIN32__
|
|
#include "windows.h"
|
|
#endif // _WINDOWS || __WIN32__
|
|
|
|
namespace gctl
|
|
{
|
|
/**
|
|
* @brief Types of method that could be recognized by the clcg_solver() function.
|
|
*/
|
|
enum clcg_solver_type
|
|
{
|
|
/**
|
|
* Jacob's Bi-Conjugate Gradient Method
|
|
*/
|
|
CLCG_BICG,
|
|
/**
|
|
* Bi-Conjugate Gradient Method accelerated for complex symmetric A
|
|
*/
|
|
CLCG_BICG_SYM,
|
|
/**
|
|
* Conjugate Gradient Squared Method with real coefficients.
|
|
*/
|
|
CLCG_CGS,
|
|
/**
|
|
* Biconjugate gradient method.
|
|
*/
|
|
CLCG_BICGSTAB,
|
|
/**
|
|
* Transpose Free Quasi-Minimal Residual Method
|
|
*/
|
|
CLCG_TFQMR,
|
|
};
|
|
|
|
/**
|
|
* @brief return value of the clcg_solver() function
|
|
*/
|
|
enum clcg_return_code
|
|
{
|
|
CLCG_SUCCESS = 0, ///< The solver function terminated successfully.
|
|
CLCG_CONVERGENCE = 0, ///< The iteration reached convergence.
|
|
CLCG_STOP, ///< The iteration is stopped by the monitoring function.
|
|
CLCG_ALREADY_OPTIMIZIED, ///< The initial solution is already optimized.
|
|
// A negative number means a error
|
|
CLCG_UNKNOWN_ERROR = -1024, ///< Unknown error.
|
|
CLCG_INVILAD_VARIABLE_SIZE, ///< The variable size is negative
|
|
CLCG_INVILAD_MAX_ITERATIONS, ///< The maximal iteration times is negative.
|
|
CLCG_INVILAD_EPSILON, ///< The epsilon is negative.
|
|
CLCG_REACHED_MAX_ITERATIONS, ///< Iteration reached maximal limit.
|
|
CLCG_NAN_VALUE, ///< Nan value.
|
|
CLCG_INVALID_POINTER, ///< Invalid pointer.
|
|
CLCG_SIZE_NOT_MATCH, ///< Sizes of m and B do not match
|
|
CLCG_UNKNOWN_SOLVER, ///< Unknown solver
|
|
};
|
|
|
|
/**
|
|
* @brief Parameters of the conjugate gradient methods.
|
|
*/
|
|
struct clcg_para
|
|
{
|
|
/**
|
|
* Maximal iteration times. The process will continue till the convergence is met
|
|
* if this option is set to zero (default).
|
|
*/
|
|
int max_iterations;
|
|
|
|
/**
|
|
* Epsilon for convergence test.
|
|
* This parameter determines the accuracy with which the solution is to be found.
|
|
* A minimization terminates when ||g||/max(||g0||, 1.0) <= epsilon or sqrt(||g||)/N
|
|
* <= epsilon for the lcg_solver() function, where ||.|| denotes the Euclidean (L2) norm.
|
|
* The default value of epsilon is 1e-8. For box-constrained methods,the convergence test
|
|
* is implemented using ||P(m-g) - m|| <= epsilon, in which P is the projector that
|
|
* transfers m into the constrained domain.
|
|
*/
|
|
double epsilon;
|
|
|
|
/**
|
|
* Whether to use absolute mean differences (AMD) between |Ax - B| to evaluate the process.
|
|
* The default value is false which means the gradient based evaluating method is used.
|
|
* The AMD based method will be used if this variable is set to true. This parameter is only
|
|
* applied to the non-constrained methods.
|
|
*/
|
|
int abs_diff;
|
|
};
|
|
|
|
class clcg_solver
|
|
{
|
|
private:
|
|
clcg_para clcg_param_;
|
|
size_t clcg_inter_;
|
|
bool clcg_silent_;
|
|
|
|
array<std::complex<double> > r1k, r2k, d1k, d2k;
|
|
array<std::complex<double> > Ax;
|
|
|
|
public:
|
|
clcg_solver();
|
|
virtual ~clcg_solver();
|
|
|
|
virtual void CLCG_Ax(const array<std::complex<double> > &x, array<std::complex<double> > &ax,
|
|
matrix_layout_e layout, conjugate_type_e conj) = 0;
|
|
virtual int CLCG_Progress(const array<std::complex<double> > &m, const double converge, const clcg_para ¶m, size_t t);
|
|
|
|
void clcg_silent();
|
|
void set_clcg_report_interval(size_t inter);
|
|
void set_clcg_para(const clcg_para ¶m);
|
|
void clcg_error_str(clcg_return_code err_code, std::ostream &ss = std::clog, bool err_throw = false);
|
|
clcg_para default_clcg_para();
|
|
|
|
#ifdef GCTL_OPTIMIZATION_TOML
|
|
void set_clcg_para(const toml::value &toml_data);
|
|
#endif // GCTL_OPTIMIZATION_TOML
|
|
|
|
clcg_return_code clbicg(array<std::complex<double> > &m, const array<std::complex<double> > &B);
|
|
clcg_return_code clbicg_symmetric(array<std::complex<double> > &m, const array<std::complex<double> > &B);
|
|
clcg_return_code clcgs(array<std::complex<double> > &m, const array<std::complex<double> > &B);
|
|
clcg_return_code clbicgstab(array<std::complex<double> > &m, const array<std::complex<double> > &B);
|
|
clcg_return_code cltfqmr(array<std::complex<double> > &m, const array<std::complex<double> > &B);
|
|
|
|
|
|
void CLCG_Minimize(array<std::complex<double> > &m, const array<std::complex<double> > &B,
|
|
clcg_solver_type solver_id = CLCG_CGS, std::ostream &ss = std::clog,
|
|
bool verbose = true, bool er_throw = false);
|
|
};
|
|
}
|
|
|
|
#endif // _GCTL_CLCG_H
|