Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BS95.c
Go to the documentation of this file.
1 /*
2 // serialBS95.c
3 //
4 // Functions to be called by FORTRAN that will solve sparse
5 // linear systems of equations using BlockSolve95.
6 //
7 //
8 // NOTE: FLOAT is defined as double, not float
9 //
10 //
11 // TO RUN FOLLOW THESE STEPS:
12 // 1 - Set up the problem
13 // 2 - Run BS95SETUP
14 // 3 - Run BS95SOLVE
15 // 4 - Repeat step 4 as needed if system needs to be solved with different rhs vectors
16 // 5 - Run BS95FREE
17 // 6 - Repeat steps 1-5 if system needs to be solved with different A matrices
18 // 7 - Run BS95FINALIZE to finalize MPI communications
19 //
20 */
21 
22 
23 /*
24 // Include standard and BlockSolve95 headers
25 */
26 #include <stdlib.h>
27 #include <stdio.h>
28 
29 #include <BSprivate.h>
30 
31 //#include "mpi.h"
32 extern MPI_Comm GetCommunicator();
33 /*
34 // Global variables
35 */
36 BSprocinfo *procinfo;
37 BSspmat *bA;
38 BSpar_mat *pA, *f_pA;
39 BScomm *Acomm, *fcomm;
40 int maxiter = 10000;
41 
42 
43 
44 
45 /*
46 // Utility functions
47 */
48 
49 
50 
51 /*
52  * NAME
53  * ctranspose
54  *
55  * FUNCTION
56  * Transposes a matrix from FORTRAN style
57  * to C style.
58  *
59  * INPUTS
60  * n -- size of one dimension of the matrix
61  * d -- the square matrix to be transposed
62  *
63  * OUTPUTS
64  * d[n][n] -- the transposed square matrix
65  *
66  * USES
67  * none
68  *
69  */
70 
71 void ctranspose(int n,double d[n][n]) {
72  double tempdmat[n][n];
73  int i;
74  int j;
75  for(i=0;i<n;i++) {
76  for(j=0;j<n;j++) {
77  tempdmat[i][j] = d[j][i];
78  }
79  }
80  for(i=0;i<n;i++) {
81  for(j=0;j<n;j++) {
82  d[i][j] = tempdmat[i][j];
83  }
84  }
85 }
86 
87 
88 
89 
90 /*
91 // Functions to be called by Fortran
92 */
93 
94 
95 
96 
97 
98 /*
99  * NAME
100  * bs95setup
101  *
102  * FUNCTION
103  * Sets up everything needed to solve a system of
104  * linear equations in parallel using BlockSolve95.
105  *
106  * INPUTS
107  * *ndim -- dimension of the A matrix were it to be explicitly formed
108  * *nnz -- number of non-zeros in the A matrix
109  * *nstart -- first row that is assigned to this processor
110  * *nrows -- number of rows assigned to this processor
111  * rp -- mapping of positions in cval vector to rows (see BS95 manual for details)
112  * cval -- mapping of values in aval to collums (see BS95 manual for details)
113  * aval -- values of all the nonzeros in the A matrix (see BS95 manual for details)
114  * *symm -- 1 if matrix nonzeros are symmetric, 0 otherwise
115  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
116  *
117  * OUTPUTS
118  * none
119  *
120  * USES
121  * BlockSolve95
122  *
123  */
124 
125 void bs95setup_(int *ndim, int *nnz, int *nstart, int *nrows, int rp[*nrows+1], int cval[*nnz], double aval[*nnz], int *symm, int *debugwrite) {
126 
127  int argc = 1;
128  int i;
129  char **argv;
130  float my_alpha;
131 
132  if(*debugwrite==1) {
133  printf("ndim = %d\n",*ndim);
134  printf("nnz = %d\n",*nnz);
135  printf("nstart = %d\n",*nstart);
136  printf("nrows = %d\n",*nrows);
137  printf("rp = [ ");
138  for(i=0;i<*nrows+1;i++) {
139  printf("%d ",rp[i]);
140  }
141  printf("]\ncval = [ ");
142  for(i=0;i<*nnz;i++) {
143  printf("%d ",cval[i]);
144  }
145  printf("]\naval = [ ");
146  for(i=0;i<*nnz;i++) {
147  printf("%f ",aval[i]);
148  }
149  printf("]\n");
150  }
151 
152 
153  /*
154  // Initialize BlockSolve with dummy command-line arguments
155  */
156  argv = (char ** ) MALLOC(sizeof(char)*argc);
157  for(i=0;i<argc;i++) {
158  argv[i] = "1";
159  }
160  if(*debugwrite==1){printf(" BS95SETUP\n initializing BS...");}
161  BSinit(&argc,&argv);
162  if(*debugwrite==1){printf("done\n");}
163 
164  /*
165  // Get the processor context
166  */
167  if(*debugwrite==1){printf(" getting the processor context...");}
168  procinfo = BScreate_ctx();
169  // MPI_Comm self = MPI_COMM_SELF;
170  MPI_Comm the_communicator = GetCommunicator();
171  BSctx_set_ps(procinfo,the_communicator);
172  BSctx_set_err(procinfo,1);
173  if(*debugwrite==1){printf("done\n");}
174 
175  /*
176  // Create the A matrix in BSspmat datatype
177  */
178  if(*debugwrite==1){printf(" creating the BSspmat A matrix...");}
179  bA = BSeasy_A(*nstart,*nrows,rp,cval,aval,procinfo);
180  if(*debugwrite==1){printf("done\n");}
181 
182  /*
183  // Define whether matrix nonzeros are symmetric
184  */
185  if(*debugwrite==1){printf(" setting up matrix storage...");}
186  BSset_mat_symmetric(bA,*symm);
187  if(*debugwrite==1){printf("done\n");}
188 
189  /*
190  // Set up the storage type (Cholesky or ILU)
191  */
192  if(*debugwrite==1){printf(" setting up storage type...");}
193  BSset_mat_icc_storage(bA,*symm);
194  if(*debugwrite==1){printf("done\n");}
195 
196  /*
197  // Convert matrix to BSpar_mat datatype
198  */
199  if(*debugwrite==1){printf(" permuting the A matrix...");}
200  pA = BSmain_perm(procinfo,bA);
201  if(*debugwrite==1){printf("done\n");}
202 
203  /*
204  // Diagonally scale the matrix
205  */
206  if(*debugwrite==1){printf(" diagonally scaling the A matrix...");}
207  BSscale_diag(pA,pA->diag,procinfo);
208  if(*debugwrite==1){printf("done\n");}
209 
210  /*
211  // Set up communication data structures
212  */
213  if(*debugwrite==1){printf(" setting up communication data structures...");}
214  Acomm = BSsetup_forward(pA,procinfo);
215  fcomm = BSsetup_factor(pA,procinfo);
216  if(*debugwrite==1){printf("done\n");}
217 
218  /*
219  // Copy the pA matrix
220  */
221  if(*debugwrite==1){printf(" creating a copy of the permuted matrix...");}
222  f_pA = BScopy_par_mat(pA);
223  if(*debugwrite==1){printf("done\n");}
224 
225  /*
226  // Factor the matrix
227  */
228  if(*debugwrite==1){printf(" performing an incomplete factorization of the matrix...");}
229  my_alpha = 1.0;
230  while (BSfactor(f_pA,fcomm,procinfo) != 0) {
231  BScopy_nz(pA,f_pA);
232  my_alpha += 0.1;
233  BSset_diag(f_pA,my_alpha,procinfo);
234  }
235  if(*debugwrite==1){printf("done\n");}
236 
237  /*
238  // Set solver parameters
239  */
240  if(*debugwrite==1){printf(" setting solver parameters...");}
241  if(*symm==1) {
242  /* // Use CG if the system is symmetric */
243  BSctx_set_pre(procinfo,PRE_ICC);
244  BSctx_set_method(procinfo,CG);
245  }
246  else {
247  /* // Use GMRES if the system is non-symmetric */
248  BSctx_set_pre(procinfo,PRE_ILU);
249  BSctx_set_method(procinfo,GMRES);
250  }
251  BSctx_set_max_it(procinfo,maxiter);
252  BSctx_set_guess(procinfo,FALSE); /* // Use vector passed in as initial guess */
253  if(*debugwrite==1){printf("done\n");}
254 
255 }
256 
257 
258 
259 
260 
261 
262 
263 
264 /*
265  * NAME
266  * bs95solve
267  *
268  * FUNCTION
269  * Solves a set of linear equations using BlockSolve95.
270  * Previously, bs95setup must have been run in order to
271  * set up the A matrix.
272  *
273  * INPUTS
274  * *ndim -- dimension of the rhs and x vectors
275  * rhs -- the right-hand side of the A*x=rhs equation
276  * x -- the solution to the A*x=rhs equation
277  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
278  *
279  * OUTPUTS
280  * none
281  *
282  * USES
283  * BlockSolve95
284  *
285  */
286 
287 
288 void bs95solve_(int *ndim, double rhs[*ndim], double x[*ndim], double *tolerance, int *debugwrite) {
289 
290  FLOAT residual;
291  int num_iter;
292  int i;
293 
294  if(*debugwrite==1) {
295  printf("rhs = [ ");
296  for(i=0;i<*ndim;i++) {
297  printf("%f ",rhs[i]);
298  }
299  printf("]\n");
300  }
301 
302  /*
303  // Solve the system
304  */
305  if(*debugwrite==1){printf(" BS95SOLVE\n solving the system...");}
306  BSctx_set_tol(procinfo,*tolerance);
307  num_iter = BSpar_solve(pA,f_pA,Acomm,rhs,x,&residual,procinfo);
308  if(num_iter >= maxiter) {
309  printf("*** WARNING *** BlockSolve95 using too many iterations. Matrix likely ill-conditioned.\n");
310  }
311  if(*debugwrite==1){
312  printf("done\n");
313  printf(" BS took %d iterations to solve the system\n",num_iter);
314  printf(" x = [ ");
315  for(i=0;i<*ndim;i++) { printf("%f ",x[i]); }
316  printf("]\n");
317  printf(" residual = %e\n",residual);
318  }
319  /* //printf(" BS took %d iterations to solve the system\n",num_iter); */
320 
321 }
322 
323 
324 
325 
326 
327 /*
328  * NAME
329  * bs95free
330  *
331  * FUNCTION
332  * Frees the contexts and memory used by BlockSolve95 when
333  * it solves a set of linear equations.
334  *
335  * INPUTS
336  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
337  *
338  * OUTPUTS
339  * none
340  *
341  * USES
342  * BlockSolve95
343  *
344  */
345 
346 void bs95free_(int *debugwrite) {
347 
348  /*
349  // Free matrices
350  */
351  if(*debugwrite==1){printf(" BS95FREE\n freeing matrices...");}
352  BSfree_par_mat(pA);
353  BSfree_copy_par_mat(f_pA);
354  BSfree_easymat(bA);
355  if(*debugwrite==1){printf("done\n");}
356 
357  /*
358  // Free the communication patterns
359  */
360  if(*debugwrite==1){printf(" freeing the communication patterns...");}
361  BSfree_comm(Acomm);
362  BSfree_comm(fcomm);
363  if(*debugwrite==1){printf("done\n");}
364 
365  /*
366  // Free the processor context
367  */
368  if(*debugwrite==1){printf(" freeing the processor context...");}
369  BSfree_ctx(procinfo);
370  if(*debugwrite==1){printf("done\n");}
371 
372 }
373 
374 
375 
376 
377 /*
378  * NAME
379  * bs95finalize
380  *
381  * FUNCTION
382  * Finalizes BlockSolve95. This should be only run once you
383  * are completely finished using BlockSolve95
384  *
385  * INPUTS
386  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
387  *
388  * OUTPUTS
389  * none
390  *
391  * USES
392  * BlockSolve95
393  *
394  */
395 
396 void bs95finalize_(int *debugwrite) {
397 
398  /*
399  // Finalize BlockSolve
400  */
401  if(*debugwrite==1){printf(" BS95FINALIZE\n finalizing BS...");}
402  BSfinalize();
403  if(*debugwrite==1){printf("done\n");}
404 
405 }
406 
407 
408 
409 
410 /*
411 // Generalized serial functions to be called by Fortran
412 */
413 
414 
415 
416 
417 /*
418  * NAME
419  * serialbs95tridiag
420  *
421  * FUNCTION
422  * Used to solve a tridiagonal matrix in serial (1 processor) using
423  * BlockSolve95 functions.
424  *
425  * INPUTS
426  * *ndim -- The dimension of one side of the square A matrix
427  * ad -- Vector containing lower diagonal entries of the matrix
428  * bd -- Vector containing on-diagonal entries of the matrix
429  * cd -- Vector containing upper diagonal entries of the matrix
430  * rhs -- The right-hand side vector
431  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
432  *
433  * OUTPUTS
434  * x -- The solution vector
435  *
436  * USES
437  * BlockSolve95
438  *
439  */
440 
441 void serialbs95tridiag_(int *ndim, double ad[*ndim], double bd[*ndim], double cd[*ndim], double rhs[*ndim], double x[*ndim], int *debugwrite) {
442 
443  /*
444  // Solve tridiagonal systems of equations:
445  //
446  // [ bd[0] cd[0] 0 ... 0 ] [ x[0] ] [ rhs[0] ]
447  // [ ad[1] bd[1] cd[1] 0 ... 0 ] [ x[1] ] [ rhs[1] ]
448  // [ . . . ] [ . ] [ . ]
449  // [ . . . ] * [ . ] = [ . ]
450  // [ . . . ] [ . ] [ . ]
451  // [ 0 ... 0 ad[ndim-2] bd[ndim-2] cd[ndim-2] ] [ x[ndim-2] ] [ rhs[ndim-2] ]
452  // [ 0 ... 0 ad[ndim-1] bd[ndim-1] ] [ x[ndim-1] ] [ rhs[ndim-1] ]
453  //
454  */
455 
456  int *rp;
457  int *cval;
458  FLOAT *aval;
459  int i;
460  int nnz;
461  int avali;
462  int nstart = 0;
463  int symm = 1;
464 
465  /*
466  // Print header
467  */
468  if(*debugwrite==1){printf(" Using BlockSolve95 to solve the tridiagonal system...\n");}
469 
470  /*
471  // Create the mapping of the nonzero entries of A
472  */
473  if(*debugwrite==1){printf(" defining matrix mapping...");}
474  nnz = 3*(*ndim)-2;
475  aval = (FLOAT *) MALLOC(sizeof(FLOAT)*nnz);
476  cval = (int *) MALLOC(sizeof(int)*nnz);
477  rp = (int *) MALLOC(sizeof(int)*(*ndim+1));
478  printf(" \b"); /* // Give the program time to realize that new stuff is allocated */
479  aval[0] = bd[0];
480  aval[1] = cd[0];
481  cval[0] = 0;
482  cval[1] = 1;
483  rp[0] = 0;
484  rp[1] = 2;
485  avali = 2;
486  for(i=1;i<*ndim-1;i++) {
487  aval[avali] = ad[i];
488  aval[avali+1] = bd[i];
489  aval[avali+2] = cd[i];
490  cval[avali] = i-1;
491  cval[avali+1] = i;
492  cval[avali+2] = i+1;
493  avali = avali + 3;
494  rp[i+1] = avali;
495  }
496  aval[nnz-2] = ad[*ndim-1];
497  aval[nnz-1] = bd[*ndim-1];
498  cval[nnz-2] = *ndim-2;
499  cval[nnz-1] = *ndim-1;
500  rp[*ndim] = nnz;
501  if(*debugwrite==1){printf("done\n");}
502 
503  /*
504  // Solve the system
505  */
506  double *tol;
507  *tol = 1.0e-09;
508  bs95setup_(ndim,&nnz,&nstart,ndim,rp,cval,aval,&symm,debugwrite);
509  bs95solve_(ndim,rhs,x,tol,debugwrite);
510  bs95free_(debugwrite);
511 
512  /*
513  // Free the matrix mapping
514  */
515  if(*debugwrite==1){printf(" freeing matrix mapping...");}
516  free(aval);
517  free(cval);
518  free(rp);
519  if(*debugwrite==1){printf("done\n");}
520 
521  /*
522  // Print footer
523  */
524  if(*debugwrite==1){printf(" Done using BlockSolve95 to solve the system\n");}
525 
526 }
527 
528 
529 
530 
531 /*
532  * NAME
533  * serialbs95
534  *
535  * FUNCTION
536  * Used to solve a general system of linear equations serial using
537  * BlockSolve95 functions.
538  *
539  * INPUTS
540  * *ndim -- The dimension of one side of the square A matrix
541  * A -- The matrix.
542  * rhs -- The right-hand side vector
543  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
544  *
545  * OUTPUTS
546  * x -- The solution vector
547  *
548  * USES
549  * BlockSolve95
550  * ctranspose
551  *
552  */
553 
554 void serialbs95_(int *ndim, double A[*ndim][*ndim], double rhs[*ndim], double x[*ndim], int *debugwrite) {
555 
556  /*
557  // Solve general systems of equations
558  //
559  // [A]*[x] = [rhs]
560  //
561  */
562 
563  int *rp;
564  int *cval;
565  FLOAT *aval;
566  int i;
567  int j;
568  int nnz;
569  int avali;
570  int nstart = 0;
571  int symm = 0;
572 
573  /*
574  // Print footer
575  */
576  if(*debugwrite==1){printf(" Using BlockSolve95 to solve the system\n");}
577 
578  /*
579  // Transpose the matrix indices of the 2D matrices from Fortran style to C style
580  */
581  ctranspose(*ndim,A);
582 
583  /*
584  // Create the mapping of the nonzero entries of A
585  */
586  if(*debugwrite==1){printf(" defining matrix mapping...");}
587  nnz = 0;
588  for(i=0;i<*ndim;i++) {
589  for(j=0;j<*ndim;j++) {
590  if(A[i][j] != 0.0) {
591  nnz++;
592  }
593  }
594  }
595  aval = (FLOAT *) MALLOC(sizeof(FLOAT)*nnz);
596  cval = (int *) MALLOC(sizeof(int)*nnz);
597  rp = (int *) MALLOC(sizeof(int)*(*ndim+1));
598  printf(" \b"); /* // Give the program time to realize that new stuff has been allocated */
599  avali = 0;
600  rp[0] = 0;
601  for(i=0;i<*ndim;i++) {
602  for(j=0;j<*ndim;j++) {
603  if(A[i][j] != 0.0) {
604  aval[avali] = A[i][j];
605  cval[avali] = j;
606  avali++;
607  }
608  }
609  rp[i+1] = avali; }
610  if(*debugwrite==1){printf("done\n");}
611 
612  /*
613  // Solve the system
614  */
615  double *tol;
616  *tol = 1.0e-09;
617  bs95setup_(ndim,&nnz,&nstart,ndim,rp,cval,aval,&symm,debugwrite);
618  bs95solve_(ndim,rhs,x,tol,debugwrite);
619  bs95free_(debugwrite);
620 
621  /*
622  // Free the matrix mapping
623  */
624  if(*debugwrite==1){printf(" freeing matrix mapping...");}
625  free(aval);
626  free(cval);
627  free(rp);
628  if(*debugwrite==1){printf("done\n");}
629 
630  /*
631  // Transpose the matrix indices of the 2D matrices from C style to Fortran style
632  */
633  ctranspose(*ndim,A);
634 
635  /*
636  // Print footer
637  */
638  if(*debugwrite==1){printf(" Done using BlockSolve95 to solve the system\n");}
639 
640 }
641 
642 
643 
644 
645 /*
646  * NAME
647  * serialbs95mat
648  *
649  * FUNCTION
650  * Takes a general matrix and puts it into compressed row storage (CRS)
651  * format for use with BlockSolve95 functions.
652  *
653  * INPUTS
654  * *ndim -- The dimension of one side of the square A matrix
655  * *nnz -- Reserved
656  * A -- The matrix.
657  * *debugwrite -- 1 if debug statements should be written to the screen, 0 otherwise
658  *
659  * OUTPUTS
660  * rp -- the row mapping CRS vector
661  * cval -- the collum mapping CRS vector
662  * aval -- the nonzero value CRS vector
663  *
664  * USES
665  * ctranspose
666  *
667  */
668 
669 void serialbs95mat_(int *ndim, int *nnz, double A[*ndim][*ndim], int rp[*ndim+1], int cval[*nnz], double aval[*nnz], int *debugwrite) {
670 
671  /*
672  // Construct the compressed row storage for a matrix
673  */
674 
675  int avali;
676  int i;
677  int j;
678 
679  /*
680  // Transpose the matrix indices of the 2D matrices from Fortran style to C style
681  */
682  ctranspose(*ndim,A);
683 
684  /*
685  // Create the mapping of the nonzero entries of A
686  */
687  if(*debugwrite==1){printf(" SERIALBS95MAT\n defining matrix mapping...");}
688  avali = 0;
689  rp[0] = 0;
690  for(i=0;i<*ndim;i++) {
691  for(j=0;j<*ndim;j++) {
692  if(A[i][j] != 0.0) {
693  aval[avali] = A[i][j];
694  cval[avali] = j;
695  avali++;
696  }
697  }
698  rp[i+1] = avali;
699  }
700  if(*debugwrite==1){printf("done\n");}
701 
702  /*
703  // Transpose the matrix indices of the 2D matrices from C style to Fortran style
704  */
705  ctranspose(*ndim,A);
706 
707 }
#define FALSE
Definition: vinci.h:133
void bs95finalize_(int *debugwrite)
Definition: BS95.c:396
BSspmat * bA
Definition: BS95.c:37
const NT & d
NT rhs
void bs95free_(int *debugwrite)
Definition: BS95.c:346
BScomm * fcomm
Definition: BS95.c:39
void serialbs95tridiag_(int *ndim, double ad[*ndim], double bd[*ndim], double cd[*ndim], double rhs[*ndim], double x[*ndim], int *debugwrite)
Definition: BS95.c:441
int maxiter
Definition: BS95.c:40
BSprocinfo * procinfo
Definition: BS95.c:36
rational * A
Definition: vinci_lass.c:67
blockLoc i
Definition: read.cpp:79
void serialbs95mat_(int *ndim, int *nnz, double A[*ndim][*ndim], int rp[*ndim+1], int cval[*nnz], double aval[*nnz], int *debugwrite)
Definition: BS95.c:669
void int int REAL * x
Definition: read.cpp:74
const NT & n
BSpar_mat * f_pA
Definition: BS95.c:38
void bs95solve_(int *ndim, double rhs[*ndim], double x[*ndim], double *tolerance, int *debugwrite)
Definition: BS95.c:288
MPI_Comm GetCommunicator()
Definition: GetComm.C:6
BSpar_mat * pA
Definition: BS95.c:38
j indices j
Definition: Indexing.h:6
void bs95setup_(int *ndim, int *nnz, int *nstart, int *nrows, int rp[*nrows+1], int cval[*nnz], double aval[*nnz], int *symm, int *debugwrite)
Definition: BS95.c:125
void ctranspose(int n, double d[n][n])
Definition: BS95.c:71
BScomm * Acomm
Definition: BS95.c:39
void serialbs95_(int *ndim, double A[*ndim][*ndim], double rhs[*ndim], double x[*ndim], int *debugwrite)
Definition: BS95.c:554