int zprimme(double *evals, Complex_Z *evecs, double *resNorms, primme_params *primme) { int ret; int *perm; double machEps; /* ------------------ */ /* zero out the timer */ /* ------------------ */ primme_wTimer(1); /* ---------------------------- */ /* Clear previous error reports */ /* ---------------------------- */ primme_DeleteStackTrace(primme); /* ----------------------- */ /* Find machine precision */ /* ----------------------- */ machEps = Num_dlamch_primme("E"); /* ------------------ */ /* Set some defaults */ /* ------------------ */ primme_set_defaults(primme); /* -------------------------------------------------------------- */ /* If needed, we are ready to estimate required memory and return */ /* -------------------------------------------------------------- */ if (evals == NULL && evecs == NULL && resNorms == NULL) return allocate_workspace(primme, FALSE); /* ----------------------------------------------------- */ /* Reset random number seed if inappropriate for DLARENV */ /* Yields unique quadruples per proc if procID < 4096^3 */ /* ----------------------------------------------------- */ if (primme->iseed[0]<0 || primme->iseed[0]>4095) primme->iseed[0] = primme->procID % 4096; if (primme->iseed[1]<0 || primme->iseed[1]>4095) primme->iseed[1] = (int)(primme->procID/4096+1) % 4096; if (primme->iseed[2]<0 || primme->iseed[2]>4095) primme->iseed[2] = (int)((primme->procID/4096)/4096+2) % 4096; if (primme->iseed[3]<0 || primme->iseed[3]>4095) primme->iseed[3] = (2*(int)(((primme->procID/4096)/4096)/4096)+1) % 4096; /* ----------------------- */ /* Set default convTetFun */ /* ----------------------- */ if (!primme->convTestFun) { primme->convTestFun = convTestFunAbsolute; } /* ------------------------------------------------------- */ /* Check primme input data for bounds, correct values etc. */ /* ------------------------------------------------------- */ ret = check_input(evals, evecs, resNorms, primme); if (ret != 0) { primme_PushErrorMessage(Primme_zprimme, Primme_check_input, ret, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return ret; } /* ----------------------------------------------------------------------- */ /* Compute AND allocate memory requirements for main_iter and subordinates */ /* ----------------------------------------------------------------------- */ ret = allocate_workspace(primme, TRUE); if (ret != 0) { primme_PushErrorMessage(Primme_zprimme, Primme_allocate_workspace, ret, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return ALLOCATE_WORKSPACE_FAILURE; } /* --------------------------------------------------------- */ /* Allocate workspace that will be needed locally by zprimme */ /* --------------------------------------------------------- */ perm = (int *)primme_calloc((primme->numEvals), sizeof(int), "Perm array"); if (perm == NULL) { primme_PushErrorMessage(Primme_zprimme, Primme_malloc, 0, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return MALLOC_FAILURE; } /*----------------------------------------------------------------------*/ /* Call the solver */ /*----------------------------------------------------------------------*/ ret = main_iter_zprimme(evals, perm, evecs, resNorms, machEps, primme->intWork, primme->realWork, primme); if (ret < 0) { primme_PushErrorMessage(Primme_zprimme, Primme_main_iter, ret, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return MAIN_ITER_FAILURE; } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* If locking is engaged, the converged Ritz vectors are stored in the */ /* order they converged. They must then be permuted so that they */ /* correspond to the sorted Ritz values in evals. */ /*----------------------------------------------------------------------*/ permute_vecs_zprimme(&evecs[primme->numOrthoConst], primme->nLocal, primme->initSize, primme->nLocal, perm, (Complex_Z*)primme->realWork, (int*)primme->intWork); free(perm); primme->stats.elapsedTime = primme_wTimer(0); return(0); }
int zprimme(double *evals, Complex_Z *evecs, double *resNorms, primme_params *primme) { int ret; int *perm; double machEps; /* ------------------ */ /* zero out the timer */ /* ------------------ */ primme_wTimer(1); /* ---------------------------- */ /* Clear previous error reports */ /* ---------------------------- */ primme_DeleteStackTrace(primme); /* ----------------------- */ /* Find machine precision */ /* ----------------------- */ machEps = Num_dlamch_primme("E"); /* ----------------------------------------- */ /* Set some defaults for sequential programs */ /* ----------------------------------------- */ if (primme->numProcs == 1) { primme->nLocal = primme->n; primme->procID = 0; if (primme->globalSumDouble == NULL) primme->globalSumDouble = primme_seq_globalSumDouble; } /* --------------------------------------------------------------------- */ /* Decide on whether to use locking (hard locking), or not (soft locking)*/ /* --------------------------------------------------------------------- */ if (primme->target != primme_smallest && primme->target != primme_largest ) { /* Locking is necessary as interior Ritz values can cross shifts */ primme->locking = 1; } else { if (primme->locking == 0) { /* use locking when not enough vectors to restart with */ primme->locking = (primme->numEvals > primme->minRestartSize); } } /* -------------------------------------------------------------- */ /* If needed, we are ready to estimate required memory and return */ /* -------------------------------------------------------------- */ if (evals == NULL && evecs == NULL && resNorms == NULL) return allocate_workspace(primme, FALSE); /* ----------------------------- */ /* Initialize random number seed */ /* ----------------------------- */ if (primme->iseed[0] == -1) { primme->iseed[0] = 1 ;//% (primme->procID+1); primme->iseed[1] = 2 ;//% (primme->procID+2); primme->iseed[2] = 3 ;//% (primme->procID+3); primme->iseed[3] = 5; } /* ------------------------------------------------------- */ /* Check primme input data for bounds, correct values etc. */ /* ------------------------------------------------------- */ ret = check_input(evals, evecs, resNorms, primme); if (ret != 0) { primme_PushErrorMessage(Primme_zprimme, Primme_check_input, ret, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return ret; } /* ----------------------------------------------------------------------- */ /* Compute AND allocate memory requirements for main_iter and subordinates */ /* ----------------------------------------------------------------------- */ ret = allocate_workspace(primme, TRUE); if (ret != 0) { primme_PushErrorMessage(Primme_zprimme, Primme_allocate_workspace, ret, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return ALLOCATE_WORKSPACE_FAILURE; } /* --------------------------------------------------------- */ /* Allocate workspace that will be needed locally by zprimme */ /* --------------------------------------------------------- */ perm = (int *)primme_calloc((primme->numEvals), sizeof(int), "Perm array"); if (perm == NULL) { primme_PushErrorMessage(Primme_zprimme, Primme_malloc, 0, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return MALLOC_FAILURE; } /*----------------------------------------------------------------------*/ /* Call the solver */ /*----------------------------------------------------------------------*/ ret = main_iter_zprimme(evals, perm, evecs, resNorms, machEps, primme->intWork, primme->realWork, primme); if (ret < 0) { primme_PushErrorMessage(Primme_zprimme, Primme_main_iter, ret, __FILE__, __LINE__, primme); primme->stats.elapsedTime = primme_wTimer(0); return MAIN_ITER_FAILURE; } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /* If locking is engaged, the converged Ritz vectors are stored in the */ /* order they converged. They must then be permuted so that they */ /* correspond to the sorted Ritz values in evals. */ /*----------------------------------------------------------------------*/ permute_evecs_zprimme((double *) &evecs[primme->numOrthoConst], 2, perm, (double *) primme->realWork, primme->numEvals, primme->nLocal); free(perm); primme->stats.elapsedTime = primme_wTimer(0); return(0); }