예제 #1
0
int main (int argc, char *argv[]) {

   /* Timing vars */
//   double ut1,ut2,st1,st2,wt1,wt2;
   double wt1,wt2;

   /* Matrix */
   int n, nnz;
   double fnorm;
   CSRMatrix matrix;

   /* Preconditioner */
   CSRMatrix Factors;

   /* Files */
   char *DriverConfigFileName, *SolverConfigFileName;
   
   /* Driver and solver I/O arrays and parameters */
   double *evals, *evecs, *rnorms;
   driver_params driver;
   primme_params primme;
   primme_preset_method method;
#ifdef Cplusplus     /* C++ has a stricter type checking */
   void (*precond_function)(void *, void *, int *, primme_params *);
#else
   void *precond_function;
#endif

   /* Other miscellaneous items */
   int i;
   int ret;

   /* --------------------------------------------------------------------- */
   /*   Read matrix and driver setup                                        */
   /* --------------------------------------------------------------------- */

   /* ------------------------------------------------------- */
   /* Get from command line the names for the 2 config files  */
   /* ------------------------------------------------------- */

   if (argc == 3) {
      DriverConfigFileName = argv[1];
      SolverConfigFileName = argv[2];
   }

   /* ----------------------------- */
   /* Read in the driver parameters */
   /* ----------------------------- */
   if (read_driver_params(DriverConfigFileName, &driver) < 0) {
      fprintf(stderr, "Reading driver parameters failed\n");

      return(-1);
   }

   /* ------------------------------------------ */
   /* Read the matrix and store it in CSR format */
   /* ------------------------------------------ */
   fprintf(stderr," Matrix: %s\n",driver.matrixFileName);


   if (!strcmp("mtx", &driver.matrixFileName[strlen(driver.matrixFileName)-3]))
   {  // coordinate format storing both lower and upper triangular parts
      ret = readfullMTX(driver.matrixFileName, &matrix.AElts, &matrix.JA, 
         &matrix.IA, &n, &nnz);
      if (ret < 0) {
         fprintf(stderr, "ERROR: Could not read matrix file\n");
         return(-1);
      }
   }
   else if (driver.matrixFileName[strlen(driver.matrixFileName)-1] == 'U') {
      // coordinate format storing only upper triangular part
      ret = readUpperMTX(driver.matrixFileName, &matrix.AElts, &matrix.JA,
         &matrix.IA, &n, &nnz);
      if (ret < 0) {
         fprintf(stderr, "ERROR: Could not read matrix file\n");
         return(-1);
      }
   }
   else {  
      //Harwell Boeing format NOT IMPLEMENTED
      //ret = readmt()
      ret = -1;
      if (ret < 0) {
         fprintf(stderr, "ERROR: Could not read matrix file\n");
         return(-1);
      }
   }

   fnorm = frobeniusNorm(n, matrix.IA, matrix.AElts);

/* ------------------------------------------------------------------------- */
/*  Set up preconditioner if needed. We provide these sample options         */
/*  in driver.PrecChoice:  (driver.PrecChoice is read in read_driver_params) */
/*     choice = 0  no preconditioner                                         */
/*     choice = 1  K=Diag(A-shift),   shift provided once by user            */
/*     choice = 2  K=Diag(A-shift_i), shifts provided by primme every step   */
/*     choice = 3  K=ILUT(A-shift)  , shift provided once by user            */
/* ------------------------------------------------------------------------- */

   ret = create_preconditioner
         (matrix, &Factors, &precond_function, n, nnz, driver);
   if (ret < 0) {
      fprintf(stderr, "ERROR: Could not create requested preconditioner \n");
      return(-1);
   }

   /* --------------------------------------------------------------------- */
   /*    Primme solver setup                                                */
   /*       primme_initialize  (not needed if ALL primme struct members set)*/
   /*       primme_set_method  (bypass it to fully customize your solver)   */
   /* --------------------------------------------------------------------- */

   /* ----------------------------- */
   /* Initialize defaults in primme */
   /* ----------------------------- */
   primme_initialize(&primme);

   /* --------------------------------------- */
   /* Read in the primme configuration file   */
   /* --------------------------------------- */
   primme.n     = n;
   primme.aNorm = fnorm; /* ||A||_frobenius. A configFile entry overwrites it */

   if (read_solver_params(SolverConfigFileName, driver.outputFileName, 
			   &primme, &method) < 0) {
      fprintf(stderr, "Reading solver parameters failed\n");
      return(-1);
   }

   /* --------------------------------------- */
   /* Pick one of the default methods(if set) */
   /* --------------------------------------- */

   if (primme_set_method(method, &primme) < 0 ) {
      fprintf(primme.outputFile, "No preset method. Using custom settings\n");
   }

   /* --------------------------------------- */
   /* Optional: report memory requirements    */
   /* --------------------------------------- */

   ret = dprimme(NULL,NULL,NULL,&primme);
   fprintf(primme.outputFile,"PRIMME will allocate the following memory:\n");
   fprintf(primme.outputFile,"real workspace, %ld bytes\n",primme.realWorkSize);
   fprintf(primme.outputFile,"int  workspace, %d bytes\n",primme.intWorkSize);
   
   /* --------------------------------------- */
   /* Set up matrix vector and preconditioner */
   /* --------------------------------------- */

   primme.matrixMatvec        = MatrixMatvec;
   primme.applyPreconditioner = precond_function;

   /* --------------------------------------- */
   /* Optional: provide matrix/preconditioner */
   /* --------------------------------------- */
   primme.matrix         = &matrix;
   primme.preconditioner = &Factors;

   /* --------------------------------------- */
   /* Display given parameter configuration   */
   /* Place this after the dprimme() to see   */
   /* any changes dprimme() made to primme    */
   /* --------------------------------------- */

   fprintf(primme.outputFile," Matrix: %s\n",driver.matrixFileName);
   primme_display_params(primme);

   /* --------------------------------------------------------------------- */
   /* 	                   Run the dprimme solver                           */
   /* --------------------------------------------------------------------- */

   /* Allocate space for converged Ritz values and residual norms */

   evals = (double *)primme_calloc(primme.numEvals, sizeof(double), "evals");
   evecs = (double *)primme_calloc(primme.n*
	   (primme.numEvals+primme.maxBlockSize), sizeof(double), "evecs");
   rnorms = (double *)primme_calloc(primme.numEvals, sizeof(double), "rnorms");

   /* ------------------------ */
   /* Initial guess (optional) */
   /* ------------------------ */
       for (i=0;i<primme.n;i++) evecs[i]=1/sqrt(primme.n);

   /* ------------- */
   /*  Call primme  */
   /* ------------- */

   wt1 = primme_wTimer2(1); 
//   primme_get_time(&ut1,&st1);

   ret = dprimme(evals, evecs, rnorms, &primme);

   wt2 = primme_wTimer2(0);
//   primme_get_time(&ut2,&st2);

   /* --------------------------------------------------------------------- */
   /* Reporting                                                             */
   /* --------------------------------------------------------------------- */

   primme_PrintStackTrace(primme);

   fprintf(primme.outputFile, "Wallclock Runtime   : %-f\n", wt2-wt1);
//   fprintf(primme.outputFile, "User Time           : %f seconds\n", ut2-ut1);
//   fprintf(primme.outputFile, "Syst Time           : %f seconds\n", st2-st1);

   if (primme.procID == 0) {
      for (i=0; i < primme.numEvals; i++) {
         fprintf(primme.outputFile, "Eval[%d]: %-22.15E rnorm: %-22.15E\n", i+1,
            evals[i], rnorms[i]); 
      }
      fprintf(primme.outputFile, " %d eigenpairs converged\n", primme.initSize);

      fprintf(primme.outputFile, "Tolerance : %-22.15E\n", 
		      				      primme.aNorm*primme.eps);
      fprintf(primme.outputFile, "Iterations: %-d\n", 
		      			      primme.stats.numOuterIterations); 
      fprintf(primme.outputFile, "Restarts  : %-d\n", primme.stats.numRestarts);
      fprintf(primme.outputFile, "Matvecs   : %-d\n", primme.stats.numMatvecs);
      fprintf(primme.outputFile, "Preconds  : %-d\n", primme.stats.numPreconds);

      fprintf(primme.outputFile, "\n\n#,%d,%.1f\n\n", primme.stats.numMatvecs,
         wt2-wt1); 

      switch (primme.dynamicMethodSwitch) {
         case -1: fprintf(primme.outputFile, 
	       "Recommended method for next run: DEFAULT_MIN_MATVECS\n"); break;
         case -2: fprintf(primme.outputFile, 
	       "Recommended method for next run: DEFAULT_MIN_TIME\n"); break;
         case -3: fprintf(primme.outputFile, 
	       "Recommended method for next run: DYNAMIC (close call)\n"); break;
      }

   }

   if (ret != 0) {
      fprintf(primme.outputFile, 
         "Error: dprimme returned with nonzero exit status\n");
      return -1;
   }

   fclose(primme.outputFile);
   primme_Free(&primme);

   return(0);

}
예제 #2
0
int main (int argc, char *argv[]) {

   /* Timing vars */
   double ut1,ut2,st1,st2,wt1,wt2;

   /* Matrix */
   int n, nLocal, nnz;
   double fnorm;
   CSRMatrix matrix; 	     // The matrix in simple SPARSKIT CSR format
   Matrix *Par_matrix;       // Pointer to the matrix in Parasails CSR format

   /* Permutation/partitioning stuff */
   int *mask, *map;
   int *fg2or, *or2fg;
   
   /* Preconditioner */
   ParaSails *Par_Factors;   // Pointer to the matrix in Parasails CSR format

   /* Files */
   char *DriverConfigFileName, *SolverConfigFileName;
   char partFileName[512];
   FILE *partFile;
   
   /* Driver and solver I/O arrays and parameters */
   double *evals, *evecs, *rnorms;
   driver_params driver;
   primme_params primme;
   primme_preset_method method;
#ifdef Cplusplus     /* C++ has a stricter type checking */
   void (*precond_function)(void *, void *, int *, primme_params *);
#else
   void *precond_function;
#endif

   /* Other miscellaneous items */
   int i,j;
   int ret, modulo;
   int rangeStart;
   int rangeEnd;
   int numProcs, procID;
   MPI_Comm comm;

   /* --------------------------------------------------------------------- */
   /* MPI INITIALIZATION						    */
   /* --------------------------------------------------------------------- */
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
   MPI_Comm_rank(MPI_COMM_WORLD, &procID);
   comm = MPI_COMM_WORLD;

   /* --------------------------------------------------------------------- */
   /*   Read matrix and driver setup                                        */
   /* --------------------------------------------------------------------- */

   /* ------------------------------------------------------- */
   /* Get from command line the names for the 2 config files  */
   /* ------------------------------------------------------- */

   if (argc == 3) {
      DriverConfigFileName = argv[1];
      SolverConfigFileName = argv[2];
   }
   else {
      MPI_Finalize();
      return(-1);
   }


   /* ----------------------------- */
   /* Read in the driver parameters */
   /* ----------------------------- */
   if (read_driver_params(DriverConfigFileName, &driver) < 0) {
      fprintf(stderr, "Reading driver parameters failed\n");
	fflush(stderr);
      MPI_Finalize();
      return(-1);
   }

   /* ------------------------------------------ */
   /* Read the matrix and store it in CSR format */
   /* ------------------------------------------ */
   if (procID == 0) {

      fprintf(stdout," Matrix: %s\n",driver.matrixFileName);
	fflush(stdout);

      if (!strcmp("mtx", 
		&driver.matrixFileName[strlen(driver.matrixFileName)-3])) {  
         // coordinate format storing both lower and upper triangular parts
         ret = readfullMTX(driver.matrixFileName, &matrix.AElts, &matrix.JA, 
            &matrix.IA, &n, &nnz);
         if (ret < 0) {
            fprintf(stderr, "ERROR: Could not read matrix file\n");
	    MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
            return(-1);
         }
      }
      else if (driver.matrixFileName[strlen(driver.matrixFileName)-1] == 'U') {
         // coordinate format storing only upper triangular part
         ret = readUpperMTX(driver.matrixFileName, &matrix.AElts, &matrix.JA,
            &matrix.IA, &n, &nnz);
         if (ret < 0) {
            fprintf(stderr, "ERROR: Could not read matrix file\n");
	    MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
            return(-1);
         }
      }
      else {  
         //Harwell Boeing format NOT IMPLEMENTED
         //ret = readmt()
         ret = -1;
         if (ret < 0) {
            fprintf(stderr, "ERROR: Could not read matrix file\n");
	    MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
            return(-1);
         }
      }
   } // if procID == 0

   /* ----------------------------------------------------------- */
   // Allocate space on other processors and broadcast the matrix
   /* ----------------------------------------------------------- */

   MPI_Bcast(&nnz, 1, MPI_INT, 0, MPI_COMM_WORLD);
   MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

   if (procID != 0) {

      matrix.AElts = (double *)primme_calloc(nnz, sizeof(double), "A");
      matrix.JA = (int *)primme_calloc(nnz, sizeof(int), "JA");
      matrix.IA = (int *)primme_calloc(n+1, sizeof(int), "IA");
   }
   else {
      // Proc 0 converts CSR to C indexing
      for (i=0; i < n+1; i++) {
         matrix.IA[i]--;
      }
      for (i=0; i < nnz; i++) {
         matrix.JA[i]--;
      }
   }

   MPI_Bcast(matrix.AElts, nnz, MPI_DOUBLE, 0, MPI_COMM_WORLD);
   MPI_Bcast(matrix.IA, n+1, MPI_INT, 0, MPI_COMM_WORLD);
   MPI_Bcast(matrix.JA, nnz, MPI_INT, 0, MPI_COMM_WORLD);

   fnorm = frobeniusNorm(n, matrix.IA, matrix.AElts);

   /* ---------------------------------------------------------------------- */
   /*  Partitioning of the matrix among the processors                       */
   /* ---------------------------------------------------------------------- */

   mask = (int *)primme_calloc(n, sizeof(int), "mask");
   map = (int *)primme_calloc(numProcs+1, sizeof(int), "map");
   fg2or = (int *)primme_calloc(n, sizeof(int), "fg2or");
   or2fg = (int *)primme_calloc(n, sizeof(int), "or2fg");
      
//   /* * * * * * * * * * * * * * * * * *
//    * Read the partition from a file
//    * * * * * * * * * * * * * * * * * */
//   sprintf(partFileName, "%s/%s", driver.partDir, driver.partId);
//   partFile = fopen(partFileName, "r");
//
//   if (partFile == 0) {
//      fprintf(stderr, "ERROR: Could not open '%s'\n", partFileName);
//      MPI_Finalize();
//      return(-1);
//   }
//
//   for (i = 0; i < n; i++) {
//      fscanf(partFile, "%d", &mask[i]);
//   }
//
//   fclose(partFile);

   /* * * * * * * * * * * * * * * * * * * * * * * */
   /* Simplistic assignment of processors to rows */
   /* * * * * * * * * * * * * * * * * * * * * * * */
   nLocal = n / numProcs;
   modulo = n % numProcs;
   rangeStart = 0;
   for (i=0; i<numProcs; i++) {
      rangeEnd = rangeStart + nLocal;
      if (i < modulo) rangeEnd = rangeEnd + 1;
      for (j = rangeStart; j< rangeEnd; j++) mask[j] = i;
      rangeStart = rangeEnd;
   }
   /* * * * * * * * * * * * * * * * * * * * * * * */

   generatePermutations(n, numProcs, mask, or2fg, fg2or, map);
   rangeStart = map[procID];
   rangeEnd = map[procID+1]-1;
   nLocal = rangeEnd - rangeStart+1;
   Par_matrix = csrToParaSails(procID, map, fg2or, or2fg, 
		               matrix.IA, matrix.JA, matrix.AElts, comm);

/* ------------------------------------------------------------------------- */
/*  Set up preconditioner if needed. For parallel programs the only choice   */
/*  in driver.PrecChoice:  (driver.PrecChoice is read in read_driver_params) */
/*     choice = 4    Parallel ParaSails preconditioners                      */
/*                   with parameters (level, threshold, filter, isymm)       */
/*                   as read in read_driver_params().                        */
/* ------------------------------------------------------------------------- */

   if (driver.PrecChoice == 4) {

      Par_Factors = generate_precond(&matrix, driver.shift, n,
	 procID, map, fg2or, or2fg, rangeStart, rangeEnd, driver.isymm, 
	 driver.level, driver.threshold, driver.filter, comm);
      precond_function = par_ApplyParasailsPrec;
   }
   else {
      Par_Factors = NULL;
      precond_function = NULL;
      // Free A as it is not further needed
      free(matrix.AElts); free(matrix.IA); free(matrix.JA);
   }

   free(mask); free(map); free(fg2or); free(or2fg);

   /* --------------------------------------------------------------------- */
   /*    Primme solver setup                                                */
   /*       primme_initialize  (not needed if ALL primme struct members set)*/
   /*       primme_set_method  (bypass it to fully customize your solver)   */
   /* --------------------------------------------------------------------- */

   /* ----------------------------- */
   /* Initialize defaults in primme */
   /* ----------------------------- */
   primme_initialize(&primme);

   /* --------------------------------------- */
   /* Read in the primme configuration file   */
   /* --------------------------------------- */
   primme.n     = n;
   primme.aNorm = fnorm; /* ||A||_frobenius. A configFile entry overwrites it */

   if (procID == 0) {
      if (read_solver_params(SolverConfigFileName, driver.outputFileName, 
			   &primme, &method) < 0) {
         fprintf(stderr, "Reading solver parameters failed\n");
	 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
         return(-1);
      }
   }

   /* ------------------------------------------------- */
   // Send read common primme members to all processors
   // Setup the primme members local to this processor  
   /* ------------------------------------------------- */
   broadCast(&primme, &method, comm);

   primme.procID = procID;
   primme.numProcs = numProcs;
   primme.nLocal = nLocal;
   primme.commInfo = &comm;
   primme.globalSumDouble = par_GlobalSumDouble;

   /* --------------------------------------- */
   /* Pick one of the default methods(if set) */
   /* --------------------------------------- */

   if (primme_set_method(method, &primme) < 0 ) {
      fprintf(primme.outputFile, "No preset method. Using custom settings\n");
   }

   /* --------------------------------------- */
   /* Optional: report memory requirements    */
   /* --------------------------------------- */

   ret = dprimme(NULL,NULL,NULL,&primme);
   fprintf(primme.outputFile,"PRIMME will allocate the following memory:\n");
   fprintf(primme.outputFile," processor %d, real workspace, %ld bytes\n",
		   		procID, primme.realWorkSize);
   fprintf(primme.outputFile," processor %d, int  workspace, %d bytes\n",
		   		procID, primme.intWorkSize);

   /* --------------------------------------- */
   /* Set up matrix vector and preconditioner */
   /* --------------------------------------- */

   primme.matrixMatvec        = par_MatrixMatvec;
   primme.applyPreconditioner = precond_function;

   /* --------------------------------------- */
   /* Optional: provide matrix/preconditioner */
   /* --------------------------------------- */
   primme.matrix         = Par_matrix;
   primme.preconditioner = Par_Factors;

   /* --------------------------------------- */
   /* Display given parameter configuration   */
   /* Place this after the dprimme() to see   */
   /* any changes dprimme() made to primme    */
   /* --------------------------------------- */

   if (procID >= 0) {
      fprintf(primme.outputFile," Matrix: %s\n",driver.matrixFileName);
      primme_display_params(primme);
   }

   /* --------------------------------------------------------------------- */
   /* 	                   Run the dprimme solver                           */
   /* --------------------------------------------------------------------- */

   /* Allocate space for converged Ritz values and residual norms */

   evals = (double *)primme_calloc(primme.numEvals, sizeof(double), "evals");
   evecs = (double *)primme_calloc(primme.nLocal*
	   (primme.numEvals+primme.maxBlockSize), sizeof(double), "evecs");
   rnorms = (double *)primme_calloc(primme.numEvals, sizeof(double), "rnorms");

   /* ------------------------ */
   /* Initial guess (optional) */
   /* ------------------------ */
    for (i=0;i<primme.nLocal;i++) evecs[i]=1/sqrt(primme.n);

   /* ------------- */
   /*  Call primme  */
   /* ------------- */

   wt1 = primme_get_wtime(); 
   primme_get_time(&ut1,&st1);

   ret = dprimme(evals, evecs, rnorms, &primme);

   wt2 = primme_get_wtime();
   primme_get_time(&ut2,&st2);

   /* --------------------------------------------------------------------- */
   /* Reporting                                                             */
   /* --------------------------------------------------------------------- */

   if (procID == 0) {
      primme_PrintStackTrace(primme);
   }

   fprintf(primme.outputFile, "Wallclock Runtime   : %-f\n", wt2-wt1);
   fprintf(primme.outputFile, "User Time           : %f seconds\n", ut2-ut1);
   fprintf(primme.outputFile, "Syst Time           : %f seconds\n", st2-st1);

   if (primme.procID == 0) {
      for (i=0; i < primme.numEvals; i++) {
         fprintf(primme.outputFile, "Eval[%d]: %-22.15E rnorm: %-22.15E\n", i+1,
            evals[i], rnorms[i]); 
      }
      fprintf(primme.outputFile, " %d eigenpairs converged\n", primme.initSize);

      fprintf(primme.outputFile, "Tolerance : %-22.15E\n", 
		      				      primme.aNorm*primme.eps);
      fprintf(primme.outputFile, "Iterations: %-d\n", 
		      			      primme.stats.numOuterIterations); 
      fprintf(primme.outputFile, "Restarts  : %-d\n", primme.stats.numRestarts);
      fprintf(primme.outputFile, "Matvecs   : %-d\n", primme.stats.numMatvecs);
      fprintf(primme.outputFile, "Preconds  : %-d\n", primme.stats.numPreconds);

      fprintf(primme.outputFile, "\n\n#,%d,%.1f\n\n", primme.stats.numMatvecs,
         wt2-wt1); 

      switch (primme.dynamicMethodSwitch) {
         case -1: fprintf(primme.outputFile,
               "Recommended method for next run: DEFAULT_MIN_MATVECS\n"); break;
         case -2: fprintf(primme.outputFile,
               "Recommended method for next run: DEFAULT_MIN_TIME\n"); break;
         case -3: fprintf(primme.outputFile,
               "Recommended method for next run: DYNAMIC (close call)\n"); break;
      }
   }

   if (ret != 0 && procID == 0) {
      fprintf(primme.outputFile, 
         "Error: dprimme returned with nonzero exit status: %d \n",ret);
      return -1;
   }


   fflush(primme.outputFile);
   fclose(primme.outputFile);
   primme_Free(&primme);

   fflush(stdout);
   fflush(stderr);
   MPI_Barrier(comm);
   MPI_Finalize();

   return(0);

}