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
25template <typename Entry, typename Int>
26Int 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