Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
klu2_extract.hpp
1 /* ========================================================================== */
2 /* === KLU_extract ========================================================== */
3 /* ========================================================================== */
4 // @HEADER
5 // *****************************************************************************
6 // KLU2: A Direct Linear Solver package
7 //
8 // Copyright 2011 NTESS and the KLU2 contributors.
9 // SPDX-License-Identifier: LGPL-2.1-or-later
10 // *****************************************************************************
11 // @HEADER
12 
13 /* Extract KLU factorization into conventional compressed-column matrices.
14  * If any output array is NULL, that part of the LU factorization is not
15  * extracted (this is not an error condition).
16  *
17  * nnz(L) = Numeric->lnz, nnz(U) = Numeric->unz, and nnz(F) = Numeric->Offp [n]
18  */
19 
20 #ifndef KLU2_EXTRACT_HPP
21 #define KLU2_EXTRACT_HPP
22 
23 #include "klu2_internal.h"
24 
25 template <typename Entry, typename Int>
26 Int KLU_extract /* returns TRUE if successful, FALSE otherwise */
27 (
28  /* inputs: */
29  KLU_numeric<Entry, Int> *Numeric,
30  KLU_symbolic<Entry, Int> *Symbolic,
31 
32  /* outputs, all of which must be allocated on input */
33 
34  /* L */
35  Int *Lp, /* size n+1 */
36  Int *Li, /* size nnz(L) */
37  double *Lx, /* size nnz(L) */
38 #ifdef COMPLEX
39  double *Lz, /* size nnz(L) for the complex case, ignored if real */
40 #endif
41 
42  /* U */
43  Int *Up, /* size n+1 */
44  Int *Ui, /* size nnz(U) */
45  double *Ux, /* size nnz(U) */
46 #ifdef COMPLEX
47  double *Uz, /* size nnz(U) for the complex case, ignored if real */
48 #endif
49 
50  /* F */
51  Int *Fp, /* size n+1 */
52  Int *Fi, /* size nnz(F) */
53  double *Fx, /* size nnz(F) */
54 #ifdef COMPLEX
55  double *Fz, /* size nnz(F) for the complex case, ignored if real */
56 #endif
57 
58  /* P, row permutation */
59  Int *P, /* size n */
60 
61  /* Q, column permutation */
62  Int *Q, /* size n */
63 
64  /* Rs, scale factors */
65  double *Rs, /* size n */
66 
67  /* R, block boundaries */
68  Int *R, /* size nblocks+1 */
69 
70  KLU_common<Entry> *Common
71 )
72 {
73  Int *Lip, *Llen, *Uip, *Ulen, *Li2, *Ui2 ;
74  Unit *LU ;
75  Entry *Lx2, *Ux2, *Ukk ;
76  Int i, k, block, nblocks, n, nz, k1, k2, nk, len, kk, p ;
77 
78  if (Common == NULL)
79  {
80  return (FALSE) ;
81  }
82 
83  if (Symbolic == NULL || Numeric == NULL)
84  {
85  Common->status = KLU_INVALID ;
86  return (FALSE) ;
87  }
88 
89  Common->status = KLU_OK ;
90  n = Symbolic->n ;
91  nblocks = Symbolic->nblocks ;
92 
93  /* ---------------------------------------------------------------------- */
94  /* extract scale factors */
95  /* ---------------------------------------------------------------------- */
96 
97  if (Rs != NULL)
98  {
99  if (Numeric->Rs != NULL)
100  {
101  for (i = 0 ; i < n ; i++)
102  {
103  Rs [i] = Numeric->Rs [i] ;
104  }
105  }
106  else
107  {
108  /* no scaling */
109  for (i = 0 ; i < n ; i++)
110  {
111  Rs [i] = 1 ;
112  }
113  }
114  }
115 
116  /* ---------------------------------------------------------------------- */
117  /* extract block boundaries */
118  /* ---------------------------------------------------------------------- */
119 
120  if (R != NULL)
121  {
122  for (block = 0 ; block <= nblocks ; block++)
123  {
124  R [block] = Symbolic->R [block] ;
125  }
126  }
127 
128  /* ---------------------------------------------------------------------- */
129  /* extract final row permutation */
130  /* ---------------------------------------------------------------------- */
131 
132  if (P != NULL)
133  {
134  for (k = 0 ; k < n ; k++)
135  {
136  P [k] = Numeric->Pnum [k] ;
137  }
138  }
139 
140  /* ---------------------------------------------------------------------- */
141  /* extract column permutation */
142  /* ---------------------------------------------------------------------- */
143 
144  if (Q != NULL)
145  {
146  for (k = 0 ; k < n ; k++)
147  {
148  Q [k] = Symbolic->Q [k] ;
149  }
150  }
151 
152  /* ---------------------------------------------------------------------- */
153  /* extract each block of L */
154  /* ---------------------------------------------------------------------- */
155 
156  if (Lp != NULL && Li != NULL && Lx != NULL
157 #ifdef COMPLEX
158  && Lz != NULL
159 #endif
160  )
161  {
162  nz = 0 ;
163  for (block = 0 ; block < nblocks ; block++)
164  {
165  k1 = Symbolic->R [block] ;
166  k2 = Symbolic->R [block+1] ;
167  nk = k2 - k1 ;
168  if (nk == 1)
169  {
170  /* singleton block */
171  Lp [k1] = nz ;
172  Li [nz] = k1 ;
173  Lx [nz] = 1 ;
174 #ifdef COMPLEX
175  Lz [nz] = 0 ;
176 #endif
177  nz++ ;
178  }
179  else
180  {
181  /* non-singleton block */
182  LU = (Unit *) Numeric->LUbx [block] ;
183  Lip = Numeric->Lip + k1 ;
184  Llen = Numeric->Llen + k1 ;
185  for (kk = 0 ; kk < nk ; kk++)
186  {
187  Lp [k1+kk] = nz ;
188  /* add the unit diagonal entry */
189  Li [nz] = k1 + kk ;
190  Lx [nz] = 1 ;
191 #ifdef COMPLEX
192  Lz [nz] = 0 ;
193 #endif
194  nz++ ;
195  GET_POINTER (LU, Lip, Llen, Li2, Lx2, kk, len) ;
196  for (p = 0 ; p < len ; p++)
197  {
198  Li [nz] = k1 + Li2 [p] ;
199  Lx [nz] = REAL (Lx2 [p]) ;
200 #ifdef COMPLEX
201  Lz [nz] = IMAG (Lx2 [p]) ;
202 #endif
203  nz++ ;
204  }
205  }
206  }
207  }
208  Lp [n] = nz ;
209  ASSERT (nz == Numeric->lnz) ;
210  }
211 
212  /* ---------------------------------------------------------------------- */
213  /* extract each block of U */
214  /* ---------------------------------------------------------------------- */
215 
216  if (Up != NULL && Ui != NULL && Ux != NULL
217 #ifdef COMPLEX
218  && Uz != NULL
219 #endif
220  )
221  {
222  nz = 0 ;
223  for (block = 0 ; block < nblocks ; block++)
224  {
225  k1 = Symbolic->R [block] ;
226  k2 = Symbolic->R [block+1] ;
227  nk = k2 - k1 ;
228  Ukk = ((Entry *) Numeric->Udiag) + k1 ;
229  if (nk == 1)
230  {
231  /* singleton block */
232  Up [k1] = nz ;
233  Ui [nz] = k1 ;
234  Ux [nz] = REAL (Ukk [0]) ;
235 #ifdef COMPLEX
236  Uz [nz] = IMAG (Ukk [0]) ;
237 #endif
238  nz++ ;
239  }
240  else
241  {
242  /* non-singleton block */
243  LU = (Unit *) Numeric->LUbx [block] ;
244  Uip = Numeric->Uip + k1 ;
245  Ulen = Numeric->Ulen + k1 ;
246  for (kk = 0 ; kk < nk ; kk++)
247  {
248  Up [k1+kk] = nz ;
249  GET_POINTER (LU, Uip, Ulen, Ui2, Ux2, kk, len) ;
250  for (p = 0 ; p < len ; p++)
251  {
252  Ui [nz] = k1 + Ui2 [p] ;
253  Ux [nz] = REAL (Ux2 [p]) ;
254 #ifdef COMPLEX
255  Uz [nz] = IMAG (Ux2 [p]) ;
256 #endif
257  nz++ ;
258  }
259  /* add the diagonal entry */
260  Ui [nz] = k1 + kk ;
261  Ux [nz] = REAL (Ukk [kk]) ;
262 #ifdef COMPLEX
263  Uz [nz] = IMAG (Ukk [kk]) ;
264 #endif
265  nz++ ;
266  }
267  }
268  }
269  Up [n] = nz ;
270  ASSERT (nz == Numeric->unz) ;
271  }
272 
273  /* ---------------------------------------------------------------------- */
274  /* extract the off-diagonal blocks, F */
275  /* ---------------------------------------------------------------------- */
276 
277  if (Fp != NULL && Fi != NULL && Fx != NULL
278 #ifdef COMPLEX
279  && Fz != NULL
280 #endif
281  )
282  {
283  for (k = 0 ; k <= n ; k++)
284  {
285  Fp [k] = Numeric->Offp [k] ;
286  }
287  nz = Fp [n] ;
288  for (k = 0 ; k < nz ; k++)
289  {
290  Fi [k] = Numeric->Offi [k] ;
291  }
292  for (k = 0 ; k < nz ; k++)
293  {
294  Fx [k] = REAL (((Entry *) Numeric->Offx) [k]) ;
295 #ifdef COMPLEX
296  Fz [k] = IMAG (((Entry *) Numeric->Offx) [k]) ;
297 #endif
298  }
299  }
300 
301  return (TRUE) ;
302 }
303 
304 #endif