Eigen::internal::SparseLUImpl< Scalar, StorageIndex > Class Template Reference

#include <SparseLUImpl.h>

Public Types

typedef Matrix< Scalar, Dynamic, 1 > ScalarVector
 
typedef Matrix< StorageIndex, Dynamic, 1 > IndexVector
 
typedef Matrix< Scalar, Dynamic, Dynamic, ColMajorScalarMatrix
 
typedef Map< ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock
 
typedef ScalarVector::RealScalar RealScalar
 
typedef Ref< Matrix< Scalar, Dynamic, 1 > > BlockScalarVector
 
typedef Ref< Matrix< StorageIndex, Dynamic, 1 > > BlockIndexVector
 
typedef LU_GlobalLU_t< IndexVector, ScalarVectorGlobalLU_t
 
typedef SparseMatrix< Scalar, ColMajor, StorageIndex > MatrixType
 

Protected Member Functions

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)
 Allocate various working space for the numerical factorization phase. More...
 
template<typename VectorType >
Index memXpand (VectorType &vec, Index &maxlen, Index nbElts, MemType memtype, Index &num_expansions)
 Expand the existing storage. More...
 
void heap_relax_snode (const Index n, IndexVector &et, const Index relax_columns, IndexVector &descendants, IndexVector &relax_end)
 Identify the initial relaxed supernodes. More...
 
void relax_snode (const Index n, IndexVector &et, const Index relax_columns, IndexVector &descendants, IndexVector &relax_end)
 Identify the initial relaxed supernodes. More...
 
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)
 Performs the numerical pivoting on the current column of L, and the CDIV operation. More...
 
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)
 Performs a symbolic factorization on a panel of columns [jcol, jcol+w) More...
 
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)
 Performs numeric block updates (sup-panel) in topological order. More...
 
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)
 Performs a symbolic factorization on column jcol and decide the supernode boundary. More...
 
Index column_bmod (const Index jcol, const Index nseg, BlockScalarVector dense, ScalarVector &tempv, BlockIndexVector segrep, BlockIndexVector repfnz, Index fpanelc, GlobalLU_t &glu)
 Performs numeric block updates (sup-col) in topological order. More...
 
Index copy_to_ucol (const Index jcol, const Index nseg, IndexVector &segrep, BlockIndexVector repfnz, IndexVector &perm_r, BlockScalarVector dense, GlobalLU_t &glu)
 Performs numeric block updates (sup-col) in topological order. More...
 
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)
 Prunes the L-structure. More...
 
void countnz (const Index n, Index &nnzL, Index &nnzU, GlobalLU_t &glu)
 Count Nonzero elements in the factors. More...
 
void fixupL (const Index n, const IndexVector &perm_r, GlobalLU_t &glu)
 Fix up the data storage lsub for L-subscripts. More...
 

Friends

template<typename , typename >
struct column_dfs_traits
 

Detailed Description

template<typename Scalar, typename StorageIndex>
class Eigen::internal::SparseLUImpl< Scalar, StorageIndex >

Base class for sparseLU

Member Typedef Documentation

◆ BlockIndexVector

template<typename Scalar , typename StorageIndex >
typedef Ref<Matrix<StorageIndex, Dynamic, 1> > Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::BlockIndexVector

◆ BlockScalarVector

template<typename Scalar , typename StorageIndex >
typedef Ref<Matrix<Scalar, Dynamic, 1> > Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::BlockScalarVector

◆ GlobalLU_t

template<typename Scalar , typename StorageIndex >
typedef LU_GlobalLU_t<IndexVector, ScalarVector> Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::GlobalLU_t

◆ IndexVector

template<typename Scalar , typename StorageIndex >
typedef Matrix<StorageIndex, Dynamic, 1> Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::IndexVector

◆ MappedMatrixBlock

template<typename Scalar , typename StorageIndex >
typedef Map<ScalarMatrix, 0, OuterStride<> > Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::MappedMatrixBlock

◆ MatrixType

template<typename Scalar , typename StorageIndex >
typedef SparseMatrix<Scalar, ColMajor, StorageIndex> Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::MatrixType

◆ RealScalar

template<typename Scalar , typename StorageIndex >
typedef ScalarVector::RealScalar Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::RealScalar

◆ ScalarMatrix

template<typename Scalar , typename StorageIndex >
typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::ScalarMatrix

◆ ScalarVector

template<typename Scalar , typename StorageIndex >
typedef Matrix<Scalar, Dynamic, 1> Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::ScalarVector

Member Function Documentation

◆ column_bmod()

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 
)
protected

Performs numeric block updates (sup-col) in topological order.

