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