update clcg
This commit is contained in:
parent
19df996294
commit
ac500c58ad
@ -123,6 +123,14 @@ int main(int argc, char const *argv[])
|
|||||||
|
|
||||||
m.assign_all(std::complex<double>(0.0, 0.0));
|
m.assign_all(std::complex<double>(0.0, 0.0));
|
||||||
test.CLCG_Minimize(m, B, gctl::CLCG_BICG);
|
test.CLCG_Minimize(m, B, gctl::CLCG_BICG);
|
||||||
|
std::clog << "maximal difference: " << max_diff(fm, m) << std::endl;
|
||||||
|
|
||||||
|
m.assign_all(std::complex<double>(0.0, 0.0));
|
||||||
|
test.CLCG_Minimize(m, B, gctl::CLCG_CGS);
|
||||||
|
std::clog << "maximal difference: " << max_diff(fm, m) << std::endl;
|
||||||
|
|
||||||
|
m.assign_all(std::complex<double>(0.0, 0.0));
|
||||||
|
test.CLCG_Minimize(m, B, gctl::CLCG_BICGSTAB);
|
||||||
std::clog << "maximal difference: " << max_diff(fm, m) << std::endl;
|
std::clog << "maximal difference: " << max_diff(fm, m) << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -30,7 +30,7 @@
|
|||||||
/**
|
/**
|
||||||
* Default parameter for conjugate gradient methods
|
* Default parameter for conjugate gradient methods
|
||||||
*/
|
*/
|
||||||
static const gctl::clcg_para clcg_defparam = {0, 1e-8, 0};
|
static const gctl::clcg_para clcg_defparam = {0, 1e-8, 0, 1e-8};
|
||||||
|
|
||||||
gctl::clcg_solver::clcg_solver()
|
gctl::clcg_solver::clcg_solver()
|
||||||
{
|
{
|
||||||
@ -259,13 +259,13 @@ void gctl::clcg_solver::CLCG_Minimize(array<std::complex<double> > &m, const arr
|
|||||||
switch (solver_id)
|
switch (solver_id)
|
||||||
{
|
{
|
||||||
case CLCG_BICG:
|
case CLCG_BICG:
|
||||||
ss << "Solver: " << std::setw(9) << "Bi-CG, Times cost: " << costime << " ms" << std::endl; break;
|
ss << "Solver: " << std::setw(9) << "BiCG, Times cost: " << costime << " ms" << std::endl; break;
|
||||||
case CLCG_BICG_SYM:
|
case CLCG_BICG_SYM:
|
||||||
ss << "Solver: " << std::setw(9) << "Bi-CG (symmetrically accelerated), Times cost: " << costime << " ms" << std::endl; break;
|
ss << "Solver: " << std::setw(9) << "BiCG-Sym, Times cost: " << costime << " ms" << std::endl; break;
|
||||||
case CLCG_CGS:
|
case CLCG_CGS:
|
||||||
ss << "Solver: " << std::setw(9) << "CGS, Times cost: " << costime << " ms" << std::endl; break;
|
ss << "Solver: " << std::setw(9) << "CGS, Times cost: " << costime << " ms" << std::endl; break;
|
||||||
case CLCG_BICGSTAB:
|
case CLCG_BICGSTAB:
|
||||||
ss << "Solver: " << std::setw(9) << "CGS, Times cost: " << costime << " ms" << std::endl; break;
|
ss << "Solver: " << std::setw(9) << "BiCG-Stab, Times cost: " << costime << " ms" << std::endl; break;
|
||||||
case CLCG_TFQMR:
|
case CLCG_TFQMR:
|
||||||
ss << "Solver: " << std::setw(9) << "TFQMR, Times cost: " << costime << " ms" << std::endl; break;
|
ss << "Solver: " << std::setw(9) << "TFQMR, Times cost: " << costime << " ms" << std::endl; break;
|
||||||
default:
|
default:
|
||||||
@ -462,12 +462,219 @@ void gctl::clcg_solver::clbicg_symmetric(array<std::complex<double> > &m, const
|
|||||||
|
|
||||||
void gctl::clcg_solver::clcgs(array<std::complex<double> > &m, const array<std::complex<double> > &B, std::ostream &ss)
|
void gctl::clcg_solver::clcgs(array<std::complex<double> > &m, const array<std::complex<double> > &B, std::ostream &ss)
|
||||||
{
|
{
|
||||||
return;
|
size_t n_size = B.size();
|
||||||
|
//check parameters
|
||||||
|
if (n_size <= 0) return clcg_error_str(CLCG_INVILAD_VARIABLE_SIZE, ss);
|
||||||
|
if (clcg_param_.max_iterations < 0) return clcg_error_str(CLCG_INVILAD_MAX_ITERATIONS, ss);
|
||||||
|
if (clcg_param_.epsilon <= 0.0 || clcg_param_.epsilon >= 1.0) return clcg_error_str(CLCG_INVILAD_EPSILON, ss);
|
||||||
|
|
||||||
|
r1k.resize(n_size); r2k.resize(n_size); d1k.resize(n_size);
|
||||||
|
uk.resize(n_size); qk.resize(n_size); wk.resize(n_size);
|
||||||
|
Ax.resize(n_size);
|
||||||
|
|
||||||
|
CLCG_Ax(m, Ax, gctl::NoTrans, gctl::NoConj);
|
||||||
|
|
||||||
|
std::complex<double> one_z(1.0, 0.0);
|
||||||
|
std::complex<double> one_one(1.0, 1.0);
|
||||||
|
vecdiff(r1k, B, Ax, one_z, one_z);
|
||||||
|
veccpy(uk, r1k, one_z);
|
||||||
|
veccpy(d1k, r1k, one_z);
|
||||||
|
|
||||||
|
srand(time(0));
|
||||||
|
std::complex<double> rhok;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < n_size; i++)
|
||||||
|
{
|
||||||
|
r2k[i] = random(one_z, 2.0*one_one);
|
||||||
|
}
|
||||||
|
|
||||||
|
rhok = vecinner(r2k, r1k);
|
||||||
|
} while (std::norm(rhok) < clcg_param_.lamda);
|
||||||
|
|
||||||
|
double r0_square, rk_square;
|
||||||
|
std::complex<double> r0_mod, rk_mod;
|
||||||
|
|
||||||
|
rk_mod = vecinner(r1k, r1k);
|
||||||
|
r0_square = rk_square = std::norm(rk_mod);
|
||||||
|
if (r0_square < 1.0) r0_square = 1.0;
|
||||||
|
|
||||||
|
if (clcg_param_.abs_diff && sqrt(rk_square)/n_size <= clcg_param_.epsilon)
|
||||||
|
{
|
||||||
|
CLCG_Progress(m, sqrt(rk_square)/n_size, clcg_param_, 0, ss);
|
||||||
|
return clcg_error_str(CLCG_ALREADY_OPTIMIZIED, ss);
|
||||||
|
}
|
||||||
|
else if (rk_square/r0_square <= clcg_param_.epsilon)
|
||||||
|
{
|
||||||
|
CLCG_Progress(m, rk_square/r0_square, clcg_param_, 0, ss);
|
||||||
|
return clcg_error_str(CLCG_ALREADY_OPTIMIZIED, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
double residual;
|
||||||
|
std::complex<double> ak, rhok2, sigma, betak;
|
||||||
|
|
||||||
|
size_t t = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if (clcg_param_.abs_diff) residual = sqrt(rk_square)/n_size;
|
||||||
|
else residual = rk_square/r0_square;
|
||||||
|
|
||||||
|
if (CLCG_Progress(m, residual, clcg_param_, t, ss))
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_STOP, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (residual <= clcg_param_.epsilon)
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_CONVERGENCE, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clcg_param_.max_iterations > 0 && t+1 > clcg_param_.max_iterations)
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_REACHED_MAX_ITERATIONS, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
t++;
|
||||||
|
|
||||||
|
CLCG_Ax(d1k, Ax, gctl::NoTrans, gctl::NoConj); // vk = Apk
|
||||||
|
sigma = vecinner(r2k, Ax);
|
||||||
|
ak = rhok/sigma;
|
||||||
|
|
||||||
|
vecdiff(qk, uk, Ax, one_z, ak);
|
||||||
|
vecadd(wk, uk, qk, one_z, one_z);
|
||||||
|
|
||||||
|
CLCG_Ax(wk, Ax, gctl::NoTrans, gctl::NoConj);
|
||||||
|
|
||||||
|
vecapp(m, wk, ak);
|
||||||
|
vecsub(r1k, Ax, ak);
|
||||||
|
|
||||||
|
rk_mod = vecinner(r1k, r1k);
|
||||||
|
rk_square = std::norm(rk_mod);
|
||||||
|
|
||||||
|
if (!vecvalid(m))
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_NAN_VALUE, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
rhok2 = vecinner(r2k, r1k);
|
||||||
|
betak = rhok2/rhok;
|
||||||
|
rhok = rhok2;
|
||||||
|
|
||||||
|
vecadd(uk, r1k, qk, one_z, betak);
|
||||||
|
vecadd(d1k, qk, d1k, one_z, betak);
|
||||||
|
vecadd(d1k, uk, d1k, one_z, betak);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clcg_error_str(CLCG_UNKNOWN_ERROR, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gctl::clcg_solver::clbicgstab(array<std::complex<double> > &m, const array<std::complex<double> > &B, std::ostream &ss)
|
void gctl::clcg_solver::clbicgstab(array<std::complex<double> > &m, const array<std::complex<double> > &B, std::ostream &ss)
|
||||||
{
|
{
|
||||||
return;
|
size_t n_size = B.size();
|
||||||
|
//check parameters
|
||||||
|
if (n_size <= 0) return clcg_error_str(CLCG_INVILAD_VARIABLE_SIZE, ss);
|
||||||
|
if (clcg_param_.max_iterations < 0) return clcg_error_str(CLCG_INVILAD_MAX_ITERATIONS, ss);
|
||||||
|
if (clcg_param_.epsilon <= 0.0 || clcg_param_.epsilon >= 1.0) return clcg_error_str(CLCG_INVILAD_EPSILON, ss);
|
||||||
|
|
||||||
|
r1k.resize(n_size); r2k.resize(n_size);
|
||||||
|
d1k.resize(n_size); d2k.resize(n_size);
|
||||||
|
Ax.resize(n_size); Ad.resize(n_size);
|
||||||
|
|
||||||
|
CLCG_Ax(m, Ax, gctl::NoTrans, gctl::NoConj);
|
||||||
|
|
||||||
|
std::complex<double> one_z(1.0, 0.0);
|
||||||
|
std::complex<double> one_one(1.0, 1.0);
|
||||||
|
vecdiff(r1k, B, Ax, one_z, one_z);
|
||||||
|
veccpy(d1k, r1k, one_z);
|
||||||
|
|
||||||
|
srand(time(0));
|
||||||
|
std::complex<double> rhok;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < n_size; i++)
|
||||||
|
{
|
||||||
|
r2k[i] = random(one_z, 2.0*one_one);
|
||||||
|
}
|
||||||
|
|
||||||
|
rhok = vecinner(r2k, r1k);
|
||||||
|
} while (std::norm(rhok) < clcg_param_.lamda);
|
||||||
|
|
||||||
|
double r0_square, rk_square;
|
||||||
|
std::complex<double> r0_mod, rk_mod;
|
||||||
|
rk_mod = vecinner(r1k, r1k);
|
||||||
|
r0_square = rk_square = std::norm(rk_mod);
|
||||||
|
|
||||||
|
if (r0_square < 1.0) r0_square = 1.0;
|
||||||
|
|
||||||
|
if (clcg_param_.abs_diff && sqrt(rk_square)/n_size <= clcg_param_.epsilon)
|
||||||
|
{
|
||||||
|
CLCG_Progress(m, sqrt(rk_square)/n_size, clcg_param_, 0, ss);
|
||||||
|
return clcg_error_str(CLCG_ALREADY_OPTIMIZIED, ss);
|
||||||
|
}
|
||||||
|
else if (rk_square/r0_square <= clcg_param_.epsilon)
|
||||||
|
{
|
||||||
|
CLCG_Progress(m, rk_square/r0_square, clcg_param_, 0, ss);
|
||||||
|
return clcg_error_str(CLCG_ALREADY_OPTIMIZIED, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
double residual;
|
||||||
|
std::complex<double> ak, rhok2, sigma, omega, betak, Ass, AsAs;
|
||||||
|
|
||||||
|
size_t t = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if (clcg_param_.abs_diff) residual = sqrt(rk_square)/n_size;
|
||||||
|
else residual = rk_square/r0_square;
|
||||||
|
|
||||||
|
if (CLCG_Progress(m, residual, clcg_param_, t, ss))
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_STOP, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (residual <= clcg_param_.epsilon)
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_CONVERGENCE, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clcg_param_.max_iterations > 0 && t+1 > clcg_param_.max_iterations)
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_REACHED_MAX_ITERATIONS, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
t++;
|
||||||
|
|
||||||
|
CLCG_Ax(d1k, Ax, gctl::NoTrans, gctl::NoConj);
|
||||||
|
sigma = vecinner(r2k, Ax);
|
||||||
|
ak = rhok/sigma;
|
||||||
|
|
||||||
|
vecdiff(d2k, r1k, Ax, one_z, ak);
|
||||||
|
|
||||||
|
CLCG_Ax(d2k, Ad, gctl::NoTrans, gctl::NoConj);
|
||||||
|
Ass = vecinner(Ad, d2k);
|
||||||
|
AsAs = vecinner(Ad, Ad);
|
||||||
|
omega = Ass/AsAs;
|
||||||
|
|
||||||
|
vecdiff(r1k, d2k, Ad, one_z, omega);
|
||||||
|
vecadd(d2k, d1k, d2k, ak, omega);
|
||||||
|
vecapp(m, d2k, one_z);
|
||||||
|
|
||||||
|
rk_mod = vecinner(r1k, r1k);
|
||||||
|
rk_square = std::norm(rk_mod);
|
||||||
|
|
||||||
|
if (!vecvalid(m))
|
||||||
|
{
|
||||||
|
return clcg_error_str(CLCG_NAN_VALUE, ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
rhok2 = vecinner(r2k, r1k);
|
||||||
|
betak = rhok2*ak/(rhok*omega);
|
||||||
|
rhok = rhok2;
|
||||||
|
|
||||||
|
vecdiff(d1k, d1k, Ax, one_z, omega);
|
||||||
|
vecadd(d1k, r1k, d1k, one_z, betak);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clcg_error_str(CLCG_UNKNOWN_ERROR, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gctl::clcg_solver::cltfqmr(array<std::complex<double> > &m, const array<std::complex<double> > &B, std::ostream &ss)
|
void gctl::clcg_solver::cltfqmr(array<std::complex<double> > &m, const array<std::complex<double> > &B, std::ostream &ss)
|
||||||
|
@ -132,6 +132,13 @@ namespace gctl
|
|||||||
* applied to the non-constrained methods.
|
* applied to the non-constrained methods.
|
||||||
*/
|
*/
|
||||||
int abs_diff;
|
int abs_diff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal value for testing if a vector's module is bigger than the threshold.
|
||||||
|
* The default value is 1e-8
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
double lamda;
|
||||||
};
|
};
|
||||||
|
|
||||||
class clcg_solver
|
class clcg_solver
|
||||||
@ -143,7 +150,8 @@ namespace gctl
|
|||||||
|
|
||||||
// make them class variables are more suitable for repetitively usages
|
// make them class variables are more suitable for repetitively usages
|
||||||
array<std::complex<double> > r1k, r2k, d1k, d2k;
|
array<std::complex<double> > r1k, r2k, d1k, d2k;
|
||||||
array<std::complex<double> > Ax;
|
array<std::complex<double> > uk, qk, wk;
|
||||||
|
array<std::complex<double> > Ax, Ad;
|
||||||
|
|
||||||
void clcg_error_str(clcg_return_code err_code, std::ostream &ss);
|
void clcg_error_str(clcg_return_code err_code, std::ostream &ss);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user