Actual source code: slepcinit.c

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.
      7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
      8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      9: */

     11: #include <slepc/private/slepcimpl.h>

     13: #if defined(SLEPC_HAVE_HPDDM)
     14: #include <petscksp.h>
     15: SLEPC_EXTERN PetscErrorCode KSPCreate_HPDDM(KSP);
     16: SLEPC_EXTERN PetscErrorCode PCCreate_HPDDM(PC);
     17: #endif

     19: /*@C
     20:     SlepcGetVersion - Gets the SLEPc version information in a string.

     22:     Not Collective

     24:     Input Parameter:
     25: .   len - length of the string

     27:     Output Parameter:
     28: .   version - version string

     30:     Level: intermediate

     32: .seealso: [](sec:writing-prog), `SlepcGetVersionNumber()`
     33: @*/
     34: PetscErrorCode SlepcGetVersion(char version[],size_t len)
     35: {
     36:   PetscFunctionBegin;
     37: #if (SLEPC_VERSION_RELEASE == 1)
     38:   PetscCall(PetscSNPrintf(version,len,"SLEPc Release Version %d.%d.%d, %s",SLEPC_VERSION_MAJOR,SLEPC_VERSION_MINOR,SLEPC_VERSION_SUBMINOR,SLEPC_VERSION_DATE));
     39: #else
     40:   PetscCall(PetscSNPrintf(version,len,"SLEPc Development Git Revision: %s Git Date: %s",SLEPC_VERSION_GIT,SLEPC_VERSION_DATE_GIT));
     41: #endif
     42:   PetscFunctionReturn(PETSC_SUCCESS);
     43: }

     45: /*@
     46:     SlepcGetVersionNumber - Gets the SLEPc version information from the library.

     48:     Not Collective

     50:     Output Parameters:
     51: +   major    - the major version
     52: .   minor    - the minor version
     53: .   subminor - the subminor version (patch number)
     54: -   release  - indicates the library is from a release

     56:     Notes:
     57:     Pass `NULL` in any argument that is not requested.

     59:     The C macros `SLEPC_VERSION_MAJOR`, `SLEPC_VERSION_MINOR`, `SLEPC_VERSION_SUBMINOR`,
     60:     `SLEPC_VERSION_RELEASE` provide the information at compile time. This can be used to confirm
     61:     that the shared library being loaded at runtime has the appropriate version updates.

     63:     This function can be called before `SlepcInitialize()`.

     65:     Level: intermediate

     67: .seealso: [](sec:writing-prog), `SlepcGetVersion()`, `SlepcInitialize()`
     68: @*/
     69: PetscErrorCode SlepcGetVersionNumber(PetscInt *major,PetscInt *minor,PetscInt *subminor,PetscInt *release)
     70: {
     71:   if (major)    *major    = SLEPC_VERSION_MAJOR;
     72:   if (minor)    *minor    = SLEPC_VERSION_MINOR;
     73:   if (subminor) *subminor = SLEPC_VERSION_SUBMINOR;
     74:   if (release)  *release  = SLEPC_VERSION_RELEASE;
     75:   return PETSC_SUCCESS;
     76: }

     78: /*
     79:    SlepcPrintVersion - Prints SLEPc version info.

     81:    Collective
     82: */
     83: static PetscErrorCode SlepcPrintVersion(MPI_Comm comm)
     84: {
     85:   char           version[256];

     87:   PetscFunctionBegin;
     88:   PetscCall(SlepcGetVersion(version,256));
     89:   PetscCall((*PetscHelpPrintf)(comm,"%s\n",version));
     90:   PetscCall((*PetscHelpPrintf)(comm,SLEPC_AUTHOR_INFO));
     91:   PetscCall((*PetscHelpPrintf)(comm,"See https://slepc.upv.es/documentation/ for help.\n"));
     92:   PetscCall((*PetscHelpPrintf)(comm,"SLEPc libraries linked from %s\n",SLEPC_LIB_DIR));
     93:   PetscFunctionReturn(PETSC_SUCCESS);
     94: }

     96: /*
     97:    SlepcPrintHelpIntro - Prints introductory SLEPc help info.

     99:    Collective
    100: */
    101: static PetscErrorCode SlepcPrintHelpIntro(MPI_Comm comm)
    102: {
    103:   PetscFunctionBegin;
    104:   PetscCall((*PetscHelpPrintf)(comm,"SLEPc help information includes that for the PETSc libraries, which provide\n"));
    105:   PetscCall((*PetscHelpPrintf)(comm,"low-level system infrastructure and linear algebra tools.\n"));
    106:   PetscCall((*PetscHelpPrintf)(comm,"----------------------------------------\n"));
    107:   PetscFunctionReturn(PETSC_SUCCESS);
    108: }

    110: /* ------------------------Nasty global variables -------------------------------*/
    111: /*
    112:    Indicates whether SLEPc started PETSc, or whether it was
    113:    already started before SLEPc was initialized.
    114: */
    115: PetscBool SlepcBeganPetsc       = PETSC_FALSE;
    116: PetscBool SlepcInitializeCalled = PETSC_FALSE;
    117: PetscBool SlepcFinalizeCalled   = PETSC_FALSE;

    119: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
    120: static PetscErrorCode SlepcLoadDynamicLibrary(const char *name,PetscBool *found)
    121: {
    122:   char           libs[PETSC_MAX_PATH_LEN],dlib[PETSC_MAX_PATH_LEN];

    124:   PetscFunctionBegin;
    125:   PetscCall(PetscStrcpy(libs,SLEPC_LIB_DIR));
    126:   PetscCall(PetscStrlcat(libs,"/libslepc",sizeof(libs)));
    127:   PetscCall(PetscStrlcat(libs,name,sizeof(libs)));
    128: #if defined(PETSC_LIB_NAME_SUFFIX)
    129:   PetscCall(PetscStrlcat(libs,PETSC_LIB_NAME_SUFFIX,sizeof(libs)));
    130: #endif
    131:   PetscCall(PetscDLLibraryRetrieve(PETSC_COMM_WORLD,libs,dlib,sizeof(dlib),found));
    132:   if (*found) PetscCall(PetscDLLibraryAppend(PETSC_COMM_WORLD,&PetscDLLibrariesLoaded,dlib));
    133:   PetscFunctionReturn(PETSC_SUCCESS);
    134: }
    135: #endif

    137: #if defined(PETSC_USE_SINGLE_LIBRARY) && !(defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES))
    138: SLEPC_EXTERN PetscErrorCode STInitializePackage(void);
    139: SLEPC_EXTERN PetscErrorCode DSInitializePackage(void);
    140: SLEPC_EXTERN PetscErrorCode FNInitializePackage(void);
    141: SLEPC_EXTERN PetscErrorCode BVInitializePackage(void);
    142: SLEPC_EXTERN PetscErrorCode RGInitializePackage(void);
    143: SLEPC_EXTERN PetscErrorCode EPSInitializePackage(void);
    144: SLEPC_EXTERN PetscErrorCode SVDInitializePackage(void);
    145: SLEPC_EXTERN PetscErrorCode PEPInitializePackage(void);
    146: SLEPC_EXTERN PetscErrorCode NEPInitializePackage(void);
    147: SLEPC_EXTERN PetscErrorCode MFNInitializePackage(void);
    148: SLEPC_EXTERN PetscErrorCode LMEInitializePackage(void);
    149: #endif

    151: /*
    152:     SlepcInitialize_DynamicLibraries - Adds the default dynamic link libraries to the
    153:     search path.
    154: */
    155: PetscErrorCode SlepcInitialize_DynamicLibraries(void)
    156: {
    157:   PetscBool      preload = PETSC_FALSE;

    159:   PetscFunctionBegin;
    160: #if defined(PETSC_HAVE_THREADSAFETY)
    161:   /* These must be all initialized here because it is not safe for individual threads to call these initialize routines */
    162:   preload = PETSC_TRUE;
    163: #endif

    165:   PetscCall(PetscOptionsGetBool(NULL,NULL,"-library_preload",&preload,NULL));
    166:   if (preload) {
    167: #if defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES)
    168:     PetscBool found;
    169: #if defined(PETSC_USE_SINGLE_LIBRARY)
    170:     PetscCall(SlepcLoadDynamicLibrary("",&found));
    171:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc dynamic library. You cannot move the dynamic libraries!");
    172: #else
    173:     PetscCall(SlepcLoadDynamicLibrary("sys",&found));
    174:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc sys dynamic library. You cannot move the dynamic libraries!");
    175:     PetscCall(SlepcLoadDynamicLibrary("eps",&found));
    176:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc EPS dynamic library. You cannot move the dynamic libraries!");
    177:     PetscCall(SlepcLoadDynamicLibrary("pep",&found));
    178:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc PEP dynamic library. You cannot move the dynamic libraries!");
    179:     PetscCall(SlepcLoadDynamicLibrary("nep",&found));
    180:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc NEP dynamic library. You cannot move the dynamic libraries!");
    181:     PetscCall(SlepcLoadDynamicLibrary("svd",&found));
    182:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc SVD dynamic library. You cannot move the dynamic libraries!");
    183:     PetscCall(SlepcLoadDynamicLibrary("mfn",&found));
    184:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc MFN dynamic library. You cannot move the dynamic libraries!");
    185:     PetscCall(SlepcLoadDynamicLibrary("lme",&found));
    186:     PetscCheck(found,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to locate SLEPc LME dynamic library. You cannot move the dynamic libraries!");
    187: #endif
    188: #else /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
    189: #if defined(PETSC_USE_SINGLE_LIBRARY)
    190:   PetscCall(STInitializePackage());
    191:   PetscCall(DSInitializePackage());
    192:   PetscCall(FNInitializePackage());
    193:   PetscCall(BVInitializePackage());
    194:   PetscCall(RGInitializePackage());
    195:   PetscCall(EPSInitializePackage());
    196:   PetscCall(SVDInitializePackage());
    197:   PetscCall(PEPInitializePackage());
    198:   PetscCall(NEPInitializePackage());
    199:   PetscCall(MFNInitializePackage());
    200:   PetscCall(LMEInitializePackage());
    201: #else
    202:   SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Cannot use -library_preload with multiple static SLEPc libraries");
    203: #endif
    204: #endif /* defined(PETSC_HAVE_DYNAMIC_LIBRARIES) && defined(PETSC_USE_SHARED_LIBRARIES) */
    205:   }

    207: #if defined(SLEPC_HAVE_HPDDM)
    208:   PetscCall(KSPRegister(KSPHPDDM,KSPCreate_HPDDM));
    209:   PetscCall(PCRegister(PCHPDDM,PCCreate_HPDDM));
    210: #endif
    211:   PetscFunctionReturn(PETSC_SUCCESS);
    212: }

    214: PetscErrorCode SlepcCitationsInitialize(void)
    215: {
    216:   PetscFunctionBegin;
    217:   PetscCall(PetscCitationsRegister("@Article{slepc-toms,\n"
    218:     "   author = \"Vicente Hernandez and Jose E. Roman and Vicente Vidal\",\n"
    219:     "   title = \"{SLEPc}: A Scalable and Flexible Toolkit for the Solution of Eigenvalue Problems\",\n"
    220:     "   journal = \"{ACM} Trans. Math. Software\",\n"
    221:     "   volume = \"31\",\n"
    222:     "   number = \"3\",\n"
    223:     "   pages = \"351--362\",\n"
    224:     "   year = \"2005\",\n"
    225:     "   doi = \"https://doi.org/10.1145/1089014.1089019\"\n"
    226:     "}\n",NULL));
    227:   PetscCall(PetscCitationsRegister("@TechReport{slepc-manual,\n"
    228:     "   author = \"J. E. Roman and C. Campos and L. Dalcin and E. Romero and A. Tomas\",\n"
    229:     "   title = \"{SLEPc} Users Manual\",\n"
    230:     "   number = \"DSIC-II/24/02 - Revision 3.24\",\n"
    231:     "   institution = \"D. Sistemes Inform\\`atics i Computaci\\'o, Universitat Polit\\`ecnica de Val\\`encia\",\n"
    232:     "   year = \"2025\"\n"
    233:     "}\n",NULL));
    234:   PetscFunctionReturn(PETSC_SUCCESS);
    235: }

    237: /*@C
    238:    SlepcInitialize - Initializes the SLEPc library. `SlepcInitialize()` calls
    239:    `PetscInitialize()` if it has not been called yet, so this function should
    240:    always be called near the beginning of your program.

    242:    Collective on `MPI_COMM_WORLD` or `PETSC_COMM_WORLD` if it has been set

    244:    Input Parameters:
    245: +  argc - count of number of command line arguments
    246: .  args - the command line arguments
    247: .  file - [optional] PETSc database file
    248: -  help - [optional] Help message to print, use `NULL` for no message

    250:    Note:
    251:    Works in the same way as `PetscInitialize()`, but in addition initializes SLEPc.
    252:    The same considerations apply with respect to command line options and
    253:    environment variables.

    255:    Fortran Notes:
    256:    In Fortran this routine can be called with
    257: .vb
    258:        call SlepcInitialize(ierr)
    259: .ve
    260: .vb
    261:        call SlepcInitialize(file,ierr)
    262: .ve
    263:    or
    264: .vb
    265:        call SlepcInitialize(file,help,ierr)
    266: .ve

    268:    If your main program is C but you call Fortran code that also uses SLEPc you need
    269:    to call `SlepcInitializeFortran()` soon after calling `SlepcInitialize()`.

    271:    Level: beginner

    273: .seealso: [](sec:writing-prog), `SlepcFinalize()`, `PetscInitialize()`, `SlepcInitializeFortran()`
    274: @*/
    275: PetscErrorCode SlepcInitialize(int *argc,char ***args,const char file[],const char help[])
    276: {
    277:   PetscBool      flg;

    279:   PetscFunctionBegin;
    280:   if (SlepcInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
    281:   PetscCall(PetscSetHelpVersionFunctions(SlepcPrintHelpIntro,SlepcPrintVersion));
    282:   PetscCall(PetscInitialized(&flg));
    283:   if (!flg) {
    284:     PetscCall(PetscInitialize(argc,args,file,help));
    285:     SlepcBeganPetsc = PETSC_TRUE;
    286:   }

    288:   PetscCall(SlepcCitationsInitialize());

    290:   /* Load the dynamic libraries (on machines that support them), this registers all the solvers etc. */
    291:   PetscCall(SlepcInitialize_DynamicLibraries());

    293:   SlepcInitializeCalled = PETSC_TRUE;
    294:   SlepcFinalizeCalled   = PETSC_FALSE;
    295:   PetscCall(PetscInfo(0,"SLEPc successfully started\n"));
    296:   PetscFunctionReturn(PETSC_SUCCESS);
    297: }

    299: /*@C
    300:    SlepcFinalize - Checks for options to be called at the conclusion
    301:    of the SLEPc program and calls `PetscFinalize()`.

    303:    Collective on `PETSC_COMM_WORLD`

    305:    Level: beginner

    307: .seealso: [](sec:writing-prog), `SlepcInitialize()`, `PetscFinalize()`
    308: @*/
    309: PetscErrorCode SlepcFinalize(void)
    310: {
    311:   PetscFunctionBegin;
    312:   if (PetscUnlikely(!SlepcInitializeCalled)) {
    313:     fprintf(PETSC_STDOUT,"SlepcInitialize() must be called before SlepcFinalize()\n");
    314:     PetscStackClearTop;
    315:     return PETSC_ERR_ARG_WRONGSTATE;
    316:   }
    317:   PetscCall(PetscInfo(NULL,"SlepcFinalize() called\n"));
    318:   if (SlepcBeganPetsc) {
    319:     PetscCall(PetscFinalize());
    320:     SlepcBeganPetsc = PETSC_FALSE;
    321:   }
    322:   SlepcInitializeCalled = PETSC_FALSE;
    323:   SlepcFinalizeCalled   = PETSC_TRUE;
    324:   PetscStackClearTop;
    325:   return PETSC_SUCCESS;
    326: }

    328: /*@C
    329:    SlepcInitializeNoArguments - Calls `SlepcInitialize()` from C/C++ without
    330:    the command line arguments.

    332:    Collective

    334:    Level: advanced

    336: .seealso: [](sec:writing-prog), `SlepcInitialize()`, `SlepcInitializeFortran()`
    337: @*/
    338: PetscErrorCode SlepcInitializeNoArguments(void) PeNS
    339: {
    340:   int  argc = 0;
    341:   char **args = NULL;

    343:   PetscFunctionBegin;
    344:   PetscCall(SlepcInitialize(&argc,&args,NULL,NULL));
    345:   PetscFunctionReturn(PETSC_SUCCESS);
    346: }

    348: /*@
    349:    SlepcInitialized - Determine whether SLEPc is initialized.

    351:    Output Parameter:
    352: .  isInitialized - the result

    354:    Level: beginner

    356: .seealso: [](sec:writing-prog), `SlepcInitialize()`, `SlepcInitializeFortran()`
    357: @*/
    358: PetscErrorCode SlepcInitialized(PetscBool *isInitialized)
    359: {
    360:   PetscFunctionBegin;
    361:   *isInitialized = SlepcInitializeCalled;
    362:   PetscFunctionReturn(PETSC_SUCCESS);
    363: }

    365: /*@
    366:    SlepcFinalized - Determine whether `SlepcFinalize()` has been called.

    368:    Output Parameter:
    369: .  isFinalized - the result

    371:    Level: beginner

    373: .seealso: [](sec:writing-prog), `SlepcFinalize()`
    374: @*/
    375: PetscErrorCode SlepcFinalized(PetscBool *isFinalized)
    376: {
    377:   PetscFunctionBegin;
    378:   *isFinalized = SlepcFinalizeCalled;
    379:   PetscFunctionReturn(PETSC_SUCCESS);
    380: }

    382: PETSC_EXTERN PetscBool PetscBeganMPI;

    384: /*@C
    385:    SlepcInitializeNoPointers - Calls `SlepcInitialize()` from C/C++ without the pointers
    386:    to `argc` and `args`.

    388:    Collective

    390:    Input Parameters:
    391: +  argc - count of number of command line arguments
    392: .  args - the command line arguments
    393: .  file - [optional] PETSc database file
    394: -  help - [optional] Help message to print, use `NULL` for no message

    396:    Note:
    397:    Check the manual page of `PetscInitializeNoPointers()` for an explanation.

    399:    Level: advanced

    401: .seealso: [](sec:writing-prog), `SlepcInitialize()`
    402: @*/
    403: PetscErrorCode SlepcInitializeNoPointers(int argc,char **args,const char *file,const char *help)
    404: {
    405:   int            myargc = argc;
    406:   char           **myargs = args;

    408:   PetscFunctionBegin;
    409:   PetscCall(SlepcInitialize(&myargc,&myargs,file,help));
    410:   PetscCall(PetscPopSignalHandler());
    411:   PetscBeganMPI = PETSC_FALSE;
    412:   PetscFunctionReturn(PETSC_SUCCESS);
    413: }