Date: 2016-03-29T14:57:21+00:00

Actual source code: bvfunc.c
slepc-3.6.3 2016-03-29
Report Typos and Errors

      1: /*
      2:    BV (basis vectors) interface routines, callable by users.

      4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      6:    Copyright (c) 2002-2015, 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/bvimpl.h>            /*I "slepcbv.h" I*/

     26: PetscClassId     BV_CLASSID = 0;
     27: PetscLogEvent    BV_Create = 0,BV_Copy = 0,BV_Mult = 0,BV_Dot = 0,BV_Orthogonalize = 0,BV_Scale = 0,BV_Norm = 0,BV_SetRandom = 0,BV_MatMult = 0,BV_MatProject = 0,BV_AXPY = 0;
     28: static PetscBool BVPackageInitialized = PETSC_FALSE;

     32: /*@C
     33:    BVFinalizePackage - This function destroys everything in the Slepc interface
     34:    to the BV package. It is called from SlepcFinalize().

     36:    Level: developer

     38: .seealso: SlepcFinalize()
     39: @*/
     40: PetscErrorCode BVFinalizePackage(void)
     41: {

     45:   PetscFunctionListDestroy(&BVList);
     46:   BVPackageInitialized = PETSC_FALSE;
     47:   BVRegisterAllCalled  = PETSC_FALSE;
     48:   return(0);
     49: }

     53: /*@C
     54:    BVInitializePackage - This function initializes everything in the BV package.
     55:    It is called from PetscDLLibraryRegister() when using dynamic libraries, and
     56:    on the first call to BVCreate() when using static libraries.

     58:    Level: developer

     60: .seealso: SlepcInitialize()
     61: @*/
     62: PetscErrorCode BVInitializePackage(void)
     63: {
     64:   char           logList[256];
     65:   char           *className;
     66:   PetscBool      opt;

     70:   if (BVPackageInitialized) return(0);
     71:   BVPackageInitialized = PETSC_TRUE;
     72:   /* Register Classes */
     73:   PetscClassIdRegister("Basis Vectors",&BV_CLASSID);
     74:   /* Register Constructors */
     75:   BVRegisterAll();
     76:   /* Register Events */
     77:   PetscLogEventRegister("BVCreate",BV_CLASSID,&BV_Create);
     78:   PetscLogEventRegister("BVCopy",BV_CLASSID,&BV_Copy);
     79:   PetscLogEventRegister("BVMult",BV_CLASSID,&BV_Mult);
     80:   PetscLogEventRegister("BVDot",BV_CLASSID,&BV_Dot);
     81:   PetscLogEventRegister("BVOrthogonalize",BV_CLASSID,&BV_Orthogonalize);
     82:   PetscLogEventRegister("BVScale",BV_CLASSID,&BV_Scale);
     83:   PetscLogEventRegister("BVNorm",BV_CLASSID,&BV_Norm);
     84:   PetscLogEventRegister("BVSetRandom",BV_CLASSID,&BV_SetRandom);
     85:   PetscLogEventRegister("BVMatMult",BV_CLASSID,&BV_MatMult);
     86:   PetscLogEventRegister("BVMatProject",BV_CLASSID,&BV_MatProject);
     87:   PetscLogEventRegister("BVAXPY",BV_CLASSID,&BV_AXPY);
     88:   /* Process info exclusions */
     89:   PetscOptionsGetString(NULL,"-info_exclude",logList,256,&opt);
     90:   if (opt) {
     91:     PetscStrstr(logList,"bv",&className);
     92:     if (className) {
     93:       PetscInfoDeactivateClass(BV_CLASSID);
     94:     }
     95:   }
     96:   /* Process summary exclusions */
     97:   PetscOptionsGetString(NULL,"-log_summary_exclude",logList,256,&opt);
     98:   if (opt) {
     99:     PetscStrstr(logList,"bv",&className);
    100:     if (className) {
    101:       PetscLogEventDeactivateClass(BV_CLASSID);
    102:     }
    103:   }
    104:   PetscRegisterFinalize(BVFinalizePackage);
    105:   return(0);
    106: }

    110: /*@
    111:    BVDestroy - Destroys BV context that was created with BVCreate().

    113:    Collective on BV

    115:    Input Parameter:
    116: .  bv - the basis vectors context

    118:    Level: beginner

    120: .seealso: BVCreate()
    121: @*/
    122: PetscErrorCode BVDestroy(BV *bv)
    123: {

    127:   if (!*bv) return(0);
    129:   if (--((PetscObject)(*bv))->refct > 0) { *bv = 0; return(0); }
    130:   if ((*bv)->ops->destroy) { (*(*bv)->ops->destroy)(*bv); }
    131:   VecDestroy(&(*bv)->t);
    132:   MatDestroy(&(*bv)->matrix);
    133:   VecDestroy(&(*bv)->Bx);
    134:   BVDestroy(&(*bv)->cached);
    135:   PetscFree((*bv)->work);
    136:   PetscFree2((*bv)->h,(*bv)->c);
    137:   PetscFree((*bv)->omega);
    138:   MatDestroy(&(*bv)->B);
    139:   MatDestroy(&(*bv)->C);
    140:   PetscHeaderDestroy(bv);
    141:   return(0);
    142: }

    146: /*@
    147:    BVCreate - Creates a basis vectors context.

    149:    Collective on MPI_Comm

    151:    Input Parameter:
    152: .  comm - MPI communicator

    154:    Output Parameter:
    155: .  bv - location to put the basis vectors context

    157:    Level: beginner

    159: .seealso: BVSetUp(), BVDestroy(), BV
    160: @*/
    161: PetscErrorCode BVCreate(MPI_Comm comm,BV *newbv)
    162: {
    164:   BV             bv;

    168:   *newbv = 0;
    169:   BVInitializePackage();
    170:   SlepcHeaderCreate(bv,BV_CLASSID,"BV","Basis Vectors","BV",comm,BVDestroy,BVView);

    172:   bv->t            = NULL;
    173:   bv->n            = -1;
    174:   bv->N            = -1;
    175:   bv->m            = 0;
    176:   bv->l            = 0;
    177:   bv->k            = 0;
    178:   bv->nc           = 0;
    179:   bv->orthog_type  = BV_ORTHOG_CGS;
    180:   bv->orthog_ref   = BV_ORTHOG_REFINE_IFNEEDED;
    181:   bv->orthog_eta   = 0.7071;
    182:   bv->orthog_block = BV_ORTHOG_BLOCK_GS;
    183:   bv->matrix       = NULL;
    184:   bv->indef        = PETSC_FALSE;
    185:   bv->vmm          = BV_MATMULT_MAT;

    187:   bv->Bx           = NULL;
    188:   bv->xid          = 0;
    189:   bv->xstate       = 0;
    190:   bv->cv[0]        = NULL;
    191:   bv->cv[1]        = NULL;
    192:   bv->ci[0]        = -1;
    193:   bv->ci[1]        = -1;
    194:   bv->st[0]        = -1;
    195:   bv->st[1]        = -1;
    196:   bv->id[0]        = 0;
    197:   bv->id[1]        = 0;
    198:   bv->h            = NULL;
    199:   bv->c            = NULL;
    200:   bv->omega        = NULL;
    201:   bv->B            = NULL;
    202:   bv->C            = NULL;
    203:   bv->Aid          = 0;
    204:   bv->defersfo     = PETSC_FALSE;
    205:   bv->cached       = NULL;
    206:   bv->bvstate      = 0;
    207:   bv->work         = NULL;
    208:   bv->lwork        = 0;
    209:   bv->data         = NULL;

    211:   *newbv = bv;
    212:   return(0);
    213: }

    217: /*@
    218:    BVInsertVec - Insert a vector into the specified column.

    220:    Collective on BV

    222:    Input Parameters:
    223: +  V - basis vectors
    224: .  j - the column of V to be overwritten
    225: -  w - the vector to be copied

    227:    Level: intermediate

    229: .seealso: BVInsertVecs()
    230: @*/
    231: PetscErrorCode BVInsertVec(BV V,PetscInt j,Vec w)
    232: {
    234:   PetscInt       n,N;
    235:   Vec            v;

    242:   BVCheckSizes(V,1);

    245:   VecGetSize(w,&N);
    246:   VecGetLocalSize(w,&n);
    247:   if (N!=V->N || n!=V->n) SETERRQ4(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %D, local %D) do not match BV sizes (global %D, local %D)",N,n,V->N,V->n);
    248:   if (j<-V->nc || j>=V->m) SETERRQ3(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument j has wrong value %D, should be between %D and %D",j,-V->nc,V->m-1);

    250:   BVGetColumn(V,j,&v);
    251:   VecCopy(w,v);
    252:   BVRestoreColumn(V,j,&v);
    253:   PetscObjectStateIncrease((PetscObject)V);
    254:   return(0);
    255: }

    259: /*@
    260:    BVInsertVecs - Insert a set of vectors into the specified columns.

    262:    Collective on BV

    264:    Input Parameters:
    265: +  V - basis vectors
    266: .  s - first column of V to be overwritten
    267: .  W - set of vectors to be copied
    268: -  orth - flag indicating if the vectors must be orthogonalized

    270:    Input/Output Parameter:
    271: .  m - number of input vectors, on output the number of linearly independent
    272:        vectors

    274:    Notes:
    275:    Copies the contents of vectors W to V(:,s:s+n). If the orthogonalization
    276:    flag is set, then the vectors are copied one by one and then orthogonalized
    277:    against the previous ones. If any of them is linearly dependent then it
    278:    is discarded and the value of m is decreased.

    280:    Level: intermediate

    282: .seealso: BVInsertVec(), BVOrthogonalizeColumn()
    283: @*/
    284: PetscErrorCode BVInsertVecs(BV V,PetscInt s,PetscInt *m,Vec *W,PetscBool orth)
    285: {
    287:   PetscInt       n,N,i,ndep;
    288:   PetscBool      lindep;
    289:   PetscReal      norm;
    290:   Vec            v;

    297:   if (!*m) return(0);
    298:   if (*m<0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",*m);
    303:   BVCheckSizes(V,1);

    306:   VecGetSize(*W,&N);
    307:   VecGetLocalSize(*W,&n);
    308:   if (N!=V->N || n!=V->n) SETERRQ4(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Vec sizes (global %D, local %D) do not match BV sizes (global %D, local %D)",N,n,V->N,V->n);
    309:   if (s<0 || s>=V->m) SETERRQ2(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument s has wrong value %D, should be between 0 and %D",s,V->m-1);
    310:   if (s+(*m)>V->m) SETERRQ1(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Too many vectors provided, there is only room for %D",V->m);

    312:   ndep = 0;
    313:   for (i=0;i<*m;i++) {
    314:     BVGetColumn(V,s+i-ndep,&v);
    315:     VecCopy(W[i],v);
    316:     BVRestoreColumn(V,s+i-ndep,&v);
    317:     if (orth) {
    318:       BVOrthogonalizeColumn(V,s+i-ndep,NULL,&norm,&lindep);
    319:       if (norm==0.0 || lindep) {
    320:         PetscInfo1(V,"Removing linearly dependent vector %D\n",i);
    321:         ndep++;
    322:       } else {
    323:         BVScaleColumn(V,s+i-ndep,1.0/norm);
    324:       }
    325:     }
    326:   }
    327:   *m -= ndep;
    328:   PetscObjectStateIncrease((PetscObject)V);
    329:   return(0);
    330: }

    334: /*@
    335:    BVInsertConstraints - Insert a set of vectors as constraints.

    337:    Collective on BV

    339:    Input Parameters:
    340: +  V - basis vectors
    341: -  C - set of vectors to be inserted as constraints

    343:    Input/Output Parameter:
    344: .  nc - number of input vectors, on output the number of linearly independent
    345:        vectors

    347:    Notes:
    348:    The constraints are relevant only during orthogonalization. Constraint
    349:    vectors span a subspace that is deflated in every orthogonalization
    350:    operation, so they are intended for removing those directions from the
    351:    orthogonal basis computed in regular BV columns.

    353:    Constraints are not stored in regular BV colums, but in a special part of
    354:    the storage. They can be accessed with negative indices in BVGetColumn().

    356:    This operation is DESTRUCTIVE, meaning that all data contained in the
    357:    columns of V is lost. This is typically invoked just after creating the BV.
    358:    Once a set of constraints has been set, it is not allowed to call this
    359:    function again.

    361:    The vectors are copied one by one and then orthogonalized against the
    362:    previous ones. If any of them is linearly dependent then it is discarded
    363:    and the value of nc is decreased. The behaviour is similar to BVInsertVecs().

    365:    Level: advanced

    367: .seealso: BVInsertVecs(), BVOrthogonalizeColumn(), BVGetColumn(), BVGetNumConstraints()
    368: @*/
    369: PetscErrorCode BVInsertConstraints(BV V,PetscInt *nc,Vec *C)
    370: {
    372:   PetscInt       msave;

    378:   if (!*nc) return(0);
    379:   if (*nc<0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of constraints (given %D) cannot be negative",*nc);
    383:   BVCheckSizes(V,1);
    385:   if (V->nc) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"Constraints already present in this BV object");
    386:   if (V->ci[0]!=-1 || V->ci[1]!=-1) SETERRQ(PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Cannot call BVInsertConstraints after BVGetColumn");

    388:   msave = V->m;
    389:   BVResize(V,*nc+V->m,PETSC_FALSE);
    390:   BVInsertVecs(V,0,nc,C,PETSC_TRUE);
    391:   V->nc = *nc;
    392:   V->m  = msave;
    393:   V->ci[0] = -V->nc-1;
    394:   V->ci[1] = -V->nc-1;
    395:   PetscObjectStateIncrease((PetscObject)V);
    396:   return(0);
    397: }

    401: /*@C
    402:    BVSetOptionsPrefix - Sets the prefix used for searching for all
    403:    BV options in the database.

    405:    Logically Collective on BV

    407:    Input Parameters:
    408: +  bv     - the basis vectors context
    409: -  prefix - the prefix string to prepend to all BV option requests

    411:    Notes:
    412:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    413:    The first character of all runtime options is AUTOMATICALLY the
    414:    hyphen.

    416:    Level: advanced

    418: .seealso: BVAppendOptionsPrefix(), BVGetOptionsPrefix()
    419: @*/
    420: PetscErrorCode BVSetOptionsPrefix(BV bv,const char *prefix)
    421: {

    426:   PetscObjectSetOptionsPrefix((PetscObject)bv,prefix);
    427:   return(0);
    428: }

    432: /*@C
    433:    BVAppendOptionsPrefix - Appends to the prefix used for searching for all
    434:    BV options in the database.

    436:    Logically Collective on BV

    438:    Input Parameters:
    439: +  bv     - the basis vectors context
    440: -  prefix - the prefix string to prepend to all BV option requests

    442:    Notes:
    443:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    444:    The first character of all runtime options is AUTOMATICALLY the
    445:    hyphen.

    447:    Level: advanced

    449: .seealso: BVSetOptionsPrefix(), BVGetOptionsPrefix()
    450: @*/
    451: PetscErrorCode BVAppendOptionsPrefix(BV bv,const char *prefix)
    452: {

    457:   PetscObjectAppendOptionsPrefix((PetscObject)bv,prefix);
    458:   return(0);
    459: }

    463: /*@C
    464:    BVGetOptionsPrefix - Gets the prefix used for searching for all
    465:    BV options in the database.

    467:    Not Collective

    469:    Input Parameters:
    470: .  bv - the basis vectors context

    472:    Output Parameters:
    473: .  prefix - pointer to the prefix string used, is returned

    475:    Notes: On the Fortran side, the user should pass in a string 'prefix' of
    476:    sufficient length to hold the prefix.

    478:    Level: advanced

    480: .seealso: BVSetOptionsPrefix(), BVAppendOptionsPrefix()
    481: @*/
    482: PetscErrorCode BVGetOptionsPrefix(BV bv,const char *prefix[])
    483: {

    489:   PetscObjectGetOptionsPrefix((PetscObject)bv,prefix);
    490:   return(0);
    491: }

    495: static PetscErrorCode BVView_Default(BV bv,PetscViewer viewer)
    496: {
    497:   PetscErrorCode    ierr;
    498:   PetscInt          j;
    499:   Vec               v;
    500:   PetscViewerFormat format;
    501:   PetscBool         isascii,ismatlab=PETSC_FALSE;
    502:   const char        *bvname,*name;

    505:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    506:   if (isascii) {
    507:     PetscViewerGetFormat(viewer,&format);
    508:     if (format == PETSC_VIEWER_ASCII_MATLAB) ismatlab = PETSC_TRUE;
    509:   }
    510:   if (ismatlab) {
    511:     PetscObjectGetName((PetscObject)bv,&bvname);
    512:     PetscViewerASCIIPrintf(viewer,"%s=[];\n",bvname);
    513:   }
    514:   for (j=bv->nc;j<bv->nc+bv->m;j++) {
    515:     BVGetColumn(bv,j,&v);
    516:     VecView(v,viewer);
    517:     if (ismatlab) {
    518:       PetscObjectGetName((PetscObject)v,&name);
    519:       PetscViewerASCIIPrintf(viewer,"%s=[%s,%s];clear %s\n",bvname,bvname,name,name);
    520:     }
    521:     BVRestoreColumn(bv,j,&v);
    522:   }
    523:   return(0);
    524: }

    528: /*@C
    529:    BVView - Prints the BV data structure.

    531:    Collective on BV

    533:    Input Parameters:
    534: +  bv     - the BV context
    535: -  viewer - optional visualization context

    537:    Note:
    538:    The available visualization contexts include
    539: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    540: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    541:          output where only the first processor opens
    542:          the file.  All other processors send their
    543:          data to the first processor to print.

    545:    The user can open an alternative visualization contexts with
    546:    PetscViewerASCIIOpen() (output to a specified file).

    548:    Level: beginner

    550: .seealso: PetscViewerASCIIOpen()
    551: @*/
    552: PetscErrorCode BVView(BV bv,PetscViewer viewer)
    553: {
    554:   PetscErrorCode    ierr;
    555:   PetscBool         isascii;
    556:   PetscViewerFormat format;
    557:   const char        *orthname[2] = {"classical","modified"};
    558:   const char        *refname[3] = {"if needed","never","always"};
    559:   const char        *borthname[2] = {"Gram-Schmidt","Cholesky"};

    563:   if (!viewer) {
    564:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)bv),&viewer);
    565:   }

    568:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    569:   if (isascii) {
    570:     PetscObjectPrintClassNamePrefixType((PetscObject)bv,viewer);
    571:     PetscViewerGetFormat(viewer,&format);
    572:     PetscViewerASCIIPushTab(viewer);
    573:     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
    574:       PetscViewerASCIIPrintf(viewer,"%D columns of global length %D\n",bv->m,bv->N);
    575:       if (bv->nc>0) {
    576:         PetscViewerASCIIPrintf(viewer,"number of constraints: %D\n",bv->nc);
    577:       }
    578:       PetscViewerASCIIPrintf(viewer,"vector orthogonalization method: %s Gram-Schmidt\n",orthname[bv->orthog_type]);
    579:       switch (bv->orthog_ref) {
    580:         case BV_ORTHOG_REFINE_IFNEEDED:
    581:           PetscViewerASCIIPrintf(viewer,"orthogonalization refinement: %s (eta: %g)\n",refname[bv->orthog_ref],(double)bv->orthog_eta);
    582:           break;
    583:         case BV_ORTHOG_REFINE_NEVER:
    584:         case BV_ORTHOG_REFINE_ALWAYS:
    585:           PetscViewerASCIIPrintf(viewer,"orthogonalization refinement: %s\n",refname[bv->orthog_ref]);
    586:           break;
    587:       }
    588:       PetscViewerASCIIPrintf(viewer,"block orthogonalization method: %s\n",borthname[bv->orthog_block]);
    589:       if (bv->matrix) {
    590:         if (bv->indef) {
    591:           PetscViewerASCIIPrintf(viewer,"indefinite inner product\n");
    592:         } else {
    593:           PetscViewerASCIIPrintf(viewer,"non-standard inner product\n");
    594:         }
    595:         PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
    596:         MatView(bv->matrix,viewer);
    597:         PetscViewerPopFormat(viewer);
    598:       }
    599:       switch (bv->vmm) {
    600:         case BV_MATMULT_VECS:
    601:           PetscViewerASCIIPrintf(viewer,"doing matmult as matrix-vector products\n");
    602:           break;
    603:         case BV_MATMULT_MAT:
    604:           PetscViewerASCIIPrintf(viewer,"doing matmult as a single matrix-matrix product\n");
    605:           break;
    606:         case BV_MATMULT_MAT_SAVE:
    607:           PetscViewerASCIIPrintf(viewer,"doing matmult as a single matrix-matrix product, saving aux matrices\n");
    608:           break;
    609:       }
    610:     } else {
    611:       if (bv->ops->view) { (*bv->ops->view)(bv,viewer); }
    612:       else { BVView_Default(bv,viewer); }
    613:     }
    614:     PetscViewerASCIIPopTab(viewer);
    615:   } else {
    616:     (*bv->ops->view)(bv,viewer);
    617:   }
    618:   return(0);
    619: }

    623: /*@C
    624:    BVRegister - Adds a new storage format to de BV package.

    626:    Not collective

    628:    Input Parameters:
    629: +  name     - name of a new user-defined BV
    630: -  function - routine to create context

    632:    Notes:
    633:    BVRegister() may be called multiple times to add several user-defined
    634:    basis vectors.

    636:    Level: advanced

    638: .seealso: BVRegisterAll()
    639: @*/
    640: PetscErrorCode BVRegister(const char *name,PetscErrorCode (*function)(BV))
    641: {

    645:   PetscFunctionListAdd(&BVList,name,function);
    646:   return(0);
    647: }

    651: PetscErrorCode BVAllocateWork_Private(BV bv,PetscInt s)
    652: {

    656:   if (s>bv->lwork) {
    657:     PetscFree(bv->work);
    658:     PetscMalloc1(s,&bv->work);
    659:     PetscLogObjectMemory((PetscObject)bv,(s-bv->lwork)*sizeof(PetscScalar));
    660:     bv->lwork = s;
    661:   }
    662:   return(0);
    663: }