Date: 2013-09-02T10:07:55+00:00

Actual source code: nepsetup.c

      1: /*
      2:       NEP routines related to problem setup.

      4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      6:    Copyright (c) 2002-2013, Universitat Politecnica de Valencia, Spain

      8:    This file is part of SLEPc.

     10:    SLEPc is free software: you can redistribute it and/or modify it under  the
     11:    terms of version 3 of the GNU Lesser General Public License as published by
     12:    the Free Software Foundation.

     14:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
     15:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
     16:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
     17:    more details.

     19:    You  should have received a copy of the GNU Lesser General  Public  License
     20:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
     21:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     22: */

     24: #include <slepc-private/nepimpl.h>       /*I "slepcnep.h" I*/
     25: #include <slepc-private/ipimpl.h>

     29: /*@
     30:    NEPSetUp - Sets up all the internal data structures necessary for the
     31:    execution of the NEP solver.

     33:    Collective on NEP

     35:    Input Parameter:
     36: .  nep   - solver context

     38:    Notes:
     39:    This function need not be called explicitly in most cases, since NEPSolve()
     40:    calls it. It can be useful when one wants to measure the set-up time
     41:    separately from the solve time.

     43:    Level: advanced

     45: .seealso: NEPCreate(), NEPSolve(), NEPDestroy()
     46: @*/
     47: PetscErrorCode NEPSetUp(NEP nep)
     48: {
     50:   Mat            T;

     54:   if (nep->setupcalled) return(0);
     55:   PetscLogEventBegin(NEP_SetUp,nep,0,0,0);

     57:   /* reset the convergence flag from the previous solves */
     58:   nep->reason = NEP_CONVERGED_ITERATING;

     60:   /* Set default solver type (NEPSetFromOptions was not called) */
     61:   if (!((PetscObject)nep)->type_name) {
     62:     NEPSetType(nep,NEPRII);
     63:   }
     64:   if (!nep->ip) { NEPGetIP(nep,&nep->ip); }
     65:   if (!((PetscObject)nep->ip)->type_name) {
     66:     IPSetType_Default(nep->ip);
     67:   }
     68:   if (!nep->ds) { NEPGetDS(nep,&nep->ds); }
     69:   DSReset(nep->ds);
     70:   if (!((PetscObject)nep->rand)->type_name) {
     71:     PetscRandomSetFromOptions(nep->rand);
     72:   }
     73:   if (!nep->ksp) {
     74:     NEPGetKSP(nep,&nep->ksp);
     75:   }

     77:   /* by default, compute eigenvalues close to target */
     78:   /* nep->target should contain the initial guess for the eigenvalue */
     79:   if (!nep->which) nep->which = NEP_TARGET_MAGNITUDE;

     81:   /* set problem dimensions */
     82:   VecDestroy(&nep->t);
     83:   if (nep->split) {
     84:     MatDuplicate(nep->A[0],MAT_DO_NOT_COPY_VALUES,&nep->function);
     85:     MatDuplicate(nep->A[0],MAT_DO_NOT_COPY_VALUES,&nep->jacobian);
     86:     PetscLogObjectParent(nep,nep->function);
     87:     PetscLogObjectParent(nep,nep->jacobian);
     88:     SlepcMatGetVecsTemplate(nep->A[0],&nep->t,NULL);
     89:   } else {
     90:     NEPGetFunction(nep,&T,NULL,NULL,NULL);
     91:     SlepcMatGetVecsTemplate(T,&nep->t,NULL);
     92:   }
     93:   PetscLogObjectParent(nep,nep->t);
     94:   VecGetSize(nep->t,&nep->n);
     95:   VecGetLocalSize(nep->t,&nep->nloc);

     97:   /* call specific solver setup */
     98:   (*nep->ops->setup)(nep);

    100:   /* set tolerances if not yet set */
    101:   if (nep->abstol==PETSC_DEFAULT) nep->abstol = 1e-50;
    102:   if (nep->rtol==PETSC_DEFAULT) nep->rtol = 100*SLEPC_DEFAULT_TOL;
    103:   if (nep->stol==PETSC_DEFAULT) nep->stol = SLEPC_DEFAULT_TOL;
    104:   nep->ktol   = 0.1;
    105:   nep->nfuncs = 0;
    106:   nep->linits = 0;

    108:   /* set eigenvalue comparison */
    109:   switch (nep->which) {
    110:     case NEP_LARGEST_MAGNITUDE:
    111:       nep->comparison    = SlepcCompareLargestMagnitude;
    112:       nep->comparisonctx = NULL;
    113:       break;
    114:     case NEP_SMALLEST_MAGNITUDE:
    115:       nep->comparison    = SlepcCompareSmallestMagnitude;
    116:       nep->comparisonctx = NULL;
    117:       break;
    118:     case NEP_LARGEST_REAL:
    119:       nep->comparison    = SlepcCompareLargestReal;
    120:       nep->comparisonctx = NULL;
    121:       break;
    122:     case NEP_SMALLEST_REAL:
    123:       nep->comparison    = SlepcCompareSmallestReal;
    124:       nep->comparisonctx = NULL;
    125:       break;
    126:     case NEP_LARGEST_IMAGINARY:
    127:       nep->comparison    = SlepcCompareLargestImaginary;
    128:       nep->comparisonctx = NULL;
    129:       break;
    130:     case NEP_SMALLEST_IMAGINARY:
    131:       nep->comparison    = SlepcCompareSmallestImaginary;
    132:       nep->comparisonctx = NULL;
    133:       break;
    134:     case NEP_TARGET_MAGNITUDE:
    135:       nep->comparison    = SlepcCompareTargetMagnitude;
    136:       nep->comparisonctx = &nep->target;
    137:       break;
    138:     case NEP_TARGET_REAL:
    139:       nep->comparison    = SlepcCompareTargetReal;
    140:       nep->comparisonctx = &nep->target;
    141:       break;
    142:     case NEP_TARGET_IMAGINARY:
    143:       nep->comparison    = SlepcCompareTargetImaginary;
    144:       nep->comparisonctx = &nep->target;
    145:       break;
    146:   }

    148:   if (nep->ncv > 2*nep->n) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"ncv must be twice the problem size at most");
    149:   if (nep->nev > nep->ncv) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"nev bigger than ncv");

    151:   /* process initial vectors */
    152:   if (nep->nini<0) {
    153:     nep->nini = -nep->nini;
    154:     if (nep->nini>nep->ncv) SETERRQ(PetscObjectComm((PetscObject)nep),1,"The number of initial vectors is larger than ncv");
    155:     IPOrthonormalizeBasis_Private(nep->ip,&nep->nini,&nep->IS,nep->V);
    156:   }
    157:   PetscLogEventEnd(NEP_SetUp,nep,0,0,0);
    158:   nep->setupcalled = 1;
    159:   return(0);
    160: }

    164: /*@
    165:    NEPSetInitialSpace - Specify a basis of vectors that constitute the initial
    166:    space, that is, the subspace from which the solver starts to iterate.

    168:    Collective on NEP and Vec

    170:    Input Parameter:
    171: +  nep   - the nonlinear eigensolver context
    172: .  n     - number of vectors
    173: -  is    - set of basis vectors of the initial space

    175:    Notes:
    176:    Some solvers start to iterate on a single vector (initial vector). In that case,
    177:    the other vectors are ignored.

    179:    These vectors do not persist from one NEPSolve() call to the other, so the
    180:    initial space should be set every time.

    182:    The vectors do not need to be mutually orthonormal, since they are explicitly
    183:    orthonormalized internally.

    185:    Common usage of this function is when the user can provide a rough approximation
    186:    of the wanted eigenspace. Then, convergence may be faster.

    188:    Level: intermediate
    189: @*/
    190: PetscErrorCode NEPSetInitialSpace(NEP nep,PetscInt n,Vec *is)
    191: {

    197:   if (n<0) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Argument n cannot be negative");
    198:   SlepcBasisReference_Private(n,is,&nep->nini,&nep->IS);
    199:   if (n>0) nep->setupcalled = 0;
    200:   return(0);
    201: }

    205: /*
    206:   NEPAllocateSolution - Allocate memory storage for common variables such
    207:   as eigenvalues and eigenvectors. All vectors in V (and W) share a
    208:   contiguous chunk of memory.
    209: */
    210: PetscErrorCode NEPAllocateSolution(NEP nep)
    211: {
    213:   PetscInt       newc,cnt;

    216:   if (nep->allocated_ncv != nep->ncv) {
    217:     newc = PetscMax(0,nep->ncv-nep->allocated_ncv);
    218:     NEPFreeSolution(nep);
    219:     cnt = 0;
    220:     PetscMalloc(nep->ncv*sizeof(PetscScalar),&nep->eig);
    221:     cnt += 2*newc*sizeof(PetscScalar);
    222:     PetscMalloc(nep->ncv*sizeof(PetscReal),&nep->errest);
    223:     PetscMalloc(nep->ncv*sizeof(PetscInt),&nep->perm);
    224:     cnt += 2*newc*sizeof(PetscReal);
    225:     PetscLogObjectMemory(nep,cnt);
    226:     VecDuplicateVecs(nep->t,nep->ncv,&nep->V);
    227:     PetscLogObjectParents(nep,nep->ncv,nep->V);
    228:     nep->allocated_ncv = nep->ncv;
    229:   }
    230:   return(0);
    231: }

    235: /*
    236:   NEPFreeSolution - Free memory storage. This routine is related to
    237:   NEPAllocateSolution().
    238: */
    239: PetscErrorCode NEPFreeSolution(NEP nep)
    240: {

    244:   if (nep->allocated_ncv > 0) {
    245:     PetscFree(nep->eig);
    246:     PetscFree(nep->errest);
    247:     PetscFree(nep->perm);
    248:     VecDestroyVecs(nep->allocated_ncv,&nep->V);
    249:     nep->allocated_ncv = 0;
    250:   }
    251:   return(0);
    252: }