17 #ifndef KLU2_FACTOR_HPP
18 #define KLU2_FACTOR_HPP
20 #include "klu2_internal.h"
22 #include "klu2_memory.hpp"
23 #include "klu2_scale.hpp"
30 template <
typename Entry,
typename Int>
37 KLU_symbolic<Entry, Int> *Symbolic,
40 KLU_numeric<Entry, Int> *Numeric,
41 KLU_common<Entry, Int> *Common
46 Int *P, *Q, *R, *Pnum, *Offp, *Offi, *Pblock, *Pinv, *Iwork,
47 *Lip, *Uip, *Llen, *Ulen ;
48 Entry *Offx, *X, s, *Udiag ;
50 Int k1, k2, nk, k, block, oldcol, pend, oldrow, n, lnz, unz, p, newrow,
51 nblocks, poff, nzoff, lnz_block, unz_block,
scale, max_lnz_block,
64 nblocks = Symbolic->nblocks ;
65 nzoff = Symbolic->nzoff ;
67 Pnum = Numeric->Pnum ;
68 Offp = Numeric->Offp ;
69 Offi = Numeric->Offi ;
70 Offx = (Entry *) Numeric->Offx ;
74 Llen = Numeric->Llen ;
75 Ulen = Numeric->Ulen ;
76 LUbx = (Unit **) Numeric->LUbx ;
77 Udiag = (Entry *) Numeric->Udiag ;
80 Pinv = Numeric->Pinv ;
81 X = (Entry *) Numeric->Xwork ;
82 Iwork = Numeric->Iwork ;
84 Pblock = Iwork + 5*((size_t) Symbolic->maxblock) ;
85 Common->nrealloc = 0 ;
86 scale = Common->scale ;
94 for (k = 0 ; k < n ; k++)
96 Pinv [k] = AMESOS2_KLU2_EMPTY ;
99 for (k = 0 ; k < n ; k++)
101 ASSERT (P [k] >= 0 && P [k] < n) ;
105 for (k = 0 ; k < n ; k++) ASSERT (Pinv [k] != AMESOS2_KLU2_EMPTY) ;
110 Common->noffdiag = 0 ;
127 KLU_scale (
scale, n,
Ap,
Ai, Ax, Rs, Pnum, Common) ;
128 if (Common->status < KLU_OK)
138 for (k = 0 ; k < n ; k++) PRINTF ((
"Rs [%d] %g\n", k, Rs [k])) ;
146 for (block = 0 ; block < nblocks ; block++)
156 PRINTF ((
"FACTOR BLOCK %d, k1 %d k2-1 %d nk %d\n", block, k1,k2-1,nk)) ;
167 pend =
Ap [oldcol+1] ;
173 for (p =
Ap [oldcol] ; p < pend ; p++)
176 newrow = Pinv [oldrow] ;
179 Offi [poff] = oldrow ;
180 Offx [poff] = Ax [p] ;
185 ASSERT (newrow == k1) ;
186 PRINTF ((
"singleton block %d", block)) ;
187 PRINT_ENTRY (Ax [p]) ;
199 for (p =
Ap [oldcol] ; p < pend ; p++)
202 newrow = Pinv [oldrow] ;
205 Offi [poff] = oldrow ;
207 SCALE_DIV_ASSIGN (Offx [poff], Ax [p], Rs [oldrow]) ;
212 ASSERT (newrow == k1) ;
213 PRINTF ((
"singleton block %d ", block)) ;
214 PRINT_ENTRY (Ax[p]) ;
215 SCALE_DIV_ASSIGN (s, Ax [p], Rs [oldrow]) ;
225 Common->status = KLU_SINGULAR ;
226 Common->numerical_rank = k1 ;
227 Common->singular_col = oldcol ;
228 if (Common->halt_if_singular)
251 lsize = -(Common->initmem) ;
255 lsize = Common->initmem_amd * Lnz [block] + nk ;
259 Numeric->LUsize [block] = KLU_kernel_factor (nk,
Ap,
Ai, Ax, Q,
260 lsize, &LUbx [block], Udiag + k1, Llen + k1, Ulen + k1,
261 Lip + k1, Uip + k1, Pblock, &lnz_block, &unz_block,
262 X, Iwork, k1, Pinv, Rs, Offp, Offi, Offx, Common) ;
264 if (Common->status < KLU_OK ||
265 (Common->status == KLU_SINGULAR && Common->halt_if_singular))
271 PRINTF ((
"\n----------------------- L %d:\n", block)) ;
272 ASSERT (KLU_valid_LU (nk, TRUE, Lip+k1, Llen+k1, LUbx [block])) ;
273 PRINTF ((
"\n----------------------- U %d:\n", block)) ;
274 ASSERT (KLU_valid_LU (nk, FALSE, Uip+k1, Ulen+k1, LUbx [block])) ;
282 max_lnz_block = MAX (max_lnz_block, lnz_block) ;
283 max_unz_block = MAX (max_unz_block, unz_block) ;
285 if (Lnz [block] == AMESOS2_KLU2_EMPTY)
288 Lnz [block] = MAX (lnz_block, unz_block) ;
295 PRINTF ((
"Pnum, 1-based:\n")) ;
296 for (k = 0 ; k < nk ; k++)
298 ASSERT (k + k1 < n) ;
299 ASSERT (Pblock [k] + k1 < n) ;
300 Pnum [k + k1] = P [Pblock [k] + k1] ;
301 PRINTF ((
"Pnum (%d + %d + 1 = %d) = %d + 1 = %d\n",
302 k, k1, k+k1+1, Pnum [k+k1], Pnum [k+k1]+1)) ;
308 ASSERT (nzoff == Offp [n]) ;
309 PRINTF ((
"\n------------------- Off diagonal entries:\n")) ;
310 ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
314 Numeric->max_lnz_block = max_lnz_block ;
315 Numeric->max_unz_block = max_unz_block ;
319 for (k = 0 ; k < n ; k++)
321 Pinv [k] = AMESOS2_KLU2_EMPTY ;
324 for (k = 0 ; k < n ; k++)
326 ASSERT (Pnum [k] >= 0 && Pnum [k] < n) ;
327 Pinv [Pnum [k]] = k ;
330 for (k = 0 ; k < n ; k++) ASSERT (Pinv [k] != AMESOS2_KLU2_EMPTY) ;
336 for (k = 0 ; k < n ; k++)
340 X [k] = Rs [Pnum [k]] ;
342 for (k = 0 ; k < n ; k++)
344 Rs [k] = REAL (X [k]) ;
348 PRINTF ((
"\n------------------- Off diagonal entries, old:\n")) ;
349 ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
352 for (p = 0 ; p < nzoff ; p++)
354 ASSERT (Offi [p] >= 0 && Offi [p] < n) ;
355 Offi [p] = Pinv [Offi [p]] ;
358 PRINTF ((
"\n------------------- Off diagonal entries, new:\n")) ;
359 ASSERT (KLU_valid (n, Offp, Offi, Offx)) ;
363 PRINTF ((
"\n ############# KLU_BTF_FACTOR done, nblocks %d\n",nblocks));
364 Entry ss, *Udiag = Numeric->Udiag ;
365 for (block = 0 ; block < nblocks && Common->status == KLU_OK ; block++)
370 PRINTF ((
"\n======================KLU_factor output: k1 %d k2 %d nk %d\n",k1,k2,nk)) ;
373 PRINTF ((
"singleton ")) ;
380 Int *Lip, *Uip, *Llen, *Ulen ;
382 Lip = Numeric->Lip + k1 ;
383 Llen = Numeric->Llen + k1 ;
384 LU = (Unit *) Numeric->LUbx [block] ;
385 PRINTF ((
"\n---- L block %d\n", block));
386 ASSERT (KLU_valid_LU (nk, TRUE, Lip, Llen, LU)) ;
387 Uip = Numeric->Uip + k1 ;
388 Ulen = Numeric->Ulen + k1 ;
389 PRINTF ((
"\n---- U block %d\n", block)) ;
390 ASSERT (KLU_valid_LU (nk, FALSE, Uip, Ulen, LU)) ;
403 template <
typename Entry,
typename Int>
404 KLU_numeric<Entry, Int> *KLU_factor
412 KLU_symbolic<Entry, Int> *Symbolic,
414 KLU_common<Entry, Int> *Common
417 Int n, nzoff, nblocks, maxblock, k, ok = TRUE ;
419 KLU_numeric<Entry, Int> *Numeric ;
420 size_t n1, nzoff1, s, b6, n3 ;
426 Common->status = KLU_OK ;
427 Common->numerical_rank = AMESOS2_KLU2_EMPTY ;
428 Common->singular_col = AMESOS2_KLU2_EMPTY ;
435 if (Symbolic == NULL)
437 Common->status = KLU_INVALID ;
442 nzoff = Symbolic->nzoff ;
443 nblocks = Symbolic->nblocks ;
444 maxblock = Symbolic->maxblock ;
446 PRINTF ((
"KLU_factor: n %d nzoff %d nblocks %d maxblock %d\n",
447 n, nzoff, nblocks, maxblock)) ;
453 Common->initmem_amd = MAX (1.0, Common->initmem_amd) ;
454 Common->initmem = MAX (1.0, Common->initmem) ;
455 Common->tol = MIN (Common->tol, 1.0) ;
456 Common->tol = MAX (0.0, Common->tol) ;
457 Common->memgrow = MAX (1.0, Common->memgrow) ;
464 n1 = ((size_t) n) + 1 ;
465 nzoff1 = ((size_t) nzoff) + 1 ;
467 Numeric = (KLU_numeric<Entry, Int> *) KLU_malloc (
sizeof (KLU_numeric<Entry, Int>), 1, Common) ;
468 if (Common->status < KLU_OK)
471 Common->status = KLU_OUT_OF_MEMORY ;
475 Numeric->nblocks = nblocks ;
476 Numeric->nzoff = nzoff ;
477 Numeric->Pnum = (Int *) KLU_malloc (n,
sizeof (Int), Common) ;
478 Numeric->Offp = (Int *) KLU_malloc (n1,
sizeof (Int), Common) ;
479 Numeric->Offi = (Int *) KLU_malloc (nzoff1,
sizeof (Int), Common) ;
480 Numeric->Offx = KLU_malloc (nzoff1,
sizeof (Entry), Common) ;
482 Numeric->Lip = (Int *) KLU_malloc (n,
sizeof (Int), Common) ;
483 Numeric->Uip = (Int *) KLU_malloc (n,
sizeof (Int), Common) ;
484 Numeric->Llen = (Int *) KLU_malloc (n,
sizeof (Int), Common) ;
485 Numeric->Ulen = (Int *) KLU_malloc (n,
sizeof (Int), Common) ;
487 Numeric->LUsize = (
size_t *) KLU_malloc (nblocks,
sizeof (
size_t), Common) ;
489 Numeric->LUbx = (
void **) KLU_malloc (nblocks,
sizeof (Unit *), Common) ;
490 if (Numeric->LUbx != NULL)
492 for (k = 0 ; k < nblocks ; k++)
494 Numeric->LUbx [k] = NULL ;
498 Numeric->Udiag = KLU_malloc (n,
sizeof (Entry), Common) ;
500 if (Common->scale > 0)
502 Numeric->Rs = (
double *) KLU_malloc (n,
sizeof (
double), Common) ;
510 Numeric->Pinv = (Int *) KLU_malloc (n,
sizeof (Int), Common) ;
519 s = KLU_mult_size_t (n,
sizeof (Entry), &ok) ;
520 n3 = KLU_mult_size_t (n, 3 *
sizeof (Entry), &ok) ;
521 b6 = KLU_mult_size_t (maxblock, 6 *
sizeof (Int), &ok) ;
522 Numeric->worksize = KLU_add_size_t (s, MAX (n3, b6), &ok) ;
523 Numeric->Work = KLU_malloc (Numeric->worksize, 1, Common) ;
524 Numeric->Xwork = Numeric->Work ;
525 Numeric->Iwork = (Int *) ((Entry *) Numeric->Xwork + n) ;
526 if (!ok || Common->status < KLU_OK)
529 Common->status = ok ? KLU_OUT_OF_MEMORY : KLU_TOO_LARGE ;
530 KLU_free_numeric (&Numeric, Common) ;
538 factor2 (Ap, Ai, (Entry *) Ax, Symbolic, Numeric, Common) ;
544 if (Common->status < KLU_OK)
547 KLU_free_numeric (&Numeric, Common) ;
549 else if (Common->status == KLU_SINGULAR)
551 if (Common->halt_if_singular)
556 KLU_free_numeric (&Numeric, Common) ;
559 else if (Common->status == KLU_OK)
562 Common->numerical_rank = n ;
563 Common->singular_col = n ;
void scale(ArrayView< Scalar1 > vals, size_t l, size_t ld, ArrayView< Scalar2 > s)
Scales a 1-D representation of a multivector.
int Ap[]
Column offsets.
Definition: klu2_simple.cpp:52
int Ai[]
Row values.
Definition: klu2_simple.cpp:54