1 /*  mkNDlinsys.c  */
2 
3 #include "../../FrontMtx.h"
4 #include "../../Drand.h"
5 #include "../../SymbFac.h"
6 #include "../../timings.h"
7 #include "../../misc.h"
8 
9 /*--------------------------------------------------------------------*/
10 /*
11    ---------------------------------------------------------------------
12    purpose -- to create a linear system A*X = B
13       for a nested dissection ordering of a 2-d or 3-d regular grid
14    input --
15 
16       n1 -- # of nodes in first direction
17       n2 -- # of nodes in second direction
18       n3 -- # of nodes in third direction
19       maxzeros -- relaxation factor for fronts,
20          maximum number of zero entries in a front
21       maxsize  -- split parameter for large fronts,
22          maximum number of internal vertices in a front
23       type -- type of entries
24          SPOOLES_REAL or SPOOLES_COMPLEX
25       symmetryflag -- symmetry of the matrix
26          SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC
27       nrhs    -- number of right hand sides
28       seed    -- seed for random number generator
29       msglvl  -- message level
30       msgFile -- message file
31 
32    output --
33 
34       pfrontETree -- to be filled with address of front tree
35       psymbfacIVL -- to be filled with address of symbolic factorization
36       pmtxA       -- to be filled with address of matrix object A
37       pmtxX       -- to be filled with address of matrix object X
38       pmtxB       -- to be filled with address of matrix object B
39 
40    created -- 98may16, cca
41    ---------------------------------------------------------------------
42 */
43 void
mkNDlinsys(int n1,int n2,int n3,int maxzeros,int maxsize,int type,int symmetryflag,int nrhs,int seed,int msglvl,FILE * msgFile,ETree ** pfrontETree,IVL ** psymbfacIVL,InpMtx ** pmtxA,DenseMtx ** pmtxX,DenseMtx ** pmtxB)44 mkNDlinsys (
45    int        n1,
46    int        n2,
47    int        n3,
48    int        maxzeros,
49    int        maxsize,
50    int        type,
51    int        symmetryflag,
52    int        nrhs,
53    int        seed,
54    int        msglvl,
55    FILE       *msgFile,
56    ETree      **pfrontETree,
57    IVL        **psymbfacIVL,
58    InpMtx     **pmtxA,
59    DenseMtx   **pmtxX,
60    DenseMtx   **pmtxB
61 ) {
62 DenseMtx   *mtxB, *mtxX ;
63 InpMtx     *mtxA ;
64 double     one[2] = {1.0, 0.0} ;
65 double     *dvec ;
66 Drand      drand ;
67 double     t1, t2 ;
68 ETree      *etree, *etree2, *frontETree ;
69 Graph      *graph ;
70 int        ient, ii, nent, neqns, nrow, v, vsize, w ;
71 int        *ivec1, *ivec2, *newToOld, *oldToNew, *rowind, *vadj ;
72 IV         *nzerosIV, *oldToNewIV ;
73 IVL        *adjIVL, *symbfacIVL ;
74 
75 /*
76    --------------------------------------
77    initialize the random number generator
78    --------------------------------------
79 */
80 Drand_setDefaultFields(&drand) ;
81 Drand_init(&drand) ;
82 Drand_setSeed(&drand, seed) ;
83 Drand_setUniform(&drand, -1.0, 1.0) ;
84 /*
85    --------------------------------
86    get the grid adjacency structure
87    --------------------------------
88 */
89 neqns = n1 * n2 * n3 ;
90 MARKTIME(t1) ;
91 if ( n1 == 1 ) {
92    adjIVL = IVL_make9P(n2, n3, 1) ;
93 } else if ( n2 == 1 ) {
94    adjIVL = IVL_make9P(n1, n3, 1) ;
95 } else if ( n3 == 1 ) {
96    adjIVL = IVL_make9P(n1, n2, 1) ;
97 } else {
98    adjIVL = IVL_make27P(n1, n2, n3, 1) ;
99 }
100 graph = Graph_new() ;
101 Graph_init2(graph, 0, neqns, 0, adjIVL->tsize, neqns,
102             adjIVL->tsize, adjIVL, NULL, NULL) ;
103 MARKTIME(t2) ;
104 fprintf(msgFile, "\n CPU %8.3f : create the grid graph",
105         t2 - t1) ;
106 if ( msglvl > 3 ) {
107    fprintf(msgFile, "\n\n grid graph") ;
108    Graph_writeForHumanEye(graph, msgFile) ;
109 }
110 /*
111    ---------------------------------------------
112    make the nested dissection permutation vector
113    ---------------------------------------------
114 */
115 MARKTIME(t1) ;
116 newToOld = IVinit(neqns, -1) ;
117 oldToNew = IVinit(neqns, -1) ;
118 mkNDperm(n1, n2, n3, newToOld, 0, n1-1, 0, n2-1, 0, n3-1) ;
119 for ( ii = 0 ; ii < neqns ; ii++ ) {
120    oldToNew[newToOld[ii]] = ii ;
121 }
122 MARKTIME(t2) ;
123 fprintf(msgFile, "\n CPU %8.3f : make the nested dissection ordering",
124         t2 - t1) ;
125 if ( msglvl > 3 ) {
126    fprintf(msgFile, "\n\n oldToNew") ;
127    IVfprintf(msgFile, neqns, oldToNew) ;
128 }
129 /*
130    ----------------------------------
131    create the elimination tree object
132    ----------------------------------
133 */
134 MARKTIME(t1) ;
135 etree = ETree_new() ;
136 ETree_initFromGraphWithPerms(etree, graph, newToOld, oldToNew) ;
137 IVfree(newToOld) ;
138 IVfree(oldToNew) ;
139 nzerosIV = IV_new() ;
140 IV_init(nzerosIV, neqns, NULL) ;
141 IV_fill(nzerosIV, 0) ;
142 etree2 = ETree_mergeFrontsOne(etree, 0, nzerosIV) ;
143 ETree_free(etree) ;
144 etree = etree2 ;
145 if ( msglvl > 3 ) {
146    fprintf(msgFile, "\n\n elimination tree") ;
147    ETree_writeForHumanEye(etree, msgFile) ;
148 }
149 etree2 = ETree_mergeFrontsOne(etree, maxzeros, nzerosIV) ;
150 ETree_free(etree) ;
151 etree = etree2 ;
152 etree2 = ETree_mergeFrontsAll(etree, maxzeros, nzerosIV) ;
153 IV_free(nzerosIV) ;
154 ETree_free(etree) ;
155 etree = etree2 ;
156 frontETree = ETree_splitFronts(etree, NULL, maxsize, 0) ;
157 ETree_free(etree) ;
158 if ( msglvl > 3 ) {
159    fprintf(msgFile, "\n\n front tree") ;
160    ETree_writeForHumanEye(frontETree, msgFile) ;
161 }
162 MARKTIME(t2) ;
163 fprintf(msgFile, "\n CPU %8.3f : create the front tree",
164         t2 - t1) ;
165 /*
166    --------------------------------------
167    permute the vertices in the front tree
168    --------------------------------------
169 */
170 MARKTIME(t1) ;
171 oldToNewIV = ETree_oldToNewVtxPerm(frontETree) ;
172 oldToNew   = IV_entries(oldToNewIV) ;
173 ETree_permuteVertices(frontETree, oldToNewIV) ;
174 MARKTIME(t2) ;
175 fprintf(msgFile, "\n CPU %8.3f : permute the front tree",
176         t2 - t1) ;
177 /*
178    ------------------------
179    set up the InpMtx object
180    ------------------------
181 */
182 MARKTIME(t1) ;
183 mtxA = InpMtx_new() ;
184 switch ( symmetryflag ) {
185 case SPOOLES_SYMMETRIC    :
186 case SPOOLES_HERMITIAN    :
187    nent = (adjIVL->tsize - neqns)/2 + neqns ;
188    break ;
189 case SPOOLES_NONSYMMETRIC :
190    nent = adjIVL->tsize ;
191    break ;
192 default :
193    fprintf(stderr, "\n fatal error in mkNDlinsys()"
194            "\n invalid symmetryflag %d\n", symmetryflag) ;
195    exit(-1) ;
196    break ;
197 }
198 if ( msglvl > 2 ) {
199    fprintf(msgFile, "\n neqns = %d, nent = %d", neqns, nent) ;
200 }
201 InpMtx_init(mtxA, INPMTX_BY_ROWS, type, nent, 0) ;
202 ivec1 = InpMtx_ivec1(mtxA) ;
203 ivec2 = InpMtx_ivec2(mtxA) ;
204 dvec  = InpMtx_dvec(mtxA) ;
205 if ( type == SPOOLES_REAL ) {
206    Drand_fillDvector(&drand, nent, dvec) ;
207 } else if ( type == SPOOLES_COMPLEX ) {
208    Drand_fillDvector(&drand, 2*nent, dvec) ;
209 }
210 switch ( symmetryflag ) {
211 case SPOOLES_SYMMETRIC :
212    for ( v = 0, ient = 0 ; v < neqns ; v++ ) {
213       IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
214       for ( ii = 0 ; ii < vsize ; ii++ ) {
215          if ( vadj[ii] >= v ) {
216             ivec1[ient] = v ;
217             ivec2[ient] = vadj[ii] ;
218             ient++ ;
219          }
220       }
221    }
222 /*
223    -----------------------------
224    code for a laplacian operator
225    -----------------------------
226 */
227 /*
228    if ( n1 == 1 || n2 == 1 || n3 == 1 ) {
229       for ( ii = 0 ; ii < ient ; ii++ ) {
230          if ( ivec1[ii] == ivec2[ii] ) {
231             dvec[ii] = 8.0 ;
232          } else {
233             dvec[ii] = -1.0 ;
234          }
235       }
236    } else {
237       for ( ii = 0 ; ii < ient ; ii++ ) {
238          if ( ivec1[ii] == ivec2[ii] ) {
239             dvec[ii] = 27.0 ;
240          } else {
241             dvec[ii] = -1.0 ;
242          }
243       }
244    }
245 */
246    break ;
247 case SPOOLES_HERMITIAN :
248    for ( v = 0, ient = 0 ; v < neqns ; v++ ) {
249       IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
250       for ( ii = 0 ; ii < vsize ; ii++ ) {
251          if ( (w = vadj[ii]) == v ) {
252             ivec1[ient] = v ;
253             ivec2[ient] = w ;
254             dvec[2*ient+1] = 0.0 ;
255             ient++ ;
256          } else if ( w > v ) {
257             ivec1[ient] = v ;
258             ivec2[ient] = w ;
259             ient++ ;
260          }
261       }
262    }
263    break ;
264 case SPOOLES_NONSYMMETRIC :
265    for ( v = 0, ient = 0 ; v < neqns ; v++ ) {
266       IVL_listAndSize(adjIVL, v, &vsize, &vadj) ;
267       for ( ii = 0 ; ii < vsize ; ii++, ient++ ) {
268          ivec1[ient] = v ;
269          ivec2[ient] = vadj[ii] ;
270       }
271    }
272    break ;
273 }
274 InpMtx_setNent(mtxA, nent) ;
275 if ( msglvl > 2 ) {
276    fprintf(msgFile, "\n\n raw matrix object") ;
277    InpMtx_writeForHumanEye(mtxA, msgFile) ;
278 }
279 InpMtx_sortAndCompress(mtxA) ;
280 if ( msglvl > 2 ) {
281    fprintf(msgFile, "\n\n original mtxA") ;
282    InpMtx_writeForHumanEye(mtxA, msgFile) ;
283    fflush(msgFile) ;
284 }
285 MARKTIME(t2) ;
286 fprintf(msgFile, "\n CPU %8.3f : set up the InpMtxA object",
287         t2 - t1) ;
288 if ( msglvl > 3 ) {
289    fprintf(msgFile, "\n %% start MATLAB FILE") ;
290    InpMtx_writeForMatlab(mtxA, "A", msgFile) ;
291    if (  symmetryflag == SPOOLES_SYMMETRIC ) {
292       fprintf(msgFile,
293               "\n neqns = %d ; "
294               "\n for ii = 1:neqns "
295               "\n    for j = ii+1:neqns "
296               "\n       A(j,ii) = A(ii,j) ;"
297               "\n    end"
298               "\n end", neqns) ;
299    } else if ( symmetryflag == SPOOLES_HERMITIAN ) {
300       fprintf(msgFile,
301               "\n neqns = %d ; "
302               "\n for ii = 1:neqns "
303               "\n    for j = i+1:neqns "
304               "\n       A(j,ii) = ctranspose(A(ii,j)) ;"
305               "\n    end"
306               "\n end", neqns) ;
307    }
308    fflush(msgFile) ;
309    fprintf(msgFile, "\n %% end MATLAB FILE") ;
310 }
311 /*
312    --------------------------------------------------------
313    generate the linear system
314    1. generate solution matrix and fill with random numbers
315    2. generate rhs matrix and fill with zeros
316    3. compute matrix-matrix multiply
317    --------------------------------------------------------
318 */
319 MARKTIME(t1) ;
320 mtxX = DenseMtx_new() ;
321 DenseMtx_init(mtxX, type, 0, -1, neqns, nrhs, 1, neqns) ;
322 DenseMtx_fillRandomEntries(mtxX, &drand) ;
323 mtxB = DenseMtx_new() ;
324 DenseMtx_init(mtxB, type, 1, -1, neqns, nrhs, 1, neqns) ;
325 DenseMtx_zero(mtxB) ;
326 switch ( symmetryflag ) {
327 case SPOOLES_SYMMETRIC :
328    InpMtx_sym_mmm(mtxA, mtxB, one, mtxX) ;
329    break ;
330 case SPOOLES_HERMITIAN :
331    InpMtx_herm_mmm(mtxA, mtxB, one, mtxX) ;
332    break ;
333 case SPOOLES_NONSYMMETRIC :
334    InpMtx_nonsym_mmm(mtxA, mtxB, one, mtxX) ;
335    break ;
336 default :
337    break ;
338 }
339 MARKTIME(t2) ;
340 fprintf(msgFile, "\n CPU %8.3f : set up the solution and rhs ",
341         t2 - t1) ;
342 if ( msglvl > 2 ) {
343    fprintf(msgFile, "\n\n original mtxX") ;
344    DenseMtx_writeForHumanEye(mtxX, msgFile) ;
345    fprintf(msgFile, "\n\n original mtxB") ;
346    DenseMtx_writeForHumanEye(mtxB, msgFile) ;
347    fflush(msgFile) ;
348 }
349 if ( msglvl > 3 ) {
350    fprintf(msgFile, "\n %% start MATLAB FILE") ;
351    DenseMtx_writeForMatlab(mtxX, "X", msgFile) ;
352    DenseMtx_writeForMatlab(mtxB, "B", msgFile) ;
353    fprintf(msgFile, "\n %% end MATLAB FILE") ;
354    fflush(msgFile) ;
355 }
356 /*
357    ------------------------------------------------------
358    permute the matrix into the nested dissection ordering
359    ------------------------------------------------------
360 */
361 MARKTIME(t1) ;
362 InpMtx_permute(mtxA, oldToNew, oldToNew) ;
363 /*
364    ------------------------------------------------
365    map entries into the upper triangle if necessary
366    ------------------------------------------------
367 */
368 switch ( symmetryflag ) {
369 case SPOOLES_SYMMETRIC :
370    InpMtx_mapToUpperTriangle(mtxA) ;
371    break ;
372 case SPOOLES_HERMITIAN :
373    InpMtx_mapToUpperTriangleH(mtxA) ;
374    break ;
375 case SPOOLES_NONSYMMETRIC :
376    break ;
377 default :
378    break ;
379 }
380 InpMtx_changeCoordType(mtxA, INPMTX_BY_CHEVRONS) ;
381 InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS) ;
382 MARKTIME(t2) ;
383 fprintf(msgFile, "\n CPU %8.3f : permute the matrix", t2 - t1) ;
384 if ( msglvl > 2 ) {
385    fprintf(msgFile, "\n\n permuted mtxA") ;
386    InpMtx_writeForHumanEye(mtxA, msgFile) ;
387    fflush(msgFile) ;
388 }
389 if ( msglvl > 3 ) {
390    fprintf(msgFile, "\n %% start MATLAB FILE") ;
391    InpMtx_writeForMatlab(mtxA, "Anew", msgFile) ;
392    if (  symmetryflag == SPOOLES_SYMMETRIC ) {
393       fprintf(msgFile,
394               "\n neqns = %d ; "
395               "\n for ii = 1:neqns "
396               "\n    for j = ii+1:neqns "
397               "\n       Anew(j,ii) = Anew(ii,j) ;"
398               "\n    end"
399               "\n end", neqns) ;
400    } else if ( symmetryflag == SPOOLES_HERMITIAN ) {
401       fprintf(msgFile,
402               "\n neqns = %d ; "
403               "\n for ii = 1:neqns "
404               "\n    for j = ii+1:neqns "
405               "\n       Anew(j,ii) = ctranspose(Anew(ii,j)) ;"
406               "\n    end"
407               "\n end", neqns) ;
408    }
409    fprintf(msgFile, "\n %% end MATLAB FILE") ;
410 }
411 /*
412    ----------------------------------------
413    permute the solution and right hand side
414    ----------------------------------------
415 */
416 MARKTIME(t1) ;
417 DenseMtx_rowIndices(mtxX, &nrow, &rowind) ;
418 IVcopy(nrow, rowind, oldToNew) ;
419 DenseMtx_sort(mtxX) ;
420 DenseMtx_rowIndices(mtxB, &nrow, &rowind) ;
421 IVcopy(nrow, rowind, oldToNew) ;
422 DenseMtx_sort(mtxB) ;
423 MARKTIME(t2) ;
424 fprintf(msgFile, "\n CPU %8.3f : permute the solution and rhs",
425         t2 - t1) ;
426 if ( msglvl > 2 ) {
427    fprintf(msgFile, "\n\n permuted mtxX") ;
428    DenseMtx_writeForHumanEye(mtxX, msgFile) ;
429    fprintf(msgFile, "\n\n permuted mtxB") ;
430    DenseMtx_writeForHumanEye(mtxB, msgFile) ;
431    fflush(msgFile) ;
432 }
433 if ( msglvl > 3 ) {
434    fprintf(msgFile, "\n %% start MATLAB FILE") ;
435    DenseMtx_writeForMatlab(mtxX, "Xnew", msgFile) ;
436    DenseMtx_writeForMatlab(mtxB, "Bnew", msgFile) ;
437    fprintf(msgFile, "\n %% end MATLAB FILE") ;
438 }
439 /*
440    --------------------------------------------
441    create the symbolic factorization IVL object
442    --------------------------------------------
443 */
444 MARKTIME(t1) ;
445 symbfacIVL = SymbFac_initFromInpMtx(frontETree, mtxA) ;
446 MARKTIME(t2) ;
447 fprintf(msgFile, "\n CPU %8.3f : compute the symbolic factorization",
448         t2 - t1) ;
449 if ( msglvl > 1 ) {
450    fprintf(msgFile, "\n\n symbolic factorization IVL object") ;
451    if ( msglvl == 2 ) {
452       IVL_writeStats(symbfacIVL, msgFile) ;
453    } else {
454       IVL_writeForHumanEye(symbfacIVL, msgFile) ;
455    }
456    fflush(msgFile) ;
457 }
458 /*
459    --------------------------------------
460    convert the matrix storage to chevrons
461    --------------------------------------
462 */
463 MARKTIME(t1) ;
464 InpMtx_changeCoordType(mtxA, INPMTX_BY_CHEVRONS) ;
465 MARKTIME(t2) ;
466 fprintf(msgFile, "\n CPU %8.3f : convert to chevron vectors ",
467         t2 - t1) ;
468 if ( msglvl > 1 ) {
469    fprintf(msgFile, "\n\n InpMtx object ") ;
470    if ( msglvl == 2 ) {
471       InpMtx_writeStats(mtxA, msgFile) ;
472    } else if ( msglvl > 3 ) {
473       InpMtx_writeForHumanEye(mtxA, msgFile) ;
474    }
475 }
476 /*
477    -----------------------
478    set the output pointers
479    -----------------------
480 */
481 *pfrontETree = frontETree ;
482 *psymbfacIVL = symbfacIVL ;
483 *pmtxA       = mtxA       ;
484 *pmtxX       = mtxX       ;
485 *pmtxB       = mtxB       ;
486 /*
487    ------------------------
488    free the working storage
489    ------------------------
490 */
491 Graph_free(graph) ;
492 IV_free(oldToNewIV) ;
493 
494 return ; }
495 
496 /*--------------------------------------------------------------------*/
497