static int allocate_workspace(primme_params *primme, int allocate) { long int realWorkSize; /* Size of real work space. */ long int rworkByteSize; /* Size of all real data in bytes */ int dataSize; /* Number of Complex_Z positions allocated, excluding */ /* doubles (see doubleSize below) and work space. */ int doubleSize=0; /* Number of doubles allocated exclusively to the */ /* double arrays: hVals, prevRitzVals, blockNorms */ int maxEvecsSize; /* Maximum number of vectors in evecs and evecsHat */ int intWorkSize; /* Size of integer work space in bytes */ int initSize; /* Amount of work space required by init routine */ int orthoSize; /* Amount of work space required by ortho routine */ int convSize; /* Amount of work space required by converg. routine */ int restartSize; /* Amount of work space required by restart routine */ int solveCorSize; /* work space for solve_correction and inner_solve */ int solveHSize; /* work space for solve_H */ int mainSize; /* work space for main_iter */ Complex_Z *evecsHat=NULL;/* not NULL when evecsHat will be used */ Complex_Z t; /* dummy variable */ maxEvecsSize = primme->numOrthoConst + primme->numEvals; /* first determine real workspace */ /*----------------------------------------------------------------------*/ /* Compute the memory required by the main iteration data structures */ /*----------------------------------------------------------------------*/ dataSize = primme->nLocal*primme->maxBasisSize /* Size of V */ + primme->nLocal*primme->maxBasisSize /* Size of W */ + primme->maxBasisSize*primme->maxBasisSize /* Size of H */ + primme->maxBasisSize*primme->maxBasisSize /* Size of hVecs */ + primme->restartingParams.maxPrevRetain*primme->maxBasisSize; /* size of prevHVecs */ /*----------------------------------------------------------------------*/ /* Add memory for Harmonic or Refined projection */ /*----------------------------------------------------------------------*/ if (primme->projectionParams.projection == primme_proj_harmonic || primme->projectionParams.projection == primme_proj_refined) { dataSize += primme->nLocal*primme->maxBasisSize /* Size of Q */ + primme->maxBasisSize*primme->maxBasisSize /* Size of R */ + primme->maxBasisSize*primme->maxBasisSize; /* Size of hU */ doubleSize += primme->maxBasisSize; /* Size of hSVals */ } /*----------------------------------------------------------------------*/ /* Add also memory needed for JD skew projectors */ /*----------------------------------------------------------------------*/ if ( (primme->correctionParams.precondition && primme->correctionParams.maxInnerIterations != 0 && primme->correctionParams.projectors.RightQ && primme->correctionParams.projectors.SkewQ ) ) { dataSize = dataSize + + primme->nLocal*maxEvecsSize /* Size of evecsHat */ + maxEvecsSize*maxEvecsSize /* Size of M */ + maxEvecsSize*maxEvecsSize; /* Size of UDU */ evecsHat = &t; /* set not NULL */ } /*----------------------------------------------------------------------*/ /* Determine workspace required by init and its children */ /*----------------------------------------------------------------------*/ initSize = init_basis_zprimme(NULL, primme->nLocal, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, &primme->maxBasisSize, NULL, NULL, NULL, primme); /*----------------------------------------------------------------------*/ /* Determine orthogalization workspace with and without locking. */ /*----------------------------------------------------------------------*/ if (primme->locking) { orthoSize = ortho_zprimme(NULL, 0, NULL, 0, primme->maxBasisSize, primme->maxBasisSize+primme->maxBlockSize-1, NULL, primme->nLocal, maxEvecsSize, primme->nLocal, NULL, 0.0, NULL, 0, primme); } else { orthoSize = ortho_zprimme(NULL, 0, NULL, 0, primme->maxBasisSize, primme->maxBasisSize+primme->maxBlockSize-1, NULL, primme->nLocal, primme->numOrthoConst+1, primme->nLocal, NULL, 0.0, NULL, 0, primme); } /*----------------------------------------------------------------------*/ /* Determine workspace required by solve_H and its children */ /*----------------------------------------------------------------------*/ solveHSize = solve_H_zprimme(NULL, primme->maxBasisSize, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, 0, NULL, NULL, primme); /*----------------------------------------------------------------------*/ /* Determine workspace required by solve_correction and its children */ /*----------------------------------------------------------------------*/ solveCorSize = solve_correction_zprimme(NULL, NULL, NULL, NULL, NULL, NULL, NULL, maxEvecsSize, 0, NULL, NULL, NULL, NULL, primme->maxBasisSize, NULL, NULL, primme->maxBlockSize, 1.0, 0.0, 1.0, NULL, NULL, 0, primme); /*----------------------------------------------------------------------*/ /* Determine workspace required by solve_H and its children */ /*----------------------------------------------------------------------*/ convSize = check_convergence_zprimme(NULL, primme->nLocal, 0, &t, 0, NULL, primme->numEvals, 0, 0, primme->maxBasisSize, NULL, NULL, NULL, 0.0, NULL, 0, NULL, primme); /*----------------------------------------------------------------------*/ /* Determine workspace required by restarting and its children */ /*----------------------------------------------------------------------*/ restartSize = restart_zprimme(NULL, NULL, primme->nLocal, primme->maxBasisSize, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, evecsHat, 0, NULL, 0, NULL, 0, NULL, NULL, NULL, &primme->numEvals, NULL, &primme->restartingParams.maxPrevRetain, primme->maxBasisSize, primme->initSize, NULL, &primme->maxBasisSize, NULL, primme->maxBasisSize, NULL, 0, NULL, 0, NULL, 0, 0, NULL, 0, 0, NULL, NULL, 0.0, NULL, 0, NULL, primme); /*----------------------------------------------------------------------*/ /* Determine workspace required by main_iter and its children */ /*----------------------------------------------------------------------*/ mainSize = max( update_projection_zprimme(NULL, 0, NULL, 0, NULL, 0, 0, 0, primme->maxBasisSize, NULL, 0, primme), prepare_candidates_zprimme(NULL, NULL, primme->nLocal, primme->maxBasisSize, 0, NULL, NULL, NULL, 0, NULL, NULL, primme->numEvals, primme->numEvals, NULL, 0, primme->maxBlockSize, NULL, primme->numEvals, NULL, NULL, 0.0, NULL, &primme->maxBlockSize, NULL, NULL, 0, NULL, primme)); /*----------------------------------------------------------------------*/ /* Workspace is reused in many functions. Allocate the max needed by any*/ /*----------------------------------------------------------------------*/ realWorkSize = Num_imax_primme(8, /* Workspace needed by init_basis */ initSize, /* Workspace needed by solve_correction and its child inner_solve */ solveCorSize, /* Workspace needed by function solve_H */ solveHSize, /* Workspace needed by function check_convergence */ convSize, /* Workspace needed by function restart*/ restartSize, /* Workspace needed by function verify_norms */ 2*primme->numEvals, /* maximum workspace needed by ortho */ orthoSize, /* maximum workspace for main */ mainSize); /*----------------------------------------------------------------------*/ /* The following size is always allocated as double */ /*----------------------------------------------------------------------*/ doubleSize += 4 /* Padding */ + primme->maxBasisSize /* Size of hVals */ + primme->numEvals+primme->maxBasisSize /* Size of prevRitzVals */ + primme->maxBlockSize; /* Size of blockNorms */ /*----------------------------------------------------------------------*/ /* Determine the integer workspace needed */ /*----------------------------------------------------------------------*/ intWorkSize = primme->maxBasisSize /* Size of flag */ + 2*primme->maxBlockSize /* Size of iev and ilev */ + maxEvecsSize /* Size of ipivot */ + 5*primme->maxBasisSize; /* Auxiliary permutation arrays */ /*----------------------------------------------------------------------*/ /* byte sizes: */ /*----------------------------------------------------------------------*/ rworkByteSize = (dataSize + realWorkSize)*sizeof(Complex_Z) + doubleSize*sizeof(double); /*----------------------------------------------------------------------*/ /* If only the amount of required workspace is needed return it in bytes*/ /*----------------------------------------------------------------------*/ if (!allocate) { primme->intWorkSize = intWorkSize*sizeof(int); primme->realWorkSize = rworkByteSize; return 1; } /*----------------------------------------------------------------------*/ /* Allocate the required workspace, if the user did not provide enough */ /*----------------------------------------------------------------------*/ if (primme->realWorkSize < rworkByteSize || primme->realWork == NULL) { if (primme->realWork != NULL) { free(primme->realWork); } primme->realWorkSize = rworkByteSize; primme->realWork = (void *) primme_valloc(rworkByteSize,"Real Alloc"); if (primme->printLevel >= 5) fprintf(primme->outputFile, "Allocating real workspace: %ld bytes\n", primme->realWorkSize); } if (primme->intWorkSize < intWorkSize*(int)sizeof(int) || primme->intWork==NULL) { if (primme->intWork != NULL) { free(primme->intWork); } primme->intWorkSize = intWorkSize*sizeof(int); primme->intWork= (int *)primme_valloc(primme->intWorkSize ,"Int Alloc"); if (primme->printLevel >= 5) fprintf(primme->outputFile, "Allocating integer workspace: %d bytes\n", primme->intWorkSize); } if (primme->intWork == NULL || primme->realWork == NULL) { primme_PushErrorMessage(Primme_allocate_workspace, Primme_malloc, 0, __FILE__, __LINE__, primme); return MALLOC_FAILURE; } return 0; /***************************************************************************/ } /* end of allocate workspace
static int allocate_workspace(primme_params *primme, int allocate) { long int realWorkSize; /* Size of real work space. */ long int rworkByteSize; /* Size of all real data in bytes */ int dataSize; /* Number of double positions allocated, excluding */ /* doubles (see doubleSize below) and work space. */ int doubleSize; /* Number of doubles allocated exclusively to the */ /* double arrays: hVals, prevRitzVals, blockNorms */ int maxEvecsSize; /* Maximum number of vectors in evecs and evecsHat */ int intWorkSize; /* Size of integer work space in bytes */ int orthoSize; /* Amount of work space required by ortho routine */ int solveCorSize; /* work space for solve_correction and inner_solve */ maxEvecsSize = primme->numOrthoConst + primme->numEvals; /* first determine real workspace */ /*----------------------------------------------------------------------*/ /* Compute the memory required by the main iteration data structures */ /*----------------------------------------------------------------------*/ dataSize = primme->nLocal*primme->maxBasisSize /* Size of V */ + primme->nLocal*primme->maxBasisSize /* Size of W */ + primme->maxBasisSize*primme->maxBasisSize /* Size of H */ + primme->maxBasisSize*primme->maxBasisSize /* Size of hVecs */ + primme->restartingParams.maxPrevRetain*primme->maxBasisSize; /* size of prevHVecs */ /*----------------------------------------------------------------------*/ /* Add also memory needed for JD skew projectors */ /*----------------------------------------------------------------------*/ if ( (primme->correctionParams.precondition && primme->correctionParams.maxInnerIterations != 0 && primme->correctionParams.projectors.RightQ && primme->correctionParams.projectors.SkewQ ) ) { dataSize = dataSize + + primme->nLocal*maxEvecsSize /* Size of evecsHat */ + maxEvecsSize*maxEvecsSize /* Size of M */ + maxEvecsSize*maxEvecsSize; /* Size of UDU */ } /*----------------------------------------------------------------------*/ /* Determine orthogalization workspace with and without locking. */ /*----------------------------------------------------------------------*/ if (primme->locking) { orthoSize = ortho_dprimme(NULL, primme->nLocal, primme->maxBasisSize, primme->maxBasisSize+primme->maxBlockSize-1, NULL, primme->nLocal, maxEvecsSize, primme->nLocal, NULL, 0.0, NULL, 0, primme); } else { orthoSize = ortho_dprimme(NULL, primme->nLocal, primme->maxBasisSize, primme->maxBasisSize+primme->maxBlockSize-1, NULL, primme->nLocal, primme->numOrthoConst+1, primme->nLocal, NULL, 0.0, NULL, 0, primme); } /*----------------------------------------------------------------------*/ /* Determine workspace required by solve_correction and its children */ /*----------------------------------------------------------------------*/ solveCorSize = solve_correction_dprimme(NULL, NULL, NULL, NULL, NULL, NULL, NULL, maxEvecsSize, 0, NULL, NULL, NULL, NULL, primme->maxBasisSize, NULL, NULL, primme->maxBlockSize, 1.0, 0.0, 1.0, NULL, NULL, 0, primme); /*----------------------------------------------------------------------*/ /* Workspace is reused in many functions. Allocate the max needed by any*/ /*----------------------------------------------------------------------*/ realWorkSize = Num_imax_primme(8, /* Workspace needed by init_basis */ Num_imax_primme(3, maxEvecsSize*primme->numOrthoConst, maxEvecsSize, orthoSize), /* Workspace needed by solve_correction and its child inner_solve */ solveCorSize, /* Workspace needed by function solve_H */ #ifdef ESSL 2*primme->maxBasisSize + primme->maxBasisSize*(primme->maxBasisSize + 1)/2, #else 3*primme->maxBasisSize, #endif /* Workspace needed by function check_convergence */ max(primme->maxBasisSize*primme->maxBlockSize + primme->maxBlockSize, 2*maxEvecsSize*primme->maxBlockSize), /* Workspace needed by function restart*/ primme->restartingParams.maxPrevRetain* primme->restartingParams.maxPrevRetain /* for submatrix of prev hvecs */ + Num_imax_primme(4, primme->maxBasisSize, 3*primme->restartingParams.maxPrevRetain, primme->maxBasisSize*primme->restartingParams.maxPrevRetain, primme->maxBasisSize*primme->maxBasisSize, /* for DTR copying */ maxEvecsSize*primme->numEvals), /*this one is for UDU w/o locking */ /* Workspace needed by function verify_norms */ 2*primme->numEvals, /* space needed by lock vectors (no need w/o lock but doesn't add any) */ (2*primme->maxBasisSize) + Num_imax_primme(3, maxEvecsSize*primme->maxBasisSize, orthoSize, 3*primme->maxBasisSize), /* maximum workspace needed by ortho */ orthoSize); /*----------------------------------------------------------------------*/ /* The following size is always alloced as double */ /*----------------------------------------------------------------------*/ doubleSize = primme->maxBasisSize /* Size of hVals */ + primme->numEvals+primme->maxBasisSize /* Size of prevRitzVals */ + primme->maxBlockSize; /* Size of blockNorms */ /*----------------------------------------------------------------------*/ /* Determine the integer workspace needed */ /*----------------------------------------------------------------------*/ intWorkSize = primme->maxBasisSize /* Size of flag */ + 2*primme->maxBlockSize /* Size of iev and ilev */ + maxEvecsSize /* Size of ipivot */ + 2*primme->maxBasisSize; /* Size of 2 perms in solve_H */ /*----------------------------------------------------------------------*/ /* byte sizes: */ /*----------------------------------------------------------------------*/ rworkByteSize = (dataSize + realWorkSize)*sizeof(double) + doubleSize*sizeof(double); /*----------------------------------------------------------------------*/ /* If only the amount of required workspace is needed return it in bytes*/ /*----------------------------------------------------------------------*/ if (!allocate) { primme->intWorkSize = intWorkSize*sizeof(int); primme->realWorkSize = rworkByteSize; return 1; } /*----------------------------------------------------------------------*/ /* Allocate the required workspace, if the user did not provide enough */ /*----------------------------------------------------------------------*/ if (primme->realWorkSize < rworkByteSize || primme->realWork == NULL) { if (primme->realWork != NULL) { free(primme->realWork); } primme->realWorkSize = rworkByteSize; primme->realWork = (void *) primme_valloc(rworkByteSize,"Real Alloc"); if (primme->printLevel >= 5) fprintf(primme->outputFile, "Allocating real workspace: %ld bytes\n", primme->realWorkSize); } if (primme->intWorkSize < intWorkSize*sizeof(int) || primme->intWork==NULL) { if (primme->intWork != NULL) { free(primme->intWork); } primme->intWorkSize = intWorkSize*sizeof(int); primme->intWork= (int *)primme_valloc(primme->intWorkSize ,"Int Alloc"); if (primme->printLevel >= 5) fprintf(primme->outputFile, "Allocating integer workspace: %d bytes\n", primme->intWorkSize); } if (primme->intWork == NULL || primme->realWork == NULL) { primme_PushErrorMessage(Primme_allocate_workspace, Primme_malloc, 0, __FILE__, __LINE__, primme); return MALLOC_FAILURE; } return 0; /***************************************************************************/ } /* end of allocate workspace