Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_camd.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Partition/cholmod_camd =============================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Partition Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Partition Module is licensed under Version 2.1 of the GNU
8  * Lesser General Public License. See lesser.txt for a text of the license.
9  * CHOLMOD is also available under other licenses; contact authors for details.
10  * http://www.cise.ufl.edu/research/sparse
11  * -------------------------------------------------------------------------- */
12 
13 /* CHOLMOD interface to the CAMD ordering routine. Orders A if the matrix is
14  * symmetric. On output, Perm [k] = i if row/column i of A is the kth
15  * row/column of P*A*P'. This corresponds to A(p,p) in MATLAB notation.
16  *
17  * If A is unsymmetric, cholmod_camd orders A*A'. On output, Perm [k] = i if
18  * row/column i of A*A' is the kth row/column of P*A*A'*P'. This corresponds to
19  * A(p,:)*A(p,:)' in MATLAB notation. If f is present, A(p,f)*A(p,f)' is
20  * ordered.
21  *
22  * Computes the flop count for a subsequent LL' factorization, the number
23  * of nonzeros in L, and the number of nonzeros in the matrix ordered (A,
24  * A*A' or A(:,f)*A(:,f)').
25  *
26  * workspace: Iwork (4*nrow). Head (nrow).
27  *
28  * Allocates a temporary copy of A+A' or A*A' (with
29  * both upper and lower triangular parts) as input to CAMD.
30  * Also allocates 3*(n+1) additional integer workspace (not in Common).
31  *
32  * Supports any xtype (pattern, real, complex, or zomplex)
33  */
34 
35 #ifndef NPARTITION
36 
38 #include "amesos_camd.h"
40 
41 #if (CAMD_VERSION < CAMD_VERSION_CODE (2,0))
42 #error "CAMD v2.0 or later is required"
43 #endif
44 
45 /* ========================================================================== */
46 /* === cholmod_camd ========================================================= */
47 /* ========================================================================== */
48 
49 int CHOLMOD(camd)
50 (
51  /* ---- input ---- */
52  cholmod_sparse *A, /* matrix to order */
53  Int *fset, /* subset of 0:(A->ncol)-1 */
54  size_t fsize, /* size of fset */
55  Int *Cmember, /* size nrow. see cholmod_ccolamd.c for description.*/
56  /* ---- output ---- */
57  Int *Perm, /* size A->nrow, output permutation */
58  /* --------------- */
59  cholmod_common *Common
60 )
61 {
62  double Info [CAMD_INFO], Control2 [CAMD_CONTROL], *Control ;
63  Int *Cp, *Len, *Nv, *Head, *Elen, *Degree, *Wi, *Next, *BucketSet,
64  *Work3n, *p ;
65  cholmod_sparse *C ;
66  Int j, n, cnz ;
67  size_t s ;
68  int ok = TRUE ;
69 
70  /* ---------------------------------------------------------------------- */
71  /* get inputs */
72  /* ---------------------------------------------------------------------- */
73 
75  RETURN_IF_NULL (A, FALSE) ;
76  n = A->nrow ;
77 
78  /* s = 4*n */
79  s = CHOLMOD(mult_size_t) (n, 4, &ok) ;
80  if (!ok)
81  {
82  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
83  return (FALSE) ;
84  }
85 
86  RETURN_IF_NULL (Perm, FALSE) ;
88  Common->status = CHOLMOD_OK ;
89  if (n == 0)
90  {
91  /* nothing to do */
92  Common->fl = 0 ;
93  Common->lnz = 0 ;
94  Common->anz = 0 ;
95  return (TRUE) ;
96  }
97 
98  /* ---------------------------------------------------------------------- */
99  /* get workspace */
100  /* ---------------------------------------------------------------------- */
101 
102  /* cholmod_analyze has allocated Cmember at Common->Iwork + 5*n+uncol, and
103  * CParent at Common->Iwork + 4*n+uncol, where uncol is 0 if A is symmetric
104  * or A->ncol otherwise. Thus, only the first 4n integers in Common->Iwork
105  * can be used here. */
106 
107  CHOLMOD(allocate_work) (n, s, 0, Common) ;
108  if (Common->status < CHOLMOD_OK)
109  {
110  return (FALSE) ;
111  }
112 
113  p = Common->Iwork ;
114  Degree = p ; p += n ; /* size n */
115  Elen = p ; p += n ; /* size n */
116  Len = p ; p += n ; /* size n */
117  Nv = p ; p += n ; /* size n */
118 
119  Work3n = CHOLMOD(malloc) (n+1, 3*sizeof (Int), Common) ;
120  if (Common->status < CHOLMOD_OK)
121  {
122  return (FALSE) ;
123  }
124  p = Work3n ;
125  Next = p ; p += n ; /* size n */
126  Wi = p ; p += (n+1) ; /* size n+1 */
127  BucketSet = p ; /* size n */
128 
129  Head = Common->Head ; /* size n+1 */
130 
131  /* ---------------------------------------------------------------------- */
132  /* construct the input matrix for CAMD */
133  /* ---------------------------------------------------------------------- */
134 
135  if (A->stype == 0)
136  {
137  /* C = A*A' or A(:,f)*A(:,f)', add extra space of nnz(C)/2+n to C */
138  C = CHOLMOD(aat) (A, fset, fsize, -2, Common) ;
139  }
140  else
141  {
142  /* C = A+A', but use only the upper triangular part of A if A->stype = 1
143  * and only the lower part of A if A->stype = -1. Add extra space of
144  * nnz(C)/2+n to C. */
145  C = CHOLMOD(copy) (A, 0, -2, Common) ;
146  }
147 
148  if (Common->status < CHOLMOD_OK)
149  {
150  /* out of memory, fset invalid, or other error */
151  CHOLMOD(free) (n+1, 3*sizeof (Int), Work3n, Common) ;
152  return (FALSE) ;
153  }
154 
155  Cp = C->p ;
156  for (j = 0 ; j < n ; j++)
157  {
158  Len [j] = Cp [j+1] - Cp [j] ;
159  }
160 
161  /* C does not include the diagonal, and both upper and lower parts.
162  * Common->anz includes the diagonal, and just the lower part of C */
163  cnz = Cp [n] ;
164  Common->anz = cnz / 2 + n ;
165 
166  /* ---------------------------------------------------------------------- */
167  /* order C using CAMD */
168  /* ---------------------------------------------------------------------- */
169 
170  /* get parameters */
171  if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS)
172  {
173  /* use CAMD defaults */
174  Control = NULL ;
175  }
176  else
177  {
178  Control = Control2 ;
179  Control [CAMD_DENSE] = Common->method [Common->current].prune_dense ;
180  Control [CAMD_AGGRESSIVE] = Common->method [Common->current].aggressive;
181  }
182 
183  /* CAMD_2 does not use camd_malloc and camd_free, but set these pointers
184  * just be safe. */
185  amesos_camd_malloc = Common->malloc_memory ;
186  amesos_camd_free = Common->free_memory ;
187  amesos_camd_calloc = Common->calloc_memory ;
188  amesos_camd_realloc = Common->realloc_memory ;
189 
190  /* CAMD_2 doesn't print anything either, but future versions might,
191  * so set the camd_printf pointer too. */
192  amesos_camd_printf = Common->print_function ;
193 
194 #ifdef LONG
195  /* DEBUG (camd_l_debug_init ("cholmod_l_camd")) ; */
196  amesos_camd_l2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen,
197  Degree, Wi, Control, Info, Cmember, BucketSet) ;
198 #else
199  /* DEBUG (camd_debug_init ("cholmod_camd")) ; */
200  amesos_camd_2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen,
201  Degree, Wi, Control, Info, Cmember, BucketSet) ;
202 #endif
203 
204  /* LL' flop count. Need to subtract n for LL' flop count. Note that this
205  * is a slight upper bound which is often exact (see CAMD/Source/camd_2.c
206  * for details). cholmod_analyze computes an exact flop count and
207  * fill-in. */
208  Common->fl = Info [CAMD_NDIV] + 2 * Info [CAMD_NMULTSUBS_LDL] + n ;
209 
210  /* Info [CAMD_LNZ] excludes the diagonal */
211  Common->lnz = n + Info [CAMD_LNZ] ;
212 
213  /* ---------------------------------------------------------------------- */
214  /* free the CAMD workspace and clear the persistent workspace in Common */
215  /* ---------------------------------------------------------------------- */
216 
217  ASSERT (IMPLIES (Common->status == CHOLMOD_OK,
218  CHOLMOD(dump_perm) (Perm, n, n, "CAMD2 perm", Common))) ;
219  CHOLMOD(free_sparse) (&C, Common) ;
220  for (j = 0 ; j <= n ; j++)
221  {
222  Head [j] = EMPTY ;
223  }
224  CHOLMOD(free) (n+1, 3*sizeof (Int), Work3n, Common) ;
225  return (TRUE) ;
226 }
227 #endif
#define CAMD_INFO
Definition: amesos_camd.h:352
#define CHOLMOD_TOO_LARGE
#define CAMD_DENSE
Definition: amesos_camd.h:355
int CHOLMOD() camd(cholmod_sparse *A, Int *fset, size_t fsize, Int *Cmember, Int *Perm, cholmod_common *Common)
#define EMPTY
EXTERN void *(* amesos_camd_realloc)(void *, size_t)
Definition: amesos_camd.h:331
#define Int
#define CAMD_AGGRESSIVE
Definition: amesos_camd.h:356
#define CAMD_LNZ
Definition: amesos_camd.h:372
#define FALSE
#define RETURN_IF_NULL_COMMON(result)
size_t CHOLMOD() mult_size_t(size_t a, size_t k, int *ok)
#define CAMD_NMULTSUBS_LDL
Definition: amesos_camd.h:374
EXTERN int(* amesos_camd_printf)(const char *,...)
Definition: amesos_camd.h:333
cholmod_sparse *CHOLMOD() aat(cholmod_sparse *A, Int *fset, size_t fsize, int mode, cholmod_common *Common)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define NULL
#define ASSERT(expression)
void amesos_camd_2(int n, int Pe[], int Iw[], int Len[], int iwlen, int pfree, int Nv[], int Next[], int Last[], int Head[], int Elen[], int Degree[], int W[], double Control[], double Info[], const int C[], int BucketSet[])
#define CAMD_NDIV
Definition: amesos_camd.h:373
EXTERN void *(* amesos_camd_calloc)(size_t, size_t)
Definition: amesos_camd.h:332
int CHOLMOD() dump_perm(Int *Perm, size_t len, size_t n, char *name, cholmod_common *Common)
#define CHOLMOD_OK
#define CAMD_CONTROL
Definition: amesos_camd.h:351
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define CHOLMOD_MAXMETHODS
EXTERN void *(* amesos_camd_malloc)(size_t)
Definition: amesos_camd.h:329
#define RETURN_IF_NULL(A, result)
#define IMPLIES(p, q)
int n
#define ERROR(status, msg)
#define TRUE
EXTERN void(* amesos_camd_free)(void *)
Definition: amesos_camd.h:330
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX
void amesos_camd_l2(UF_long n, UF_long Pe[], UF_long Iw[], UF_long Len[], UF_long iwlen, UF_long pfree, UF_long Nv[], UF_long Next[], UF_long Last[], UF_long Head[], UF_long Elen[], UF_long Degree[], UF_long W[], double Control[], double Info[], const UF_long C[], UF_long BucketSet[])
cholmod_sparse *CHOLMOD() copy(cholmod_sparse *A, int stype, int mode, cholmod_common *Common)