Parameters
jcolcurrent column to update
nsegNumber of segments in the U part
denseStore the full representation of the column
tempvworking array
segrepsegment representative ...
repfnz??? First nonzero column in each row ??? ...
fpanelcFirst column in the current panel
gluGlobal LU data.
Returns
0 - successful return > 0 - number of bytes allocated when run out of space
58  {
59  Index jsupno, k, ksub, krep, ksupno;
60  Index lptr, nrow, isub, irow, nextlu, new_next, ufirst;
61  Index fsupc, nsupc, nsupr, luptr, kfnz, no_zeros;
62  /* krep = representative of current k-th supernode
63  * fsupc = first supernodal column
64  * nsupc = number of columns in a supernode
65  * nsupr = number of rows in a supernode
66  * luptr = location of supernodal LU-block in storage
67  * kfnz = first nonz in the k-th supernodal segment
68  * no_zeros = no lf leading zeros in a supernodal U-segment
69  */
70 
71  jsupno = glu.supno(jcol);
72  // For each nonzero supernode segment of U[*,j] in topological order
73  k = nseg - 1;
74  Index d_fsupc; // distance between the first column of the current panel and the
75  // first column of the current snode
76  Index fst_col; // First column within small LU update
77  Index segsize;
78  for (ksub = 0; ksub < nseg; ksub++) {
79  krep = segrep(k);
80  k--;
81  ksupno = glu.supno(krep);
82  if (jsupno != ksupno) {
83  // outside the rectangular supernode
84  fsupc = glu.xsup(ksupno);
85  fst_col = (std::max)(fsupc, fpanelc);
86 
87  // Distance from the current supernode to the current panel;
88  // d_fsupc = 0 if fsupc > fpanelc
89  d_fsupc = fst_col - fsupc;
90 
91  luptr = glu.xlusup(fst_col) + d_fsupc;
92  lptr = glu.xlsub(fsupc) + d_fsupc;
93 
94  kfnz = repfnz(krep);
95  kfnz = (std::max)(kfnz, fpanelc);
96 
97  segsize = krep - kfnz + 1;
98  nsupc = krep - fst_col + 1;
99  nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
100  nrow = nsupr - d_fsupc - nsupc;
101  Index lda = glu.xlusup(fst_col + 1) - glu.xlusup(fst_col);
102 
103  // Perform a triangular solver and block update,
104  // then scatter the result of sup-col update to dense
105  no_zeros = kfnz - fst_col;
106  if (segsize == 1)
107  LU_kernel_bmod<1>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
108  else
109  LU_kernel_bmod<Dynamic>::run(segsize, dense, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
110  } // end if jsupno
111  } // end for each segment
112 
113  // Process the supernodal portion of L\U[*,j]
114  nextlu = glu.xlusup(jcol);
115  fsupc = glu.xsup(jsupno);
116 
117  // copy the SPA dense into L\U[*,j]
118  Index mem;
119  new_next = nextlu + glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
120  Index offset = internal::first_multiple<Index>(new_next, internal::packet_traits<Scalar>::size) - new_next;
121  if (offset) new_next += offset;
122  while (new_next > glu.nzlumax) {
123  mem = memXpand<ScalarVector>(glu.lusup, glu.nzlumax, nextlu, LUSUP, glu.num_expansions);
124  if (mem) return mem;
125  }
126 
127  for (isub = glu.xlsub(fsupc); isub < glu.xlsub(fsupc + 1); isub++) {
128  irow = glu.lsub(isub);
129  glu.lusup(nextlu) = dense(irow);
130  dense(irow) = Scalar(0.0);
131  ++nextlu;
132  }
133 
134  if (offset) {
135  glu.lusup.segment(nextlu, offset).setZero();
136  nextlu += offset;
137  }
138  glu.xlusup(jcol + 1) = StorageIndex(nextlu); // close L\U(*,jcol);
139 
140  /* For more updates within the panel (also within the current supernode),
141  * should start from the first column of the panel, or the first column
142  * of the supernode, whichever is bigger. There are two cases:
143  * 1) fsupc < fpanelc, then fst_col <-- fpanelc
144  * 2) fsupc >= fpanelc, then fst_col <-- fsupc
145  */
146  fst_col = (std::max)(fsupc, fpanelc);
147 
148  if (fst_col < jcol) {
149  // Distance between the current supernode and the current panel
150  // d_fsupc = 0 if fsupc >= fpanelc
151  d_fsupc = fst_col - fsupc;
152 
153  lptr = glu.xlsub(fsupc) + d_fsupc;
154  luptr = glu.xlusup(fst_col) + d_fsupc;
155  nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc); // leading dimension
156  nsupc = jcol - fst_col; // excluding jcol
157  nrow = nsupr - d_fsupc - nsupc;
158 
159  // points to the beginning of jcol in snode L\U(jsupno)
160  ufirst = glu.xlusup(jcol) + d_fsupc;
161  Index lda = glu.xlusup(jcol + 1) - glu.xlusup(jcol);
162  MappedMatrixBlock A(&(glu.lusup.data()[luptr]), nsupc, nsupc, OuterStride<>(lda));
163  VectorBlock<ScalarVector> u(glu.lusup, ufirst, nsupc);
164  u = A.template triangularView<UnitLower>().solve(u);
165 
166  new (&A) MappedMatrixBlock(&(glu.lusup.data()[luptr + nsupc]), nrow, nsupc, OuterStride<>(lda));
167  VectorBlock<ScalarVector> l(glu.lusup, ufirst + nsupc, nrow);
168  l.noalias() -= A * u;
169 
170  } // End if fst_col
171  return 0;
172 }
SCALAR Scalar
Definition: bench_gemm.cpp:45
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
Map< ScalarMatrix, 0, OuterStride<> > MappedMatrixBlock
Definition: SparseLUImpl.h:28
#define max(a, b)
Definition: datatypes.h:23
const char const int const RealScalar const RealScalar const int * lda
Definition: level2_cplx_impl.h:20
char char char int int * k
Definition: level2_impl.h:374
@ LUSUP
Definition: SparseLU_Structs.h:77
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
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)
Performs numeric block updates from a given supernode to a single column.
Definition: SparseLU_kernel_bmod.h:43
@ size
Definition: GenericPacketMath.h:113
int * xlsub
Definition: slu_cdefs.h:93
int * xlusup
Definition: slu_cdefs.h:95
int num_expansions
Definition: slu_cdefs.h:104
int * lsub
Definition: slu_cdefs.h:92
int * supno
Definition: slu_cdefs.h:91
complex * lusup
Definition: slu_cdefs.h:94
int nzlumax
Definition: slu_cdefs.h:101
int * xsup
Definition: slu_cdefs.h:90

References k.

◆ column_dfs()

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 
)
protected

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.

Parameters
mnumber of rows in the matrix
jcolCurrent column
perm_rRow permutation
maxsuperMaximum number of column allowed in a supernode
[in,out]nsegNumber of segments in current U[*,j] - new segments appended
lsub_coldefines the rhs vector to start the dfs
[in,out]segrepSegment representatives - new segments appended
repfnzFirst nonzero location in each row
xprune
markermarker[i] == jj, if i was visited during dfs of current column jj;
parent
xploreworking array
gluglobal LU data
Returns
0 success > 0 number of bytes allocated when run out of space
94  {
95  Index jsuper = glu.supno(jcol);
96  Index nextl = glu.xlsub(jcol);
97  VectorBlock<IndexVector> marker2(marker, 2 * m, m);
98 
99  column_dfs_traits<IndexVector, ScalarVector> traits(jcol, jsuper, glu, *this);
100 
101  // For each nonzero in A(*,jcol) do dfs
102  for (Index k = 0; ((k < m) ? lsub_col[k] != emptyIdxLU : false); k++) {
103  Index krow = lsub_col(k);
104  lsub_col(k) = emptyIdxLU;
105  Index kmark = marker2(krow);
106 
107  // krow was visited before, go to the next nonz;
108  if (kmark == jcol) continue;
109 
110  dfs_kernel(StorageIndex(jcol), perm_r, nseg, glu.lsub, segrep, repfnz, xprune, marker2, parent, xplore, glu, nextl,
111  krow, traits);
112  } // for each nonzero ...
113 
114  Index fsupc;
115  StorageIndex nsuper = glu.supno(jcol);
116  StorageIndex jcolp1 = StorageIndex(jcol) + 1;
117  Index jcolm1 = jcol - 1;
118 
119  // check to see if j belongs in the same supernode as j-1
120  if (jcol == 0) { // Do nothing for column 0
121  nsuper = glu.supno(0) = 0;
122  } else {
123  fsupc = glu.xsup(nsuper);
124  StorageIndex jptr = glu.xlsub(jcol); // Not yet compressed
125  StorageIndex jm1ptr = glu.xlsub(jcolm1);
126 
127  // Use supernodes of type T2 : see SuperLU paper
128  if ((nextl - jptr != jptr - jm1ptr - 1)) jsuper = emptyIdxLU;
129 
130  // Make sure the number of columns in a supernode doesn't
131  // exceed threshold
132  if ((jcol - fsupc) >= maxsuper) jsuper = emptyIdxLU;
133 
134  /* If jcol starts a new supernode, reclaim storage space in
135  * glu.lsub from previous supernode. Note we only store
136  * the subscript set of the first and last columns of
137  * a supernode. (first for num values, last for pruning)
138  */
139  if (jsuper == emptyIdxLU) { // starts a new supernode
140  if ((fsupc < jcolm1 - 1)) { // >= 3 columns in nsuper
141  StorageIndex ito = glu.xlsub(fsupc + 1);
142  glu.xlsub(jcolm1) = ito;
143  StorageIndex istop = ito + jptr - jm1ptr;
144  xprune(jcolm1) = istop; // initialize xprune(jcol-1)
145  glu.xlsub(jcol) = istop;
146 
147  for (StorageIndex ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito) glu.lsub(ito) = glu.lsub(ifrom);
148  nextl = ito; // = istop + length(jcol)
149  }
150  nsuper++;
151  glu.supno(jcol) = nsuper;
152  } // if a new supernode
153  } // end else: jcol > 0
154 
155  // Tidy up the pointers before exit
156  glu.xsup(nsuper + 1) = jcolp1;
157  glu.supno(jcolp1) = nsuper;
158  xprune(jcol) = StorageIndex(nextl); // Initialize upper bound for pruning
159  glu.xlsub(jcolp1) = StorageIndex(nextl);
160 
161  return 0;
162 }
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)
Definition: SparseLU_panel_dfs.h:59
int * m
Definition: level2_cplx_impl.h:294
@ emptyIdxLU
Definition: SparseLU_Memory.h:41

References Eigen::internal::emptyIdxLU, k, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lsub, m, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup.

◆ copy_to_ucol()

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 
)
protected

Performs numeric block updates (sup-col) in topological order.

Parameters
jcolcurrent column to update
nsegNumber of segments in the U part
segrepsegment representative ...
repfnzFirst nonzero column in each row ...
perm_rRow permutation
denseStore the full representation of the column
gluGlobal LU data.
Returns
0 - successful return > 0 - number of bytes allocated when run out of space
55  {
56  Index ksub, krep, ksupno;
57 
58  Index jsupno = glu.supno(jcol);
59 
60  // For each nonzero supernode segment of U[*,j] in topological order
61  Index k = nseg - 1, i;
62  StorageIndex nextu = glu.xusub(jcol);
63  Index kfnz, isub, segsize;
64  Index new_next, irow;
65  Index fsupc, mem;
66  for (ksub = 0; ksub < nseg; ksub++) {
67  krep = segrep(k);
68  k--;
69  ksupno = glu.supno(krep);
70  if (jsupno != ksupno) // should go into ucol();
71  {
72  kfnz = repfnz(krep);
73  if (kfnz != emptyIdxLU) { // Nonzero U-segment
74  fsupc = glu.xsup(ksupno);
75  isub = glu.xlsub(fsupc) + kfnz - fsupc;
76  segsize = krep - kfnz + 1;
77  new_next = nextu + segsize;
78  while (new_next > glu.nzumax) {
79  mem = memXpand<ScalarVector>(glu.ucol, glu.nzumax, nextu, UCOL, glu.num_expansions);
80  if (mem) return mem;
81  mem = memXpand<IndexVector>(glu.usub, glu.nzumax, nextu, USUB, glu.num_expansions);
82  if (mem) return mem;
83  }
84 
85  for (i = 0; i < segsize; i++) {
86  irow = glu.lsub(isub);
87  glu.usub(nextu) = perm_r(irow); // Unlike the L part, the U part is stored in its final order
88  glu.ucol(nextu) = dense(irow);
89  dense(irow) = Scalar(0.0);
90  nextu++;
91  isub++;
92  }
93 
94  } // end nonzero U-segment
95 
96  } // end if jsupno
97 
98  } // end for each segment
99  glu.xusub(jcol + 1) = nextu; // close U(*,jcol)
100  return 0;
101 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
@ USUB
Definition: SparseLU_Structs.h:77
@ UCOL
Definition: SparseLU_Structs.h:77
int * xusub
Definition: slu_cdefs.h:98
int nzumax
Definition: slu_cdefs.h:100
int * usub
Definition: slu_cdefs.h:97
complex * ucol
Definition: slu_cdefs.h:96

References i, k, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xusub.

◆ countnz()

template<typename Scalar , typename StorageIndex >
void SparseLUImpl< Scalar, StorageIndex >::countnz ( const Index  n,
Index nnzL,
Index nnzU,
GlobalLU_t glu 
)
protected

Count Nonzero elements in the factors.

23  {
24  nnzL = 0;
25  nnzU = (glu.xusub)(n);
26  Index nsuper = (glu.supno)(n);
27  Index jlen;
28  Index i, j, fsupc;
29  if (n <= 0) return;
30  // For each supernode
31  for (i = 0; i <= nsuper; i++) {
32  fsupc = glu.xsup(i);
33  jlen = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
34 
35  for (j = fsupc; j < glu.xsup(i + 1); j++) {
36  nnzL += jlen;
37  nnzU += j - fsupc + 1;
38  jlen--;
39  }
40  }
41 }
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References i, j, n, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xusub.

◆ dfs_kernel()

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 
)
protected
63  {
64  StorageIndex kmark = marker(krow);
65 
66  // For each unmarked krow of jj
67  marker(krow) = jj;
68  StorageIndex kperm = perm_r(krow);
69  if (kperm == emptyIdxLU) {
70  // krow is in L : place it in structure of L(*, jj)
71  panel_lsub(nextl_col++) = StorageIndex(krow); // krow is indexed into A
72 
73  traits.mem_expand(panel_lsub, nextl_col, kmark);
74  } else {
75  // krow is in U : if its supernode-representative krep
76  // has been explored, update repfnz(*)
77  // krep = supernode representative of the current row
78  StorageIndex krep = glu.xsup(glu.supno(kperm) + 1) - 1;
79  // First nonzero element in the current column:
80  StorageIndex myfnz = repfnz_col(krep);
81 
82  if (myfnz != emptyIdxLU) {
83  // Representative visited before
84  if (myfnz > kperm) repfnz_col(krep) = kperm;
85 
86  } else {
87  // Otherwise, perform dfs starting at krep
88  StorageIndex oldrep = emptyIdxLU;
89  parent(krep) = oldrep;
90  repfnz_col(krep) = kperm;
91  StorageIndex xdfs = glu.xlsub(krep);
92  Index maxdfs = xprune(krep);
93 
94  StorageIndex kpar;
95  do {
96  // For each unmarked kchild of krep
97  while (xdfs < maxdfs) {
98  StorageIndex kchild = glu.lsub(xdfs);
99  xdfs++;
100  StorageIndex chmark = marker(kchild);
101 
102  if (chmark != jj) {
103  marker(kchild) = jj;
104  StorageIndex chperm = perm_r(kchild);
105 
106  if (chperm == emptyIdxLU) {
107  // case kchild is in L: place it in L(*, j)
108  panel_lsub(nextl_col++) = kchild;
109  traits.mem_expand(panel_lsub, nextl_col, chmark);
110  } else {
111  // case kchild is in U :
112  // chrep = its supernode-rep. If its rep has been explored,
113  // update its repfnz(*)
114  StorageIndex chrep = glu.xsup(glu.supno(chperm) + 1) - 1;
115  myfnz = repfnz_col(chrep);
116 
117  if (myfnz != emptyIdxLU) { // Visited before
118  if (myfnz > chperm) repfnz_col(chrep) = chperm;
119  } else { // Cont. dfs at snode-rep of kchild
120  xplore(krep) = xdfs;
121  oldrep = krep;
122  krep = chrep; // Go deeper down G(L)
123  parent(krep) = oldrep;
124  repfnz_col(krep) = chperm;
125  xdfs = glu.xlsub(krep);
126  maxdfs = xprune(krep);
127 
128  } // end if myfnz != -1
129  } // end if chperm == -1
130 
131  } // end if chmark !=jj
132  } // end while xdfs < maxdfs
133 
134  // krow has no more unexplored nbrs :
135  // Place snode-rep krep in postorder DFS, if this
136  // segment is seen for the first time. (Note that
137  // "repfnz(krep)" may change later.)
138  // Baktrack dfs to its parent
139  if (traits.update_segrep(krep, jj))
140  // if (marker1(krep) < jcol )
141  {
142  segrep(nseg) = krep;
143  ++nseg;
144  // marker1(krep) = jj;
145  }
146 
147  kpar = parent(krep); // Pop recursion, mimic recursion
148  if (kpar == emptyIdxLU) break; // dfs done
149  krep = kpar;
150  xdfs = xplore(krep);
151  maxdfs = xprune(krep);
152 
153  } while (kpar != emptyIdxLU); // Do until empty stack
154 
155  } // end if (myfnz = -1)
156 
157  } // end if (kperm == -1)
158 }

References Eigen::internal::emptyIdxLU, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup.

◆ expand()

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 
)
protected

Expand the existing storage to accommodate more fill-ins

Parameters
vecValid pointer to the vector to allocate or expand
[in,out]lengthAt input, contain the current length of the vector that is to be increased. At output, length of the newly allocated vector
[in]nbEltsCurrent number of elements in the factors
keep_prev1: use length and do not expand the vector; 0: compute new_len and expand
[in,out]num_expansionsNumber of times the memory has been expanded
60  {
61  float alpha = 1.5; // Ratio of the memory increase
62  Index new_len; // New size of the allocated memory
63 
64  if (num_expansions == 0 || keep_prev)
65  new_len = length; // First time allocate requested
66  else
67  new_len = (std::max)(length + 1, Index(alpha * length));
68 
69  VectorType old_vec; // Temporary vector to hold the previous values
70  if (nbElts > 0) old_vec = vec.segment(0, nbElts);
71 
72  // Allocate or expand the current vector
73 #ifdef EIGEN_EXCEPTIONS
74  try
75 #endif
76  {
77  vec.resize(new_len);
78  }
79 #ifdef EIGEN_EXCEPTIONS
80  catch (std::bad_alloc&)
81 #else
82  if (!vec.size())
83 #endif
84  {
85  if (!num_expansions) {
86  // First time to allocate from LUMemInit()
87  // Let LUMemInit() deals with it.
88  return -1;
89  }
90  if (keep_prev) {
91  // In this case, the memory length should not not be reduced
92  return new_len;
93  } else {
94  // Reduce the size and increase again
95  Index tries = 0; // Number of attempts
96  do {
97  alpha = (alpha + 1) / 2;
98  new_len = (std::max)(length + 1, Index(alpha * length));
99 #ifdef EIGEN_EXCEPTIONS
100  try
101 #endif
102  {
103  vec.resize(new_len);
104  }
105 #ifdef EIGEN_EXCEPTIONS
106  catch (std::bad_alloc&)
107 #else
108  if (!vec.size())
109 #endif
110  {
111  tries += 1;
112  if (tries > 10) return new_len;
113  }
114  } while (!vec.size());
115  }
116  }
117  // Copy the previous values to the newly allocated space
118  if (nbElts > 0) vec.segment(0, nbElts) = old_vec;
119 
120  length = new_len;
121  if (num_expansions) ++num_expansions;
122  return 0;
123 }
RealScalar alpha
Definition: level1_cplx_impl.h:151
Definition: fft_test_shared.h:66

References alpha, and max.

◆ fixupL()

template<typename Scalar , typename StorageIndex >
void SparseLUImpl< Scalar, StorageIndex >::fixupL ( const Index  n,
const IndexVector perm_r,
GlobalLU_t glu 
)
protected

Fix up the data storage lsub for L-subscripts.

It removes the subscripts sets for structural pruning, and applies permutation to the remaining subscripts

51  {
52  Index fsupc, i, j, k, jstart;
53 
54  StorageIndex nextl = 0;
55  Index nsuper = (glu.supno)(n);
56 
57  // For each supernode
58  for (i = 0; i <= nsuper; i++) {
59  fsupc = glu.xsup(i);
60  jstart = glu.xlsub(fsupc);
61  glu.xlsub(fsupc) = nextl;
62  for (j = jstart; j < glu.xlsub(fsupc + 1); j++) {
63  glu.lsub(nextl) = perm_r(glu.lsub(j)); // Now indexed into P*A
64  nextl++;
65  }
66  for (k = fsupc + 1; k < glu.xsup(i + 1); k++) glu.xlsub(k) = nextl; // other columns in supernode i
67  }
68 
69  glu.xlsub(n) = nextl;
70 }

References i, j, k, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lsub, n, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup.

◆ heap_relax_snode()

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 
)
protected

Identify the initial relaxed supernodes.

This routine applied to a symmetric elimination tree. It assumes that the matrix has been reordered according to the postorder of the etree

Parameters
nThe number of columns
etelimination tree
relax_columnsMaximum number of columns allowed in a relaxed snode
descendantsNumber of descendants of each node in the etree
relax_endlast column in a supernode
50  {
51  // The etree may not be postordered, but its heap ordered
52  IndexVector post;
53  internal::treePostorder(StorageIndex(n), et, post); // Post order etree
54  IndexVector inv_post(n + 1);
55  for (StorageIndex i = 0; i < n + 1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
56 
57  // Renumber etree in postorder
58  IndexVector iwork(n);
59  IndexVector et_save(n + 1);
60  for (Index i = 0; i < n; ++i) {
61  iwork(post(i)) = post(et(i));
62  }
63  et_save = et; // Save the original etree
64  et = iwork;
65 
66  // compute the number of descendants of each node in the etree
67  relax_end.setConstant(emptyIdxLU);
68  Index j, parent;
69  descendants.setZero();
70  for (j = 0; j < n; j++) {
71  parent = et(j);
72  if (parent != n) // not the dummy root
73  descendants(parent) += descendants(j) + 1;
74  }
75  // Identify the relaxed supernodes by postorder traversal of the etree
76  Index snode_start; // beginning of a snode
77  StorageIndex k;
78  StorageIndex l;
79  for (j = 0; j < n;) {
80  parent = et(j);
81  snode_start = j;
82  while (parent != n && descendants(parent) < relax_columns) {
83  j = parent;
84  parent = et(j);
85  }
86  // Found a supernode in postordered etree, j is the last column
87  k = StorageIndex(n);
88  for (Index i = snode_start; i <= j; ++i) k = (std::min)(k, inv_post(i));
89  l = inv_post(j);
90  if ((l - k) == (j - snode_start)) // Same number of columns in the snode
91  {
92  // This is also a supernode in the original etree
93  relax_end(k) = l; // Record last column
94  } else {
95  for (Index i = snode_start; i <= j; ++i) {
96  l = inv_post(i);
97  if (descendants(i) == 0) {
98  relax_end(l) = l;
99  }
100  }
101  }
102  j++;
103  // Search for a new leaf
104  while (descendants(j) != 0 && j < n) j++;
105  } // End postorder traversal of the etree
106 
107  // Recover the original etree
108  et = et_save;
109 }
Matrix< StorageIndex, Dynamic, 1 > IndexVector
Definition: SparseLUImpl.h:26
#define min(a, b)
Definition: datatypes.h:22
void treePostorder(typename IndexVector::Scalar n, IndexVector &parent, IndexVector &post)
Post order a tree.
Definition: SparseColEtree.h:168

References Eigen::internal::emptyIdxLU, i, j, k, min, n, Eigen::PlainObjectBase< Derived >::setConstant(), Eigen::PlainObjectBase< Derived >::setZero(), and Eigen::internal::treePostorder().

◆ memInit()

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 
)
protected

Allocate various working space for the numerical factorization phase.

Parameters
mnumber of rows of the input matrix
nnumber of columns
annznumber of initial nonzeros in the matrix
lworkif lwork=-1, this routine returns an estimated size of the required memory
glupersistent data to facilitate multiple factors : will be deleted later ??
fillratioestimated ratio of fill in the factors
panel_sizeSize of a panel
Returns
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
140  {
141  Index& num_expansions = glu.num_expansions; // No memory expansions so far
142  num_expansions = 0;
143  glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz + 1) / n, m) * n; // estimated number of nonzeros in U
144  glu.nzlmax = (std::max)(Index(4), fillratio) * (annz + 1) / 4; // estimated nnz in L factor
145  // Return the estimated size to the user if necessary
146  Index tempSpace;
147  tempSpace = (2 * panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
148  if (lwork == emptyIdxLU) {
149  Index estimated_size;
150  estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace + (glu.nzlmax + glu.nzumax) * sizeof(Index) +
151  (glu.nzlumax + glu.nzumax) * sizeof(Scalar) + n;
152  return estimated_size;
153  }
154 
155  // Setup the required space
156 
157  // First allocate Integer pointers for L\U factors
158  glu.xsup.resize(n + 1);
159  glu.supno.resize(n + 1);
160  glu.xlsub.resize(n + 1);
161  glu.xlusup.resize(n + 1);
162  glu.xusub.resize(n + 1);
163 
164  // Reserve memory for L/U factors
165  do {
166  if ((expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions) < 0) ||
167  (expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions) < 0) ||
168  (expand<IndexVector>(glu.lsub, glu.nzlmax, 0, 0, num_expansions) < 0) ||
169  (expand<IndexVector>(glu.usub, glu.nzumax, 0, 1, num_expansions) < 0)) {
170  // Reduce the estimated size and retry
171  glu.nzlumax /= 2;
172  glu.nzumax /= 2;
173  glu.nzlmax /= 2;
174  if (glu.nzlumax < annz) return glu.nzlumax;
175  }
176  } while (!glu.lusup.size() || !glu.ucol.size() || !glu.lsub.size() || !glu.usub.size());
177 
178  ++num_expansions;
179  return 0;
180 
181 } // end LuMemInit
@ LUNoMarker
Definition: SparseLU_Memory.h:40
int nzlmax
Definition: slu_cdefs.h:99

References Eigen::internal::emptyIdxLU, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lsub, Eigen::internal::LUNoMarker, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lusup, m, max, min, n, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::num_expansions, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::nzlmax, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::nzlumax, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::nzumax, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::ucol, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::usub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlusup, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xusub.

◆ memXpand()

template<typename Scalar , typename StorageIndex >
template<typename VectorType >
Index SparseLUImpl< Scalar, StorageIndex >::memXpand ( VectorType vec,
Index maxlen,
Index  nbElts,
MemType  memtype,
Index num_expansions 
)
protected

Expand the existing storage.

Parameters
vecvector to expand
[in,out]maxlenOn input, previous size of vec (Number of elements to copy ). on output, new size
nbEltscurrent number of elements in the vector.
memtypeType of the element to expand
num_expansionsNumber of expansions
Returns
0 on success, > 0 size of the memory allocated so far
195  {
196  Index failed_size;
197  if (memtype == USUB)
198  failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
199  else
200  failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 0, num_expansions);
201 
202  if (failed_size) return failed_size;
203 
204  return 0;
205 }

References Eigen::internal::USUB.

◆ panel_bmod()

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 
)
protected

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]

Parameters
mnumber of rows in the matrix
wPanel size
jcolStarting column of the panel
nsegNumber of segments in the U part
denseStore the full representation of the panel
tempvworking array
segrepsegment representative... first row in the segment
repfnzFirst nonzero rows
gluGlobal LU data.
61  {
62  Index ksub, jj, nextl_col;
63  Index fsupc, nsupc, nsupr, nrow;
64  Index krep, kfnz;
65  Index lptr; // points to the row subscripts of a supernode
66  Index luptr; // ...
67  Index segsize, no_zeros;
68  // For each nonz supernode segment of U[*,j] in topological order
69  Index k = nseg - 1;
71 
72  for (ksub = 0; ksub < nseg; ksub++) { // For each updating supernode
73  /* krep = representative of current k-th supernode
74  * fsupc = first supernodal column
75  * nsupc = number of columns in a supernode
76  * nsupr = number of rows in a supernode
77  */
78  krep = segrep(k);
79  k--;
80  fsupc = glu.xsup(glu.supno(krep));
81  nsupc = krep - fsupc + 1;
82  nsupr = glu.xlsub(fsupc + 1) - glu.xlsub(fsupc);
83  nrow = nsupr - nsupc;
84  lptr = glu.xlsub(fsupc);
85 
86  // loop over the panel columns to detect the actual number of columns and rows
87  Index u_rows = 0;
88  Index u_cols = 0;
89  for (jj = jcol; jj < jcol + w; jj++) {
90  nextl_col = (jj - jcol) * m;
91  VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
92 
93  kfnz = repfnz_col(krep);
94  if (kfnz == emptyIdxLU) continue; // skip any zero segment
95 
96  segsize = krep - kfnz + 1;
97  u_cols++;
98  u_rows = (std::max)(segsize, u_rows);
99  }
100 
101  if (nsupc >= 2) {
102  Index ldu = internal::first_multiple<Index>(u_rows, PacketSize);
103  Map<ScalarMatrix, Aligned, OuterStride<> > U(tempv.data(), u_rows, u_cols, OuterStride<>(ldu));
104 
105  // gather U
106  Index u_col = 0;
107  for (jj = jcol; jj < jcol + w; jj++) {
108  nextl_col = (jj - jcol) * m;
109  VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
110  VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
111 
112  kfnz = repfnz_col(krep);
113  if (kfnz == emptyIdxLU) continue; // skip any zero segment
114 
115  segsize = krep - kfnz + 1;
116  luptr = glu.xlusup(fsupc);
117  no_zeros = kfnz - fsupc;
118 
119  Index isub = lptr + no_zeros;
120  Index off = u_rows - segsize;
121  for (Index i = 0; i < off; i++) U(i, u_col) = 0;
122  for (Index i = 0; i < segsize; i++) {
123  Index irow = glu.lsub(isub);
124  U(i + off, u_col) = dense_col(irow);
125  ++isub;
126  }
127  u_col++;
128  }
129  // solve U = A^-1 U
130  luptr = glu.xlusup(fsupc);
131  Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc);
132  no_zeros = (krep - u_rows + 1) - fsupc;
133  luptr += lda * no_zeros + no_zeros;
134  MappedMatrixBlock A(glu.lusup.data() + luptr, u_rows, u_rows, OuterStride<>(lda));
135  U = A.template triangularView<UnitLower>().solve(U);
136 
137  // update
138  luptr += u_rows;
139  MappedMatrixBlock B(glu.lusup.data() + luptr, nrow, u_rows, OuterStride<>(lda));
140  eigen_assert(tempv.size() > w * ldu + nrow * w + 1);
141 
142  Index ldl = internal::first_multiple<Index>(nrow, PacketSize);
143  Index offset = (PacketSize - internal::first_default_aligned(B.data(), PacketSize)) % PacketSize;
144  MappedMatrixBlock L(tempv.data() + w * ldu + offset, nrow, u_cols, OuterStride<>(ldl));
145 
146  L.noalias() = B * U;
147 
148  // scatter U and L
149  u_col = 0;
150  for (jj = jcol; jj < jcol + w; jj++) {
151  nextl_col = (jj - jcol) * m;
152  VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
153  VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
154 
155  kfnz = repfnz_col(krep);
156  if (kfnz == emptyIdxLU) continue; // skip any zero segment
157 
158  segsize = krep - kfnz + 1;
159  no_zeros = kfnz - fsupc;
160  Index isub = lptr + no_zeros;
161 
162  Index off = u_rows - segsize;
163  for (Index i = 0; i < segsize; i++) {
164  Index irow = glu.lsub(isub++);
165  dense_col(irow) = U.coeff(i + off, u_col);
166  U.coeffRef(i + off, u_col) = 0;
167  }
168 
169  // Scatter l into SPA dense[]
170  for (Index i = 0; i < nrow; i++) {
171  Index irow = glu.lsub(isub++);
172  dense_col(irow) -= L.coeff(i, u_col);
173  L.coeffRef(i, u_col) = 0;
174  }
175  u_col++;
176  }
177  } else // level 2 only
178  {
179  // Sequence through each column in the panel
180  for (jj = jcol; jj < jcol + w; jj++) {
181  nextl_col = (jj - jcol) * m;
182  VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero column index for each row
183  VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Scatter/gather entire matrix column from/to here
184 
185  kfnz = repfnz_col(krep);
186  if (kfnz == emptyIdxLU) continue; // skip any zero segment
187 
188  segsize = krep - kfnz + 1;
189  luptr = glu.xlusup(fsupc);
190 
191  Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // nsupr
192 
193  // Perform a trianglar solve and block update,
194  // then scatter the result of sup-col update to dense[]
195  no_zeros = kfnz - fsupc;
196  if (segsize == 1)
197  LU_kernel_bmod<1>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
198  else if (segsize == 2)
199  LU_kernel_bmod<2>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
200  else if (segsize == 3)
201  LU_kernel_bmod<3>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr, no_zeros);
202  else
203  LU_kernel_bmod<Dynamic>::run(segsize, dense_col, tempv, glu.lusup, luptr, lda, nrow, glu.lsub, lptr,
204  no_zeros);
205  } // End for each column in the panel
206  }
207 
208  } // End for each updating supernode
209 } // end panel bmod
MatrixXd L
Definition: LLT_example.cpp:6
#define eigen_assert(x)
Definition: Macros.h:910
RowVector3d w
Definition: Matrix_resize_int.cpp:3
Matrix< SCALARB, Dynamic, Dynamic, opt_B > B
Definition: bench_gemm.cpp:48
Definition: matrices.h:74
static Index first_default_aligned(const DenseBase< Derived > &m)
Definition: DenseCoeffsBase.h:539
double U
Swimming speed.
Definition: two_d_variable_diff_adapt.cc:53

References Eigen::PlainObjectBase< Derived >::data(), eigen_assert, Eigen::internal::emptyIdxLU, Eigen::internal::first_default_aligned(), i, k, L, lda, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lusup, m, max, Eigen::internal::LU_kernel_bmod< SegSizeAtCompileTime >::run(), Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, RachelsAdvectionDiffusion::U, w, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlusup, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup.

◆ panel_dfs()

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 
)
protected

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 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.

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;

Parameters
[in]mnumber of rows in the matrix
[in]wPanel size
[in]jcolStarting column of the panel
[in]AInput matrix in column-major storage
[in]perm_rRow permutation
[out]nsegNumber of U segments
[out]denseAccumulate the column vectors of the panel
[out]panel_lsubSubscripts of the row in the panel
[out]segrepSegment representative i.e first nonzero row of each segment
[out]repfnzFirst nonzero location in each row
[out]xpruneThe pruned elimination tree
[out]markerwork vector
parentThe elimination tree
xplorework vector
gluThe global data structure
201  {
202  Index nextl_col; // Next available position in panel_lsub[*,jj]
203 
204  // Initialize pointers
205  VectorBlock<IndexVector> marker1(marker, m, m);
206  nseg = 0;
207 
208  panel_dfs_traits<IndexVector> traits(jcol, marker1.data());
209 
210  // For each column in the panel
211  for (StorageIndex jj = StorageIndex(jcol); jj < jcol + w; jj++) {
212  nextl_col = (jj - jcol) * m;
213 
214  VectorBlock<IndexVector> repfnz_col(repfnz, nextl_col, m); // First nonzero location in each row
215  VectorBlock<ScalarVector> dense_col(dense, nextl_col, m); // Accumulate a column vector here
216 
217  // For each nnz in A[*, jj] do depth first search
218  for (typename MatrixType::InnerIterator it(A, jj); it; ++it) {
219  Index krow = it.row();
220  dense_col(krow) = it.value();
221 
222  StorageIndex kmark = marker(krow);
223  if (kmark == jj) continue; // krow visited before, go to the next nonzero
224 
225  dfs_kernel(jj, perm_r, nseg, panel_lsub, segrep, repfnz_col, xprune, marker, parent, xplore, glu, nextl_col, krow,
226  traits);
227  } // end for nonzeros in column jj
228 
229  } // end for column jj
230 }
Base::InnerIterator InnerIterator
Definition: SparseMatrix.h:138

References m, and w.

◆ pivotL()

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 
)
protected

Performs the numerical pivoting 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 pivot row = k; ELSE IF abs(A_jj) >= thresh THEN pivot row = j; ELSE pivot row = m;

Note: If you absolutely want to use a given pivot order, then set u=0.0.

Parameters
jcolThe current column of L
diagpivotthreshdiagonal pivoting threshold
[in,out]perm_rRow permutation (threshold pivoting)
[in]iperm_ccolumn permutation - used to finf diagonal of Pc*A*Pc'
[out]pivrowThe pivot row
gluGlobal LU data
Returns
0 if success, i > 0 if U(i,i) is exactly zero
65  {
66  Index fsupc = (glu.xsup)((glu.supno)(jcol)); // First column in the supernode containing the column jcol
67  Index nsupc = jcol - fsupc; // Number of columns in the supernode portion, excluding jcol; nsupc >=0
68  Index lptr = glu.xlsub(fsupc); // pointer to the starting location of the row subscripts for this supernode portion
69  Index nsupr = glu.xlsub(fsupc + 1) - lptr; // Number of rows in the supernode
70  Index lda = glu.xlusup(fsupc + 1) - glu.xlusup(fsupc); // leading dimension
71  Scalar* lu_sup_ptr = &(glu.lusup.data()[glu.xlusup(fsupc)]); // Start of the current supernode
72  Scalar* lu_col_ptr = &(glu.lusup.data()[glu.xlusup(jcol)]); // Start of jcol in the supernode
73  StorageIndex* lsub_ptr = &(glu.lsub.data()[lptr]); // Start of row indices of the supernode
74 
75  // Determine the largest abs numerical value for partial pivoting
76  Index diagind = iperm_c(jcol); // diagonal index
77  RealScalar pivmax(-1.0);
78  Index pivptr = nsupc;
80  RealScalar rtemp;
81  Index isub, icol, itemp, k;
82  for (isub = nsupc; isub < nsupr; ++isub) {
83  using std::abs;
84  rtemp = abs(lu_col_ptr[isub]);
85  if (rtemp > pivmax) {
86  pivmax = rtemp;
87  pivptr = isub;
88  }
89  if (lsub_ptr[isub] == diagind) diag = isub;
90  }
91 
92  // Test for singularity
93  if (pivmax <= RealScalar(0.0)) {
94  // if pivmax == -1, the column is structurally empty, otherwise it is only numerically zero
95  pivrow = pivmax < RealScalar(0.0) ? diagind : lsub_ptr[pivptr];
96  perm_r(pivrow) = StorageIndex(jcol);
97  return (jcol + 1);
98  }
99 
100  RealScalar thresh = diagpivotthresh * pivmax;
101 
102  // Choose appropriate pivotal element
103 
104  {
105  // Test if the diagonal element can be used as a pivot (given the threshold value)
106  if (diag >= 0) {
107  // Diagonal element exists
108  using std::abs;
109  rtemp = abs(lu_col_ptr[diag]);
110  if (rtemp != RealScalar(0.0) && rtemp >= thresh) pivptr = diag;
111  }
112  pivrow = lsub_ptr[pivptr];
113  }
114 
115  // Record pivot row
116  perm_r(pivrow) = StorageIndex(jcol);
117  // Interchange row subscripts
118  if (pivptr != nsupc) {
119  std::swap(lsub_ptr[pivptr], lsub_ptr[nsupc]);
120  // Interchange numerical values as well, for the two rows in the whole snode
121  // such that L is indexed the same way as A
122  for (icol = 0; icol <= nsupc; icol++) {
123  itemp = pivptr + icol * lda;
124  std::swap(lu_sup_ptr[itemp], lu_sup_ptr[nsupc + icol * lda]);
125  }
126  }
127  // cdiv operations
128  Scalar temp = Scalar(1.0) / lu_col_ptr[nsupc];
129  for (k = nsupc + 1; k < nsupr; k++) lu_col_ptr[k] *= temp;
130  return 0;
131 }
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:46
ScalarVector::RealScalar RealScalar
Definition: SparseLUImpl.h:29
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117
const char const char const char * diag
Definition: level2_impl.h:86

References abs(), diag, Eigen::internal::emptyIdxLU, k, lda, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::lusup, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno, swap(), Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlsub, Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xlusup, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::xsup.

◆ pruneL()

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 
)
protected

Prunes the L-structure.

It prunes the L-structure of supernodes whose L-structure contains the current pivot row "pivrow"

Parameters
jcolThe current column of L
[in]perm_rRow permutation
[out]pivrowThe pivot row
nsegNumber of segments
segrep
repfnz
[out]xprune
gluGlobal LU data
58  {
59  // For each supernode-rep irep in U(*,j]
60  Index jsupno = glu.supno(jcol);
61  Index i, irep, irep1;
62  bool movnum, do_prune = false;
63  Index kmin = 0, kmax = 0, minloc, maxloc, krow;
64  for (i = 0; i < nseg; i++) {
65  irep = segrep(i);
66  irep1 = irep + 1;
67  do_prune = false;
68 
69  // Don't prune with a zero U-segment
70  if (repfnz(irep) == emptyIdxLU) continue;
71 
72  // If a snode overlaps with the next panel, then the U-segment
73  // is fragmented into two parts -- irep and irep1. We should let
74  // pruning occur at the rep-column in irep1s snode.
75  if (glu.supno(irep) == glu.supno(irep1)) continue; // don't prune
76 
77  // If it has not been pruned & it has a nonz in row L(pivrow,i)
78  if (glu.supno(irep) != jsupno) {
79  if (xprune(irep) >= glu.xlsub(irep1)) {
80  kmin = glu.xlsub(irep);
81  kmax = glu.xlsub(irep1) - 1;
82  for (krow = kmin; krow <= kmax; krow++) {
83  if (glu.lsub(krow) == pivrow) {
84  do_prune = true;
85  break;
86  }
87  }
88  }
89 
90  if (do_prune) {
91  // do a quicksort-type partition
92  // movnum=true means that the num values have to be exchanged
93  movnum = false;
94  if (irep == glu.xsup(glu.supno(irep))) // Snode of size 1
95  movnum = true;
96 
97  while (kmin <= kmax) {
98  if (perm_r(glu.lsub(kmax)) == emptyIdxLU)
99  kmax--;
100  else if (perm_r(glu.lsub(kmin)) != emptyIdxLU)
101  kmin++;
102  else {
103  // kmin below pivrow (not yet pivoted), and kmax
104  // above pivrow: interchange the two subscripts
105  std::swap(glu.lsub(kmin), glu.lsub(kmax));
106 
107  // If the supernode has only one column, then we
108  // only keep one set of subscripts. For any subscript
109  // intercnahge performed, similar interchange must be
110  // done on the numerical values.
111  if (movnum) {
112  minloc = glu.xlusup(irep) + (kmin - glu.xlsub(irep));
113  maxloc = glu.xlusup(irep) + (kmax - glu.xlsub(irep));
114  std::swap(glu.lusup(minloc), glu.lusup(maxloc));
115  }
116  kmin++;
117  kmax--;
118  }
119  } // end while
120 
121  xprune(irep) = StorageIndex(kmin); // Pruning
122  } // end if do_prune
123  } // end pruning
124  } // End for each U-segment
125 }

References i, and Eigen::internal::LU_GlobalLU_t< IndexVector, ScalarVector >::supno.

◆ relax_snode()

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 
)
protected

Identify the initial relaxed supernodes.

This routine is applied to a column elimination tree. It assumes that the matrix has been reordered according to the postorder of the etree

Parameters
nthe number of columns
etelimination tree
relax_columnsMaximum number of columns allowed in a relaxed snode
descendantsNumber of descendants of each node in the etree
relax_endlast column in a supernode
51  {
52  // compute the number of descendants of each node in the etree
53  Index parent;
54  relax_end.setConstant(emptyIdxLU);
55  descendants.setZero();
56  for (Index j = 0; j < n; j++) {
57  parent = et(j);
58  if (parent != n) // not the dummy root
59  descendants(parent) += descendants(j) + 1;
60  }
61  // Identify the relaxed supernodes by postorder traversal of the etree
62  Index snode_start; // beginning of a snode
63  for (Index j = 0; j < n;) {
64  parent = et(j);
65  snode_start = j;
66  while (parent != n && descendants(parent) < relax_columns) {
67  j = parent;
68  parent = et(j);
69  }
70  // Found a supernode in postordered etree, j is the last column
71  relax_end(snode_start) = StorageIndex(j); // Record last column
72  j++;
73  // Search for a new leaf
74  while (descendants(j) != 0 && j < n) j++;
75  } // End postorder traversal of the etree
76 }

References Eigen::internal::emptyIdxLU, j, n, Eigen::PlainObjectBase< Derived >::setConstant(), and Eigen::PlainObjectBase< Derived >::setZero().

◆ snode_bmod()

template<typename Scalar , typename StorageIndex >
Index Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::snode_bmod ( const Index  jcol,
const Index  fsupc,
ScalarVector dense,
GlobalLU_t glu 
)
protected

◆ snode_dfs()

template<typename Scalar , typename StorageIndex >
Index Eigen::internal::SparseLUImpl< Scalar, StorageIndex >::snode_dfs ( const Index  jcol,
const Index  kcol,
const MatrixType mat,
IndexVector xprune,
IndexVector marker,
GlobalLU_t glu 
)
protected

Friends And Related Function Documentation

◆ column_dfs_traits

template<typename Scalar , typename StorageIndex >
template<typename , typename >
friend struct column_dfs_traits
friend

The documentation for this class was generated from the following files: