void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) // Input: Phi1 [r1',r1,ra1], A[ra1,n',n,ra2], Phi2[r2,ra2,r2'], tol, B, sol_prev, max_matvecs = 500, max_basis_size = 100 // Output: sol, lambda, num_matvecs { double *scal, *dsol_prev; double tol; double *dsol, *dlambda, *dnum_matvecs, *drnorms; long max_matvecs, max_basis_size; long dimcount, *rhsdims; long dims[4]; long rx1, rx2, ra1, ra2, n, i, j, B; primme_params primme; primme_preset_method method; if (nrhs<6) { mexPrintf("Specify at least Phi1,A,Phi2,tol,B,sol_prev\n"); return; } if (nrhs<7) max_matvecs=500; else { scal = mxGetPr(prhs[6]); max_matvecs = (long)round(scal[0]); } if (nrhs<8) max_basis_size=100; else { scal = mxGetPr(prhs[7]); max_basis_size = (long)round(scal[0]); } // Fetch the data g_Phi1 = mxGetPr(prhs[0]); dimcount=mxGetNumberOfDimensions(prhs[0]); rhsdims = mxGetDimensions(prhs[0]); for (i=0; i<dimcount; i++) dims[i]=rhsdims[i]; for (i=dimcount; i<3; i++) dims[i]=1; rx1 = dims[0]; if (dims[1]!=rx1) { mexPrintf("Phi1 is not square!\n"); return; } ra1 = dims[2]; g_A = mxGetPr(prhs[1]); dimcount=mxGetNumberOfDimensions(prhs[1]); rhsdims = mxGetDimensions(prhs[1]); for (i=0; i<dimcount; i++) dims[i]=rhsdims[i]; for (i=dimcount; i<4; i++) dims[i]=1; if (ra1 != dims[0]) { mexPrintf("ra1 in Phi1 and A are not consistent!\n"); return; } n = dims[1]; if (n!=dims[2]) { mexPrintf("A is not square!\n"); return; } ra2 = dims[3]; g_Phi2 = mxGetPr(prhs[2]); dimcount=mxGetNumberOfDimensions(prhs[2]); rhsdims = mxGetDimensions(prhs[2]); for (i=0; i<dimcount; i++) dims[i]=rhsdims[i]; for (i=dimcount; i<3; i++) dims[i]=1; rx2 = dims[0]; if (dims[2]!=rx2) { mexPrintf("Phi2 is not square!\n"); return; } if (ra2 != dims[1]) { mexPrintf("ra2 in Phi2 and A are not consistent!\n"); return; } scal = mxGetPr(prhs[3]); tol = scal[0]; scal = mxGetPr(prhs[4]); B = (long)round(scal[0]); dsol_prev = mxGetPr(prhs[5]); if ((mxGetM(prhs[5])*mxGetN(prhs[5]))!=(rx1*n*rx2*B)) { mexPrintf("SOL_PREV size is not consistent!\n"); return; } // Allocate the output plhs[0] = mxCreateDoubleMatrix(rx1*n*rx2, B, mxREAL); // dsol = mxGetPr(plhs[0]); plhs[1] = mxCreateDoubleMatrix(B, 1, mxREAL); dlambda = mxGetPr(plhs[1]); if (nlhs>2) { plhs[2] = mxCreateDoubleMatrix(1, 1, mxREAL); dnum_matvecs = mxGetPr(plhs[2]); } // Allocate the work arrays drnorms = (double *)malloc(sizeof(double)*B); dsol = (double *)malloc(sizeof(double)*rx1*n*rx2*(max_basis_size+B+1)); g_rx1 = rx1; g_n = n; g_rx2 = rx2; g_ra1 = ra1; g_ra2 = ra2; g_B = B; i = ra1; if (ra2>ra1) { i=ra2; } i = rx1*n*rx2*i; g_res1 = (double *)malloc(sizeof(double)*i); g_res2 = (double *)malloc(sizeof(double)*i); // Call the solver //Initialization of the primme stuff; primme_initialize(&primme); method=DYNAMIC; primme_set_method(method, &primme); primme.n = rx1*n*rx2; primme.numEvals = B; primme.matrixMatvec = PrimmeMatvec; primme.printLevel = 1; primme.maxMatvecs = max_matvecs; primme.minRestartSize = B+1; if (B+1>rx1*n*rx2-1) { primme.minRestartSize = rx1*n*rx2-1; } primme.maxBasisSize = max_basis_size; primme.eps = tol; // primme.aNorm = 1.0; // It should be 1 to truncate in the residual norm. Default is fro primme.initSize = B; i = rx1*n*rx2*B; j = 1; dcopy(&i, dsol_prev, &j, dsol, &j); // solution i = dprimme(dlambda, dsol, drnorms, &primme); if (nlhs>2) { dnum_matvecs[0] = (double)(primme.stats.numMatvecs); } // finalize primme primme_Free(&primme); if (i < 0) { mexPrintf("Primme failed with err=%d",i); return; } // output i = rx1*n*rx2*B; dcopy(&i, dsol, &j, mxGetPr(plhs[0]), &j); // free the rest free(dsol); free(drnorms); free(g_res1); free(g_res2); }
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); }
int main (int argc, char *argv[]) { /* Solver arrays and parameters */ complex double *evals; /* Array with the computed eigenvalues */ double *rnorms; /* Array with the computed eigenpairs residual norms */ complex double *evecs; /* Array with the computed eigenvectors; first vector starts in evecs[0], second vector starts in evecs[primme.n], third vector starts in evecs[primme.n*2]... */ primme_params primme; /* PRIMME configuration struct */ double targetShifts[1]; /* Other miscellaneous items */ int ret; int i; /* Set default values in PRIMME configuration struct */ primme_initialize(&primme); /* Set problem matrix */ primme.matrixMatvec = LaplacianLikeMatrixMatvec; /* Function that implements the matrix-vector product A*x for solving the problem A*x = l*x */ /* Set problem parameters */ primme.n = 100; /* set problem dimension */ primme.numEvals = 10; /* Number of wanted eigenpairs */ primme.eps = 1e-9; /* ||r|| <= eps * ||matrix|| */ targetShifts[0] = .5; primme.targetShifts = targetShifts; primme.numTargetShifts = 1; primme.target = primme_closest_abs; /* Wanted the smallest eigenvalues */ /* Set preconditioner (optional) */ primme.applyPreconditioner = LaplacianLikeApplyPreconditioner; primme.correctionParams.precondition = 1; /* Set advanced parameters if you know what are you doing (optional) */ /* primme.maxBasisSize = 14; primme.minRestartSize = 4; primme.maxBlockSize = 1; primme.maxMatvecs = 1000; */ /* Set method to solve the problem */ /* NOTE: PRIMME_DEFAULT_MIN_TIME is not supported normal operators */ primme_set_method(PRIMME_DEFAULT_MIN_MATVECS, &primme); /* You can set other methods, such as PRIMME_LOBPCG_OrthoBasis_Window */ /* NOTE: cheap Olsen approximation is not supported for normal operators */ primme.correctionParams.projectors.RightX = 0; primme.printLevel = 3; /* Display PRIMME configuration struct (optional) */ primme_display_params(primme); /* Allocate space for converged Ritz values and residual norms */ evals = (complex double*)malloc(primme.numEvals*sizeof(complex double)); evecs = (complex double*)malloc(primme.n*primme.numEvals*sizeof(complex double)); rnorms = (double*)malloc(primme.numEvals*sizeof(double)); /* Call primme */ ret = zprimme_normal(evals, evecs, rnorms, &primme); if (ret != 0) { fprintf(primme.outputFile, "Error: primme returned with nonzero exit status: %d \n",ret); return -1; } /* Reporting (optional) */ for (i=0; i < primme.initSize; i++) { fprintf(primme.outputFile, "Eval[%d]: %-22.15E + %-22.15E I rnorm: %-22.15E\n", i+1, creal(evals[i]), cimag(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: %-" PRIMME_INT_P "\n", primme.stats.numOuterIterations); fprintf(primme.outputFile, "Restarts : %-" PRIMME_INT_P "\n", primme.stats.numRestarts); fprintf(primme.outputFile, "Matvecs : %-" PRIMME_INT_P "\n", primme.stats.numMatvecs); fprintf(primme.outputFile, "Preconds : %-" PRIMME_INT_P "\n", primme.stats.numPreconds); if (primme.stats.lockingIssue) { fprintf(primme.outputFile, "\nA locking problem has occurred.\n"); fprintf(primme.outputFile, "Some eigenpairs do not have a residual norm less than the tolerance.\n"); fprintf(primme.outputFile, "However, the subspace of evecs is accurate to the required tolerance.\n"); } 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; } /* Note that d/zprimme can be called more than once before call primme_free. */ /* Find the 5 eigenpairs closest to .5 */ primme.numTargetShifts = 1; targetShifts[0] = .5; primme.targetShifts = targetShifts; primme.target = primme_closest_abs; primme.numEvals = 5; primme.initSize = 0; /* primme.initSize may be not zero after a d/zprimme; so set it to zero to avoid the already converged eigenvectors being used as initial vectors. */ /* Call primme */ ret = zprimme_normal(evals, evecs, rnorms, &primme); if (ret != 0) { fprintf(primme.outputFile, "Error: primme returned with nonzero exit status: %d \n",ret); return -1; } /* Reporting (optional) */ for (i=0; i < primme.initSize; i++) { fprintf(primme.outputFile, "Eval[%d]: %-22.15E + %-22.15E I rnorm: %-22.15E\n", i+1, creal(evals[i]), cimag(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: %-" PRIMME_INT_P "\n", primme.stats.numOuterIterations); fprintf(primme.outputFile, "Restarts : %-" PRIMME_INT_P "\n", primme.stats.numRestarts); fprintf(primme.outputFile, "Matvecs : %-" PRIMME_INT_P "\n", primme.stats.numMatvecs); fprintf(primme.outputFile, "Preconds : %-" PRIMME_INT_P "\n", primme.stats.numPreconds); if (primme.stats.lockingIssue) { fprintf(primme.outputFile, "\nA locking problem has occurred.\n"); fprintf(primme.outputFile, "Some eigenpairs do not have a residual norm less than the tolerance.\n"); fprintf(primme.outputFile, "However, the subspace of evecs is accurate to the required tolerance.\n"); } 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; } /* Perturb the 5 approximate eigenvectors in evecs and used them as initial solution. This time the solver should converge faster than the last one. */ for (i=0; i<primme.n*5; i++) evecs[i] += rand()/(double)RAND_MAX*1e-4; primme.initSize = 5; primme.numEvals = 5; /* Call primme */ ret = zprimme_normal(evals, evecs, rnorms, &primme); if (ret != 0) { fprintf(primme.outputFile, "Error: primme returned with nonzero exit status: %d \n",ret); return -1; } /* Reporting (optional) */ for (i=0; i < primme.initSize; i++) { fprintf(primme.outputFile, "Eval[%d]: %-22.15E + %-22.15E I rnorm: %-22.15E\n", i+1, creal(evals[i]), cimag(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: %-" PRIMME_INT_P "\n", primme.stats.numOuterIterations); fprintf(primme.outputFile, "Restarts : %-" PRIMME_INT_P "\n", primme.stats.numRestarts); fprintf(primme.outputFile, "Matvecs : %-" PRIMME_INT_P "\n", primme.stats.numMatvecs); fprintf(primme.outputFile, "Preconds : %-" PRIMME_INT_P "\n", primme.stats.numPreconds); if (primme.stats.lockingIssue) { fprintf(primme.outputFile, "\nA locking problem has occurred.\n"); fprintf(primme.outputFile, "Some eigenpairs do not have a residual norm less than the tolerance.\n"); fprintf(primme.outputFile, "However, the subspace of evecs is accurate to the required tolerance.\n"); } 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; } /* Find the next 5 eigenpairs closest to .5 */ primme.initSize = 0; primme.numEvals = 5; primme.numOrthoConst = 5; /* solver will find solutions orthogonal to the already 5 approximate eigenvectors in evecs */ /* Call primme */ ret = zprimme_normal(evals, evecs, rnorms, &primme); if (ret != 0) { fprintf(primme.outputFile, "Error: primme returned with nonzero exit status: %d \n",ret); return -1; } /* Reporting (optional) */ for (i=0; i < primme.initSize; i++) { fprintf(primme.outputFile, "Eval[%d]: %-22.15E + %-22.15E I rnorm: %-22.15E\n", i+1, creal(evals[i]), cimag(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: %-" PRIMME_INT_P "\n", primme.stats.numOuterIterations); fprintf(primme.outputFile, "Restarts : %-" PRIMME_INT_P "\n", primme.stats.numRestarts); fprintf(primme.outputFile, "Matvecs : %-" PRIMME_INT_P "\n", primme.stats.numMatvecs); fprintf(primme.outputFile, "Preconds : %-" PRIMME_INT_P "\n", primme.stats.numPreconds); if (primme.stats.lockingIssue) { fprintf(primme.outputFile, "\nA locking problem has occurred.\n"); fprintf(primme.outputFile, "Some eigenpairs do not have a residual norm less than the tolerance.\n"); fprintf(primme.outputFile, "However, the subspace of evecs is accurate to the required tolerance.\n"); } 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; } primme_free(&primme); free(evals); free(evecs); free(rnorms); return(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); }
void primme_set_method_f77(primme_params **primme, int *method, int *returnValue) #endif { int d; switch (*method) { case PRIMMEF77_DYNAMIC: d = primme_set_method(DYNAMIC, *primme); break; case PRIMMEF77_DEFAULT_MIN_TIME: d = primme_set_method(DEFAULT_MIN_TIME, *primme); break; case PRIMMEF77_DEFAULT_MIN_MATVECS: d = primme_set_method(DEFAULT_MIN_MATVECS, *primme); break; case PRIMMEF77_Arnoldi: d = primme_set_method(Arnoldi, *primme); break; case PRIMMEF77_GD: d = primme_set_method(GD, *primme); break; case PRIMMEF77_GD_plusK: d = primme_set_method(GD_plusK, *primme); break; case PRIMMEF77_GD_Olsen_plusK: d = primme_set_method(GD_Olsen_plusK, *primme); break; case PRIMMEF77_JD_Olsen_plusK: d = primme_set_method(JD_Olsen_plusK, *primme); break; case PRIMMEF77_RQI: d = primme_set_method(RQI, *primme); break; case PRIMMEF77_JDQR: d = primme_set_method(JDQR, *primme); break; case PRIMMEF77_JDQMR: d = primme_set_method(JDQMR, *primme); break; case PRIMMEF77_JDQMR_ETol: d = primme_set_method(JDQMR_ETol, *primme); break; case PRIMMEF77_SUBSPACE_ITERATION: d = primme_set_method(SUBSPACE_ITERATION, *primme); break; case PRIMMEF77_LOBPCG_OrthoBasis: d = primme_set_method(LOBPCG_OrthoBasis, *primme); break; case PRIMMEF77_LOBPCG_OrthoBasis_Window: d = primme_set_method(LOBPCG_OrthoBasis_Window, *primme); break; default : fprintf(stderr," Using user parameter settings.\n"); d = primme_set_method( (primme_preset_method) -1, *primme); break; } *returnValue = d; }