Commit 9c33d2c1 authored by Kirill Terekhov's avatar Kirill Terekhov

Residual class annotation in inmost_autodiff.h

parent b2fb0655
......@@ -401,6 +401,86 @@ namespace INMOST
return ret;
}
#endif //USE_MESH
#if defined(USE_SOLVER)
void Residual::GetInterval(INMOST_DATA_ENUM_TYPE & start, INMOST_DATA_ENUM_TYPE & end) const
{
start = residual.GetFirstIndex();
end = residual.GetLastIndex();
}
void Residual::SetInterval(INMOST_DATA_ENUM_TYPE beg, INMOST_DATA_ENUM_TYPE end)
{
jacobian.SetInterval(beg,end);
residual.SetInterval(beg,end);
}
void Residual::ClearResidual()
{
for(Sparse::Vector::iterator it = residual.Begin(); it != residual.End(); ++it) (*it) = 0.0;
}
void Residual::ClearJacobian()
{
for(Sparse::Matrix::iterator it = jacobian.Begin(); it != jacobian.End(); ++it) it->Clear();
}
void Residual::Clear()
{
#if defined(USE_OMP)
#pragma omp for
#endif //USE_OMP
for(int k = (int)GetFirstIndex(); k < (int)GetLastIndex(); ++k)
{
residual[k] = 0.0;
jacobian[k].Clear();
}
}
INMOST_DATA_REAL_TYPE Residual::Norm()
{
INMOST_DATA_REAL_TYPE ret = 0;
#if defined(USE_OMP)
#pragma omp parallel for reduction(+:ret)
#endif //USE_OMP
for(int k = (int)GetFirstIndex(); k < (int)GetLastIndex(); ++k)
ret += residual[k]*residual[k];
#if defined(USE_MPI)
INMOST_DATA_REAL_TYPE tmp = ret;
MPI_Allreduce(&tmp, &ret, 1, INMOST_MPI_DATA_REAL_TYPE, MPI_SUM, jacobian.GetCommunicator());
#endif
return sqrt(ret);
}
Residual & Residual::operator =(Residual const & other)
{
jacobian = other.jacobian;
residual = other.residual;
return *this;
}
void Residual::Rescale()
{
#if defined(USE_OMP)
#pragma omp parallel for
#endif //USE_OMP
for(int k = (int)GetFirstIndex(); k < (int)GetLastIndex(); ++k)
{
INMOST_DATA_REAL_TYPE norm = 0.0;
for(INMOST_DATA_ENUM_TYPE q = 0; q < jacobian[k].Size(); ++q)
norm += jacobian[k].GetValue(q)*jacobian[k].GetValue(q);
norm = sqrt(norm);
if( norm )
{
norm = 1.0/norm;
residual[k] *= norm;
for(INMOST_DATA_ENUM_TYPE q = 0; q < jacobian[k].Size(); ++q)
jacobian[k].GetValue(q) *= norm;
}
}
}
Residual::Residual(std::string name, INMOST_DATA_ENUM_TYPE start, INMOST_DATA_ENUM_TYPE end, INMOST_MPI_Comm _comm)
: jacobian(name,start,end,_comm),residual(name,start,end,_comm)
{
}
Residual::Residual(const Residual & other)
: jacobian(other.jacobian), residual(other.residual)
{
}
#endif //USE_SOLVER
};
#endif //USE_AUTODIFF
......@@ -14,104 +14,78 @@ namespace INMOST
class Automatizator; //forward declaration
#if defined(USE_SOLVER)
/// The Residual class provides a representation for array of residuals of nonlinear equations.
/// By working with the residual class you automatically assemble right hand side and
/// the jacobian of a nonlinear system of equation.
/// Jacobian matrix has a sparse representation.
/// \todo
/// 1. Extend for hessian calculation.
class Residual
{
Sparse::Matrix jacobian;
Sparse::Vector residual;
Sparse::LockService locks;
Sparse::Matrix jacobian; ///< Jacobian matrix.
Sparse::Vector residual; ///< Right hand side vector.
Sparse::LockService locks; ///< Array of locks for openmp shared access.
public:
Residual(std::string name = "", INMOST_DATA_ENUM_TYPE start = 0, INMOST_DATA_ENUM_TYPE end = 0, INMOST_MPI_Comm _comm = INMOST_MPI_COMM_WORLD)
: jacobian(name,start,end,_comm),residual(name,start,end,_comm) {}
Residual(const Residual & other)
: jacobian(other.jacobian), residual(other.residual)
{}
Residual & operator =(Residual const & other)
{
jacobian = other.jacobian;
residual = other.residual;
return *this;
}
/// Constructor
/// @param name Name for the matrix and right hand side. Can be used to set options for linear solver.
/// @param start First index of the equation in the local partition. Use Automatizator::GetFirstIndex.
/// @param end Last index of the equation in the local partition. Use Automatizator::GetLastIndex.
/// @param _comm MPI Communicator.
Residual(std::string name = "", INMOST_DATA_ENUM_TYPE start = 0, INMOST_DATA_ENUM_TYPE end = 0, INMOST_MPI_Comm _comm = INMOST_MPI_COMM_WORLD);
/// Copy constructor.
/// \warning May be expensive if matrices are large.
Residual(const Residual & other);
/// Assignment operator.
/// \warning May be expensive if matrices are large.
Residual & operator =(Residual const & other);
/// Retrive jacobian matrix. Use in Sparse::Solver::Solve function.
Sparse::Matrix & GetJacobian() {return jacobian;}
/// Retrive jacobian matrix without right of modificaiton.
const Sparse::Matrix & GetJacobian() const {return jacobian;}
/// Retrive right hand side vector. Use in Sparse::Solver::Solve function.
Sparse::Vector & GetResidual() {return residual;}
/// Retrive right hand side vector without right of modification.
const Sparse::Vector & GetResidual() const {return residual;}
/// Retrive the first index of the equations in the local partition.
INMOST_DATA_ENUM_TYPE GetFirstIndex() const {return residual.GetFirstIndex();}
/// Retrive the last index of the equations in the local partition.
INMOST_DATA_ENUM_TYPE GetLastIndex() const {return residual.GetLastIndex();}
void GetInterval(INMOST_DATA_ENUM_TYPE & start, INMOST_DATA_ENUM_TYPE & end) const
{
start = residual.GetFirstIndex();
end = residual.GetLastIndex();
}
void SetInterval(INMOST_DATA_ENUM_TYPE beg, INMOST_DATA_ENUM_TYPE end)
{
jacobian.SetInterval(beg,end);
residual.SetInterval(beg,end);
}
multivar_expression_reference operator [](INMOST_DATA_ENUM_TYPE row)
{
return multivar_expression_reference(residual[row],&jacobian[row]);
}
void ClearResidual()
{
for(Sparse::Vector::iterator it = residual.Begin(); it != residual.End(); ++it) (*it) = 0.0;
}
void ClearJacobian()
{
for(Sparse::Matrix::iterator it = jacobian.Begin(); it != jacobian.End(); ++it)
it->Clear();
}
void Clear()
{
#if defined(USE_OMP)
#pragma omp for
#endif
for(int k = (int)GetFirstIndex(); k < (int)GetLastIndex(); ++k)
{
residual[k] = 0.0;
jacobian[k].Clear();
}
}
INMOST_DATA_REAL_TYPE Norm()
{
INMOST_DATA_REAL_TYPE ret = 0;
#if defined(USE_OMP)
#pragma omp parallel for reduction(+:ret)
#endif
for(int k = (int)GetFirstIndex(); k < (int)GetLastIndex(); ++k)
ret += residual[k]*residual[k];
#if defined(USE_MPI)
INMOST_DATA_REAL_TYPE tmp = ret;
MPI_Allreduce(&tmp, &ret, 1, INMOST_MPI_DATA_REAL_TYPE, MPI_SUM, jacobian.GetCommunicator());
#endif
return sqrt(ret);
}
/// Normalize entries in jacobian and right hand side
void Rescale()
{
#if defined(USE_OMP)
#pragma omp parallel for
#endif
for(int k = (int)GetFirstIndex(); k < (int)GetLastIndex(); ++k)
{
INMOST_DATA_REAL_TYPE norm = 0.0;
for(INMOST_DATA_ENUM_TYPE q = 0; q < jacobian[k].Size(); ++q)
norm += jacobian[k].GetValue(q)*jacobian[k].GetValue(q);
norm = sqrt(norm);
if( norm )
{
norm = 1.0/norm;
residual[k] *= norm;
for(INMOST_DATA_ENUM_TYPE q = 0; q < jacobian[k].Size(); ++q)
jacobian[k].GetValue(q) *= norm;
}
}
}
/// Retrive the first and the last indices of the equations in the local partition
/// @param start The first index of the equations will be recorded here.
/// @param end The last index of the equations will be recorded here.
void GetInterval(INMOST_DATA_ENUM_TYPE & start, INMOST_DATA_ENUM_TYPE & end) const;
/// Assign the new first and last indices of the equations in the local partition.
/// @param start The new first index of the equations.
/// @param end The new last index of the equations.
void SetInterval(INMOST_DATA_ENUM_TYPE beg, INMOST_DATA_ENUM_TYPE end);
/// Retrive a residual value and a jacobian row corresponding to certain equation.
/// @param row Equation number.
/// @return A structure that can be used in or assigned an automatic differentiation expression.
__INLINE multivar_expression_reference operator [](INMOST_DATA_ENUM_TYPE row) {return multivar_expression_reference(residual[row],&jacobian[row]);}
/// Zero out right hand side vector.
void ClearResidual();
/// Remove all entries in jacobian matrix.
void ClearJacobian();
/// Zero out right hand side vector and remove all entries in jacobian matrix.
void Clear();
/// Compute the second norm of the right hand side vector over all of the processors.
INMOST_DATA_REAL_TYPE Norm();
/// Normalize jacobian rows to unit second norms and scale right hand side accordingly.
void Rescale();
/// Initialize openmp locks.
void InitLocks() {locks.SetInterval(GetFirstIndex(),GetLastIndex());}
void Lock(INMOST_DATA_ENUM_TYPE pos) {if(!locks.Empty()) locks.Lock(pos);}
void UnLock(INMOST_DATA_ENUM_TYPE pos) {if(!locks.Empty()) locks.UnLock(pos);}
void TestLock(INMOST_DATA_ENUM_TYPE pos) {if(!locks.Empty()) locks.TestLock(pos);}
/// Lock an equation to avoid simultaneous shared access.
/// @param pos Equation number.
__INLINE void Lock(INMOST_DATA_ENUM_TYPE pos) {if(!locks.Empty()) locks.Lock(pos);}
/// UnLock an equation to allow simultaneous shared access.
/// @param pos Equation number.
__INLINE void UnLock(INMOST_DATA_ENUM_TYPE pos) {if(!locks.Empty()) locks.UnLock(pos);}
/// Try to lock the equation.
/// @param pos Equation number.
/// @return True if equation was locked.
__INLINE bool TestLock(INMOST_DATA_ENUM_TYPE pos) {if(!locks.Empty()) return locks.TestLock(pos); return false;}
};
#endif
#endif //USE_SOLVER
#if defined(USE_MESH)
/// The Automatizator class helps in defining primary unknowns of the model and
......@@ -123,26 +97,26 @@ namespace INMOST
/// In addition this class provides automatic differentiation with acceleration structures
/// that help evaluate expressions faster.
/// \todo
/// 1. UnRegisterTag.
/// 1. (test) UnRegisterTag.
/// 2. (test) Copy constructor.
class Automatizator
{
private:
static Automatizator * CurrentAutomatizator; //< Currently used automatizator for automatic differentiation acceleration structures.
static Automatizator * CurrentAutomatizator; ///< Currently used automatizator for automatic differentiation acceleration structures.
#if defined(USE_OMP)
std::vector<Sparse::RowMerger> merger; //< Automatic differentiation acceleration structures.
std::vector<Sparse::RowMerger> merger; ///< Automatic differentiation acceleration structures.
#else
Sparse::RowMerger merger; //< Automatic differentiation acceleration structures.
#endif
typedef struct{ Tag t, indices; MarkerType domain_mask; bool active;} tagdata; //< Pair of tag and it's mask marker.
typedef std::vector<tagdata> tag_enum; //< A type for an array of registered tags.
typedef std::vector<INMOST_DATA_ENUM_TYPE> del_enum; // A type for an array of deleted positions.
Sparse::RowMerger merger; ///< Automatic differentiation acceleration structures.
#endif //USE_OMP
typedef struct{ Tag t, indices; MarkerType domain_mask; bool active;} tagdata; ///< Pair of tag and it's mask marker.
typedef std::vector<tagdata> tag_enum; ///< A type for an array of registered tags.
typedef std::vector<INMOST_DATA_ENUM_TYPE> del_enum; ///< A type for an array of deleted positions.
private:
std::string name; //< Name of the automatizator.
del_enum del_tags; //< Array of deleted positions.
tag_enum reg_tags; //< Array of registered tags.
INMOST_DATA_ENUM_TYPE first_num; //< First index in unknowns of locally owned elements.
INMOST_DATA_ENUM_TYPE last_num; //< Last index in unknowns of locally owned elements.
std::string name; ///< Name of the automatizator.
del_enum del_tags; ///< Array of deleted positions.
tag_enum reg_tags; ///< Array of registered tags.
INMOST_DATA_ENUM_TYPE first_num; ///< First index in unknowns of locally owned elements.
INMOST_DATA_ENUM_TYPE last_num; ///< Last index in unknowns of locally owned elements.
public:
/// Make a copy.
/// \warning
......@@ -218,13 +192,13 @@ namespace INMOST
/// Retrive acceleration structure for automatic differentiation.
/// This structure can be used for operations on the matrix.
/// @return Acceleration structure.
Sparse::RowMerger & GetMerger()
__INLINE Sparse::RowMerger & GetMerger()
{
#if defined(USE_OMP)
return merger[omp_get_thread_num()];
#else
return merger;
#endif
#endif //USE_OMP
}
/// Remove global current automatizator used to set acceleration structures for automatic differentation.
static void RemoveCurrent() {CurrentAutomatizator = NULL;}
......@@ -239,7 +213,7 @@ namespace INMOST
/// @return An array with indices corresponding to all registered tags.
std::vector<INMOST_DATA_ENUM_TYPE> ListRegisteredTags() const;
};
#endif
#endif //USE_MESH
} //namespace INMOST
#endif //USE_AUTODIFF
......
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