mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Apply clang-format
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -14,56 +14,66 @@
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
/** \ingroup SparseLU_Module
|
||||
* \class SparseLUImpl
|
||||
* Base class for sparseLU
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
class SparseLUImpl
|
||||
{
|
||||
public:
|
||||
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
|
||||
typedef Matrix<StorageIndex,Dynamic,1> IndexVector;
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> ScalarMatrix;
|
||||
typedef Map<ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock;
|
||||
typedef typename ScalarVector::RealScalar RealScalar;
|
||||
typedef Ref<Matrix<Scalar,Dynamic,1> > BlockScalarVector;
|
||||
typedef Ref<Matrix<StorageIndex,Dynamic,1> > BlockIndexVector;
|
||||
typedef LU_GlobalLU_t<IndexVector, ScalarVector> GlobalLU_t;
|
||||
typedef SparseMatrix<Scalar,ColMajor,StorageIndex> MatrixType;
|
||||
|
||||
protected:
|
||||
template <typename VectorType>
|
||||
Index expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions);
|
||||
Index memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu);
|
||||
template <typename VectorType>
|
||||
Index memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions);
|
||||
void heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end);
|
||||
void relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end);
|
||||
Index snode_dfs(const Index jcol, const Index kcol,const MatrixType& mat, IndexVector& xprune, IndexVector& marker, GlobalLU_t& glu);
|
||||
Index snode_bmod (const Index jcol, const Index fsupc, ScalarVector& dense, GlobalLU_t& glu);
|
||||
Index pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow, GlobalLU_t& glu);
|
||||
template <typename Traits>
|
||||
void dfs_kernel(const StorageIndex jj, IndexVector& perm_r,
|
||||
Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
|
||||
Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
|
||||
IndexVector& xplore, GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits);
|
||||
void panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg, ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
|
||||
|
||||
void panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg, ScalarVector& dense, ScalarVector& tempv, IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu);
|
||||
Index column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg, BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
|
||||
Index column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv, BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu);
|
||||
Index copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep, BlockIndexVector repfnz ,IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu);
|
||||
void pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu);
|
||||
void countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu);
|
||||
void fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu);
|
||||
|
||||
template<typename , typename >
|
||||
friend struct column_dfs_traits;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // namespace Eigen
|
||||
/** \ingroup SparseLU_Module
|
||||
* \class SparseLUImpl
|
||||
* Base class for sparseLU
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
class SparseLUImpl {
|
||||
public:
|
||||
typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
|
||||
typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> ScalarMatrix;
|
||||
typedef Map<ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock;
|
||||
typedef typename ScalarVector::RealScalar RealScalar;
|
||||
typedef Ref<Matrix<Scalar, Dynamic, 1> > BlockScalarVector;
|
||||
typedef Ref<Matrix<StorageIndex, Dynamic, 1> > BlockIndexVector;
|
||||
typedef LU_GlobalLU_t<IndexVector, ScalarVector> GlobalLU_t;
|
||||
typedef SparseMatrix<Scalar, ColMajor, StorageIndex> MatrixType;
|
||||
|
||||
protected:
|
||||
template <typename VectorType>
|
||||
Index expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions);
|
||||
Index memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu);
|
||||
template <typename VectorType>
|
||||
Index memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions);
|
||||
void heap_relax_snode(const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants,
|
||||
IndexVector& relax_end);
|
||||
void relax_snode(const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants,
|
||||
IndexVector& relax_end);
|
||||
Index snode_dfs(const Index jcol, const Index kcol, const MatrixType& mat, IndexVector& xprune, IndexVector& marker,
|
||||
GlobalLU_t& glu);
|
||||
Index snode_bmod(const Index jcol, const Index fsupc, ScalarVector& dense, GlobalLU_t& glu);
|
||||
Index pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c,
|
||||
Index& pivrow, GlobalLU_t& glu);
|
||||
template <typename Traits>
|
||||
void dfs_kernel(const StorageIndex jj, IndexVector& perm_r, Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
|
||||
Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
|
||||
IndexVector& xplore, GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits);
|
||||
void panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg,
|
||||
ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz,
|
||||
IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
|
||||
|
||||
void panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg, ScalarVector& dense,
|
||||
ScalarVector& tempv, IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu);
|
||||
Index column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg,
|
||||
BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune,
|
||||
IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu);
|
||||
Index column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv,
|
||||
BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu);
|
||||
Index copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep, BlockIndexVector repfnz,
|
||||
IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu);
|
||||
void pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg,
|
||||
const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu);
|
||||
void countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu);
|
||||
void fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu);
|
||||
|
||||
template <typename, typename>
|
||||
friend struct column_dfs_traits;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // namespace Eigen
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]memory.c files in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]memory.c files in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 3.1) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -36,194 +36,175 @@
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
|
||||
enum { LUNoMarker = 3 };
|
||||
enum {emptyIdxLU = -1};
|
||||
inline Index LUnumTempV(Index& m, Index& w, Index& t, Index& b)
|
||||
{
|
||||
return (std::max)(m, (t+b)*w);
|
||||
enum { emptyIdxLU = -1 };
|
||||
inline Index LUnumTempV(Index& m, Index& w, Index& t, Index& b) { return (std::max)(m, (t + b) * w); }
|
||||
|
||||
template <typename Scalar>
|
||||
inline Index LUTempSpace(Index& m, Index& w) {
|
||||
return (2 * w + 4 + LUNoMarker) * m * sizeof(Index) + (w + 1) * m * sizeof(Scalar);
|
||||
}
|
||||
|
||||
template< typename Scalar>
|
||||
inline Index LUTempSpace(Index&m, Index& w)
|
||||
{
|
||||
return (2*w + 4 + LUNoMarker) * m * sizeof(Index) + (w + 1) * m * sizeof(Scalar);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Expand the existing storage to accommodate more fill-ins
|
||||
* \param vec Valid pointer to the vector to allocate or expand
|
||||
* \param[in,out] length At input, contain the current length of the vector that is to be increased. At output, length of the newly allocated vector
|
||||
* \param[in] nbElts Current number of elements in the factors
|
||||
* \param keep_prev 1: use length and do not expand the vector; 0: compute new_len and expand
|
||||
* \param[in,out] num_expansions Number of times the memory has been expanded
|
||||
*/
|
||||
/**
|
||||
* Expand the existing storage to accommodate more fill-ins
|
||||
* \param vec Valid pointer to the vector to allocate or expand
|
||||
* \param[in,out] length At input, contain the current length of the vector that is to be increased. At output, length
|
||||
* of the newly allocated vector \param[in] nbElts Current number of elements in the factors \param keep_prev 1: use
|
||||
* length and do not expand the vector; 0: compute new_len and expand \param[in,out] num_expansions Number of times the
|
||||
* memory has been expanded
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
template <typename VectorType>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev, Index& num_expansions)
|
||||
{
|
||||
|
||||
float alpha = 1.5; // Ratio of the memory increase
|
||||
Index new_len; // New size of the allocated memory
|
||||
|
||||
if(num_expansions == 0 || keep_prev)
|
||||
new_len = length ; // First time allocate requested
|
||||
else
|
||||
new_len = (std::max)(length+1,Index(alpha * length));
|
||||
|
||||
VectorType old_vec; // Temporary vector to hold the previous values
|
||||
if (nbElts > 0 )
|
||||
old_vec = vec.segment(0,nbElts);
|
||||
|
||||
//Allocate or expand the current vector
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev,
|
||||
Index& num_expansions) {
|
||||
float alpha = 1.5; // Ratio of the memory increase
|
||||
Index new_len; // New size of the allocated memory
|
||||
|
||||
if (num_expansions == 0 || keep_prev)
|
||||
new_len = length; // First time allocate requested
|
||||
else
|
||||
new_len = (std::max)(length + 1, Index(alpha * length));
|
||||
|
||||
VectorType old_vec; // Temporary vector to hold the previous values
|
||||
if (nbElts > 0) old_vec = vec.segment(0, nbElts);
|
||||
|
||||
// Allocate or expand the current vector
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
vec.resize(new_len);
|
||||
vec.resize(new_len);
|
||||
}
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
catch(std::bad_alloc& )
|
||||
catch (std::bad_alloc&)
|
||||
#else
|
||||
if(!vec.size())
|
||||
if (!vec.size())
|
||||
#endif
|
||||
{
|
||||
if (!num_expansions)
|
||||
{
|
||||
if (!num_expansions) {
|
||||
// First time to allocate from LUMemInit()
|
||||
// Let LUMemInit() deals with it.
|
||||
return -1;
|
||||
}
|
||||
if (keep_prev)
|
||||
{
|
||||
if (keep_prev) {
|
||||
// In this case, the memory length should not not be reduced
|
||||
return new_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reduce the size and increase again
|
||||
Index tries = 0; // Number of attempts
|
||||
do
|
||||
{
|
||||
alpha = (alpha + 1)/2;
|
||||
new_len = (std::max)(length+1,Index(alpha * length));
|
||||
} else {
|
||||
// Reduce the size and increase again
|
||||
Index tries = 0; // Number of attempts
|
||||
do {
|
||||
alpha = (alpha + 1) / 2;
|
||||
new_len = (std::max)(length + 1, Index(alpha * length));
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
vec.resize(new_len);
|
||||
vec.resize(new_len);
|
||||
}
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
catch(std::bad_alloc& )
|
||||
catch (std::bad_alloc&)
|
||||
#else
|
||||
if (!vec.size())
|
||||
#endif
|
||||
{
|
||||
tries += 1;
|
||||
if ( tries > 10) return new_len;
|
||||
tries += 1;
|
||||
if (tries > 10) return new_len;
|
||||
}
|
||||
} while (!vec.size());
|
||||
}
|
||||
}
|
||||
//Copy the previous values to the newly allocated space
|
||||
if (nbElts > 0)
|
||||
vec.segment(0, nbElts) = old_vec;
|
||||
|
||||
|
||||
length = new_len;
|
||||
if(num_expansions) ++num_expansions;
|
||||
return 0;
|
||||
// Copy the previous values to the newly allocated space
|
||||
if (nbElts > 0) vec.segment(0, nbElts) = old_vec;
|
||||
|
||||
length = new_len;
|
||||
if (num_expansions) ++num_expansions;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocate various working space for the numerical factorization phase.
|
||||
* \param m number of rows of the input matrix
|
||||
* \param n number of columns
|
||||
* \param annz number of initial nonzeros in the matrix
|
||||
* \param m number of rows of the input matrix
|
||||
* \param n number of columns
|
||||
* \param annz number of initial nonzeros in the matrix
|
||||
* \param lwork if lwork=-1, this routine returns an estimated size of the required memory
|
||||
* \param glu persistent data to facilitate multiple factors : will be deleted later ??
|
||||
* \param fillratio estimated ratio of fill in the factors
|
||||
* \param panel_size Size of a panel
|
||||
* \return an estimated size of the required memory if lwork = -1; otherwise, return the size of actually allocated memory when allocation failed, and 0 on success
|
||||
* \note Unlike SuperLU, this routine does not support successive factorization with the same pattern and the same row permutation
|
||||
* \return an estimated size of the required memory if lwork = -1; otherwise, return the size of actually allocated
|
||||
* memory when allocation failed, and 0 on success \note Unlike SuperLU, this routine does not support successive
|
||||
* factorization with the same pattern and the same row permutation
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::memInit(Index m, Index n, Index annz, Index lwork, Index fillratio, Index panel_size, GlobalLU_t& glu)
|
||||
{
|
||||
Index& num_expansions = glu.num_expansions; //No memory expansions so far
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::memInit(Index m, Index n, Index annz, Index lwork, Index fillratio,
|
||||
Index panel_size, GlobalLU_t& glu) {
|
||||
Index& num_expansions = glu.num_expansions; // No memory expansions so far
|
||||
num_expansions = 0;
|
||||
glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz+1) / n, m) * n; // estimated number of nonzeros in U
|
||||
glu.nzlmax = (std::max)(Index(4), fillratio) * (annz+1) / 4; // estimated nnz in L factor
|
||||
glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz + 1) / n, m) * n; // estimated number of nonzeros in U
|
||||
glu.nzlmax = (std::max)(Index(4), fillratio) * (annz + 1) / 4; // estimated nnz in L factor
|
||||
// Return the estimated size to the user if necessary
|
||||
Index tempSpace;
|
||||
tempSpace = (2*panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
|
||||
if (lwork == emptyIdxLU)
|
||||
{
|
||||
tempSpace = (2 * panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
|
||||
if (lwork == emptyIdxLU) {
|
||||
Index estimated_size;
|
||||
estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace
|
||||
+ (glu.nzlmax + glu.nzumax) * sizeof(Index) + (glu.nzlumax+glu.nzumax) * sizeof(Scalar) + n;
|
||||
estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace + (glu.nzlmax + glu.nzumax) * sizeof(Index) +
|
||||
(glu.nzlumax + glu.nzumax) * sizeof(Scalar) + n;
|
||||
return estimated_size;
|
||||
}
|
||||
|
||||
// Setup the required space
|
||||
|
||||
|
||||
// Setup the required space
|
||||
|
||||
// First allocate Integer pointers for L\U factors
|
||||
glu.xsup.resize(n+1);
|
||||
glu.supno.resize(n+1);
|
||||
glu.xlsub.resize(n+1);
|
||||
glu.xlusup.resize(n+1);
|
||||
glu.xusub.resize(n+1);
|
||||
glu.xsup.resize(n + 1);
|
||||
glu.supno.resize(n + 1);
|
||||
glu.xlsub.resize(n + 1);
|
||||
glu.xlusup.resize(n + 1);
|
||||
glu.xusub.resize(n + 1);
|
||||
|
||||
// Reserve memory for L/U factors
|
||||
do
|
||||
{
|
||||
if( (expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions)<0)
|
||||
|| (expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions)<0)
|
||||
|| (expand<IndexVector> (glu.lsub, glu.nzlmax, 0, 0, num_expansions)<0)
|
||||
|| (expand<IndexVector> (glu.usub, glu.nzumax, 0, 1, num_expansions)<0) )
|
||||
{
|
||||
//Reduce the estimated size and retry
|
||||
do {
|
||||
if ((expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions) < 0) ||
|
||||
(expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions) < 0) ||
|
||||
(expand<IndexVector>(glu.lsub, glu.nzlmax, 0, 0, num_expansions) < 0) ||
|
||||
(expand<IndexVector>(glu.usub, glu.nzumax, 0, 1, num_expansions) < 0)) {
|
||||
// Reduce the estimated size and retry
|
||||
glu.nzlumax /= 2;
|
||||
glu.nzumax /= 2;
|
||||
glu.nzlmax /= 2;
|
||||
if (glu.nzlumax < annz ) return glu.nzlumax;
|
||||
if (glu.nzlumax < annz) return glu.nzlumax;
|
||||
}
|
||||
} while (!glu.lusup.size() || !glu.ucol.size() || !glu.lsub.size() || !glu.usub.size());
|
||||
|
||||
|
||||
++num_expansions;
|
||||
return 0;
|
||||
|
||||
} // end LuMemInit
|
||||
|
||||
/**
|
||||
* \brief Expand the existing storage
|
||||
* \param vec vector to expand
|
||||
} // end LuMemInit
|
||||
|
||||
/**
|
||||
* \brief Expand the existing storage
|
||||
* \param vec vector to expand
|
||||
* \param[in,out] maxlen On input, previous size of vec (Number of elements to copy ). on output, new size
|
||||
* \param nbElts current number of elements in the vector.
|
||||
* \param memtype Type of the element to expand
|
||||
* \param num_expansions Number of expansions
|
||||
* \param num_expansions Number of expansions
|
||||
* \return 0 on success, > 0 size of the memory allocated so far
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
template <typename VectorType>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype, Index& num_expansions)
|
||||
{
|
||||
Index failed_size;
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype,
|
||||
Index& num_expansions) {
|
||||
Index failed_size;
|
||||
if (memtype == USUB)
|
||||
failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
|
||||
failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
|
||||
else
|
||||
failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 0, num_expansions);
|
||||
|
||||
if (failed_size)
|
||||
return failed_size;
|
||||
|
||||
return 0 ;
|
||||
if (failed_size) return failed_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
#endif // EIGEN_SPARSELU_MEMORY
|
||||
} // end namespace Eigen
|
||||
#endif // EIGEN_SPARSELU_MEMORY
|
||||
|
||||
@@ -7,26 +7,26 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
/*
|
||||
* NOTE: This file comes from a partly modified version of files slu_[s,d,c,z]defs.h
|
||||
* -- SuperLU routine (version 4.1) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
* November, 2010
|
||||
*
|
||||
*
|
||||
* Global data structures used in LU factorization -
|
||||
*
|
||||
*
|
||||
* nsuper: #supernodes = nsuper + 1, numbered [0, nsuper].
|
||||
* (xsup,supno): supno[i] is the supernode no to which i belongs;
|
||||
* xsup(s) points to the beginning of the s-th supernode.
|
||||
* e.g. supno 0 1 2 2 3 3 3 4 4 4 4 4 (n=12)
|
||||
* xsup 0 1 2 4 7 12
|
||||
* Note: dfs will be performed on supernode rep. relative to the new
|
||||
* Note: dfs will be performed on supernode rep. relative to the new
|
||||
* row pivoting ordering
|
||||
*
|
||||
* (xlsub,lsub): lsub[*] contains the compressed subscript of
|
||||
* rectangular supernodes; xlsub[j] points to the starting
|
||||
* location of the j-th column in lsub[*]. Note that xlsub
|
||||
* location of the j-th column in lsub[*]. Note that xlsub
|
||||
* is indexed by column.
|
||||
* Storage: original row subscripts
|
||||
*
|
||||
@@ -74,40 +74,40 @@
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
enum MemType {LUSUP, UCOL, LSUB, USUB, LLVL, ULVL};
|
||||
enum MemType { LUSUP, UCOL, LSUB, USUB, LLVL, ULVL };
|
||||
|
||||
template <typename IndexVector, typename ScalarVector>
|
||||
struct LU_GlobalLU_t {
|
||||
typedef typename IndexVector::Scalar StorageIndex;
|
||||
IndexVector xsup; //First supernode column ... xsup(s) points to the beginning of the s-th supernode
|
||||
IndexVector supno; // Supernode number corresponding to this column (column to supernode mapping)
|
||||
ScalarVector lusup; // nonzero values of L ordered by columns
|
||||
IndexVector lsub; // Compressed row indices of L rectangular supernodes.
|
||||
IndexVector xlusup; // pointers to the beginning of each column in lusup
|
||||
IndexVector xlsub; // pointers to the beginning of each column in lsub
|
||||
Index nzlmax; // Current max size of lsub
|
||||
Index nzlumax; // Current max size of lusup
|
||||
ScalarVector ucol; // nonzero values of U ordered by columns
|
||||
IndexVector usub; // row indices of U columns in ucol
|
||||
IndexVector xusub; // Pointers to the beginning of each column of U in ucol
|
||||
Index nzumax; // Current max size of ucol
|
||||
Index n; // Number of columns in the matrix
|
||||
Index num_expansions;
|
||||
typedef typename IndexVector::Scalar StorageIndex;
|
||||
IndexVector xsup; // First supernode column ... xsup(s) points to the beginning of the s-th supernode
|
||||
IndexVector supno; // Supernode number corresponding to this column (column to supernode mapping)
|
||||
ScalarVector lusup; // nonzero values of L ordered by columns
|
||||
IndexVector lsub; // Compressed row indices of L rectangular supernodes.
|
||||
IndexVector xlusup; // pointers to the beginning of each column in lusup
|
||||
IndexVector xlsub; // pointers to the beginning of each column in lsub
|
||||
Index nzlmax; // Current max size of lsub
|
||||
Index nzlumax; // Current max size of lusup
|
||||
ScalarVector ucol; // nonzero values of U ordered by columns
|
||||
IndexVector usub; // row indices of U columns in ucol
|
||||
IndexVector xusub; // Pointers to the beginning of each column of U in ucol
|
||||
Index nzumax; // Current max size of ucol
|
||||
Index n; // Number of columns in the matrix
|
||||
Index num_expansions;
|
||||
};
|
||||
|
||||
// Values to set for performance
|
||||
struct perfvalues {
|
||||
Index panel_size; // a panel consists of at most <panel_size> consecutive columns
|
||||
Index relax; // To control degree of relaxing supernodes. If the number of nodes (columns)
|
||||
// in a subtree of the elimination tree is less than relax, this subtree is considered
|
||||
// as one supernode regardless of the row structures of those columns
|
||||
Index maxsuper; // The maximum size for a supernode in complete LU
|
||||
Index rowblk; // The minimum row dimension for 2-D blocking to be used;
|
||||
Index colblk; // The minimum column dimension for 2-D blocking to be used;
|
||||
Index fillfactor; // The estimated fills factors for L and U, compared with A
|
||||
};
|
||||
Index panel_size; // a panel consists of at most <panel_size> consecutive columns
|
||||
Index relax; // To control degree of relaxing supernodes. If the number of nodes (columns)
|
||||
// in a subtree of the elimination tree is less than relax, this subtree is considered
|
||||
// as one supernode regardless of the row structures of those columns
|
||||
Index maxsuper; // The maximum size for a supernode in complete LU
|
||||
Index rowblk; // The minimum row dimension for 2-D blocking to be used;
|
||||
Index colblk; // The minimum column dimension for 2-D blocking to be used;
|
||||
Index fillfactor; // The estimated fills factors for L and U, compared with A
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
#endif // EIGEN_LU_STRUCTS
|
||||
} // end namespace Eigen
|
||||
#endif // EIGEN_LU_STRUCTS
|
||||
|
||||
@@ -19,359 +19,301 @@ namespace internal {
|
||||
|
||||
/** \ingroup SparseLU_Module
|
||||
* \brief a class to manipulate the L supernodal factor from the SparseLU factorization
|
||||
*
|
||||
* This class contain the data to easily store
|
||||
* and manipulate the supernodes during the factorization and solution phase of Sparse LU.
|
||||
*
|
||||
* This class contain the data to easily store
|
||||
* and manipulate the supernodes during the factorization and solution phase of Sparse LU.
|
||||
* Only the lower triangular matrix has supernodes.
|
||||
*
|
||||
*
|
||||
* NOTE : This class corresponds to the SCformat structure in SuperLU
|
||||
*
|
||||
*
|
||||
*/
|
||||
/* TODO
|
||||
* InnerIterator as for sparsematrix
|
||||
* SuperInnerIterator to iterate through all supernodes
|
||||
* InnerIterator as for sparsematrix
|
||||
* SuperInnerIterator to iterate through all supernodes
|
||||
* Function for triangular solve
|
||||
*/
|
||||
template <typename Scalar_, typename StorageIndex_>
|
||||
class MappedSuperNodalMatrix
|
||||
{
|
||||
public:
|
||||
typedef Scalar_ Scalar;
|
||||
typedef StorageIndex_ StorageIndex;
|
||||
typedef Matrix<StorageIndex,Dynamic,1> IndexVector;
|
||||
typedef Matrix<Scalar,Dynamic,1> ScalarVector;
|
||||
public:
|
||||
MappedSuperNodalMatrix()
|
||||
{
|
||||
|
||||
}
|
||||
MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
|
||||
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
|
||||
{
|
||||
setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
|
||||
}
|
||||
|
||||
~MappedSuperNodalMatrix()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* Set appropriate pointers for the lower triangular supernodal matrix
|
||||
* These infos are available at the end of the numerical factorization
|
||||
* FIXME This class will be modified such that it can be use in the course
|
||||
* of the factorization.
|
||||
*/
|
||||
void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
|
||||
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col )
|
||||
{
|
||||
m_row = m;
|
||||
m_col = n;
|
||||
m_nzval = nzval.data();
|
||||
m_nzval_colptr = nzval_colptr.data();
|
||||
m_rowind = rowind.data();
|
||||
m_rowind_colptr = rowind_colptr.data();
|
||||
m_nsuper = col_to_sup(n);
|
||||
m_col_to_sup = col_to_sup.data();
|
||||
m_sup_to_col = sup_to_col.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of rows
|
||||
*/
|
||||
Index rows() const { return m_row; }
|
||||
|
||||
/**
|
||||
* Number of columns
|
||||
*/
|
||||
Index cols() const { return m_col; }
|
||||
|
||||
/**
|
||||
* Return the array of nonzero values packed by column
|
||||
*
|
||||
* The size is nnz
|
||||
*/
|
||||
Scalar* valuePtr() { return m_nzval; }
|
||||
|
||||
const Scalar* valuePtr() const
|
||||
{
|
||||
return m_nzval;
|
||||
}
|
||||
/**
|
||||
* Return the pointers to the beginning of each column in \ref valuePtr()
|
||||
*/
|
||||
StorageIndex* colIndexPtr()
|
||||
{
|
||||
return m_nzval_colptr;
|
||||
}
|
||||
|
||||
const StorageIndex* colIndexPtr() const
|
||||
{
|
||||
return m_nzval_colptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array of compressed row indices of all supernodes
|
||||
*/
|
||||
StorageIndex* rowIndex() { return m_rowind; }
|
||||
|
||||
const StorageIndex* rowIndex() const
|
||||
{
|
||||
return m_rowind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the location in \em rowvaluePtr() which starts each column
|
||||
*/
|
||||
StorageIndex* rowIndexPtr() { return m_rowind_colptr; }
|
||||
|
||||
const StorageIndex* rowIndexPtr() const
|
||||
{
|
||||
return m_rowind_colptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array of column-to-supernode mapping
|
||||
*/
|
||||
StorageIndex* colToSup() { return m_col_to_sup; }
|
||||
|
||||
const StorageIndex* colToSup() const
|
||||
{
|
||||
return m_col_to_sup;
|
||||
}
|
||||
/**
|
||||
* Return the array of supernode-to-column mapping
|
||||
*/
|
||||
StorageIndex* supToCol() { return m_sup_to_col; }
|
||||
|
||||
const StorageIndex* supToCol() const
|
||||
{
|
||||
return m_sup_to_col;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of supernodes
|
||||
*/
|
||||
Index nsuper() const
|
||||
{
|
||||
return m_nsuper;
|
||||
}
|
||||
|
||||
class InnerIterator;
|
||||
template<typename Dest>
|
||||
void solveInPlace( MatrixBase<Dest>&X) const;
|
||||
template<bool Conjugate, typename Dest>
|
||||
void solveTransposedInPlace( MatrixBase<Dest>&X) const;
|
||||
class MappedSuperNodalMatrix {
|
||||
public:
|
||||
typedef Scalar_ Scalar;
|
||||
typedef StorageIndex_ StorageIndex;
|
||||
typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;
|
||||
typedef Matrix<Scalar, Dynamic, 1> ScalarVector;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
Index m_row; // Number of rows
|
||||
Index m_col; // Number of columns
|
||||
Index m_nsuper; // Number of supernodes
|
||||
Scalar* m_nzval; //array of nonzero values packed by column
|
||||
StorageIndex* m_nzval_colptr; //nzval_colptr[j] Stores the location in nzval[] which starts column j
|
||||
StorageIndex* m_rowind; // Array of compressed row indices of rectangular supernodes
|
||||
StorageIndex* m_rowind_colptr; //rowind_colptr[j] stores the location in rowind[] which starts column j
|
||||
StorageIndex* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
|
||||
StorageIndex* m_sup_to_col; //sup_to_col[s] points to the starting column of the s-th supernode
|
||||
|
||||
private :
|
||||
public:
|
||||
MappedSuperNodalMatrix() {}
|
||||
MappedSuperNodalMatrix(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
|
||||
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
|
||||
setInfos(m, n, nzval, nzval_colptr, rowind, rowind_colptr, col_to_sup, sup_to_col);
|
||||
}
|
||||
|
||||
~MappedSuperNodalMatrix() {}
|
||||
/**
|
||||
* Set appropriate pointers for the lower triangular supernodal matrix
|
||||
* These infos are available at the end of the numerical factorization
|
||||
* FIXME This class will be modified such that it can be use in the course
|
||||
* of the factorization.
|
||||
*/
|
||||
void setInfos(Index m, Index n, ScalarVector& nzval, IndexVector& nzval_colptr, IndexVector& rowind,
|
||||
IndexVector& rowind_colptr, IndexVector& col_to_sup, IndexVector& sup_to_col) {
|
||||
m_row = m;
|
||||
m_col = n;
|
||||
m_nzval = nzval.data();
|
||||
m_nzval_colptr = nzval_colptr.data();
|
||||
m_rowind = rowind.data();
|
||||
m_rowind_colptr = rowind_colptr.data();
|
||||
m_nsuper = col_to_sup(n);
|
||||
m_col_to_sup = col_to_sup.data();
|
||||
m_sup_to_col = sup_to_col.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of rows
|
||||
*/
|
||||
Index rows() const { return m_row; }
|
||||
|
||||
/**
|
||||
* Number of columns
|
||||
*/
|
||||
Index cols() const { return m_col; }
|
||||
|
||||
/**
|
||||
* Return the array of nonzero values packed by column
|
||||
*
|
||||
* The size is nnz
|
||||
*/
|
||||
Scalar* valuePtr() { return m_nzval; }
|
||||
|
||||
const Scalar* valuePtr() const { return m_nzval; }
|
||||
/**
|
||||
* Return the pointers to the beginning of each column in \ref valuePtr()
|
||||
*/
|
||||
StorageIndex* colIndexPtr() { return m_nzval_colptr; }
|
||||
|
||||
const StorageIndex* colIndexPtr() const { return m_nzval_colptr; }
|
||||
|
||||
/**
|
||||
* Return the array of compressed row indices of all supernodes
|
||||
*/
|
||||
StorageIndex* rowIndex() { return m_rowind; }
|
||||
|
||||
const StorageIndex* rowIndex() const { return m_rowind; }
|
||||
|
||||
/**
|
||||
* Return the location in \em rowvaluePtr() which starts each column
|
||||
*/
|
||||
StorageIndex* rowIndexPtr() { return m_rowind_colptr; }
|
||||
|
||||
const StorageIndex* rowIndexPtr() const { return m_rowind_colptr; }
|
||||
|
||||
/**
|
||||
* Return the array of column-to-supernode mapping
|
||||
*/
|
||||
StorageIndex* colToSup() { return m_col_to_sup; }
|
||||
|
||||
const StorageIndex* colToSup() const { return m_col_to_sup; }
|
||||
/**
|
||||
* Return the array of supernode-to-column mapping
|
||||
*/
|
||||
StorageIndex* supToCol() { return m_sup_to_col; }
|
||||
|
||||
const StorageIndex* supToCol() const { return m_sup_to_col; }
|
||||
|
||||
/**
|
||||
* Return the number of supernodes
|
||||
*/
|
||||
Index nsuper() const { return m_nsuper; }
|
||||
|
||||
class InnerIterator;
|
||||
template <typename Dest>
|
||||
void solveInPlace(MatrixBase<Dest>& X) const;
|
||||
template <bool Conjugate, typename Dest>
|
||||
void solveTransposedInPlace(MatrixBase<Dest>& X) const;
|
||||
|
||||
protected:
|
||||
Index m_row; // Number of rows
|
||||
Index m_col; // Number of columns
|
||||
Index m_nsuper; // Number of supernodes
|
||||
Scalar* m_nzval; // array of nonzero values packed by column
|
||||
StorageIndex* m_nzval_colptr; // nzval_colptr[j] Stores the location in nzval[] which starts column j
|
||||
StorageIndex* m_rowind; // Array of compressed row indices of rectangular supernodes
|
||||
StorageIndex* m_rowind_colptr; // rowind_colptr[j] stores the location in rowind[] which starts column j
|
||||
StorageIndex* m_col_to_sup; // col_to_sup[j] is the supernode number to which column j belongs
|
||||
StorageIndex* m_sup_to_col; // sup_to_col[s] points to the starting column of the s-th supernode
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief InnerIterator class to iterate over nonzero values of the current column in the supernodal matrix L
|
||||
*
|
||||
*/
|
||||
template<typename Scalar, typename StorageIndex>
|
||||
class MappedSuperNodalMatrix<Scalar,StorageIndex>::InnerIterator
|
||||
{
|
||||
public:
|
||||
InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
|
||||
* \brief InnerIterator class to iterate over nonzero values of the current column in the supernodal matrix L
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
class MappedSuperNodalMatrix<Scalar, StorageIndex>::InnerIterator {
|
||||
public:
|
||||
InnerIterator(const MappedSuperNodalMatrix& mat, Index outer)
|
||||
: m_matrix(mat),
|
||||
m_outer(outer),
|
||||
m_supno(mat.colToSup()[outer]),
|
||||
m_idval(mat.colIndexPtr()[outer]),
|
||||
m_startidval(m_idval),
|
||||
m_endidval(mat.colIndexPtr()[outer+1]),
|
||||
m_endidval(mat.colIndexPtr()[outer + 1]),
|
||||
m_idrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]]),
|
||||
m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]]+1])
|
||||
{}
|
||||
inline InnerIterator& operator++()
|
||||
{
|
||||
m_idval++;
|
||||
m_idrow++;
|
||||
return *this;
|
||||
}
|
||||
inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
|
||||
|
||||
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
|
||||
|
||||
inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
|
||||
inline Index row() const { return index(); }
|
||||
inline Index col() const { return m_outer; }
|
||||
|
||||
inline Index supIndex() const { return m_supno; }
|
||||
|
||||
inline operator bool() const
|
||||
{
|
||||
return ( (m_idval < m_endidval) && (m_idval >= m_startidval)
|
||||
&& (m_idrow < m_endidrow) );
|
||||
}
|
||||
|
||||
protected:
|
||||
const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
|
||||
const Index m_outer; // Current column
|
||||
const Index m_supno; // Current SuperNode number
|
||||
Index m_idval; // Index to browse the values in the current column
|
||||
const Index m_startidval; // Start of the column value
|
||||
const Index m_endidval; // End of the column value
|
||||
Index m_idrow; // Index to browse the row indices
|
||||
Index m_endidrow; // End index of row indices of the current column
|
||||
m_endidrow(mat.rowIndexPtr()[mat.supToCol()[mat.colToSup()[outer]] + 1]) {}
|
||||
inline InnerIterator& operator++() {
|
||||
m_idval++;
|
||||
m_idrow++;
|
||||
return *this;
|
||||
}
|
||||
inline Scalar value() const { return m_matrix.valuePtr()[m_idval]; }
|
||||
|
||||
inline Scalar& valueRef() { return const_cast<Scalar&>(m_matrix.valuePtr()[m_idval]); }
|
||||
|
||||
inline Index index() const { return m_matrix.rowIndex()[m_idrow]; }
|
||||
inline Index row() const { return index(); }
|
||||
inline Index col() const { return m_outer; }
|
||||
|
||||
inline Index supIndex() const { return m_supno; }
|
||||
|
||||
inline operator bool() const {
|
||||
return ((m_idval < m_endidval) && (m_idval >= m_startidval) && (m_idrow < m_endidrow));
|
||||
}
|
||||
|
||||
protected:
|
||||
const MappedSuperNodalMatrix& m_matrix; // Supernodal lower triangular matrix
|
||||
const Index m_outer; // Current column
|
||||
const Index m_supno; // Current SuperNode number
|
||||
Index m_idval; // Index to browse the values in the current column
|
||||
const Index m_startidval; // Start of the column value
|
||||
const Index m_endidval; // End of the column value
|
||||
Index m_idrow; // Index to browse the row indices
|
||||
Index m_endidrow; // End index of row indices of the current column
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Solve with the supernode triangular matrix
|
||||
*
|
||||
*
|
||||
*/
|
||||
template<typename Scalar, typename Index_>
|
||||
template<typename Dest>
|
||||
void MappedSuperNodalMatrix<Scalar,Index_>::solveInPlace( MatrixBase<Dest>&X) const
|
||||
{
|
||||
/* Explicit type conversion as the Index type of MatrixBase<Dest> may be wider than Index */
|
||||
// eigen_assert(X.rows() <= NumTraits<Index>::highest());
|
||||
// eigen_assert(X.cols() <= NumTraits<Index>::highest());
|
||||
Index n = int(X.rows());
|
||||
Index nrhs = Index(X.cols());
|
||||
const Scalar * Lval = valuePtr(); // Nonzero values
|
||||
Matrix<Scalar,Dynamic,Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
|
||||
work.setZero();
|
||||
for (Index k = 0; k <= nsuper(); k ++)
|
||||
{
|
||||
Index fsupc = supToCol()[k]; // First column of the current supernode
|
||||
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
|
||||
Index nsupr = rowIndexPtr()[fsupc+1] - istart; // Number of rows in the current supernode
|
||||
Index nsupc = supToCol()[k+1] - fsupc; // Number of columns in the current supernode
|
||||
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
|
||||
Index irow; //Current index row
|
||||
|
||||
if (nsupc == 1 )
|
||||
{
|
||||
for (Index j = 0; j < nrhs; j++)
|
||||
{
|
||||
InnerIterator it(*this, fsupc);
|
||||
++it; // Skip the diagonal element
|
||||
for (; it; ++it)
|
||||
{
|
||||
irow = it.row();
|
||||
X(irow, j) -= X(fsupc, j) * it.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The supernode has more than one column
|
||||
Index luptr = colIndexPtr()[fsupc];
|
||||
Index lda = colIndexPtr()[fsupc+1] - luptr;
|
||||
|
||||
// Triangular solve
|
||||
Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
||||
typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
|
||||
U = A.template triangularView<UnitLower>().solve(U);
|
||||
// Matrix-vector product
|
||||
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > ( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
||||
work.topRows(nrow).noalias() = A * U;
|
||||
|
||||
//Begin Scatter
|
||||
for (Index j = 0; j < nrhs; j++)
|
||||
{
|
||||
Index iptr = istart + nsupc;
|
||||
for (Index i = 0; i < nrow; i++)
|
||||
{
|
||||
irow = rowIndex()[iptr];
|
||||
X(irow, j) -= work(i, j); // Scatter operation
|
||||
work(i, j) = Scalar(0);
|
||||
iptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Index_>
|
||||
template<bool Conjugate, typename Dest>
|
||||
void MappedSuperNodalMatrix<Scalar,Index_>::solveTransposedInPlace( MatrixBase<Dest>&X) const
|
||||
{
|
||||
using numext::conj;
|
||||
Index n = int(X.rows());
|
||||
template <typename Scalar, typename Index_>
|
||||
template <typename Dest>
|
||||
void MappedSuperNodalMatrix<Scalar, Index_>::solveInPlace(MatrixBase<Dest>& X) const {
|
||||
/* Explicit type conversion as the Index type of MatrixBase<Dest> may be wider than Index */
|
||||
// eigen_assert(X.rows() <= NumTraits<Index>::highest());
|
||||
// eigen_assert(X.cols() <= NumTraits<Index>::highest());
|
||||
Index n = int(X.rows());
|
||||
Index nrhs = Index(X.cols());
|
||||
const Scalar * Lval = valuePtr(); // Nonzero values
|
||||
Matrix<Scalar,Dynamic,Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
|
||||
const Scalar* Lval = valuePtr(); // Nonzero values
|
||||
Matrix<Scalar, Dynamic, Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
|
||||
work.setZero();
|
||||
for (Index k = nsuper(); k >= 0; k--)
|
||||
{
|
||||
Index fsupc = supToCol()[k]; // First column of the current supernode
|
||||
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
|
||||
Index nsupr = rowIndexPtr()[fsupc+1] - istart; // Number of rows in the current supernode
|
||||
Index nsupc = supToCol()[k+1] - fsupc; // Number of columns in the current supernode
|
||||
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
|
||||
Index irow; //Current index row
|
||||
for (Index k = 0; k <= nsuper(); k++) {
|
||||
Index fsupc = supToCol()[k]; // First column of the current supernode
|
||||
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
|
||||
Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
|
||||
Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
|
||||
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
|
||||
Index irow; // Current index row
|
||||
|
||||
if (nsupc == 1 )
|
||||
{
|
||||
for (Index j = 0; j < nrhs; j++)
|
||||
{
|
||||
if (nsupc == 1) {
|
||||
for (Index j = 0; j < nrhs; j++) {
|
||||
InnerIterator it(*this, fsupc);
|
||||
++it; // Skip the diagonal element
|
||||
for (; it; ++it)
|
||||
{
|
||||
++it; // Skip the diagonal element
|
||||
for (; it; ++it) {
|
||||
irow = it.row();
|
||||
X(fsupc,j) -= X(irow, j) * (Conjugate?conj(it.value()):it.value());
|
||||
X(irow, j) -= X(fsupc, j) * it.value();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The supernode has more than one column
|
||||
Index luptr = colIndexPtr()[fsupc];
|
||||
Index lda = colIndexPtr()[fsupc + 1] - luptr;
|
||||
|
||||
// Triangular solve
|
||||
Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr]), nsupc, nsupc,
|
||||
OuterStride<>(lda));
|
||||
typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
|
||||
U = A.template triangularView<UnitLower>().solve(U);
|
||||
// Matrix-vector product
|
||||
new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr + nsupc]), nrow,
|
||||
nsupc, OuterStride<>(lda));
|
||||
work.topRows(nrow).noalias() = A * U;
|
||||
|
||||
// Begin Scatter
|
||||
for (Index j = 0; j < nrhs; j++) {
|
||||
Index iptr = istart + nsupc;
|
||||
for (Index i = 0; i < nrow; i++) {
|
||||
irow = rowIndex()[iptr];
|
||||
X(irow, j) -= work(i, j); // Scatter operation
|
||||
work(i, j) = Scalar(0);
|
||||
iptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Scalar, typename Index_>
|
||||
template <bool Conjugate, typename Dest>
|
||||
void MappedSuperNodalMatrix<Scalar, Index_>::solveTransposedInPlace(MatrixBase<Dest>& X) const {
|
||||
using numext::conj;
|
||||
Index n = int(X.rows());
|
||||
Index nrhs = Index(X.cols());
|
||||
const Scalar* Lval = valuePtr(); // Nonzero values
|
||||
Matrix<Scalar, Dynamic, Dest::ColsAtCompileTime, ColMajor> work(n, nrhs); // working vector
|
||||
work.setZero();
|
||||
for (Index k = nsuper(); k >= 0; k--) {
|
||||
Index fsupc = supToCol()[k]; // First column of the current supernode
|
||||
Index istart = rowIndexPtr()[fsupc]; // Pointer index to the subscript of the current column
|
||||
Index nsupr = rowIndexPtr()[fsupc + 1] - istart; // Number of rows in the current supernode
|
||||
Index nsupc = supToCol()[k + 1] - fsupc; // Number of columns in the current supernode
|
||||
Index nrow = nsupr - nsupc; // Number of rows in the non-diagonal part of the supernode
|
||||
Index irow; // Current index row
|
||||
|
||||
if (nsupc == 1) {
|
||||
for (Index j = 0; j < nrhs; j++) {
|
||||
InnerIterator it(*this, fsupc);
|
||||
++it; // Skip the diagonal element
|
||||
for (; it; ++it) {
|
||||
irow = it.row();
|
||||
X(fsupc, j) -= X(irow, j) * (Conjugate ? conj(it.value()) : it.value());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The supernode has more than one column
|
||||
Index luptr = colIndexPtr()[fsupc];
|
||||
Index lda = colIndexPtr()[fsupc+1] - luptr;
|
||||
Index lda = colIndexPtr()[fsupc + 1] - luptr;
|
||||
|
||||
//Begin Gather
|
||||
for (Index j = 0; j < nrhs; j++)
|
||||
{
|
||||
// Begin Gather
|
||||
for (Index j = 0; j < nrhs; j++) {
|
||||
Index iptr = istart + nsupc;
|
||||
for (Index i = 0; i < nrow; i++)
|
||||
{
|
||||
for (Index i = 0; i < nrow; i++) {
|
||||
irow = rowIndex()[iptr];
|
||||
work.topRows(nrow)(i,j)= X(irow,j); // Gather operation
|
||||
work.topRows(nrow)(i, j) = X(irow, j); // Gather operation
|
||||
iptr++;
|
||||
}
|
||||
}
|
||||
|
||||
// Matrix-vector product with transposed submatrix
|
||||
Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > A( &(Lval[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
||||
Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> > A(&(Lval[luptr + nsupc]), nrow, nsupc,
|
||||
OuterStride<>(lda));
|
||||
typename Dest::RowsBlockXpr U = X.derived().middleRows(fsupc, nsupc);
|
||||
if(Conjugate)
|
||||
if (Conjugate)
|
||||
U = U - A.adjoint() * work.topRows(nrow);
|
||||
else
|
||||
U = U - A.transpose() * work.topRows(nrow);
|
||||
|
||||
// Triangular solve (of transposed diagonal block)
|
||||
new (&A) Map<const Matrix<Scalar,Dynamic,Dynamic, ColMajor>, 0, OuterStride<> > ( &(Lval[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
||||
if(Conjugate)
|
||||
new (&A) Map<const Matrix<Scalar, Dynamic, Dynamic, ColMajor>, 0, OuterStride<> >(&(Lval[luptr]), nsupc, nsupc,
|
||||
OuterStride<>(lda));
|
||||
if (Conjugate)
|
||||
U = A.adjoint().template triangularView<UnitUpper>().solve(U);
|
||||
else
|
||||
U = A.transpose().template triangularView<UnitUpper>().solve(U);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_SPARSELU_MATRIX_H
|
||||
#endif // EIGEN_SPARSELU_MATRIX_H
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
#ifndef EIGEN_SPARSELU_UTILS_H
|
||||
#define EIGEN_SPARSELU_UTILS_H
|
||||
|
||||
@@ -21,63 +20,56 @@ namespace internal {
|
||||
* \brief Count Nonzero elements in the factors
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu)
|
||||
{
|
||||
nnzL = 0;
|
||||
nnzU = (glu.xusub)(n);
|
||||
Index nsuper = (glu.supno)(n);
|
||||
Index jlen;
|
||||
Index i, j, fsupc;
|
||||
if (n <= 0 ) return;
|
||||
// For each supernode
|
||||
for (i = 0; i <= nsuper; i++)
|
||||
{
|
||||
fsupc = glu.xsup(i);
|
||||
jlen = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
|
||||
|
||||
for (j = fsupc; j < glu.xsup(i+1); j++)
|
||||
{
|
||||
nnzL += jlen;
|
||||
nnzU += j - fsupc + 1;
|
||||
jlen--;
|
||||
}
|
||||
}
|
||||
void SparseLUImpl<Scalar, StorageIndex>::countnz(const Index n, Index& nnzL, Index& nnzU, GlobalLU_t& glu) {
|
||||
nnzL = 0;
|
||||
nnzU = (glu.xusub)(n);
|
||||
Index nsuper = (glu.supno)(n);
|
||||
Index jlen;
|
||||
Index i, j, fsupc;
|
||||
if (n <= 0) return;
|
||||
// For each supernode
|
||||
for (i = 0; i <= nsuper; i++) {
|
||||
fsupc = glu.xsup(i);
|
||||
jlen = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
|
||||
|
||||
for (j = fsupc; j < glu.xsup(i + 1); j++) {
|
||||
nnzL += jlen;
|
||||
nnzU += j - fsupc + 1;
|
||||
jlen--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fix up the data storage lsub for L-subscripts.
|
||||
*
|
||||
* It removes the subscripts sets for structural pruning,
|
||||
* \brief Fix up the data storage lsub for L-subscripts.
|
||||
*
|
||||
* It removes the subscripts sets for structural pruning,
|
||||
* and applies permutation to the remaining subscripts
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu)
|
||||
{
|
||||
Index fsupc, i, j, k, jstart;
|
||||
|
||||
StorageIndex nextl = 0;
|
||||
Index nsuper = (glu.supno)(n);
|
||||
|
||||
// For each supernode
|
||||
for (i = 0; i <= nsuper; i++)
|
||||
{
|
||||
fsupc = glu.xsup(i);
|
||||
jstart = glu.xlsub(fsupc);
|
||||
glu.xlsub(fsupc) = nextl;
|
||||
for (j = jstart; j < glu.xlsub(fsupc + 1); j++)
|
||||
{
|
||||
glu.lsub(nextl) = perm_r(glu.lsub(j)); // Now indexed into P*A
|
||||
void SparseLUImpl<Scalar, StorageIndex>::fixupL(const Index n, const IndexVector& perm_r, GlobalLU_t& glu) {
|
||||
Index fsupc, i, j, k, jstart;
|
||||
|
||||
StorageIndex nextl = 0;
|
||||
Index nsuper = (glu.supno)(n);
|
||||
|
||||
// For each supernode
|
||||
for (i = 0; i <= nsuper; i++) {
|
||||
fsupc = glu.xsup(i);
|
||||
jstart = glu.xlsub(fsupc);
|
||||
glu.xlsub(fsupc) = nextl;
|
||||
for (j = jstart; j < glu.xlsub(fsupc + 1); j++) {
|
||||
glu.lsub(nextl) = perm_r(glu.lsub(j)); // Now indexed into P*A
|
||||
nextl++;
|
||||
}
|
||||
for (k = fsupc+1; k < glu.xsup(i+1); k++)
|
||||
glu.xlsub(k) = nextl; // other columns in supernode i
|
||||
for (k = fsupc + 1; k < glu.xsup(i + 1); k++) glu.xlsub(k) = nextl; // other columns in supernode i
|
||||
}
|
||||
|
||||
glu.xlsub(n) = nextl;
|
||||
|
||||
glu.xlsub(n) = nextl;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
#endif // EIGEN_SPARSELU_UTILS_H
|
||||
} // end namespace Eigen
|
||||
#endif // EIGEN_SPARSELU_UTILS_H
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of xcolumn_bmod.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of xcolumn_bmod.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 3.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -39,146 +39,139 @@ namespace Eigen {
|
||||
namespace internal {
|
||||
/**
|
||||
* \brief Performs numeric block updates (sup-col) in topological order
|
||||
*
|
||||
*
|
||||
* \param jcol current column to update
|
||||
* \param nseg Number of segments in the U part
|
||||
* \param dense Store the full representation of the column
|
||||
* \param tempv working array
|
||||
* \param tempv working array
|
||||
* \param segrep segment representative ...
|
||||
* \param repfnz ??? First nonzero column in each row ??? ...
|
||||
* \param fpanelc First column in the current panel
|
||||
* \param glu Global LU data.
|
||||
* \return 0 - successful return
|
||||
* \param glu Global LU data.
|
||||
* \return 0 - successful return
|
||||
* > 0 - number of bytes allocated when run out of space
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector& tempv,
|
||||
BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu)
|
||||
{
|
||||
Index jsupno, k, ksub, krep, ksupno;
|
||||
Index lptr, nrow, isub, irow, nextlu, new_next, ufirst;
|
||||
Index fsupc, nsupc, nsupr, luptr, kfnz, no_zeros;
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::column_bmod(const Index jcol, const Index nseg, BlockScalarVector dense,
|
||||
ScalarVector& tempv, BlockIndexVector segrep,
|
||||
BlockIndexVector repfnz, Index fpanelc, GlobalLU_t& glu) {
|
||||
Index jsupno, k, ksub, krep, ksupno;
|
||||
Index lptr, nrow, isub, irow, nextlu, new_next, ufirst;
|
||||
Index fsupc, nsupc, nsupr, luptr, kfnz, no_zeros;
|
||||
/* krep = representative of current k-th supernode
|
||||
* fsupc = first supernodal column
|
||||
* nsupc = number of columns in a supernode
|
||||
* nsupr = number of rows in a supernode
|
||||
* luptr = location of supernodal LU-block in storage
|
||||
* kfnz = first nonz in the k-th supernodal segment
|
||||
* no_zeros = no lf leading zeros in a supernodal U-segment
|
||||
*/
|
||||
|
||||
* fsupc = first supernodal column
|
||||
* nsupc = number of columns in a supernode
|
||||
* nsupr = number of rows in a supernode
|
||||
* luptr = location of supernodal LU-block in storage
|
||||
* kfnz = first nonz in the k-th supernodal segment
|
||||
* no_zeros = no lf leading zeros in a supernodal U-segment
|
||||
*/
|
||||
|
||||
jsupno = glu.supno(jcol);
|
||||
// For each nonzero supernode segment of U[*,j] in topological order
|
||||
k = nseg - 1;
|
||||
Index d_fsupc; // distance between the first column of the current panel and the
|
||||
// first column of the current snode
|
||||
Index fst_col; // First column within small LU update
|
||||
Index segsize;
|
||||
for (ksub = 0; ksub < nseg; ksub++)
|
||||
{
|
||||
krep = segrep(k); k--;
|
||||
ksupno = glu.supno(krep);
|
||||
if (jsupno != ksupno )
|
||||
{
|
||||
// outside the rectangular supernode
|
||||
fsupc = glu.xsup(ksupno);
|
||||
fst_col = (std::max)(fsupc, fpanelc);
|
||||
|
||||
// Distance from the current supernode to the current panel;
|
||||
// For each nonzero supernode segment of U[*,j] in topological order
|
||||
k = nseg - 1;
|
||||
Index d_fsupc; // distance between the first column of the current panel and the
|
||||
// first column of the current snode
|
||||
Index fst_col; // First column within small LU update
|
||||
Index segsize;
|
||||
for (ksub = 0; ksub < nseg; ksub++) {
|
||||
krep = segrep(k);
|
||||
k--;
|
||||
ksupno = glu.supno(krep);
|
||||
if (jsupno != ksupno) {
|
||||
// outside the rectangular supernode
|
||||
fsupc = glu.xsup(ksupno);
|
||||
fst_col = (std::max)(fsupc, fpanelc);
|
||||
|
||||
// Distance from the current supernode to the current panel;
|
||||
// d_fsupc = 0 if fsupc > fpanelc
|
||||
d_fsupc = fst_col - fsupc;
|
||||
|
||||
luptr = glu.xlusup(fst_col) + d_fsupc;
|
||||
lptr = glu.xlsub(fsupc) + d_fsupc;
|
||||
|
||||
kfnz = repfnz(krep);
|
||||
kfnz = (std::max)(kfnz, fpanelc);
|
||||
|
||||
segsize = krep - kfnz + 1;
|
||||
nsupc = krep - fst_col + 1;
|
||||
nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
|
||||
d_fsupc = fst_col - fsupc;
|
||||
|
||||
luptr = glu.xlusup(fst_col) + d_fsupc;
|
||||
lptr = glu.xlsub(fsupc) + d_fsupc;
|
||||
|
||||
kfnz = repfnz(krep);
|
||||
kfnz = (std::max)(kfnz, fpanelc);
|
||||
|
||||
segsize = krep - kfnz + 1;
|
||||
nsupc = krep - fst_col + 1;
|
||||
nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
|
||||
nrow = nsupr - d_fsupc - nsupc;
|
||||
Index lda = glu.xlusup(fst_col+1) - glu.xlusup(fst_col);
|
||||
|
||||
|
||||
// Perform a triangular solver and block update,
|
||||
Index lda = glu.xlusup(fst_col + 1) - glu.xlusup(fst_col);
|
||||
|
||||
// Perform a triangular solver and block update,
|
||||
// then scatter the result of sup-col update to dense
|
||||
no_zeros = kfnz - fst_col;
|
||||
if(segsize==1)
|
||||
no_zeros = kfnz - fst_col;
|
||||
if (segsize == 1)
|
||||
LU_kernel_bmod<1>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else
|
||||
LU_kernel_bmod<Dynamic>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
} // end if jsupno
|
||||
} // end for each segment
|
||||
|
||||
} // end if jsupno
|
||||
} // end for each segment
|
||||
|
||||
// Process the supernodal portion of L\U[*,j]
|
||||
nextlu = glu.xlusup(jcol);
|
||||
nextlu = glu.xlusup(jcol);
|
||||
fsupc = glu.xsup(jsupno);
|
||||
|
||||
|
||||
// copy the SPA dense into L\U[*,j]
|
||||
Index mem;
|
||||
new_next = nextlu + glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
|
||||
Index mem;
|
||||
new_next = nextlu + glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
|
||||
Index offset = internal::first_multiple<Index>(new_next, internal::packet_traits<Scalar>::size) - new_next;
|
||||
if(offset)
|
||||
new_next += offset;
|
||||
while (new_next > glu.nzlumax )
|
||||
{
|
||||
mem = memXpand<ScalarVector>(glu.lusup, glu.nzlumax, nextlu, LUSUP, glu.num_expansions);
|
||||
if (mem) return mem;
|
||||
if (offset) new_next += offset;
|
||||
while (new_next > glu.nzlumax) {
|
||||
mem = memXpand<ScalarVector>(glu.lusup, glu.nzlumax, nextlu, LUSUP, glu.num_expansions);
|
||||
if (mem) return mem;
|
||||
}
|
||||
|
||||
for (isub = glu.xlsub(fsupc); isub < glu.xlsub(fsupc+1); isub++)
|
||||
{
|
||||
|
||||
for (isub = glu.xlsub(fsupc); isub < glu.xlsub(fsupc + 1); isub++) {
|
||||
irow = glu.lsub(isub);
|
||||
glu.lusup(nextlu) = dense(irow);
|
||||
dense(irow) = Scalar(0.0);
|
||||
++nextlu;
|
||||
dense(irow) = Scalar(0.0);
|
||||
++nextlu;
|
||||
}
|
||||
|
||||
if(offset)
|
||||
{
|
||||
glu.lusup.segment(nextlu,offset).setZero();
|
||||
|
||||
if (offset) {
|
||||
glu.lusup.segment(nextlu, offset).setZero();
|
||||
nextlu += offset;
|
||||
}
|
||||
glu.xlusup(jcol + 1) = StorageIndex(nextlu); // close L\U(*,jcol);
|
||||
|
||||
glu.xlusup(jcol + 1) = StorageIndex(nextlu); // close L\U(*,jcol);
|
||||
|
||||
/* For more updates within the panel (also within the current supernode),
|
||||
* should start from the first column of the panel, or the first column
|
||||
* of the supernode, whichever is bigger. There are two cases:
|
||||
* 1) fsupc < fpanelc, then fst_col <-- fpanelc
|
||||
* 2) fsupc >= fpanelc, then fst_col <-- fsupc
|
||||
*/
|
||||
fst_col = (std::max)(fsupc, fpanelc);
|
||||
|
||||
if (fst_col < jcol)
|
||||
{
|
||||
fst_col = (std::max)(fsupc, fpanelc);
|
||||
|
||||
if (fst_col < jcol) {
|
||||
// Distance between the current supernode and the current panel
|
||||
// d_fsupc = 0 if fsupc >= fpanelc
|
||||
d_fsupc = fst_col - fsupc;
|
||||
|
||||
lptr = glu.xlsub(fsupc) + d_fsupc;
|
||||
luptr = glu.xlusup(fst_col) + d_fsupc;
|
||||
nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc); // leading dimension
|
||||
nsupc = jcol - fst_col; // excluding jcol
|
||||
nrow = nsupr - d_fsupc - nsupc;
|
||||
|
||||
// points to the beginning of jcol in snode L\U(jsupno)
|
||||
ufirst = glu.xlusup(jcol) + d_fsupc;
|
||||
Index lda = glu.xlusup(jcol+1) - glu.xlusup(jcol);
|
||||
MappedMatrixBlock A( &(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda) );
|
||||
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
|
||||
u = A.template triangularView<UnitLower>().solve(u);
|
||||
|
||||
new (&A) MappedMatrixBlock ( &(glu.lusup.data()[luptr+nsupc]), nrow, nsupc, OuterStride<>(lda) );
|
||||
VectorBlock<ScalarVector> l(glu.lusup, ufirst+nsupc, nrow);
|
||||
d_fsupc = fst_col - fsupc;
|
||||
|
||||
lptr = glu.xlsub(fsupc) + d_fsupc;
|
||||
luptr = glu.xlusup(fst_col) + d_fsupc;
|
||||
nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc); // leading dimension
|
||||
nsupc = jcol - fst_col; // excluding jcol
|
||||
nrow = nsupr - d_fsupc - nsupc;
|
||||
|
||||
// points to the beginning of jcol in snode L\U(jsupno)
|
||||
ufirst = glu.xlusup(jcol) + d_fsupc;
|
||||
Index lda = glu.xlusup(jcol + 1) - glu.xlusup(jcol);
|
||||
MappedMatrixBlock A(&(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda));
|
||||
VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
|
||||
u = A.template triangularView<UnitLower>().solve(u);
|
||||
|
||||
new (&A) MappedMatrixBlock(&(glu.lusup.data()[luptr + nsupc]), nrow, nsupc, OuterStride<>(lda));
|
||||
VectorBlock<ScalarVector> l(glu.lusup, ufirst + nsupc, nrow);
|
||||
l.noalias() -= A * u;
|
||||
|
||||
} // End if fst_col
|
||||
return 0;
|
||||
|
||||
} // End if fst_col
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // SPARSELU_COLUMN_BMOD_H
|
||||
#endif // SPARSELU_COLUMN_BMOD_H
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]column_dfs.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]column_dfs.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 2.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -30,7 +30,8 @@
|
||||
#ifndef SPARSELU_COLUMN_DFS_H
|
||||
#define SPARSELU_COLUMN_DFS_H
|
||||
|
||||
template <typename Scalar, typename StorageIndex> class SparseLUImpl;
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
class SparseLUImpl;
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
@@ -38,145 +39,130 @@ namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename IndexVector, typename ScalarVector>
|
||||
struct column_dfs_traits : no_assignment_operator
|
||||
{
|
||||
template <typename IndexVector, typename ScalarVector>
|
||||
struct column_dfs_traits : no_assignment_operator {
|
||||
typedef typename ScalarVector::Scalar Scalar;
|
||||
typedef typename IndexVector::Scalar StorageIndex;
|
||||
column_dfs_traits(Index jcol, Index& jsuper, typename SparseLUImpl<Scalar, StorageIndex>::GlobalLU_t& glu, SparseLUImpl<Scalar, StorageIndex>& luImpl)
|
||||
: m_jcol(jcol), m_jsuper_ref(jsuper), m_glu(glu), m_luImpl(luImpl)
|
||||
{}
|
||||
bool update_segrep(Index /*krep*/, Index /*jj*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void mem_expand(IndexVector& lsub, Index& nextl, Index chmark)
|
||||
{
|
||||
if (nextl >= m_glu.nzlmax)
|
||||
m_luImpl.memXpand(lsub, m_glu.nzlmax, nextl, LSUB, m_glu.num_expansions);
|
||||
if (chmark != (m_jcol-1)) m_jsuper_ref = emptyIdxLU;
|
||||
column_dfs_traits(Index jcol, Index& jsuper, typename SparseLUImpl<Scalar, StorageIndex>::GlobalLU_t& glu,
|
||||
SparseLUImpl<Scalar, StorageIndex>& luImpl)
|
||||
: m_jcol(jcol), m_jsuper_ref(jsuper), m_glu(glu), m_luImpl(luImpl) {}
|
||||
bool update_segrep(Index /*krep*/, Index /*jj*/) { return true; }
|
||||
void mem_expand(IndexVector& lsub, Index& nextl, Index chmark) {
|
||||
if (nextl >= m_glu.nzlmax) m_luImpl.memXpand(lsub, m_glu.nzlmax, nextl, LSUB, m_glu.num_expansions);
|
||||
if (chmark != (m_jcol - 1)) m_jsuper_ref = emptyIdxLU;
|
||||
}
|
||||
enum { ExpandMem = true };
|
||||
|
||||
|
||||
Index m_jcol;
|
||||
Index& m_jsuper_ref;
|
||||
typename SparseLUImpl<Scalar, StorageIndex>::GlobalLU_t& m_glu;
|
||||
SparseLUImpl<Scalar, StorageIndex>& m_luImpl;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Performs a symbolic factorization on column jcol and decide the supernode boundary
|
||||
*
|
||||
*
|
||||
* A supernode representative is the last column of a supernode.
|
||||
* The nonzeros in U[*,j] are segments that end at supernodes representatives.
|
||||
* The routine returns a list of the supernodal representatives
|
||||
* in topological order of the dfs that generates them.
|
||||
* The location of the first nonzero in each supernodal segment
|
||||
* (supernodal entry location) is also returned.
|
||||
*
|
||||
* The nonzeros in U[*,j] are segments that end at supernodes representatives.
|
||||
* The routine returns a list of the supernodal representatives
|
||||
* in topological order of the dfs that generates them.
|
||||
* The location of the first nonzero in each supernodal segment
|
||||
* (supernodal entry location) is also returned.
|
||||
*
|
||||
* \param m number of rows in the matrix
|
||||
* \param jcol Current column
|
||||
* \param jcol Current column
|
||||
* \param perm_r Row permutation
|
||||
* \param maxsuper Maximum number of column allowed in a supernode
|
||||
* \param [in,out] nseg Number of segments in current U[*,j] - new segments appended
|
||||
* \param lsub_col defines the rhs vector to start the dfs
|
||||
* \param [in,out] segrep Segment representatives - new segments appended
|
||||
* \param [in,out] segrep Segment representatives - new segments appended
|
||||
* \param repfnz First nonzero location in each row
|
||||
* \param xprune
|
||||
* \param xprune
|
||||
* \param marker marker[i] == jj, if i was visited during dfs of current column jj;
|
||||
* \param parent
|
||||
* \param xplore working array
|
||||
* \param glu global LU data
|
||||
* \param glu global LU data
|
||||
* \return 0 success
|
||||
* > 0 number of bytes allocated when run out of space
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::column_dfs(const Index m, const Index jcol, IndexVector& perm_r, Index maxsuper, Index& nseg,
|
||||
BlockIndexVector lsub_col, IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune,
|
||||
IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu)
|
||||
{
|
||||
|
||||
Index jsuper = glu.supno(jcol);
|
||||
Index nextl = glu.xlsub(jcol);
|
||||
VectorBlock<IndexVector> marker2(marker, 2*m, m);
|
||||
|
||||
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::column_dfs(const Index m, const Index jcol, IndexVector& perm_r,
|
||||
Index maxsuper, Index& nseg, BlockIndexVector lsub_col,
|
||||
IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune,
|
||||
IndexVector& marker, IndexVector& parent, IndexVector& xplore,
|
||||
GlobalLU_t& glu) {
|
||||
Index jsuper = glu.supno(jcol);
|
||||
Index nextl = glu.xlsub(jcol);
|
||||
VectorBlock<IndexVector> marker2(marker, 2 * m, m);
|
||||
|
||||
column_dfs_traits<IndexVector, ScalarVector> traits(jcol, jsuper, glu, *this);
|
||||
|
||||
// For each nonzero in A(*,jcol) do dfs
|
||||
for (Index k = 0; ((k < m) ? lsub_col[k] != emptyIdxLU : false) ; k++)
|
||||
{
|
||||
Index krow = lsub_col(k);
|
||||
lsub_col(k) = emptyIdxLU;
|
||||
Index kmark = marker2(krow);
|
||||
|
||||
// krow was visited before, go to the next nonz;
|
||||
|
||||
// For each nonzero in A(*,jcol) do dfs
|
||||
for (Index k = 0; ((k < m) ? lsub_col[k] != emptyIdxLU : false); k++) {
|
||||
Index krow = lsub_col(k);
|
||||
lsub_col(k) = emptyIdxLU;
|
||||
Index kmark = marker2(krow);
|
||||
|
||||
// krow was visited before, go to the next nonz;
|
||||
if (kmark == jcol) continue;
|
||||
|
||||
dfs_kernel(StorageIndex(jcol), perm_r, nseg, glu.lsub, segrep, repfnz, xprune, marker2, parent,
|
||||
xplore, glu, nextl, krow, traits);
|
||||
} // for each nonzero ...
|
||||
|
||||
|
||||
dfs_kernel(StorageIndex(jcol), perm_r, nseg, glu.lsub, segrep, repfnz, xprune, marker2, parent, xplore, glu, nextl,
|
||||
krow, traits);
|
||||
} // for each nonzero ...
|
||||
|
||||
Index fsupc;
|
||||
StorageIndex nsuper = glu.supno(jcol);
|
||||
StorageIndex jcolp1 = StorageIndex(jcol) + 1;
|
||||
Index jcolm1 = jcol - 1;
|
||||
|
||||
|
||||
// check to see if j belongs in the same supernode as j-1
|
||||
if ( jcol == 0 )
|
||||
{ // Do nothing for column 0
|
||||
nsuper = glu.supno(0) = 0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
fsupc = glu.xsup(nsuper);
|
||||
StorageIndex jptr = glu.xlsub(jcol); // Not yet compressed
|
||||
StorageIndex jm1ptr = glu.xlsub(jcolm1);
|
||||
|
||||
if (jcol == 0) { // Do nothing for column 0
|
||||
nsuper = glu.supno(0) = 0;
|
||||
} else {
|
||||
fsupc = glu.xsup(nsuper);
|
||||
StorageIndex jptr = glu.xlsub(jcol); // Not yet compressed
|
||||
StorageIndex jm1ptr = glu.xlsub(jcolm1);
|
||||
|
||||
// Use supernodes of type T2 : see SuperLU paper
|
||||
if ( (nextl-jptr != jptr-jm1ptr-1) ) jsuper = emptyIdxLU;
|
||||
|
||||
if ((nextl - jptr != jptr - jm1ptr - 1)) jsuper = emptyIdxLU;
|
||||
|
||||
// Make sure the number of columns in a supernode doesn't
|
||||
// exceed threshold
|
||||
if ( (jcol - fsupc) >= maxsuper) jsuper = emptyIdxLU;
|
||||
|
||||
if ((jcol - fsupc) >= maxsuper) jsuper = emptyIdxLU;
|
||||
|
||||
/* If jcol starts a new supernode, reclaim storage space in
|
||||
* glu.lsub from previous supernode. Note we only store
|
||||
* the subscript set of the first and last columns of
|
||||
* glu.lsub from previous supernode. Note we only store
|
||||
* the subscript set of the first and last columns of
|
||||
* a supernode. (first for num values, last for pruning)
|
||||
*/
|
||||
if (jsuper == emptyIdxLU)
|
||||
{ // starts a new supernode
|
||||
if ( (fsupc < jcolm1-1) )
|
||||
{ // >= 3 columns in nsuper
|
||||
StorageIndex ito = glu.xlsub(fsupc+1);
|
||||
glu.xlsub(jcolm1) = ito;
|
||||
StorageIndex istop = ito + jptr - jm1ptr;
|
||||
xprune(jcolm1) = istop; // initialize xprune(jcol-1)
|
||||
glu.xlsub(jcol) = istop;
|
||||
|
||||
for (StorageIndex ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito)
|
||||
glu.lsub(ito) = glu.lsub(ifrom);
|
||||
if (jsuper == emptyIdxLU) { // starts a new supernode
|
||||
if ((fsupc < jcolm1 - 1)) { // >= 3 columns in nsuper
|
||||
StorageIndex ito = glu.xlsub(fsupc + 1);
|
||||
glu.xlsub(jcolm1) = ito;
|
||||
StorageIndex istop = ito + jptr - jm1ptr;
|
||||
xprune(jcolm1) = istop; // initialize xprune(jcol-1)
|
||||
glu.xlsub(jcol) = istop;
|
||||
|
||||
for (StorageIndex ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito) glu.lsub(ito) = glu.lsub(ifrom);
|
||||
nextl = ito; // = istop + length(jcol)
|
||||
}
|
||||
nsuper++;
|
||||
glu.supno(jcol) = nsuper;
|
||||
} // if a new supernode
|
||||
} // end else: jcol > 0
|
||||
|
||||
nsuper++;
|
||||
glu.supno(jcol) = nsuper;
|
||||
} // if a new supernode
|
||||
} // end else: jcol > 0
|
||||
|
||||
// Tidy up the pointers before exit
|
||||
glu.xsup(nsuper+1) = jcolp1;
|
||||
glu.supno(jcolp1) = nsuper;
|
||||
glu.xsup(nsuper + 1) = jcolp1;
|
||||
glu.supno(jcolp1) = nsuper;
|
||||
xprune(jcol) = StorageIndex(nextl); // Initialize upper bound for pruning
|
||||
glu.xlsub(jcolp1) = StorageIndex(nextl);
|
||||
|
||||
return 0;
|
||||
glu.xlsub(jcolp1) = StorageIndex(nextl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]copy_to_ucol.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]copy_to_ucol.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 2.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -37,74 +37,70 @@ namespace internal {
|
||||
|
||||
/**
|
||||
* \brief Performs numeric block updates (sup-col) in topological order
|
||||
*
|
||||
*
|
||||
* \param jcol current column to update
|
||||
* \param nseg Number of segments in the U part
|
||||
* \param segrep segment representative ...
|
||||
* \param repfnz First nonzero column in each row ...
|
||||
* \param perm_r Row permutation
|
||||
* \param perm_r Row permutation
|
||||
* \param dense Store the full representation of the column
|
||||
* \param glu Global LU data.
|
||||
* \return 0 - successful return
|
||||
* \param glu Global LU data.
|
||||
* \return 0 - successful return
|
||||
* > 0 - number of bytes allocated when run out of space
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep,
|
||||
BlockIndexVector repfnz ,IndexVector& perm_r, BlockScalarVector dense, GlobalLU_t& glu)
|
||||
{
|
||||
Index ksub, krep, ksupno;
|
||||
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::copy_to_ucol(const Index jcol, const Index nseg, IndexVector& segrep,
|
||||
BlockIndexVector repfnz, IndexVector& perm_r,
|
||||
BlockScalarVector dense, GlobalLU_t& glu) {
|
||||
Index ksub, krep, ksupno;
|
||||
|
||||
Index jsupno = glu.supno(jcol);
|
||||
|
||||
// For each nonzero supernode segment of U[*,j] in topological order
|
||||
Index k = nseg - 1, i;
|
||||
StorageIndex nextu = glu.xusub(jcol);
|
||||
Index kfnz, isub, segsize;
|
||||
Index new_next,irow;
|
||||
Index fsupc, mem;
|
||||
for (ksub = 0; ksub < nseg; ksub++)
|
||||
{
|
||||
krep = segrep(k); k--;
|
||||
ksupno = glu.supno(krep);
|
||||
if (jsupno != ksupno ) // should go into ucol();
|
||||
|
||||
// For each nonzero supernode segment of U[*,j] in topological order
|
||||
Index k = nseg - 1, i;
|
||||
StorageIndex nextu = glu.xusub(jcol);
|
||||
Index kfnz, isub, segsize;
|
||||
Index new_next, irow;
|
||||
Index fsupc, mem;
|
||||
for (ksub = 0; ksub < nseg; ksub++) {
|
||||
krep = segrep(k);
|
||||
k--;
|
||||
ksupno = glu.supno(krep);
|
||||
if (jsupno != ksupno) // should go into ucol();
|
||||
{
|
||||
kfnz = repfnz(krep);
|
||||
if (kfnz != emptyIdxLU)
|
||||
{ // Nonzero U-segment
|
||||
fsupc = glu.xsup(ksupno);
|
||||
isub = glu.xlsub(fsupc) + kfnz - fsupc;
|
||||
segsize = krep - kfnz + 1;
|
||||
new_next = nextu + segsize;
|
||||
while (new_next > glu.nzumax)
|
||||
{
|
||||
mem = memXpand<ScalarVector>(glu.ucol, glu.nzumax, nextu, UCOL, glu.num_expansions);
|
||||
if (mem) return mem;
|
||||
mem = memXpand<IndexVector>(glu.usub, glu.nzumax, nextu, USUB, glu.num_expansions);
|
||||
if (mem) return mem;
|
||||
|
||||
kfnz = repfnz(krep);
|
||||
if (kfnz != emptyIdxLU) { // Nonzero U-segment
|
||||
fsupc = glu.xsup(ksupno);
|
||||
isub = glu.xlsub(fsupc) + kfnz - fsupc;
|
||||
segsize = krep - kfnz + 1;
|
||||
new_next = nextu + segsize;
|
||||
while (new_next > glu.nzumax) {
|
||||
mem = memXpand<ScalarVector>(glu.ucol, glu.nzumax, nextu, UCOL, glu.num_expansions);
|
||||
if (mem) return mem;
|
||||
mem = memXpand<IndexVector>(glu.usub, glu.nzumax, nextu, USUB, glu.num_expansions);
|
||||
if (mem) return mem;
|
||||
}
|
||||
|
||||
for (i = 0; i < segsize; i++)
|
||||
{
|
||||
irow = glu.lsub(isub);
|
||||
glu.usub(nextu) = perm_r(irow); // Unlike the L part, the U part is stored in its final order
|
||||
glu.ucol(nextu) = dense(irow);
|
||||
dense(irow) = Scalar(0.0);
|
||||
|
||||
for (i = 0; i < segsize; i++) {
|
||||
irow = glu.lsub(isub);
|
||||
glu.usub(nextu) = perm_r(irow); // Unlike the L part, the U part is stored in its final order
|
||||
glu.ucol(nextu) = dense(irow);
|
||||
dense(irow) = Scalar(0.0);
|
||||
nextu++;
|
||||
isub++;
|
||||
}
|
||||
|
||||
} // end nonzero U-segment
|
||||
|
||||
} // end if jsupno
|
||||
|
||||
} // end for each segment
|
||||
glu.xusub(jcol + 1) = nextu; // close U(*,jcol)
|
||||
return 0;
|
||||
|
||||
} // end nonzero U-segment
|
||||
|
||||
} // end if jsupno
|
||||
|
||||
} // end for each segment
|
||||
glu.xusub(jcol + 1) = nextu; // close U(*,jcol)
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // end namespace Eigen
|
||||
} // namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // SPARSELU_COPY_TO_UCOL_H
|
||||
#endif // SPARSELU_COPY_TO_UCOL_H
|
||||
|
||||
@@ -34,77 +34,67 @@
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
/**
|
||||
* \brief Identify the initial relaxed supernodes
|
||||
*
|
||||
* This routine applied to a symmetric elimination tree.
|
||||
*
|
||||
* This routine applied to a symmetric elimination tree.
|
||||
* It assumes that the matrix has been reordered according to the postorder of the etree
|
||||
* \param n The number of columns
|
||||
* \param et elimination tree
|
||||
* \param relax_columns Maximum number of columns allowed in a relaxed snode
|
||||
* \param et elimination tree
|
||||
* \param relax_columns Maximum number of columns allowed in a relaxed snode
|
||||
* \param descendants Number of descendants of each node in the etree
|
||||
* \param relax_end last column in a supernode
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
|
||||
{
|
||||
|
||||
// The etree may not be postordered, but its heap ordered
|
||||
void SparseLUImpl<Scalar, StorageIndex>::heap_relax_snode(const Index n, IndexVector& et, const Index relax_columns,
|
||||
IndexVector& descendants, IndexVector& relax_end) {
|
||||
// The etree may not be postordered, but its heap ordered
|
||||
IndexVector post;
|
||||
internal::treePostorder(StorageIndex(n), et, post); // Post order etree
|
||||
IndexVector inv_post(n+1);
|
||||
for (StorageIndex i = 0; i < n+1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
|
||||
|
||||
// Renumber etree in postorder
|
||||
internal::treePostorder(StorageIndex(n), et, post); // Post order etree
|
||||
IndexVector inv_post(n + 1);
|
||||
for (StorageIndex i = 0; i < n + 1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
|
||||
|
||||
// Renumber etree in postorder
|
||||
IndexVector iwork(n);
|
||||
IndexVector et_save(n+1);
|
||||
for (Index i = 0; i < n; ++i)
|
||||
{
|
||||
IndexVector et_save(n + 1);
|
||||
for (Index i = 0; i < n; ++i) {
|
||||
iwork(post(i)) = post(et(i));
|
||||
}
|
||||
et_save = et; // Save the original etree
|
||||
et = iwork;
|
||||
|
||||
et_save = et; // Save the original etree
|
||||
et = iwork;
|
||||
|
||||
// compute the number of descendants of each node in the etree
|
||||
relax_end.setConstant(emptyIdxLU);
|
||||
Index j, parent;
|
||||
Index j, parent;
|
||||
descendants.setZero();
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
for (j = 0; j < n; j++) {
|
||||
parent = et(j);
|
||||
if (parent != n) // not the dummy root
|
||||
if (parent != n) // not the dummy root
|
||||
descendants(parent) += descendants(j) + 1;
|
||||
}
|
||||
// Identify the relaxed supernodes by postorder traversal of the etree
|
||||
Index snode_start; // beginning of a snode
|
||||
Index snode_start; // beginning of a snode
|
||||
StorageIndex k;
|
||||
StorageIndex l;
|
||||
for (j = 0; j < n; )
|
||||
{
|
||||
StorageIndex l;
|
||||
for (j = 0; j < n;) {
|
||||
parent = et(j);
|
||||
snode_start = j;
|
||||
while ( parent != n && descendants(parent) < relax_columns )
|
||||
{
|
||||
j = parent;
|
||||
snode_start = j;
|
||||
while (parent != n && descendants(parent) < relax_columns) {
|
||||
j = parent;
|
||||
parent = et(j);
|
||||
}
|
||||
// Found a supernode in postordered etree, j is the last column
|
||||
// Found a supernode in postordered etree, j is the last column
|
||||
k = StorageIndex(n);
|
||||
for (Index i = snode_start; i <= j; ++i)
|
||||
k = (std::min)(k, inv_post(i));
|
||||
for (Index i = snode_start; i <= j; ++i) k = (std::min)(k, inv_post(i));
|
||||
l = inv_post(j);
|
||||
if ( (l - k) == (j - snode_start) ) // Same number of columns in the snode
|
||||
if ((l - k) == (j - snode_start)) // Same number of columns in the snode
|
||||
{
|
||||
// This is also a supernode in the original etree
|
||||
relax_end(k) = l; // Record last column
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Index i = snode_start; i <= j; ++i)
|
||||
{
|
||||
relax_end(k) = l; // Record last column
|
||||
} else {
|
||||
for (Index i = snode_start; i <= j; ++i) {
|
||||
l = inv_post(i);
|
||||
if (descendants(i) == 0)
|
||||
{
|
||||
if (descendants(i) == 0) {
|
||||
relax_end(l) = l;
|
||||
}
|
||||
}
|
||||
@@ -112,13 +102,13 @@ void SparseLUImpl<Scalar,StorageIndex>::heap_relax_snode (const Index n, IndexVe
|
||||
j++;
|
||||
// Search for a new leaf
|
||||
while (descendants(j) != 0 && j < n) j++;
|
||||
} // End postorder traversal of the etree
|
||||
|
||||
} // End postorder traversal of the etree
|
||||
|
||||
// Recover the original etree
|
||||
et = et_save;
|
||||
et = et_save;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
#endif // SPARSELU_HEAP_RELAX_SNODE_H
|
||||
} // end namespace Eigen
|
||||
#endif // SPARSELU_HEAP_RELAX_SNODE_H
|
||||
|
||||
@@ -16,117 +16,118 @@
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
template <int SegSizeAtCompileTime> struct LU_kernel_bmod
|
||||
{
|
||||
|
||||
template <int SegSizeAtCompileTime>
|
||||
struct LU_kernel_bmod {
|
||||
/** \internal
|
||||
* \brief Performs numeric block updates from a given supernode to a single column
|
||||
*
|
||||
* \param segsize Size of the segment (and blocks ) to use for updates
|
||||
* \param[in,out] dense Packed values of the original matrix
|
||||
* \param tempv temporary vector to use for updates
|
||||
* \param lusup array containing the supernodes
|
||||
* \param lda Leading dimension in the supernode
|
||||
* \param nrow Number of rows in the rectangular part of the supernode
|
||||
* \param lsub compressed row subscripts of supernodes
|
||||
* \param lptr pointer to the first column of the current supernode in lsub
|
||||
* \param no_zeros Number of nonzeros elements before the diagonal part of the supernode
|
||||
*/
|
||||
* \brief Performs numeric block updates from a given supernode to a single column
|
||||
*
|
||||
* \param segsize Size of the segment (and blocks ) to use for updates
|
||||
* \param[in,out] dense Packed values of the original matrix
|
||||
* \param tempv temporary vector to use for updates
|
||||
* \param lusup array containing the supernodes
|
||||
* \param lda Leading dimension in the supernode
|
||||
* \param nrow Number of rows in the rectangular part of the supernode
|
||||
* \param lsub compressed row subscripts of supernodes
|
||||
* \param lptr pointer to the first column of the current supernode in lsub
|
||||
* \param no_zeros Number of nonzeros elements before the diagonal part of the supernode
|
||||
*/
|
||||
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
|
||||
static EIGEN_DONT_INLINE void run(const Index segsize, BlockScalarVector& dense, ScalarVector& tempv, ScalarVector& lusup, Index& luptr, const Index lda,
|
||||
const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros);
|
||||
static EIGEN_DONT_INLINE void run(const Index segsize, BlockScalarVector& dense, ScalarVector& tempv,
|
||||
ScalarVector& lusup, Index& luptr, const Index lda, const Index nrow,
|
||||
IndexVector& lsub, const Index lptr, const Index no_zeros);
|
||||
};
|
||||
|
||||
template <int SegSizeAtCompileTime>
|
||||
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
|
||||
EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const Index segsize, BlockScalarVector& dense, ScalarVector& tempv, ScalarVector& lusup, Index& luptr, const Index lda,
|
||||
const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros)
|
||||
{
|
||||
EIGEN_DONT_INLINE void LU_kernel_bmod<SegSizeAtCompileTime>::run(const Index segsize, BlockScalarVector& dense,
|
||||
ScalarVector& tempv, ScalarVector& lusup, Index& luptr,
|
||||
const Index lda, const Index nrow, IndexVector& lsub,
|
||||
const Index lptr, const Index no_zeros) {
|
||||
typedef typename ScalarVector::Scalar Scalar;
|
||||
// First, copy U[*,j] segment from dense(*) to tempv(*)
|
||||
// The result of triangular solve is in tempv[*];
|
||||
// The result of matric-vector update is in dense[*]
|
||||
Index isub = lptr + no_zeros;
|
||||
// The result of triangular solve is in tempv[*];
|
||||
// The result of matric-vector update is in dense[*]
|
||||
Index isub = lptr + no_zeros;
|
||||
Index i;
|
||||
Index irow;
|
||||
for (i = 0; i < ((SegSizeAtCompileTime==Dynamic)?segsize:SegSizeAtCompileTime); i++)
|
||||
{
|
||||
irow = lsub(isub);
|
||||
tempv(i) = dense(irow);
|
||||
++isub;
|
||||
for (i = 0; i < ((SegSizeAtCompileTime == Dynamic) ? segsize : SegSizeAtCompileTime); i++) {
|
||||
irow = lsub(isub);
|
||||
tempv(i) = dense(irow);
|
||||
++isub;
|
||||
}
|
||||
// Dense triangular solve -- start effective triangle
|
||||
luptr += lda * no_zeros + no_zeros;
|
||||
// Form Eigen matrix and vector
|
||||
Map<Matrix<Scalar,SegSizeAtCompileTime,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda) );
|
||||
Map<Matrix<Scalar,SegSizeAtCompileTime,1> > u(tempv.data(), segsize);
|
||||
|
||||
u = A.template triangularView<UnitLower>().solve(u);
|
||||
|
||||
// Dense matrix-vector product y <-- B*x
|
||||
luptr += lda * no_zeros + no_zeros;
|
||||
// Form Eigen matrix and vector
|
||||
Map<Matrix<Scalar, SegSizeAtCompileTime, SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > A(
|
||||
&(lusup.data()[luptr]), segsize, segsize, OuterStride<>(lda));
|
||||
Map<Matrix<Scalar, SegSizeAtCompileTime, 1> > u(tempv.data(), segsize);
|
||||
|
||||
u = A.template triangularView<UnitLower>().solve(u);
|
||||
|
||||
// Dense matrix-vector product y <-- B*x
|
||||
luptr += segsize;
|
||||
const Index PacketSize = internal::packet_traits<Scalar>::size;
|
||||
Index ldl = internal::first_multiple(nrow, PacketSize);
|
||||
Map<Matrix<Scalar,Dynamic,SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > B( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(lda) );
|
||||
Index aligned_offset = internal::first_default_aligned(tempv.data()+segsize, PacketSize);
|
||||
Index aligned_with_B_offset = (PacketSize-internal::first_default_aligned(B.data(), PacketSize))%PacketSize;
|
||||
Map<Matrix<Scalar,Dynamic,1>, 0, OuterStride<> > l(tempv.data()+segsize+aligned_offset+aligned_with_B_offset, nrow, OuterStride<>(ldl) );
|
||||
|
||||
Map<Matrix<Scalar, Dynamic, SegSizeAtCompileTime, ColMajor>, 0, OuterStride<> > B(&(lusup.data()[luptr]), nrow,
|
||||
segsize, OuterStride<>(lda));
|
||||
Index aligned_offset = internal::first_default_aligned(tempv.data() + segsize, PacketSize);
|
||||
Index aligned_with_B_offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
|
||||
Map<Matrix<Scalar, Dynamic, 1>, 0, OuterStride<> > l(tempv.data() + segsize + aligned_offset + aligned_with_B_offset,
|
||||
nrow, OuterStride<>(ldl));
|
||||
|
||||
l.noalias() = B * u;
|
||||
|
||||
// Scatter tempv[] into SPA dense[] as a temporary storage
|
||||
|
||||
// Scatter tempv[] into SPA dense[] as a temporary storage
|
||||
isub = lptr + no_zeros;
|
||||
for (i = 0; i < ((SegSizeAtCompileTime==Dynamic)?segsize:SegSizeAtCompileTime); i++)
|
||||
{
|
||||
irow = lsub(isub++);
|
||||
for (i = 0; i < ((SegSizeAtCompileTime == Dynamic) ? segsize : SegSizeAtCompileTime); i++) {
|
||||
irow = lsub(isub++);
|
||||
dense(irow) = tempv(i);
|
||||
}
|
||||
|
||||
|
||||
// Scatter l into SPA dense[]
|
||||
for (i = 0; i < nrow; i++)
|
||||
{
|
||||
irow = lsub(isub++);
|
||||
for (i = 0; i < nrow; i++) {
|
||||
irow = lsub(isub++);
|
||||
dense(irow) -= l(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <> struct LU_kernel_bmod<1>
|
||||
{
|
||||
template <>
|
||||
struct LU_kernel_bmod<1> {
|
||||
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
|
||||
static EIGEN_DONT_INLINE void run(const Index /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
|
||||
const Index lda, const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros);
|
||||
static EIGEN_DONT_INLINE void run(const Index /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/,
|
||||
ScalarVector& lusup, Index& luptr, const Index lda, const Index nrow,
|
||||
IndexVector& lsub, const Index lptr, const Index no_zeros);
|
||||
};
|
||||
|
||||
|
||||
template <typename BlockScalarVector, typename ScalarVector, typename IndexVector>
|
||||
EIGEN_DONT_INLINE void LU_kernel_bmod<1>::run(const Index /*segsize*/, BlockScalarVector& dense, ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
|
||||
const Index lda, const Index nrow, IndexVector& lsub, const Index lptr, const Index no_zeros)
|
||||
{
|
||||
EIGEN_DONT_INLINE void LU_kernel_bmod<1>::run(const Index /*segsize*/, BlockScalarVector& dense,
|
||||
ScalarVector& /*tempv*/, ScalarVector& lusup, Index& luptr,
|
||||
const Index lda, const Index nrow, IndexVector& lsub, const Index lptr,
|
||||
const Index no_zeros) {
|
||||
typedef typename ScalarVector::Scalar Scalar;
|
||||
typedef typename IndexVector::Scalar StorageIndex;
|
||||
Scalar f = dense(lsub(lptr + no_zeros));
|
||||
luptr += lda * no_zeros + no_zeros + 1;
|
||||
const Scalar* a(lusup.data() + luptr);
|
||||
const StorageIndex* irow(lsub.data()+lptr + no_zeros + 1);
|
||||
const StorageIndex* irow(lsub.data() + lptr + no_zeros + 1);
|
||||
Index i = 0;
|
||||
for (; i+1 < nrow; i+=2)
|
||||
{
|
||||
for (; i + 1 < nrow; i += 2) {
|
||||
Index i0 = *(irow++);
|
||||
Index i1 = *(irow++);
|
||||
Scalar a0 = *(a++);
|
||||
Scalar a1 = *(a++);
|
||||
Scalar d0 = dense.coeff(i0);
|
||||
Scalar d1 = dense.coeff(i1);
|
||||
d0 -= f*a0;
|
||||
d1 -= f*a1;
|
||||
d0 -= f * a0;
|
||||
d1 -= f * a1;
|
||||
dense.coeffRef(i0) = d0;
|
||||
dense.coeffRef(i1) = d1;
|
||||
}
|
||||
if(i<nrow)
|
||||
dense.coeffRef(*(irow++)) -= f * *(a++);
|
||||
if (i < nrow) dense.coeffRef(*(irow++)) -= f * *(a++);
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
#endif // SPARSELU_KERNEL_BMOD_H
|
||||
} // end namespace Eigen
|
||||
#endif // SPARSELU_KERNEL_BMOD_H
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]panel_bmod.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]panel_bmod.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 3.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -39,187 +39,177 @@ namespace internal {
|
||||
|
||||
/**
|
||||
* \brief Performs numeric block updates (sup-panel) in topological order.
|
||||
*
|
||||
*
|
||||
* Before entering this routine, the original nonzeros in the panel
|
||||
* were already copied into the spa[m,w]
|
||||
*
|
||||
*
|
||||
* \param m number of rows in the matrix
|
||||
* \param w Panel size
|
||||
* \param jcol Starting column of the panel
|
||||
* \param nseg Number of segments in the U part
|
||||
* \param dense Store the full representation of the panel
|
||||
* \param tempv working array
|
||||
* \param dense Store the full representation of the panel
|
||||
* \param tempv working array
|
||||
* \param segrep segment representative... first row in the segment
|
||||
* \param repfnz First nonzero rows
|
||||
* \param glu Global LU data.
|
||||
*
|
||||
*
|
||||
* \param glu Global LU data.
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::panel_bmod(const Index m, const Index w, const Index jcol,
|
||||
const Index nseg, ScalarVector& dense, ScalarVector& tempv,
|
||||
IndexVector& segrep, IndexVector& repfnz, GlobalLU_t& glu)
|
||||
{
|
||||
|
||||
Index ksub,jj,nextl_col;
|
||||
Index fsupc, nsupc, nsupr, nrow;
|
||||
Index krep, kfnz;
|
||||
Index lptr; // points to the row subscripts of a supernode
|
||||
Index luptr; // ...
|
||||
Index segsize,no_zeros ;
|
||||
void SparseLUImpl<Scalar, StorageIndex>::panel_bmod(const Index m, const Index w, const Index jcol, const Index nseg,
|
||||
ScalarVector& dense, ScalarVector& tempv, IndexVector& segrep,
|
||||
IndexVector& repfnz, GlobalLU_t& glu) {
|
||||
Index ksub, jj, nextl_col;
|
||||
Index fsupc, nsupc, nsupr, nrow;
|
||||
Index krep, kfnz;
|
||||
Index lptr; // points to the row subscripts of a supernode
|
||||
Index luptr; // ...
|
||||
Index segsize, no_zeros;
|
||||
// For each nonz supernode segment of U[*,j] in topological order
|
||||
Index k = nseg - 1;
|
||||
Index k = nseg - 1;
|
||||
const Index PacketSize = internal::packet_traits<Scalar>::size;
|
||||
|
||||
for (ksub = 0; ksub < nseg; ksub++)
|
||||
{ // For each updating supernode
|
||||
|
||||
for (ksub = 0; ksub < nseg; ksub++) { // For each updating supernode
|
||||
/* krep = representative of current k-th supernode
|
||||
* fsupc = first supernodal column
|
||||
* nsupc = number of columns in a supernode
|
||||
* nsupr = number of rows in a supernode
|
||||
*/
|
||||
krep = segrep(k); k--;
|
||||
fsupc = glu.xsup(glu.supno(krep));
|
||||
nsupc = krep - fsupc + 1;
|
||||
nsupr = glu.xlsub(fsupc+1) - glu.xlsub(fsupc);
|
||||
nrow = nsupr - nsupc;
|
||||
lptr = glu.xlsub(fsupc);
|
||||
|
||||
krep = segrep(k);
|
||||
k--;
|
||||
fsupc = glu.xsup(glu.supno(krep));
|
||||
nsupc = krep - fsupc + 1;
|
||||
nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
|
||||
nrow = nsupr - nsupc;
|
||||
lptr = glu.xlsub(fsupc);
|
||||
|
||||
// loop over the panel columns to detect the actual number of columns and rows
|
||||
Index u_rows = 0;
|
||||
Index u_cols = 0;
|
||||
for (jj = jcol; jj < jcol + w; jj++)
|
||||
{
|
||||
nextl_col = (jj-jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if ( kfnz == emptyIdxLU )
|
||||
continue; // skip any zero segment
|
||||
|
||||
for (jj = jcol; jj < jcol + w; jj++) {
|
||||
nextl_col = (jj - jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if (kfnz == emptyIdxLU) continue; // skip any zero segment
|
||||
|
||||
segsize = krep - kfnz + 1;
|
||||
u_cols++;
|
||||
u_rows = (std::max)(segsize,u_rows);
|
||||
u_rows = (std::max)(segsize, u_rows);
|
||||
}
|
||||
|
||||
if(nsupc >= 2)
|
||||
{
|
||||
|
||||
if (nsupc >= 2) {
|
||||
Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
|
||||
Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
|
||||
|
||||
Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
|
||||
|
||||
// gather U
|
||||
Index u_col = 0;
|
||||
for (jj = jcol; jj < jcol + w; jj++)
|
||||
{
|
||||
nextl_col = (jj-jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if ( kfnz == emptyIdxLU )
|
||||
continue; // skip any zero segment
|
||||
|
||||
for (jj = jcol; jj < jcol + w; jj++) {
|
||||
nextl_col = (jj - jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if (kfnz == emptyIdxLU) continue; // skip any zero segment
|
||||
|
||||
segsize = krep - kfnz + 1;
|
||||
luptr = glu.xlusup(fsupc);
|
||||
no_zeros = kfnz - fsupc;
|
||||
|
||||
luptr = glu.xlusup(fsupc);
|
||||
no_zeros = kfnz - fsupc;
|
||||
|
||||
Index isub = lptr + no_zeros;
|
||||
Index off = u_rows-segsize;
|
||||
for (Index i = 0; i < off; i++) U(i,u_col) = 0;
|
||||
for (Index i = 0; i < segsize; i++)
|
||||
{
|
||||
Index irow = glu.lsub(isub);
|
||||
U(i+off,u_col) = dense_col(irow);
|
||||
++isub;
|
||||
Index off = u_rows - segsize;
|
||||
for (Index i = 0; i < off; i++) U(i, u_col) = 0;
|
||||
for (Index i = 0; i < segsize; i++) {
|
||||
Index irow = glu.lsub(isub);
|
||||
U(i + off, u_col) = dense_col(irow);
|
||||
++isub;
|
||||
}
|
||||
u_col++;
|
||||
}
|
||||
// solve U = A^-1 U
|
||||
luptr = glu.xlusup(fsupc);
|
||||
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc);
|
||||
Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc);
|
||||
no_zeros = (krep - u_rows + 1) - fsupc;
|
||||
luptr += lda * no_zeros + no_zeros;
|
||||
MappedMatrixBlock A(glu.lusup.data()+luptr, u_rows, u_rows, OuterStride<>(lda) );
|
||||
MappedMatrixBlock A(glu.lusup.data() + luptr, u_rows, u_rows, OuterStride<>(lda));
|
||||
U = A.template triangularView<UnitLower>().solve(U);
|
||||
|
||||
|
||||
// update
|
||||
luptr += u_rows;
|
||||
MappedMatrixBlock B(glu.lusup.data()+luptr, nrow, u_rows, OuterStride<>(lda) );
|
||||
eigen_assert(tempv.size()>w*ldu + nrow*w + 1);
|
||||
|
||||
MappedMatrixBlock B(glu.lusup.data() + luptr, nrow, u_rows, OuterStride<>(lda));
|
||||
eigen_assert(tempv.size() > w * ldu + nrow * w + 1);
|
||||
|
||||
Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
|
||||
Index offset = (PacketSize-internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
|
||||
MappedMatrixBlock L(tempv.data()+w*ldu+offset, nrow, u_cols, OuterStride<>(ldl));
|
||||
|
||||
Index offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
|
||||
MappedMatrixBlock L(tempv.data() + w * ldu + offset, nrow, u_cols, OuterStride<>(ldl));
|
||||
|
||||
L.noalias() = B * U;
|
||||
|
||||
|
||||
// scatter U and L
|
||||
u_col = 0;
|
||||
for (jj = jcol; jj < jcol + w; jj++)
|
||||
{
|
||||
nextl_col = (jj-jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if ( kfnz == emptyIdxLU )
|
||||
continue; // skip any zero segment
|
||||
|
||||
for (jj = jcol; jj < jcol + w; jj++) {
|
||||
nextl_col = (jj - jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if (kfnz == emptyIdxLU) continue; // skip any zero segment
|
||||
|
||||
segsize = krep - kfnz + 1;
|
||||
no_zeros = kfnz - fsupc;
|
||||
no_zeros = kfnz - fsupc;
|
||||
Index isub = lptr + no_zeros;
|
||||
|
||||
Index off = u_rows-segsize;
|
||||
for (Index i = 0; i < segsize; i++)
|
||||
{
|
||||
Index irow = glu.lsub(isub++);
|
||||
dense_col(irow) = U.coeff(i+off,u_col);
|
||||
U.coeffRef(i+off,u_col) = 0;
|
||||
|
||||
Index off = u_rows - segsize;
|
||||
for (Index i = 0; i < segsize; i++) {
|
||||
Index irow = glu.lsub(isub++);
|
||||
dense_col(irow) = U.coeff(i + off, u_col);
|
||||
U.coeffRef(i + off, u_col) = 0;
|
||||
}
|
||||
|
||||
|
||||
// Scatter l into SPA dense[]
|
||||
for (Index i = 0; i < nrow; i++)
|
||||
{
|
||||
Index irow = glu.lsub(isub++);
|
||||
dense_col(irow) -= L.coeff(i,u_col);
|
||||
L.coeffRef(i,u_col) = 0;
|
||||
for (Index i = 0; i < nrow; i++) {
|
||||
Index irow = glu.lsub(isub++);
|
||||
dense_col(irow) -= L.coeff(i, u_col);
|
||||
L.coeffRef(i, u_col) = 0;
|
||||
}
|
||||
u_col++;
|
||||
}
|
||||
}
|
||||
else // level 2 only
|
||||
} else // level 2 only
|
||||
{
|
||||
// Sequence through each column in the panel
|
||||
for (jj = jcol; jj < jcol + w; jj++)
|
||||
{
|
||||
nextl_col = (jj-jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if ( kfnz == emptyIdxLU )
|
||||
continue; // skip any zero segment
|
||||
|
||||
for (jj = jcol; jj < jcol + w; jj++) {
|
||||
nextl_col = (jj - jcol) * m;
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
|
||||
|
||||
kfnz = repfnz_col(krep);
|
||||
if (kfnz == emptyIdxLU) continue; // skip any zero segment
|
||||
|
||||
segsize = krep - kfnz + 1;
|
||||
luptr = glu.xlusup(fsupc);
|
||||
|
||||
Index lda = glu.xlusup(fsupc+1)-glu.xlusup(fsupc);// nsupr
|
||||
|
||||
// Perform a trianglar solve and block update,
|
||||
|
||||
Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // nsupr
|
||||
|
||||
// Perform a trianglar solve and block update,
|
||||
// then scatter the result of sup-col update to dense[]
|
||||
no_zeros = kfnz - fsupc;
|
||||
if(segsize==1) LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else if(segsize==2) LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else if(segsize==3) LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
} // End for each column in the panel
|
||||
no_zeros = kfnz - fsupc;
|
||||
if (segsize == 1)
|
||||
LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else if (segsize == 2)
|
||||
LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else if (segsize == 3)
|
||||
LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
|
||||
else
|
||||
LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr,
|
||||
no_zeros);
|
||||
} // End for each column in the panel
|
||||
}
|
||||
|
||||
} // End for each updating supernode
|
||||
} // end panel bmod
|
||||
|
||||
} // end namespace internal
|
||||
} // End for each updating supernode
|
||||
} // end panel bmod
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace internal
|
||||
|
||||
#endif // SPARSELU_PANEL_BMOD_H
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // SPARSELU_PANEL_BMOD_H
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]panel_dfs.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]panel_dfs.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 2.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -36,19 +36,14 @@
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename IndexVector>
|
||||
struct panel_dfs_traits
|
||||
{
|
||||
|
||||
template <typename IndexVector>
|
||||
struct panel_dfs_traits {
|
||||
typedef typename IndexVector::Scalar StorageIndex;
|
||||
panel_dfs_traits(Index jcol, StorageIndex* marker)
|
||||
: m_jcol(jcol), m_marker(marker)
|
||||
{}
|
||||
bool update_segrep(Index krep, StorageIndex jj)
|
||||
{
|
||||
if(m_marker[krep]<m_jcol)
|
||||
{
|
||||
m_marker[krep] = jj;
|
||||
panel_dfs_traits(Index jcol, StorageIndex* marker) : m_jcol(jcol), m_marker(marker) {}
|
||||
bool update_segrep(Index krep, StorageIndex jj) {
|
||||
if (m_marker[krep] < m_jcol) {
|
||||
m_marker[krep] = jj;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -59,147 +54,127 @@ struct panel_dfs_traits
|
||||
StorageIndex* m_marker;
|
||||
};
|
||||
|
||||
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
template <typename Traits>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::dfs_kernel(const StorageIndex jj, IndexVector& perm_r,
|
||||
Index& nseg, IndexVector& panel_lsub, IndexVector& segrep,
|
||||
Ref<IndexVector> repfnz_col, IndexVector& xprune, Ref<IndexVector> marker, IndexVector& parent,
|
||||
IndexVector& xplore, GlobalLU_t& glu,
|
||||
Index& nextl_col, Index krow, Traits& traits
|
||||
)
|
||||
{
|
||||
|
||||
void SparseLUImpl<Scalar, StorageIndex>::dfs_kernel(const StorageIndex jj, IndexVector& perm_r, Index& nseg,
|
||||
IndexVector& panel_lsub, IndexVector& segrep,
|
||||
Ref<IndexVector> repfnz_col, IndexVector& xprune,
|
||||
Ref<IndexVector> marker, IndexVector& parent, IndexVector& xplore,
|
||||
GlobalLU_t& glu, Index& nextl_col, Index krow, Traits& traits) {
|
||||
StorageIndex kmark = marker(krow);
|
||||
|
||||
|
||||
// For each unmarked krow of jj
|
||||
marker(krow) = jj;
|
||||
StorageIndex kperm = perm_r(krow);
|
||||
if (kperm == emptyIdxLU ) {
|
||||
marker(krow) = jj;
|
||||
StorageIndex kperm = perm_r(krow);
|
||||
if (kperm == emptyIdxLU) {
|
||||
// krow is in L : place it in structure of L(*, jj)
|
||||
panel_lsub(nextl_col++) = StorageIndex(krow); // krow is indexed into A
|
||||
|
||||
|
||||
traits.mem_expand(panel_lsub, nextl_col, kmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// krow is in U : if its supernode-representative krep
|
||||
// has been explored, update repfnz(*)
|
||||
// krep = supernode representative of the current row
|
||||
StorageIndex krep = glu.xsup(glu.supno(kperm)+1) - 1;
|
||||
StorageIndex krep = glu.xsup(glu.supno(kperm) + 1) - 1;
|
||||
// First nonzero element in the current column:
|
||||
StorageIndex myfnz = repfnz_col(krep);
|
||||
|
||||
if (myfnz != emptyIdxLU )
|
||||
{
|
||||
StorageIndex myfnz = repfnz_col(krep);
|
||||
|
||||
if (myfnz != emptyIdxLU) {
|
||||
// Representative visited before
|
||||
if (myfnz > kperm ) repfnz_col(krep) = kperm;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (myfnz > kperm) repfnz_col(krep) = kperm;
|
||||
|
||||
} else {
|
||||
// Otherwise, perform dfs starting at krep
|
||||
StorageIndex oldrep = emptyIdxLU;
|
||||
parent(krep) = oldrep;
|
||||
repfnz_col(krep) = kperm;
|
||||
StorageIndex xdfs = glu.xlsub(krep);
|
||||
Index maxdfs = xprune(krep);
|
||||
|
||||
StorageIndex oldrep = emptyIdxLU;
|
||||
parent(krep) = oldrep;
|
||||
repfnz_col(krep) = kperm;
|
||||
StorageIndex xdfs = glu.xlsub(krep);
|
||||
Index maxdfs = xprune(krep);
|
||||
|
||||
StorageIndex kpar;
|
||||
do
|
||||
{
|
||||
do {
|
||||
// For each unmarked kchild of krep
|
||||
while (xdfs < maxdfs)
|
||||
{
|
||||
StorageIndex kchild = glu.lsub(xdfs);
|
||||
xdfs++;
|
||||
StorageIndex chmark = marker(kchild);
|
||||
|
||||
if (chmark != jj )
|
||||
{
|
||||
marker(kchild) = jj;
|
||||
StorageIndex chperm = perm_r(kchild);
|
||||
|
||||
if (chperm == emptyIdxLU)
|
||||
{
|
||||
while (xdfs < maxdfs) {
|
||||
StorageIndex kchild = glu.lsub(xdfs);
|
||||
xdfs++;
|
||||
StorageIndex chmark = marker(kchild);
|
||||
|
||||
if (chmark != jj) {
|
||||
marker(kchild) = jj;
|
||||
StorageIndex chperm = perm_r(kchild);
|
||||
|
||||
if (chperm == emptyIdxLU) {
|
||||
// case kchild is in L: place it in L(*, j)
|
||||
panel_lsub(nextl_col++) = kchild;
|
||||
traits.mem_expand(panel_lsub, nextl_col, chmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// case kchild is in U :
|
||||
// chrep = its supernode-rep. If its rep has been explored,
|
||||
// chrep = its supernode-rep. If its rep has been explored,
|
||||
// update its repfnz(*)
|
||||
StorageIndex chrep = glu.xsup(glu.supno(chperm)+1) - 1;
|
||||
myfnz = repfnz_col(chrep);
|
||||
|
||||
if (myfnz != emptyIdxLU)
|
||||
{ // Visited before
|
||||
if (myfnz > chperm)
|
||||
repfnz_col(chrep) = chperm;
|
||||
}
|
||||
else
|
||||
{ // Cont. dfs at snode-rep of kchild
|
||||
xplore(krep) = xdfs;
|
||||
oldrep = krep;
|
||||
krep = chrep; // Go deeper down G(L)
|
||||
parent(krep) = oldrep;
|
||||
repfnz_col(krep) = chperm;
|
||||
xdfs = glu.xlsub(krep);
|
||||
maxdfs = xprune(krep);
|
||||
|
||||
} // end if myfnz != -1
|
||||
} // end if chperm == -1
|
||||
|
||||
} // end if chmark !=jj
|
||||
} // end while xdfs < maxdfs
|
||||
|
||||
StorageIndex chrep = glu.xsup(glu.supno(chperm) + 1) - 1;
|
||||
myfnz = repfnz_col(chrep);
|
||||
|
||||
if (myfnz != emptyIdxLU) { // Visited before
|
||||
if (myfnz > chperm) repfnz_col(chrep) = chperm;
|
||||
} else { // Cont. dfs at snode-rep of kchild
|
||||
xplore(krep) = xdfs;
|
||||
oldrep = krep;
|
||||
krep = chrep; // Go deeper down G(L)
|
||||
parent(krep) = oldrep;
|
||||
repfnz_col(krep) = chperm;
|
||||
xdfs = glu.xlsub(krep);
|
||||
maxdfs = xprune(krep);
|
||||
|
||||
} // end if myfnz != -1
|
||||
} // end if chperm == -1
|
||||
|
||||
} // end if chmark !=jj
|
||||
} // end while xdfs < maxdfs
|
||||
|
||||
// krow has no more unexplored nbrs :
|
||||
// Place snode-rep krep in postorder DFS, if this
|
||||
// segment is seen for the first time. (Note that
|
||||
// Place snode-rep krep in postorder DFS, if this
|
||||
// segment is seen for the first time. (Note that
|
||||
// "repfnz(krep)" may change later.)
|
||||
// Baktrack dfs to its parent
|
||||
if(traits.update_segrep(krep,jj))
|
||||
//if (marker1(krep) < jcol )
|
||||
if (traits.update_segrep(krep, jj))
|
||||
// if (marker1(krep) < jcol )
|
||||
{
|
||||
segrep(nseg) = krep;
|
||||
++nseg;
|
||||
//marker1(krep) = jj;
|
||||
segrep(nseg) = krep;
|
||||
++nseg;
|
||||
// marker1(krep) = jj;
|
||||
}
|
||||
|
||||
kpar = parent(krep); // Pop recursion, mimic recursion
|
||||
if (kpar == emptyIdxLU)
|
||||
break; // dfs done
|
||||
krep = kpar;
|
||||
xdfs = xplore(krep);
|
||||
maxdfs = xprune(krep);
|
||||
|
||||
} while (kpar != emptyIdxLU); // Do until empty stack
|
||||
|
||||
} // end if (myfnz = -1)
|
||||
kpar = parent(krep); // Pop recursion, mimic recursion
|
||||
if (kpar == emptyIdxLU) break; // dfs done
|
||||
krep = kpar;
|
||||
xdfs = xplore(krep);
|
||||
maxdfs = xprune(krep);
|
||||
|
||||
} // end if (kperm == -1)
|
||||
} while (kpar != emptyIdxLU); // Do until empty stack
|
||||
|
||||
} // end if (myfnz = -1)
|
||||
|
||||
} // end if (kperm == -1)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Performs a symbolic factorization on a panel of columns [jcol, jcol+w)
|
||||
*
|
||||
*
|
||||
* A supernode representative is the last column of a supernode.
|
||||
* The nonzeros in U[*,j] are segments that end at supernodes representatives
|
||||
*
|
||||
* The routine returns a list of the supernodal representatives
|
||||
* in topological order of the dfs that generates them. This list is
|
||||
* a superset of the topological order of each individual column within
|
||||
*
|
||||
* The routine returns a list of the supernodal representatives
|
||||
* in topological order of the dfs that generates them. This list is
|
||||
* a superset of the topological order of each individual column within
|
||||
* the panel.
|
||||
* The location of the first nonzero in each supernodal segment
|
||||
* (supernodal entry location) is also returned. Each column has
|
||||
* a separate list for this purpose.
|
||||
*
|
||||
* The location of the first nonzero in each supernodal segment
|
||||
* (supernodal entry location) is also returned. Each column has
|
||||
* a separate list for this purpose.
|
||||
*
|
||||
* Two markers arrays are used for dfs :
|
||||
* marker[i] == jj, if i was visited during dfs of current column jj;
|
||||
* marker1[i] >= jcol, if i was visited by earlier columns in this panel;
|
||||
*
|
||||
* marker1[i] >= jcol, if i was visited by earlier columns in this panel;
|
||||
*
|
||||
* \param[in] m number of rows in the matrix
|
||||
* \param[in] w Panel size
|
||||
* \param[in] jcol Starting column of the panel
|
||||
@@ -207,7 +182,7 @@ void SparseLUImpl<Scalar,StorageIndex>::dfs_kernel(const StorageIndex jj, IndexV
|
||||
* \param[in] perm_r Row permutation
|
||||
* \param[out] nseg Number of U segments
|
||||
* \param[out] dense Accumulate the column vectors of the panel
|
||||
* \param[out] panel_lsub Subscripts of the row in the panel
|
||||
* \param[out] panel_lsub Subscripts of the row in the panel
|
||||
* \param[out] segrep Segment representative i.e first nonzero row of each segment
|
||||
* \param[out] repfnz First nonzero location in each row
|
||||
* \param[out] xprune The pruned elimination tree
|
||||
@@ -215,47 +190,46 @@ void SparseLUImpl<Scalar,StorageIndex>::dfs_kernel(const StorageIndex jj, IndexV
|
||||
* \param parent The elimination tree
|
||||
* \param xplore work vector
|
||||
* \param glu The global data structure
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A, IndexVector& perm_r, Index& nseg, ScalarVector& dense, IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz, IndexVector& xprune, IndexVector& marker, IndexVector& parent, IndexVector& xplore, GlobalLU_t& glu)
|
||||
{
|
||||
Index nextl_col; // Next available position in panel_lsub[*,jj]
|
||||
|
||||
// Initialize pointers
|
||||
VectorBlock<IndexVector> marker1(marker, m, m);
|
||||
nseg = 0;
|
||||
|
||||
void SparseLUImpl<Scalar, StorageIndex>::panel_dfs(const Index m, const Index w, const Index jcol, MatrixType& A,
|
||||
IndexVector& perm_r, Index& nseg, ScalarVector& dense,
|
||||
IndexVector& panel_lsub, IndexVector& segrep, IndexVector& repfnz,
|
||||
IndexVector& xprune, IndexVector& marker, IndexVector& parent,
|
||||
IndexVector& xplore, GlobalLU_t& glu) {
|
||||
Index nextl_col; // Next available position in panel_lsub[*,jj]
|
||||
|
||||
// Initialize pointers
|
||||
VectorBlock<IndexVector> marker1(marker, m, m);
|
||||
nseg = 0;
|
||||
|
||||
panel_dfs_traits<IndexVector> traits(jcol, marker1.data());
|
||||
|
||||
// For each column in the panel
|
||||
for (StorageIndex jj = StorageIndex(jcol); jj < jcol + w; jj++)
|
||||
{
|
||||
nextl_col = (jj - jcol) * m;
|
||||
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
|
||||
VectorBlock<ScalarVector> dense_col(dense,nextl_col, m); // Accumulate a column vector here
|
||||
|
||||
|
||||
|
||||
// For each column in the panel
|
||||
for (StorageIndex jj = StorageIndex(jcol); jj < jcol + w; jj++) {
|
||||
nextl_col = (jj - jcol) * m;
|
||||
|
||||
VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
|
||||
VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Accumulate a column vector here
|
||||
|
||||
// For each nnz in A[*, jj] do depth first search
|
||||
for (typename MatrixType::InnerIterator it(A, jj); it; ++it)
|
||||
{
|
||||
Index krow = it.row();
|
||||
for (typename MatrixType::InnerIterator it(A, jj); it; ++it) {
|
||||
Index krow = it.row();
|
||||
dense_col(krow) = it.value();
|
||||
|
||||
StorageIndex kmark = marker(krow);
|
||||
if (kmark == jj)
|
||||
continue; // krow visited before, go to the next nonzero
|
||||
|
||||
dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent,
|
||||
xplore, glu, nextl_col, krow, traits);
|
||||
}// end for nonzeros in column jj
|
||||
|
||||
} // end for column jj
|
||||
|
||||
StorageIndex kmark = marker(krow);
|
||||
if (kmark == jj) continue; // krow visited before, go to the next nonzero
|
||||
|
||||
dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent, xplore, glu, nextl_col, krow,
|
||||
traits);
|
||||
} // end for nonzeros in column jj
|
||||
|
||||
} // end for column jj
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // SPARSELU_PANEL_DFS_H
|
||||
#endif // SPARSELU_PANEL_DFS_H
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of xpivotL.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of xpivotL.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 3.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -35,10 +35,10 @@
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
|
||||
/**
|
||||
* \brief Performs the numerical pivotin on the current column of L, and the CDIV operation.
|
||||
*
|
||||
*
|
||||
* Pivot policy :
|
||||
* (1) Compute thresh = u * max_(i>=j) abs(A_ij);
|
||||
* (2) IF user specifies pivot row k and abs(A_kj) >= thresh THEN
|
||||
@@ -47,64 +47,63 @@ namespace internal {
|
||||
* pivot row = j;
|
||||
* ELSE
|
||||
* pivot row = m;
|
||||
*
|
||||
*
|
||||
* Note: If you absolutely want to use a given pivot order, then set u=0.0.
|
||||
*
|
||||
*
|
||||
* \param jcol The current column of L
|
||||
* \param diagpivotthresh diagonal pivoting threshold
|
||||
* \param[in,out] perm_r Row permutation (threshold pivoting)
|
||||
* \param[in] iperm_c column permutation - used to finf diagonal of Pc*A*Pc'
|
||||
* \param[out] pivrow The pivot row
|
||||
* \param glu Global LU data
|
||||
* \return 0 if success, i > 0 if U(i,i) is exactly zero
|
||||
*
|
||||
* \return 0 if success, i > 0 if U(i,i) is exactly zero
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
Index SparseLUImpl<Scalar,StorageIndex>::pivotL(const Index jcol, const RealScalar& diagpivotthresh, IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow, GlobalLU_t& glu)
|
||||
{
|
||||
|
||||
Index fsupc = (glu.xsup)((glu.supno)(jcol)); // First column in the supernode containing the column jcol
|
||||
Index nsupc = jcol - fsupc; // Number of columns in the supernode portion, excluding jcol; nsupc >=0
|
||||
Index lptr = glu.xlsub(fsupc); // pointer to the starting location of the row subscripts for this supernode portion
|
||||
Index nsupr = glu.xlsub(fsupc+1) - lptr; // Number of rows in the supernode
|
||||
Index lda = glu.xlusup(fsupc+1) - glu.xlusup(fsupc); // leading dimension
|
||||
Scalar* lu_sup_ptr = &(glu.lusup.data()[glu.xlusup(fsupc)]); // Start of the current supernode
|
||||
Scalar* lu_col_ptr = &(glu.lusup.data()[glu.xlusup(jcol)]); // Start of jcol in the supernode
|
||||
StorageIndex* lsub_ptr = &(glu.lsub.data()[lptr]); // Start of row indices of the supernode
|
||||
|
||||
// Determine the largest abs numerical value for partial pivoting
|
||||
Index diagind = iperm_c(jcol); // diagonal index
|
||||
Index SparseLUImpl<Scalar, StorageIndex>::pivotL(const Index jcol, const RealScalar& diagpivotthresh,
|
||||
IndexVector& perm_r, IndexVector& iperm_c, Index& pivrow,
|
||||
GlobalLU_t& glu) {
|
||||
Index fsupc = (glu.xsup)((glu.supno)(jcol)); // First column in the supernode containing the column jcol
|
||||
Index nsupc = jcol - fsupc; // Number of columns in the supernode portion, excluding jcol; nsupc >=0
|
||||
Index lptr = glu.xlsub(fsupc); // pointer to the starting location of the row subscripts for this supernode portion
|
||||
Index nsupr = glu.xlsub(fsupc + 1) - lptr; // Number of rows in the supernode
|
||||
Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // leading dimension
|
||||
Scalar* lu_sup_ptr = &(glu.lusup.data()[glu.xlusup(fsupc)]); // Start of the current supernode
|
||||
Scalar* lu_col_ptr = &(glu.lusup.data()[glu.xlusup(jcol)]); // Start of jcol in the supernode
|
||||
StorageIndex* lsub_ptr = &(glu.lsub.data()[lptr]); // Start of row indices of the supernode
|
||||
|
||||
// Determine the largest abs numerical value for partial pivoting
|
||||
Index diagind = iperm_c(jcol); // diagonal index
|
||||
RealScalar pivmax(-1.0);
|
||||
Index pivptr = nsupc;
|
||||
Index diag = emptyIdxLU;
|
||||
Index pivptr = nsupc;
|
||||
Index diag = emptyIdxLU;
|
||||
RealScalar rtemp;
|
||||
Index isub, icol, itemp, k;
|
||||
Index isub, icol, itemp, k;
|
||||
for (isub = nsupc; isub < nsupr; ++isub) {
|
||||
using std::abs;
|
||||
rtemp = abs(lu_col_ptr[isub]);
|
||||
if (rtemp > pivmax) {
|
||||
pivmax = rtemp;
|
||||
pivmax = rtemp;
|
||||
pivptr = isub;
|
||||
}
|
||||
}
|
||||
if (lsub_ptr[isub] == diagind) diag = isub;
|
||||
}
|
||||
|
||||
|
||||
// Test for singularity
|
||||
if ( pivmax <= RealScalar(0.0) ) {
|
||||
if (pivmax <= RealScalar(0.0)) {
|
||||
// if pivmax == -1, the column is structurally empty, otherwise it is only numerically zero
|
||||
pivrow = pivmax < RealScalar(0.0) ? diagind : lsub_ptr[pivptr];
|
||||
perm_r(pivrow) = StorageIndex(jcol);
|
||||
return (jcol+1);
|
||||
return (jcol + 1);
|
||||
}
|
||||
|
||||
RealScalar thresh = diagpivotthresh * pivmax;
|
||||
|
||||
// Choose appropriate pivotal element
|
||||
|
||||
|
||||
RealScalar thresh = diagpivotthresh * pivmax;
|
||||
|
||||
// Choose appropriate pivotal element
|
||||
|
||||
{
|
||||
// Test if the diagonal element can be used as a pivot (given the threshold value)
|
||||
if (diag >= 0 )
|
||||
{
|
||||
if (diag >= 0) {
|
||||
// Diagonal element exists
|
||||
using std::abs;
|
||||
rtemp = abs(lu_col_ptr[diag]);
|
||||
@@ -112,29 +111,26 @@ Index SparseLUImpl<Scalar,StorageIndex>::pivotL(const Index jcol, const RealScal
|
||||
}
|
||||
pivrow = lsub_ptr[pivptr];
|
||||
}
|
||||
|
||||
|
||||
// Record pivot row
|
||||
perm_r(pivrow) = StorageIndex(jcol);
|
||||
// Interchange row subscripts
|
||||
if (pivptr != nsupc )
|
||||
{
|
||||
std::swap( lsub_ptr[pivptr], lsub_ptr[nsupc] );
|
||||
if (pivptr != nsupc) {
|
||||
std::swap(lsub_ptr[pivptr], lsub_ptr[nsupc]);
|
||||
// Interchange numerical values as well, for the two rows in the whole snode
|
||||
// such that L is indexed the same way as A
|
||||
for (icol = 0; icol <= nsupc; icol++)
|
||||
{
|
||||
itemp = pivptr + icol * lda;
|
||||
for (icol = 0; icol <= nsupc; icol++) {
|
||||
itemp = pivptr + icol * lda;
|
||||
std::swap(lu_sup_ptr[itemp], lu_sup_ptr[nsupc + icol * lda]);
|
||||
}
|
||||
}
|
||||
// cdiv operations
|
||||
Scalar temp = Scalar(1.0) / lu_col_ptr[nsupc];
|
||||
for (k = nsupc+1; k < nsupr; k++)
|
||||
lu_col_ptr[k] *= temp;
|
||||
for (k = nsupc + 1; k < nsupr; k++) lu_col_ptr[k] *= temp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // SPARSELU_PIVOTL_H
|
||||
#endif // SPARSELU_PIVOTL_H
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]pruneL.c file in SuperLU
|
||||
|
||||
/*
|
||||
|
||||
* NOTE: This file is the modified version of [s,d,c,z]pruneL.c file in SuperLU
|
||||
|
||||
* -- SuperLU routine (version 2.0) --
|
||||
* Univ. of California Berkeley, Xerox Palo Alto Research Center,
|
||||
* and Lawrence Berkeley National Lab.
|
||||
@@ -40,100 +40,91 @@ namespace internal {
|
||||
* \brief Prunes the L-structure.
|
||||
*
|
||||
* It prunes the L-structure of supernodes whose L-structure contains the current pivot row "pivrow"
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* \param jcol The current column of L
|
||||
* \param[in] perm_r Row permutation
|
||||
* \param[out] pivrow The pivot row
|
||||
* \param nseg Number of segments
|
||||
* \param segrep
|
||||
* \param segrep
|
||||
* \param repfnz
|
||||
* \param[out] xprune
|
||||
* \param[out] xprune
|
||||
* \param glu Global LU data
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow, const Index nseg,
|
||||
const IndexVector& segrep, BlockIndexVector repfnz, IndexVector& xprune, GlobalLU_t& glu)
|
||||
{
|
||||
void SparseLUImpl<Scalar, StorageIndex>::pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow,
|
||||
const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz,
|
||||
IndexVector& xprune, GlobalLU_t& glu) {
|
||||
// For each supernode-rep irep in U(*,j]
|
||||
Index jsupno = glu.supno(jcol);
|
||||
Index i,irep,irep1;
|
||||
bool movnum, do_prune = false;
|
||||
Index kmin = 0, kmax = 0, minloc, maxloc,krow;
|
||||
for (i = 0; i < nseg; i++)
|
||||
{
|
||||
irep = segrep(i);
|
||||
irep1 = irep + 1;
|
||||
do_prune = false;
|
||||
|
||||
// Don't prune with a zero U-segment
|
||||
if (repfnz(irep) == emptyIdxLU) continue;
|
||||
|
||||
Index jsupno = glu.supno(jcol);
|
||||
Index i, irep, irep1;
|
||||
bool movnum, do_prune = false;
|
||||
Index kmin = 0, kmax = 0, minloc, maxloc, krow;
|
||||
for (i = 0; i < nseg; i++) {
|
||||
irep = segrep(i);
|
||||
irep1 = irep + 1;
|
||||
do_prune = false;
|
||||
|
||||
// Don't prune with a zero U-segment
|
||||
if (repfnz(irep) == emptyIdxLU) continue;
|
||||
|
||||
// If a snode overlaps with the next panel, then the U-segment
|
||||
// is fragmented into two parts -- irep and irep1. We should let
|
||||
// pruning occur at the rep-column in irep1s snode.
|
||||
if (glu.supno(irep) == glu.supno(irep1) ) continue; // don't prune
|
||||
|
||||
// is fragmented into two parts -- irep and irep1. We should let
|
||||
// pruning occur at the rep-column in irep1s snode.
|
||||
if (glu.supno(irep) == glu.supno(irep1)) continue; // don't prune
|
||||
|
||||
// If it has not been pruned & it has a nonz in row L(pivrow,i)
|
||||
if (glu.supno(irep) != jsupno )
|
||||
{
|
||||
if ( xprune (irep) >= glu.xlsub(irep1) )
|
||||
{
|
||||
if (glu.supno(irep) != jsupno) {
|
||||
if (xprune(irep) >= glu.xlsub(irep1)) {
|
||||
kmin = glu.xlsub(irep);
|
||||
kmax = glu.xlsub(irep1) - 1;
|
||||
for (krow = kmin; krow <= kmax; krow++)
|
||||
{
|
||||
if (glu.lsub(krow) == pivrow)
|
||||
{
|
||||
do_prune = true;
|
||||
break;
|
||||
kmax = glu.xlsub(irep1) - 1;
|
||||
for (krow = kmin; krow <= kmax; krow++) {
|
||||
if (glu.lsub(krow) == pivrow) {
|
||||
do_prune = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_prune)
|
||||
{
|
||||
|
||||
if (do_prune) {
|
||||
// do a quicksort-type partition
|
||||
// movnum=true means that the num values have to be exchanged
|
||||
movnum = false;
|
||||
if (irep == glu.xsup(glu.supno(irep)) ) // Snode of size 1
|
||||
movnum = true;
|
||||
|
||||
while (kmin <= kmax)
|
||||
{
|
||||
movnum = false;
|
||||
if (irep == glu.xsup(glu.supno(irep))) // Snode of size 1
|
||||
movnum = true;
|
||||
|
||||
while (kmin <= kmax) {
|
||||
if (perm_r(glu.lsub(kmax)) == emptyIdxLU)
|
||||
kmax--;
|
||||
else if ( perm_r(glu.lsub(kmin)) != emptyIdxLU)
|
||||
kmax--;
|
||||
else if (perm_r(glu.lsub(kmin)) != emptyIdxLU)
|
||||
kmin++;
|
||||
else
|
||||
{
|
||||
else {
|
||||
// kmin below pivrow (not yet pivoted), and kmax
|
||||
// above pivrow: interchange the two suscripts
|
||||
std::swap(glu.lsub(kmin), glu.lsub(kmax));
|
||||
|
||||
// If the supernode has only one column, then we
|
||||
std::swap(glu.lsub(kmin), glu.lsub(kmax));
|
||||
|
||||
// If the supernode has only one column, then we
|
||||
// only keep one set of subscripts. For any subscript
|
||||
// intercnahge performed, similar interchange must be
|
||||
// done on the numerical values.
|
||||
if (movnum)
|
||||
{
|
||||
minloc = glu.xlusup(irep) + ( kmin - glu.xlsub(irep) );
|
||||
maxloc = glu.xlusup(irep) + ( kmax - glu.xlsub(irep) );
|
||||
std::swap(glu.lusup(minloc), glu.lusup(maxloc));
|
||||
// intercnahge performed, similar interchange must be
|
||||
// done on the numerical values.
|
||||
if (movnum) {
|
||||
minloc = glu.xlusup(irep) + (kmin - glu.xlsub(irep));
|
||||
maxloc = glu.xlusup(irep) + (kmax - glu.xlsub(irep));
|
||||
std::swap(glu.lusup(minloc), glu.lusup(maxloc));
|
||||
}
|
||||
kmin++;
|
||||
kmax--;
|
||||
}
|
||||
} // end while
|
||||
|
||||
xprune(irep) = StorageIndex(kmin); //Pruning
|
||||
} // end if do_prune
|
||||
} // end pruning
|
||||
} // End for each U-segment
|
||||
} // end while
|
||||
|
||||
xprune(irep) = StorageIndex(kmin); // Pruning
|
||||
} // end if do_prune
|
||||
} // end pruning
|
||||
} // End for each U-segment
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // SPARSELU_PRUNEL_H
|
||||
#endif // SPARSELU_PRUNEL_H
|
||||
|
||||
@@ -34,53 +34,48 @@
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* \brief Identify the initial relaxed supernodes
|
||||
*
|
||||
* This routine is applied to a column elimination tree.
|
||||
*
|
||||
* This routine is applied to a column elimination tree.
|
||||
* It assumes that the matrix has been reordered according to the postorder of the etree
|
||||
* \param n the number of columns
|
||||
* \param et elimination tree
|
||||
* \param relax_columns Maximum number of columns allowed in a relaxed snode
|
||||
* \param et elimination tree
|
||||
* \param relax_columns Maximum number of columns allowed in a relaxed snode
|
||||
* \param descendants Number of descendants of each node in the etree
|
||||
* \param relax_end last column in a supernode
|
||||
*/
|
||||
template <typename Scalar, typename StorageIndex>
|
||||
void SparseLUImpl<Scalar,StorageIndex>::relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
|
||||
{
|
||||
|
||||
void SparseLUImpl<Scalar, StorageIndex>::relax_snode(const Index n, IndexVector& et, const Index relax_columns,
|
||||
IndexVector& descendants, IndexVector& relax_end) {
|
||||
// compute the number of descendants of each node in the etree
|
||||
Index parent;
|
||||
Index parent;
|
||||
relax_end.setConstant(emptyIdxLU);
|
||||
descendants.setZero();
|
||||
for (Index j = 0; j < n; j++)
|
||||
{
|
||||
for (Index j = 0; j < n; j++) {
|
||||
parent = et(j);
|
||||
if (parent != n) // not the dummy root
|
||||
if (parent != n) // not the dummy root
|
||||
descendants(parent) += descendants(j) + 1;
|
||||
}
|
||||
// Identify the relaxed supernodes by postorder traversal of the etree
|
||||
Index snode_start; // beginning of a snode
|
||||
for (Index j = 0; j < n; )
|
||||
{
|
||||
Index snode_start; // beginning of a snode
|
||||
for (Index j = 0; j < n;) {
|
||||
parent = et(j);
|
||||
snode_start = j;
|
||||
while ( parent != n && descendants(parent) < relax_columns )
|
||||
{
|
||||
j = parent;
|
||||
snode_start = j;
|
||||
while (parent != n && descendants(parent) < relax_columns) {
|
||||
j = parent;
|
||||
parent = et(j);
|
||||
}
|
||||
// Found a supernode in postordered etree, j is the last column
|
||||
relax_end(snode_start) = StorageIndex(j); // Record last column
|
||||
// Found a supernode in postordered etree, j is the last column
|
||||
relax_end(snode_start) = StorageIndex(j); // Record last column
|
||||
j++;
|
||||
// Search for a new leaf
|
||||
while (descendants(j) != 0 && j < n) j++;
|
||||
} // End postorder traversal of the etree
|
||||
|
||||
} // End postorder traversal of the etree
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
} // end namespace Eigen
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user