2 * KLU: a sparse LU factorization algorithm.
3 * Copyright (C) 2004-2009, Timothy A. Davis.
4 * Copyright (C) 2011, Richard W. Lincoln.
5 * http://www.cise.ufl.edu/research/sparse/klu
7 * -------------------------------------------------------------------------
9 * KLU is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * KLU is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this Module; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 package edu
.ufl
.cise
.klu
.tdouble
;
27 import edu
.ufl
.cise
.klu
.common
.KLU_common
;
28 import edu
.ufl
.cise
.klu
.common
.KLU_symbolic
;
31 * Given an input permutation P and Q, create the Symbolic object. BTF can
32 * be done to modify the user's P and Q (does not perform the max transversal;
33 * just finds the strongly-connected components).
35 public class Dklu_analyze_given
extends Dklu_internal
39 * Allocate Symbolic object, and check input matrix. Not user callable.
47 protected static KLU_symbolic
klu_alloc_symbolic(int n
, int[] Ap
, int[] Ai
,
50 KLU_symbolic Symbolic
;
53 int nz
, i
, j
, p
, pend
;
59 Common
.status
= KLU_common
.KLU_OK
;
61 /* A is n-by-n, with n > 0. Ap [0] = 0 and nz = Ap [n] >= 0 required.
62 * Ap [j] <= Ap [j+1] must hold for all j = 0 to n-1. Row indices in Ai
63 * must be in the range 0 to n-1, and no duplicate entries can be present.
64 * The list of row indices in each column of A need not be sorted.
67 if (n
<= 0 || Ap
== null || Ai
== null)
69 /* Ap and Ai must be present, and n must be > 0 */
70 Common
.status
= KLU_common
.KLU_INVALID
;
75 if (Ap
[0] != 0 || nz
< 0)
77 /* nz must be >= 0 and Ap [0] must equal zero */
78 Common
.status
= KLU_common
.KLU_INVALID
;
82 for (j
= 0 ; j
< n
; j
++)
84 if (Ap
[j
] > Ap
[j
+1])
86 /* column pointers must be non-decreasing */
87 Common
.status
= KLU_common
.KLU_INVALID
;
91 P
= Dklu_memory
.klu_malloc (n
, sizeof (Int
), Common
) ;
92 if (Common
.status
< KLU_common
.KLU_OK
)
95 Common
.status
= KLU_common
.KLU_OUT_OF_MEMORY
;
98 for (i
= 0 ; i
< n
; i
++)
102 for (j
= 0 ; j
< n
; j
++)
105 for (p
= Ap
[j
] ; p
< pend
; p
++)
108 if (i
< 0 || i
>= n
|| P
[i
] == j
)
110 /* row index out of range, or duplicate entry */
111 Dklu_memory
.klu_free (P
, n
, sizeof (Int
), Common
) ;
112 Common
.status
= KLU_common
.KLU_INVALID
;
115 /* flag row i as appearing in column j */
120 /* ---------------------------------------------------------------------- */
121 /* allocate the Symbolic object */
122 /* ---------------------------------------------------------------------- */
124 Symbolic
= Dklu_memory
.klu_malloc (sizeof (KLU_symbolic
), 1, Common
) ;
125 if (Common
.status
< KLU_common
.KLU_OK
)
128 Dklu_memory
.klu_free (P
, n
, sizeof (Int
), Common
) ;
129 Common
.status
= KLU_common
.KLU_OUT_OF_MEMORY
;
133 Q
= Dklu_memory
.klu_malloc (n
, sizeof (Int
), Common
) ;
134 R
= Dklu_memory
.klu_malloc (n
+1, sizeof (Int
), Common
) ;
135 Lnz
= Dklu_memory
.klu_malloc (n
, sizeof (double), Common
) ;
144 if (Common
.status
< KLU_common
.KLU_OK
)
147 Dklu_free_symbolic
.klu_free_symbolic (Symbolic
, Common
) ;
148 Common
.status
= KLU_common
.KLU_OUT_OF_MEMORY
;
157 * @param n A is n-by-n
158 * @param Ap size n+1, column pointers
159 * @param Ai size nz, row indices
160 * @param Puser size n, user's row permutation (may be null)
161 * @param Quser size n, user's column permutation (may be null)
165 public static KLU_symbolic
klu_analyze_given(int n
, int[] Ap
, int[] Ai
,
166 int[] Puser
, int[] Quser
, KLU_common Common
)
168 KLU_symbolic Symbolic
;
170 int nblocks
, nz
, block
, maxblock
, nzoff
, p
, pend
, do_btf
, k
;
173 /* ---------------------------------------------------------------------- */
174 /* determine if input matrix is valid, and get # of nonzeros */
175 /* ---------------------------------------------------------------------- */
177 Symbolic
= Dklu_alloc_symbolic
.klu_alloc_symbolic (n
, Ap
, Ai
, Common
) ;
178 if (Symbolic
== null)
188 /* ---------------------------------------------------------------------- */
189 /* Q = Quser, or identity if Quser is null */
190 /* ---------------------------------------------------------------------- */
194 for (k
= 0 ; k
< n
; k
++)
201 for (k
= 0 ; k
< n
; k
++)
207 /* ---------------------------------------------------------------------- */
208 /* get the control parameters for BTF and ordering method */
209 /* ---------------------------------------------------------------------- */
211 do_btf
= Common
.btf
;
212 do_btf
= (do_btf
) ? TRUE
: FALSE
;
213 Symbolic
.ordering
= 2 ;
214 Symbolic
.do_btf
= do_btf
;
216 /* ---------------------------------------------------------------------- */
217 /* find the block triangular form, if requested */
218 /* ---------------------------------------------------------------------- */
223 /* ------------------------------------------------------------------ */
224 /* get workspace for BTF_strongcomp */
225 /* ------------------------------------------------------------------ */
227 int[] Pinv
, Work
, Bi
;
228 int k1
, k2
, nk
, oldcol
;
230 Work
= Dklu_memory
.klu_malloc (4*n
, sizeof (Int
), Common
) ;
231 Pinv
= Dklu_memory
.klu_malloc (n
, sizeof (Int
), Common
) ;
234 Bi
= Dklu_memory
.klu_malloc (nz
+1, sizeof (Int
), Common
) ;
241 if (Common
.status
< KLU_common
.KLU_OK
)
244 Dklu_memory
.klu_free (Work
, 4*n
, sizeof (Int
), Common
) ;
245 Dklu_memory
.klu_free (Pinv
, n
, sizeof (Int
), Common
) ;
248 Dklu_memory
.klu_free (Bi
, nz
+1, sizeof (Int
), Common
) ;
250 Dklu_free_symbolic
.klu_free_symbolic (Symbolic
, Common
) ;
251 Common
.status
= KLU_common
.KLU_OUT_OF_MEMORY
;
255 /* ------------------------------------------------------------------ */
257 /* ------------------------------------------------------------------ */
261 for (k
= 0 ; k
< n
; k
++)
263 Pinv
[Puser
[k
]] = k
;
265 for (p
= 0 ; p
< nz
; p
++)
267 Bi
[p
] = Pinv
[Ai
[p
]] ;
271 /* ------------------------------------------------------------------ */
272 /* find the strongly-connected components */
273 /* ------------------------------------------------------------------ */
275 /* modifies Q, and determines P and R */
276 nblocks
= Dbtf_strongcomp
.btf_strongcomp (n
, Ap
, Bi
, Q
, P
, R
, Work
) ;
278 /* ------------------------------------------------------------------ */
280 /* ------------------------------------------------------------------ */
284 for (k
= 0 ; k
< n
; k
++)
286 Work
[k
] = Puser
[P
[k
]] ;
288 for (k
= 0 ; k
< n
; k
++)
294 /* ------------------------------------------------------------------ */
295 /* Pinv = inverse of P */
296 /* ------------------------------------------------------------------ */
298 for (k
= 0 ; k
< n
; k
++)
303 /* ------------------------------------------------------------------ */
304 /* analyze each block */
305 /* ------------------------------------------------------------------ */
307 nzoff
= 0 ; /* nz in off-diagonal part */
308 maxblock
= 1 ; /* size of the largest block */
310 for (block
= 0 ; block
< nblocks
; block
++)
313 /* -------------------------------------------------------------- */
314 /* the block is from rows/columns k1 to k2-1 */
315 /* -------------------------------------------------------------- */
320 PRINTF (("BLOCK %d, k1 %d k2-1 %d nk %d\n", block
, k1
, k2
-1, nk
)) ;
321 maxblock
= MAX (maxblock
, nk
) ;
323 /* -------------------------------------------------------------- */
324 /* scan the kth block, C */
325 /* -------------------------------------------------------------- */
327 for (k
= k1
; k
< k2
; k
++)
330 pend
= Ap
[oldcol
+1] ;
331 for (p
= Ap
[oldcol
] ; p
< pend
; p
++)
333 if (Pinv
[Ai
[p
]] < k1
)
340 /* fill-in not estimated */
341 Lnz
[block
] = EMPTY
;
344 /* ------------------------------------------------------------------ */
345 /* free all workspace */
346 /* ------------------------------------------------------------------ */
348 Dklu_memory
.klu_free (Work
, 4*n
, sizeof (Int
), Common
) ;
349 Dklu_memory
.klu_free (Pinv
, n
, sizeof (Int
), Common
) ;
352 Dklu_memory
.klu_free (Bi
, nz
+1, sizeof (Int
), Common
) ;
359 /* ------------------------------------------------------------------ */
360 /* BTF not requested */
361 /* ------------------------------------------------------------------ */
370 /* ------------------------------------------------------------------ */
371 /* P = Puser, or identity if Puser is null */
372 /* ------------------------------------------------------------------ */
374 for (k
= 0 ; k
< n
; k
++)
376 P
[k
] = (Puser
== null) ? k
: Puser
[k
] ;
380 /* ---------------------------------------------------------------------- */
381 /* return the symbolic object */
382 /* ---------------------------------------------------------------------- */
384 Symbolic
.nblocks
= nblocks
;
385 Symbolic
.maxblock
= maxblock
;
386 Symbolic
.lnz
= EMPTY
;
387 Symbolic
.unz
= EMPTY
;
388 Symbolic
.nzoff
= nzoff
;