Commit da034104 authored by Kirill Terekhov's avatar Kirill Terekhov

Features

BCGStab(L) solver: perturbation of r_tilde to avoid breakdown.
Possibility to annotate matrix.
parent 63eee555
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "inmost_common.h" #include "inmost_common.h"
//#include "solver_prototypes.hpp" //#include "solver_prototypes.hpp"
#define MTX_ALLOW_ANNOTATION
#define DEFAULT_ADDITIVE_SCHWARTZ_OVERLAP 1 #define DEFAULT_ADDITIVE_SCHWARTZ_OVERLAP 1
#define DEFAULT_ABSOLUTE_TOLERANCE 1.0e-5 #define DEFAULT_ABSOLUTE_TOLERANCE 1.0e-5
#define DEFAULT_RELATIVE_TOLERANCE 1.0e-12 #define DEFAULT_RELATIVE_TOLERANCE 1.0e-12
...@@ -210,7 +211,9 @@ namespace INMOST ...@@ -210,7 +211,9 @@ namespace INMOST
class Row class Row
{ {
public: public:
#if defined(MTX_ALLOW_ANNOTATION)
std::string annotation;
#endif
/// Entry of the sparse matrix row. /// Entry of the sparse matrix row.
typedef struct entry_s typedef struct entry_s
{ {
...@@ -251,35 +254,25 @@ namespace INMOST ...@@ -251,35 +254,25 @@ namespace INMOST
bool marker; bool marker;
Entries data; Entries data;
public: public:
std::string GetAnnotation();
void SetAnnotation(std::string input);
void Report() {data.report_addr();} void Report() {data.report_addr();}
void SetMarker() { marker = true; } void SetMarker() { marker = true; }
void RemMarker() { marker = false; } void RemMarker() { marker = false; }
bool GetMarker() { return marker; } bool GetMarker() { return marker; }
Row() :data() Row();
{ Row(const Row & other);
#if defined(USE_OMP) Row(entry * pbegin, entry * pend);
omp_init_lock(&lock); bool HaveLock()
#endif {
modified_pattern = marker = false;
}
Row(const Row & other) :marker(other.marker),data(other.data)
{
//std::cout << __FUNCTION__ << " ";
//for(iterator it = Begin(); it != End(); ++it) std::cout << it->first << "," << it->second << " ";
//std::cout << std::endl;
#if defined(USE_OMP)
omp_init_lock(&lock);
#endif
modified_pattern = other.modified_pattern;
}
Row(entry * pbegin, entry * pend) :data(pbegin, pend)
{
#if defined(USE_OMP) #if defined(USE_OMP)
omp_init_lock(&lock); return true;
#else
return false;
#endif #endif
modified_pattern = true; marker = false; }
} void Lock()
void Lock()
{ {
#if defined(USE_OMP) #if defined(USE_OMP)
omp_set_lock(&lock); omp_set_lock(&lock);
...@@ -291,8 +284,8 @@ namespace INMOST ...@@ -291,8 +284,8 @@ namespace INMOST
omp_unset_lock(&lock); omp_unset_lock(&lock);
#endif #endif
} }
~Row() {} ~Row();
Row & operator = (Row const & other) { data = other.data; marker = other.marker; return *this; } Row & operator = (Row const & other);
/// The operator [] used to fill the sparse matrix row, but not to access individual elements of the row. /// The operator [] used to fill the sparse matrix row, but not to access individual elements of the row.
INMOST_DATA_REAL_TYPE & operator [](INMOST_DATA_ENUM_TYPE i) // use to fill matrix, not to access individual elements INMOST_DATA_REAL_TYPE & operator [](INMOST_DATA_ENUM_TYPE i) // use to fill matrix, not to access individual elements
{ {
...@@ -325,7 +318,7 @@ namespace INMOST ...@@ -325,7 +318,7 @@ namespace INMOST
//void Reserve(INMOST_DATA_ENUM_TYPE num) { data.reserve(num);} //void Reserve(INMOST_DATA_ENUM_TYPE num) { data.reserve(num);}
/// Clear all data of the current row. /// Clear all data of the current row.
void Clear() { data.clear(); } void Clear() { data.clear(); }
void Swap(Solver::Row & other) { data.swap(other.data); bool tmp = marker; marker = other.marker; other.marker = tmp; } void Swap(Solver::Row & other);
/// The size of the sparse row, i.e. the total number of nonzero elements. /// The size of the sparse row, i.e. the total number of nonzero elements.
INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); } INMOST_DATA_ENUM_TYPE Size() const { return static_cast<INMOST_DATA_ENUM_TYPE>(data.size()); }
INMOST_DATA_ENUM_TYPE & GetIndex(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->first;} INMOST_DATA_ENUM_TYPE & GetIndex(INMOST_DATA_ENUM_TYPE k) {assert(k < data.size()); return (data.begin()+k)->first;}
......
...@@ -1295,8 +1295,13 @@ namespace INMOST ...@@ -1295,8 +1295,13 @@ namespace INMOST
mtx.precision(15); mtx.precision(15);
for(iterator it = Begin(); it != End(); ++it) for(iterator it = Begin(); it != End(); ++it)
{ {
#if defined(MTX_ALLOW_ANNOTATION)
if( it->GetAnnotation() != "" ) mtx << "% " << it->GetAnnotation() << "\n";
#endif
for(Row::iterator jt = it->Begin(); jt != it->End(); ++jt) for(Row::iterator jt = it->Begin(); jt != it->End(); ++jt)
mtx << row << " " << jt->first+1 << " " << jt->second << std::endl; {
mtx << row << " " << jt->first+1 << " " << jt->second << "\n";
}
++row; ++row;
} }
#if defined(USE_MPI) && defined(USE_MPI_FILE) // USE_MPI2? #if defined(USE_MPI) && defined(USE_MPI_FILE) // USE_MPI2?
...@@ -2874,6 +2879,76 @@ namespace INMOST ...@@ -2874,6 +2879,76 @@ namespace INMOST
} }
else return 0.0; else return 0.0;
} }
std::string Solver::Row::GetAnnotation()
{
#if defined(MTX_ALLOW_ANNOTATION)
return annotation;
#else
return "";
#endif
}
void Solver::Row::SetAnnotation(std::string input)
{
#if defined(MTX_ALLOW_ANNOTATION)
annotation = input;
#endif
}
Solver::Row::Row() :data()
{
#if defined(MTX_ALLOW_ANNOTATION)
annotation = "";
#endif
#if defined(USE_OMP)
omp_init_lock(&lock);
#endif
modified_pattern = marker = false;
}
Solver::Row::Row(const Row & other) :marker(other.marker),data(other.data)
{
#if defined(MTX_ALLOW_ANNOTATION)
annotation = other.annotation;
#endif
#if defined(USE_OMP)
omp_init_lock(&lock);
#endif
modified_pattern = other.modified_pattern;
}
Solver::Row::Row(entry * pbegin, entry * pend) :data(pbegin, pend)
{
#if defined(MTX_ALLOW_ANNOTATION)
annotation = "";
#endif
#if defined(USE_OMP)
omp_init_lock(&lock);
#endif
modified_pattern = true; marker = false;
}
Solver::Row & Solver::Row::operator = (Row const & other)
{
data = other.data;
marker = other.marker;
#if defined(MTX_ALLOW_ANNOTATION)
annotation = other.annotation;
#endif
return *this;
}
Solver::Row::~Row()
{
}
void Solver::Row::Swap(Solver::Row & other)
{
data.swap(other.data);
bool tmp = marker;
marker = other.marker;
other.marker = tmp;
#if defined(MTX_ALLOW_ANNOTATION)
annotation.swap(other.annotation);
#endif
#if defined(USE_OMP)
//swap locks?
#endif
}
} }
#endif #endif
...@@ -433,6 +433,7 @@ namespace INMOST ...@@ -433,6 +433,7 @@ namespace INMOST
#endif //PSEUDOINVERSE #endif //PSEUDOINVERSE
class BCGSL_solver : public IterativeMethod class BCGSL_solver : public IterativeMethod
{ {
INMOST_DATA_REAL_TYPE length, r_tilde_norm;
INMOST_DATA_REAL_TYPE rtol, atol, divtol, last_resid; INMOST_DATA_REAL_TYPE rtol, atol, divtol, last_resid;
INMOST_DATA_ENUM_TYPE iters, maxits, l, last_it; INMOST_DATA_ENUM_TYPE iters, maxits, l, last_it;
INMOST_DATA_REAL_TYPE resid; INMOST_DATA_REAL_TYPE resid;
...@@ -608,12 +609,12 @@ namespace INMOST ...@@ -608,12 +609,12 @@ namespace INMOST
resid += r[0][k]*r[0][k]; resid += r[0][k]*r[0][k];
info->Integrate(&resid,1); info->Integrate(&resid,1);
//info->ScalarProd(r[0],r[0],vlocbeg,vlocend,resid); //resid = dot(r[0],r[0]) //info->ScalarProd(r[0],r[0],vlocbeg,vlocend,resid); //resid = dot(r[0],r[0])
last_resid = resid = resid0 = sqrt(resid/rhs_norm); //resid = sqrt(dot(r[0],r[0])
#if defined(USE_OMP) #if defined(USE_OMP)
#pragma omp parallel for #pragma omp parallel for
#endif #endif
for(INMOST_DATA_INTEGER_TYPE k = ivbeg; k < ivend; ++k) // r_tilde = r[0] / dot(r[0],r[0]) for(INMOST_DATA_INTEGER_TYPE k = ivbeg; k < ivend; ++k) // r_tilde = r[0] / dot(r[0],r[0])
r_tilde[k] /= resid; r_tilde[k] /= resid;
last_resid = resid = resid0 = sqrt(resid/rhs_norm); //resid = sqrt(dot(r[0],r[0])
last_it = 0; last_it = 0;
#if defined(REPORT_RESIDUAL) #if defined(REPORT_RESIDUAL)
if( info->GetRank() == 0 ) if( info->GetRank() == 0 )
...@@ -652,6 +653,56 @@ namespace INMOST ...@@ -652,6 +653,56 @@ namespace INMOST
tt = Timer(); tt = Timer();
for(INMOST_DATA_ENUM_TYPE j = 0; j < l; j++) for(INMOST_DATA_ENUM_TYPE j = 0; j < l; j++)
{ {
if( false )
{
perturbate:
//std::cout << "Rescue solver by perturbing orthogonal direction!" << std::endl;
//Compute length of the vector
#if defined(USE_OMP)
#pragma omp single
#endif
{
length = static_cast<INMOST_DATA_REAL_TYPE>(ivlocend-ivlocbeg);
r_tilde_norm = 0.0;
}
info->Integrate(&length,1);
//perform perturbation (note that rand() with openmp may give identical sequences of random values
#if defined(USE_OMP)
#pragma omp for
#endif
for(INMOST_DATA_INTEGER_TYPE k = ivlocbeg; k < ivlocend; ++k)
{
INMOST_DATA_REAL_TYPE unit = 2*static_cast<INMOST_DATA_REAL_TYPE>(rand())/static_cast<INMOST_DATA_REAL_TYPE>(RAND_MAX)-1.0;
r_tilde[k] += unit/length;
}
//compute norm for orthogonal vector
#if defined(USE_OMP)
#pragma omp for reduction(+:r_tilde_norm)
#endif
for(INMOST_DATA_INTEGER_TYPE k = ivlocbeg; k < ivlocend; ++k)
r_tilde_norm += r_tilde[k]*r_tilde[k];
r_tilde_norm = sqrt(r_tilde_norm);
info->Integrate(&r_tilde_norm,1);
//normalize orthogonal vector to unity
#if defined(USE_OMP)
#pragma omp for
#endif
for(INMOST_DATA_INTEGER_TYPE k = ivlocbeg; k < ivlocend; ++k)
r_tilde[k] /= r_tilde_norm;
//Recompute rho1
/*
#if defined(USE_OMP)
#pragma omp single
#endif
rho1 = 0;
#if defined(USE_OMP)
#pragma omp for reduction(+:rho1)
#endif
for(INMOST_DATA_INTEGER_TYPE k = ivlocbeg; k < ivlocend; ++k)
rho1+= r[j][k]*r_tilde[k];
info->Integrate(&rho1,1);
*/
}
#if defined(USE_OMP) #if defined(USE_OMP)
#pragma omp single #pragma omp single
#endif #endif
...@@ -662,6 +713,11 @@ namespace INMOST ...@@ -662,6 +713,11 @@ namespace INMOST
for(INMOST_DATA_INTEGER_TYPE k = ivlocbeg; k < ivlocend; ++k) for(INMOST_DATA_INTEGER_TYPE k = ivlocbeg; k < ivlocend; ++k)
rho1+= r[j][k]*r_tilde[k]; rho1+= r[j][k]*r_tilde[k];
info->Integrate(&rho1,1); info->Integrate(&rho1,1);
if( fabs(rho1) < 1.0e-50 )
{
//std::cout << "Asking to perturbate r_tilde since rho1 is too small " << rho1 << std::endl;
goto perturbate;
}
//info->ScalarProd(r[j],r_tilde,vlocbeg,vlocend,rho1); // rho1 = dot(r[j],r_tilde) //info->ScalarProd(r[j],r_tilde,vlocbeg,vlocend,rho1); // rho1 = dot(r[j],r_tilde)
#if defined(USE_OMP) #if defined(USE_OMP)
#pragma omp single #pragma omp single
...@@ -683,6 +739,7 @@ namespace INMOST ...@@ -683,6 +739,7 @@ namespace INMOST
if( beta != beta ) if( beta != beta )
{ {
//std::cout << "alpha " << alpha << " rho1 " << rho1 << " rho0 " << rho0 << " beta " << beta << std::endl;
#if defined(USE_OMP) #if defined(USE_OMP)
#pragma omp single #pragma omp single
#endif #endif
...@@ -719,6 +776,12 @@ namespace INMOST ...@@ -719,6 +776,12 @@ namespace INMOST
info->Integrate(&eta,1); info->Integrate(&eta,1);
//info->ScalarProd(u[j+1],r_tilde,vlocbeg,vlocend,eta); //eta = dot(u[j+1],r_tilde) //info->ScalarProd(u[j+1],r_tilde,vlocbeg,vlocend,eta); //eta = dot(u[j+1],r_tilde)
if( fabs(eta) < 1.0e-50 )
{
//std::cout << "Asking to perturbate r_tilde since eta is too small " << eta << std::endl;
goto perturbate;
}
#if defined(USE_OMP) #if defined(USE_OMP)
#pragma omp single #pragma omp single
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment