aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/SparseLU/SparseLU_panel_bmod.h
blob: 93daa938c9ab68a1d71bfb4eedf5d5df62e4a974 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

/* 
 
 * NOTE: This file is the modified version of xpanel_bmod.c file in SuperLU 
 
 * -- SuperLU routine (version 3.0) --
 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
 * and Lawrence Berkeley National Lab.
 * October 15, 2003
 *
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 *
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
 * EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 * Permission is hereby granted to use or copy this program for any
 * purpose, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is
 * granted, provided the above notices are retained, and a notice that
 * the code was modified is included with the above copyright notice.
 */
#ifndef SPARSELU_PANEL_BMOD_H
#define SPARSELU_PANEL_BMOD_H
/**
 * \brief Performs numeric block updates (sup-panel) in topological order.
 * 
 * Before entering this routine, the original nonzeros in the panel
 * were already copied i nto the spa[m,w] ... FIXME to be checked
 * 
 * \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 segrep in ...
 * \param repfnz in ...
 * \param Glu Global LU data. 
 * 
 * 
 */
template <typename VectorType>
void SparseLU::LU_panel_bmod(const int m, const int w, const int jcol, const int nseg, VectorType& dense, VectorType& tempv, VectorXi& segrep, VectorXi& repfnz, LU_GlobalLu_t& Glu)
{
  VectorXi& xsup = Glu.xsup; 
  VectorXi& supno = Glu.supno; 
  VectorXi& lsub = Glu.lsub; 
  VectorXi& xlsub = Glu.xlsub; 
  VectorXi& xlusup = Glu.xlusup; 
  VectorType& lusup = Glu.lusup; 
  
  int i,ksub,jj,nextl_col,irow; 
  int fsupc, nsupc, nsupr, nrow; 
  int krep, krep_ind; 
  int nrow; 
  int lptr; // points to the row subscripts of a supernode 
  int luptr; // ...
  int segsze,no_zeros,irow ; 
  // For each nonz supernode segment of U[*,j] in topological order
  int k = nseg - 1; 
  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 = xsup(supno(krep)); 
    nsupc = krep - fsupc + 1; 
    nsupr = xlsub(fsupc+1) - xlsub(fsupc); 
    nrow = nsupr - nsupc; 
    lptr = xlsub(fsupc); 
    krep_ind = lptr + nsupc - 1; 
    
    repfnz_col = repfnz; 
    dense_col = dense; 
    
    // NOTE : Unlike the original implementation in SuperLU, the present implementation
    // does not include a 2-D block update. 
    
    // Sequence through each column in the panel
    for (jj = jcol; jj < jcol + w; jj++)
    {
      nextl_col = (jj-jcol) * m; 
      VectorBlock<VectorXi> repfnz_col(repfnz.segment(nextl_col, m)); // First nonzero column index for each row
      VectorBLock<VectorXi> dense_col(dense.segment(nextl_col, m)); // Scatter/gather entire matrix column from/to here
      
      kfnz = repfnz_col(krep); 
      if ( kfnz == IND_EMPTY ) 
        continue; // skip any zero segment
      
      segsize = krep - kfnz + 1;
      luptr = xlusup(fsupc);    
      
      // NOTE : Unlike the original implementation in SuperLU, 
      // there is no update feature for  col-col, 2col-col ... 
      
      // Perform a trianglar solve and block update, 
      // then scatter the result of sup-col update to dense[]
      no_zeros = kfnz - fsupc; 
      
      // 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_col[*]
      isub = lptr + no_zeros; 
      for (i = 0; i < segsize; ++i) 
      {
        irow = lsub(isub); 
        tempv(i) = dense_col(irow); // Gather to a compact vector
        ++isub;
      }
      // Start effective triangle 
      luptr += nsupr * no_zeros + no_zeros; 
      // triangular solve with Eigen
      Map<Matrix<Scalar,Dynamic, Dynamic>, 0, OuterStride<> > A( &(lusup.data()[luptr]), segsize, segsize, OuterStride<>(nsupr) ); 
      Map<Matrix<Scalar,Dynamic,1> > u( tempv.data(), segsize); 
      u = A.triangularView<Lower>().solve(u); 
      
      luptr += segsize; 
      // Dense Matrix vector product y <-- A*x; 
      new (&A) Map<Matrix<Scalar,Dynamic, Dynamic>, 0, OuterStride<> > ( &(lusup.data()[luptr]), nrow, segsize, OuterStride<>(nsupr) ); 
      Map<VectorType> l( &(tempv.data()[segsize]), segsize); 
      l= A * u;
      
      // Scatter tempv(*) into SPA dense(*) such that tempv(*) 
      // can be used for the triangular solve of the next 
      // column of the panel. The y will be copied into ucol(*) 
      // after the whole panel has been finished.
      
      isub = lptr + no_zeros; 
      for (i = 0; i < segsize; i++) 
      {
        irow = lsub(isub); 
        dense_col(irow) = tempv(i);
        tempv(i) = Scalar(0.0); 
        isub++;
      }
     
     // Scatter the update from &tempv[segsize] into SPA dense(*)
     // Start dense rectangular L 
     for (i = 0; i < nrow; i++) 
     {
       irow = lsub(isub); 
       dense_col(irow) -= tempv(segsize + i); 
       tempv(segsize + i) = 0; 
       ++isub; 
     }
     
    } // End for each column in the panel 
    
  } // End for each updating supernode
}
#endif