LCOV - code coverage report
Current view: top level - sys/classes/fn/interface - fnbasic.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 399 407 98.0 %
Date: 2024-11-24 01:01:48 Functions: 30 31 96.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       3             :    SLEPc - Scalable Library for Eigenvalue Problem Computations
       4             :    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
       5             : 
       6             :    This file is part of SLEPc.
       7             :    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
       8             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       9             : */
      10             : /*
      11             :    Basic FN routines
      12             : */
      13             : 
      14             : #include <slepc/private/fnimpl.h>      /*I "slepcfn.h" I*/
      15             : #include <slepcblaslapack.h>
      16             : 
      17             : PetscFunctionList FNList = NULL;
      18             : PetscBool         FNRegisterAllCalled = PETSC_FALSE;
      19             : PetscClassId      FN_CLASSID = 0;
      20             : PetscLogEvent     FN_Evaluate = 0;
      21             : static PetscBool  FNPackageInitialized = PETSC_FALSE;
      22             : 
      23             : const char *FNParallelTypes[] = {"REDUNDANT","SYNCHRONIZED","FNParallelType","FN_PARALLEL_",NULL};
      24             : 
      25             : /*@C
      26             :    FNFinalizePackage - This function destroys everything in the Slepc interface
      27             :    to the FN package. It is called from SlepcFinalize().
      28             : 
      29             :    Level: developer
      30             : 
      31             : .seealso: SlepcFinalize()
      32             : @*/
      33         178 : PetscErrorCode FNFinalizePackage(void)
      34             : {
      35         178 :   PetscFunctionBegin;
      36         178 :   PetscCall(PetscFunctionListDestroy(&FNList));
      37         178 :   FNPackageInitialized = PETSC_FALSE;
      38         178 :   FNRegisterAllCalled  = PETSC_FALSE;
      39         178 :   PetscFunctionReturn(PETSC_SUCCESS);
      40             : }
      41             : 
      42             : /*@C
      43             :   FNInitializePackage - This function initializes everything in the FN package.
      44             :   It is called from PetscDLLibraryRegister() when using dynamic libraries, and
      45             :   on the first call to FNCreate() when using static libraries.
      46             : 
      47             :   Level: developer
      48             : 
      49             : .seealso: SlepcInitialize()
      50             : @*/
      51        1694 : PetscErrorCode FNInitializePackage(void)
      52             : {
      53        1694 :   char           logList[256];
      54        1694 :   PetscBool      opt,pkg;
      55        1694 :   PetscClassId   classids[1];
      56             : 
      57        1694 :   PetscFunctionBegin;
      58        1694 :   if (FNPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
      59         178 :   FNPackageInitialized = PETSC_TRUE;
      60             :   /* Register Classes */
      61         178 :   PetscCall(PetscClassIdRegister("Math Function",&FN_CLASSID));
      62             :   /* Register Constructors */
      63         178 :   PetscCall(FNRegisterAll());
      64             :   /* Register Events */
      65         178 :   PetscCall(PetscLogEventRegister("FNEvaluate",FN_CLASSID,&FN_Evaluate));
      66             :   /* Process Info */
      67         178 :   classids[0] = FN_CLASSID;
      68         178 :   PetscCall(PetscInfoProcessClass("fn",1,&classids[0]));
      69             :   /* Process summary exclusions */
      70         178 :   PetscCall(PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt));
      71         178 :   if (opt) {
      72           5 :     PetscCall(PetscStrInList("fn",logList,',',&pkg));
      73           5 :     if (pkg) PetscCall(PetscLogEventDeactivateClass(FN_CLASSID));
      74             :   }
      75             :   /* Register package finalizer */
      76         178 :   PetscCall(PetscRegisterFinalize(FNFinalizePackage));
      77         178 :   PetscFunctionReturn(PETSC_SUCCESS);
      78             : }
      79             : 
      80             : /*@
      81             :    FNCreate - Creates an FN context.
      82             : 
      83             :    Collective
      84             : 
      85             :    Input Parameter:
      86             : .  comm - MPI communicator
      87             : 
      88             :    Output Parameter:
      89             : .  newfn - location to put the FN context
      90             : 
      91             :    Level: beginner
      92             : 
      93             : .seealso: FNDestroy(), FN
      94             : @*/
      95         447 : PetscErrorCode FNCreate(MPI_Comm comm,FN *newfn)
      96             : {
      97         447 :   FN             fn;
      98             : 
      99         447 :   PetscFunctionBegin;
     100         447 :   PetscAssertPointer(newfn,2);
     101         447 :   PetscCall(FNInitializePackage());
     102         447 :   PetscCall(SlepcHeaderCreate(fn,FN_CLASSID,"FN","Math Function","FN",comm,FNDestroy,FNView));
     103             : 
     104         447 :   fn->alpha    = 1.0;
     105         447 :   fn->beta     = 1.0;
     106         447 :   fn->method   = 0;
     107             : 
     108         447 :   fn->nw       = 0;
     109         447 :   fn->cw       = 0;
     110         447 :   fn->data     = NULL;
     111             : 
     112         447 :   *newfn = fn;
     113         447 :   PetscFunctionReturn(PETSC_SUCCESS);
     114             : }
     115             : 
     116             : /*@
     117             :    FNSetOptionsPrefix - Sets the prefix used for searching for all
     118             :    FN options in the database.
     119             : 
     120             :    Logically Collective
     121             : 
     122             :    Input Parameters:
     123             : +  fn - the math function context
     124             : -  prefix - the prefix string to prepend to all FN option requests
     125             : 
     126             :    Notes:
     127             :    A hyphen (-) must NOT be given at the beginning of the prefix name.
     128             :    The first character of all runtime options is AUTOMATICALLY the
     129             :    hyphen.
     130             : 
     131             :    Level: advanced
     132             : 
     133             : .seealso: FNAppendOptionsPrefix()
     134             : @*/
     135           3 : PetscErrorCode FNSetOptionsPrefix(FN fn,const char *prefix)
     136             : {
     137           3 :   PetscFunctionBegin;
     138           3 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     139           3 :   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fn,prefix));
     140           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     141             : }
     142             : 
     143             : /*@
     144             :    FNAppendOptionsPrefix - Appends to the prefix used for searching for all
     145             :    FN options in the database.
     146             : 
     147             :    Logically Collective
     148             : 
     149             :    Input Parameters:
     150             : +  fn - the math function context
     151             : -  prefix - the prefix string to prepend to all FN option requests
     152             : 
     153             :    Notes:
     154             :    A hyphen (-) must NOT be given at the beginning of the prefix name.
     155             :    The first character of all runtime options is AUTOMATICALLY the hyphen.
     156             : 
     157             :    Level: advanced
     158             : 
     159             : .seealso: FNSetOptionsPrefix()
     160             : @*/
     161           1 : PetscErrorCode FNAppendOptionsPrefix(FN fn,const char *prefix)
     162             : {
     163           1 :   PetscFunctionBegin;
     164           1 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     165           1 :   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)fn,prefix));
     166           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     167             : }
     168             : 
     169             : /*@
     170             :    FNGetOptionsPrefix - Gets the prefix used for searching for all
     171             :    FN options in the database.
     172             : 
     173             :    Not Collective
     174             : 
     175             :    Input Parameters:
     176             : .  fn - the math function context
     177             : 
     178             :    Output Parameters:
     179             : .  prefix - pointer to the prefix string used is returned
     180             : 
     181             :    Note:
     182             :    On the Fortran side, the user should pass in a string 'prefix' of
     183             :    sufficient length to hold the prefix.
     184             : 
     185             :    Level: advanced
     186             : 
     187             : .seealso: FNSetOptionsPrefix(), FNAppendOptionsPrefix()
     188             : @*/
     189           0 : PetscErrorCode FNGetOptionsPrefix(FN fn,const char *prefix[])
     190             : {
     191           0 :   PetscFunctionBegin;
     192           0 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     193           0 :   PetscAssertPointer(prefix,2);
     194           0 :   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)fn,prefix));
     195           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     196             : }
     197             : 
     198             : /*@
     199             :    FNSetType - Selects the type for the FN object.
     200             : 
     201             :    Logically Collective
     202             : 
     203             :    Input Parameters:
     204             : +  fn   - the math function context
     205             : -  type - a known type
     206             : 
     207             :    Notes:
     208             :    The default is FNRATIONAL, which includes polynomials as a particular
     209             :    case as well as simple functions such as f(x)=x and f(x)=constant.
     210             : 
     211             :    Level: intermediate
     212             : 
     213             : .seealso: FNGetType()
     214             : @*/
     215         456 : PetscErrorCode FNSetType(FN fn,FNType type)
     216             : {
     217         456 :   PetscErrorCode (*r)(FN);
     218         456 :   PetscBool      match;
     219             : 
     220         456 :   PetscFunctionBegin;
     221         456 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     222         456 :   PetscAssertPointer(type,2);
     223             : 
     224         456 :   PetscCall(PetscObjectTypeCompare((PetscObject)fn,type,&match));
     225         456 :   if (match) PetscFunctionReturn(PETSC_SUCCESS);
     226             : 
     227         450 :   PetscCall(PetscFunctionListFind(FNList,type,&r));
     228         450 :   PetscCheck(r,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested FN type %s",type);
     229             : 
     230         450 :   PetscTryTypeMethod(fn,destroy);
     231         450 :   PetscCall(PetscMemzero(fn->ops,sizeof(struct _FNOps)));
     232             : 
     233         450 :   PetscCall(PetscObjectChangeTypeName((PetscObject)fn,type));
     234         450 :   PetscCall((*r)(fn));
     235         450 :   PetscFunctionReturn(PETSC_SUCCESS);
     236             : }
     237             : 
     238             : /*@
     239             :    FNGetType - Gets the FN type name (as a string) from the FN context.
     240             : 
     241             :    Not Collective
     242             : 
     243             :    Input Parameter:
     244             : .  fn - the math function context
     245             : 
     246             :    Output Parameter:
     247             : .  type - name of the math function
     248             : 
     249             :    Level: intermediate
     250             : 
     251             : .seealso: FNSetType()
     252             : @*/
     253          44 : PetscErrorCode FNGetType(FN fn,FNType *type)
     254             : {
     255          44 :   PetscFunctionBegin;
     256          44 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     257          44 :   PetscAssertPointer(type,2);
     258          44 :   *type = ((PetscObject)fn)->type_name;
     259          44 :   PetscFunctionReturn(PETSC_SUCCESS);
     260             : }
     261             : 
     262             : /*@
     263             :    FNSetScale - Sets the scaling parameters that define the matematical function.
     264             : 
     265             :    Logically Collective
     266             : 
     267             :    Input Parameters:
     268             : +  fn    - the math function context
     269             : .  alpha - inner scaling (argument)
     270             : -  beta  - outer scaling (result)
     271             : 
     272             :    Notes:
     273             :    Given a function f(x) specified by the FN type, the scaling parameters can
     274             :    be used to realize the function beta*f(alpha*x). So when these values are given,
     275             :    the procedure for function evaluation will first multiply the argument by alpha,
     276             :    then evaluate the function itself, and finally scale the result by beta.
     277             :    Likewise, these values are also considered when evaluating the derivative.
     278             : 
     279             :    If you want to provide only one of the two scaling factors, set the other
     280             :    one to 1.0.
     281             : 
     282             :    Level: intermediate
     283             : 
     284             : .seealso: FNGetScale(), FNEvaluateFunction()
     285             : @*/
     286         175 : PetscErrorCode FNSetScale(FN fn,PetscScalar alpha,PetscScalar beta)
     287             : {
     288         175 :   PetscFunctionBegin;
     289         175 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     290         525 :   PetscValidLogicalCollectiveScalar(fn,alpha,2);
     291         525 :   PetscValidLogicalCollectiveScalar(fn,beta,3);
     292         175 :   PetscCheck(PetscAbsScalar(alpha)!=0.0 && PetscAbsScalar(beta)!=0.0,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_WRONG,"Scaling factors must be nonzero");
     293         175 :   fn->alpha = alpha;
     294         175 :   fn->beta  = beta;
     295         175 :   PetscFunctionReturn(PETSC_SUCCESS);
     296             : }
     297             : 
     298             : /*@
     299             :    FNGetScale - Gets the scaling parameters that define the matematical function.
     300             : 
     301             :    Not Collective
     302             : 
     303             :    Input Parameter:
     304             : .  fn    - the math function context
     305             : 
     306             :    Output Parameters:
     307             : +  alpha - inner scaling (argument)
     308             : -  beta  - outer scaling (result)
     309             : 
     310             :    Level: intermediate
     311             : 
     312             : .seealso: FNSetScale()
     313             : @*/
     314         943 : PetscErrorCode FNGetScale(FN fn,PetscScalar *alpha,PetscScalar *beta)
     315             : {
     316         943 :   PetscFunctionBegin;
     317         943 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     318         943 :   if (alpha) *alpha = fn->alpha;
     319         943 :   if (beta)  *beta  = fn->beta;
     320         943 :   PetscFunctionReturn(PETSC_SUCCESS);
     321             : }
     322             : 
     323             : /*@
     324             :    FNSetMethod - Selects the method to be used to evaluate functions of matrices.
     325             : 
     326             :    Logically Collective
     327             : 
     328             :    Input Parameters:
     329             : +  fn   - the math function context
     330             : -  meth - an index identifying the method
     331             : 
     332             :    Options Database Key:
     333             : .  -fn_method <meth> - Sets the method
     334             : 
     335             :    Notes:
     336             :    In some FN types there are more than one algorithms available for computing
     337             :    matrix functions. In that case, this function allows choosing the wanted method.
     338             : 
     339             :    If meth is currently set to 0 (the default) and the input argument A of
     340             :    FNEvaluateFunctionMat() is a symmetric/Hermitian matrix, then the computation
     341             :    is done via the eigendecomposition of A, rather than with the general algorithm.
     342             : 
     343             :    Level: intermediate
     344             : 
     345             : .seealso: FNGetMethod(), FNEvaluateFunctionMat()
     346             : @*/
     347          80 : PetscErrorCode FNSetMethod(FN fn,PetscInt meth)
     348             : {
     349          80 :   PetscFunctionBegin;
     350          80 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     351         240 :   PetscValidLogicalCollectiveInt(fn,meth,2);
     352          80 :   PetscCheck(meth>=0,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_OUTOFRANGE,"The method must be a non-negative integer");
     353          80 :   PetscCheck(meth<=FN_MAX_SOLVE,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_OUTOFRANGE,"Too large value for the method");
     354          80 :   fn->method = meth;
     355          80 :   PetscFunctionReturn(PETSC_SUCCESS);
     356             : }
     357             : 
     358             : /*@
     359             :    FNGetMethod - Gets the method currently used in the FN.
     360             : 
     361             :    Not Collective
     362             : 
     363             :    Input Parameter:
     364             : .  fn - the math function context
     365             : 
     366             :    Output Parameter:
     367             : .  meth - identifier of the method
     368             : 
     369             :    Level: intermediate
     370             : 
     371             : .seealso: FNSetMethod()
     372             : @*/
     373          44 : PetscErrorCode FNGetMethod(FN fn,PetscInt *meth)
     374             : {
     375          44 :   PetscFunctionBegin;
     376          44 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     377          44 :   PetscAssertPointer(meth,2);
     378          44 :   *meth = fn->method;
     379          44 :   PetscFunctionReturn(PETSC_SUCCESS);
     380             : }
     381             : 
     382             : /*@
     383             :    FNSetParallel - Selects the mode of operation in parallel runs.
     384             : 
     385             :    Logically Collective
     386             : 
     387             :    Input Parameters:
     388             : +  fn    - the math function context
     389             : -  pmode - the parallel mode
     390             : 
     391             :    Options Database Key:
     392             : .  -fn_parallel <mode> - Sets the parallel mode, either 'redundant' or 'synchronized'
     393             : 
     394             :    Notes:
     395             :    This is relevant only when the function is evaluated on a matrix, with
     396             :    either FNEvaluateFunctionMat() or FNEvaluateFunctionMatVec().
     397             : 
     398             :    In the 'redundant' parallel mode, all processes will make the computation
     399             :    redundantly, starting from the same data, and producing the same result.
     400             :    This result may be slightly different in the different processes if using a
     401             :    multithreaded BLAS library, which may cause issues in ill-conditioned problems.
     402             : 
     403             :    In the 'synchronized' parallel mode, only the first MPI process performs the
     404             :    computation and then the computed matrix is broadcast to the other
     405             :    processes in the communicator. This communication is done automatically at
     406             :    the end of FNEvaluateFunctionMat() or FNEvaluateFunctionMatVec().
     407             : 
     408             :    Level: advanced
     409             : 
     410             : .seealso: FNEvaluateFunctionMat() or FNEvaluateFunctionMatVec(), FNGetParallel()
     411             : @*/
     412          50 : PetscErrorCode FNSetParallel(FN fn,FNParallelType pmode)
     413             : {
     414          50 :   PetscFunctionBegin;
     415          50 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     416         150 :   PetscValidLogicalCollectiveEnum(fn,pmode,2);
     417          50 :   fn->pmode = pmode;
     418          50 :   PetscFunctionReturn(PETSC_SUCCESS);
     419             : }
     420             : 
     421             : /*@
     422             :    FNGetParallel - Gets the mode of operation in parallel runs.
     423             : 
     424             :    Not Collective
     425             : 
     426             :    Input Parameter:
     427             : .  fn - the math function context
     428             : 
     429             :    Output Parameter:
     430             : .  pmode - the parallel mode
     431             : 
     432             :    Level: advanced
     433             : 
     434             : .seealso: FNSetParallel()
     435             : @*/
     436          44 : PetscErrorCode FNGetParallel(FN fn,FNParallelType *pmode)
     437             : {
     438          44 :   PetscFunctionBegin;
     439          44 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     440          44 :   PetscAssertPointer(pmode,2);
     441          44 :   *pmode = fn->pmode;
     442          44 :   PetscFunctionReturn(PETSC_SUCCESS);
     443             : }
     444             : 
     445             : /*@
     446             :    FNEvaluateFunction - Computes the value of the function f(x) for a given x.
     447             : 
     448             :    Not Collective
     449             : 
     450             :    Input Parameters:
     451             : +  fn - the math function context
     452             : -  x  - the value where the function must be evaluated
     453             : 
     454             :    Output Parameter:
     455             : .  y  - the result of f(x)
     456             : 
     457             :    Note:
     458             :    Scaling factors are taken into account, so the actual function evaluation
     459             :    will return beta*f(alpha*x).
     460             : 
     461             :    Level: intermediate
     462             : 
     463             : .seealso: FNEvaluateDerivative(), FNEvaluateFunctionMat(), FNSetScale()
     464             : @*/
     465       15417 : PetscErrorCode FNEvaluateFunction(FN fn,PetscScalar x,PetscScalar *y)
     466             : {
     467       15417 :   PetscScalar    xf,yf;
     468             : 
     469       15417 :   PetscFunctionBegin;
     470       15417 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     471       15417 :   PetscValidType(fn,1);
     472       15417 :   PetscAssertPointer(y,3);
     473       15417 :   PetscCall(PetscLogEventBegin(FN_Evaluate,fn,0,0,0));
     474       15417 :   xf = fn->alpha*x;
     475       15417 :   PetscUseTypeMethod(fn,evaluatefunction,xf,&yf);
     476       15417 :   *y = fn->beta*yf;
     477       15417 :   PetscCall(PetscLogEventEnd(FN_Evaluate,fn,0,0,0));
     478       15417 :   PetscFunctionReturn(PETSC_SUCCESS);
     479             : }
     480             : 
     481             : /*@
     482             :    FNEvaluateDerivative - Computes the value of the derivative f'(x) for a given x.
     483             : 
     484             :    Not Collective
     485             : 
     486             :    Input Parameters:
     487             : +  fn - the math function context
     488             : -  x  - the value where the derivative must be evaluated
     489             : 
     490             :    Output Parameter:
     491             : .  y  - the result of f'(x)
     492             : 
     493             :    Note:
     494             :    Scaling factors are taken into account, so the actual derivative evaluation will
     495             :    return alpha*beta*f'(alpha*x).
     496             : 
     497             :    Level: intermediate
     498             : 
     499             : .seealso: FNEvaluateFunction()
     500             : @*/
     501        5077 : PetscErrorCode FNEvaluateDerivative(FN fn,PetscScalar x,PetscScalar *y)
     502             : {
     503        5077 :   PetscScalar    xf,yf;
     504             : 
     505        5077 :   PetscFunctionBegin;
     506        5077 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     507        5077 :   PetscValidType(fn,1);
     508        5077 :   PetscAssertPointer(y,3);
     509        5077 :   PetscCall(PetscLogEventBegin(FN_Evaluate,fn,0,0,0));
     510        5077 :   xf = fn->alpha*x;
     511        5077 :   PetscUseTypeMethod(fn,evaluatederivative,xf,&yf);
     512        5077 :   *y = fn->alpha*fn->beta*yf;
     513        5077 :   PetscCall(PetscLogEventEnd(FN_Evaluate,fn,0,0,0));
     514        5077 :   PetscFunctionReturn(PETSC_SUCCESS);
     515             : }
     516             : 
     517          42 : static PetscErrorCode FNEvaluateFunctionMat_Sym_Private(FN fn,const PetscScalar *As,PetscScalar *Bs,PetscInt m,PetscBool firstonly)
     518             : {
     519          42 :   PetscInt       i,j;
     520          42 :   PetscBLASInt   n,k,ld,lwork,info;
     521          42 :   PetscScalar    *Q,*W,*work,adummy,a,x,y,one=1.0,zero=0.0;
     522          42 :   PetscReal      *eig,dummy;
     523             : #if defined(PETSC_USE_COMPLEX)
     524          42 :   PetscReal      *rwork,rdummy;
     525             : #endif
     526             : 
     527          42 :   PetscFunctionBegin;
     528          42 :   PetscCall(PetscBLASIntCast(m,&n));
     529          42 :   ld = n;
     530          42 :   k = firstonly? 1: n;
     531             : 
     532             :   /* workspace query and memory allocation */
     533          42 :   lwork = -1;
     534             : #if defined(PETSC_USE_COMPLEX)
     535          42 :   PetscCallBLAS("LAPACKsyev",LAPACKsyev_("V","L",&n,&adummy,&ld,&dummy,&a,&lwork,&rdummy,&info));
     536          42 :   PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(a),&lwork));
     537          42 :   PetscCall(PetscMalloc5(m,&eig,m*m,&Q,m*k,&W,lwork,&work,PetscMax(1,3*m-2),&rwork));
     538             : #else
     539             :   PetscCallBLAS("LAPACKsyev",LAPACKsyev_("V","L",&n,&adummy,&ld,&dummy,&a,&lwork,&info));
     540             :   PetscCall(PetscBLASIntCast((PetscInt)a,&lwork));
     541             :   PetscCall(PetscMalloc4(m,&eig,m*m,&Q,m*k,&W,lwork,&work));
     542             : #endif
     543             : 
     544             :   /* compute eigendecomposition */
     545       58803 :   for (j=0;j<n;j++) for (i=j;i<n;i++) Q[i+j*ld] = As[i+j*ld];
     546             : #if defined(PETSC_USE_COMPLEX)
     547          42 :   PetscCallBLAS("LAPACKsyev",LAPACKsyev_("V","L",&n,Q,&ld,eig,work,&lwork,rwork,&info));
     548             : #else
     549             :   PetscCallBLAS("LAPACKsyev",LAPACKsyev_("V","L",&n,Q,&ld,eig,work,&lwork,&info));
     550             : #endif
     551          42 :   SlepcCheckLapackInfo("syev",info);
     552             : 
     553             :   /* W = f(Lambda)*Q' */
     554        1428 :   for (i=0;i<n;i++) {
     555        1386 :     x = fn->alpha*eig[i];
     556        1386 :     PetscUseTypeMethod(fn,evaluatefunction,x,&y);  /* y = f(x) */
     557       57912 :     for (j=0;j<k;j++) W[i+j*ld] = PetscConj(Q[j+i*ld])*fn->beta*y;
     558             :   }
     559             :   /* Bs = Q*W */
     560          42 :   PetscCallBLAS("BLASgemm",BLASgemm_("N","N",&n,&k,&n,&one,Q,&ld,W,&ld,&zero,Bs,&ld));
     561             : #if defined(PETSC_USE_COMPLEX)
     562          42 :   PetscCall(PetscFree5(eig,Q,W,work,rwork));
     563             : #else
     564             :   PetscCall(PetscFree4(eig,Q,W,work));
     565             : #endif
     566          42 :   PetscCall(PetscLogFlops(9.0*n*n*n+2.0*n*n*n));
     567          42 :   PetscFunctionReturn(PETSC_SUCCESS);
     568             : }
     569             : 
     570             : /*
     571             :    FNEvaluateFunctionMat_Sym_Default - given a symmetric matrix A,
     572             :    compute the matrix function as f(A)=Q*f(D)*Q' where the spectral
     573             :    decomposition of A is A=Q*D*Q'
     574             : */
     575          19 : static PetscErrorCode FNEvaluateFunctionMat_Sym_Default(FN fn,Mat A,Mat B)
     576             : {
     577          19 :   PetscInt          m;
     578          19 :   const PetscScalar *As;
     579          19 :   PetscScalar       *Bs;
     580             : 
     581          19 :   PetscFunctionBegin;
     582          19 :   PetscCall(MatDenseGetArrayRead(A,&As));
     583          19 :   PetscCall(MatDenseGetArray(B,&Bs));
     584          19 :   PetscCall(MatGetSize(A,&m,NULL));
     585          19 :   PetscCall(FNEvaluateFunctionMat_Sym_Private(fn,As,Bs,m,PETSC_FALSE));
     586          19 :   PetscCall(MatDenseRestoreArrayRead(A,&As));
     587          19 :   PetscCall(MatDenseRestoreArray(B,&Bs));
     588          19 :   PetscFunctionReturn(PETSC_SUCCESS);
     589             : }
     590             : 
     591        1862 : static PetscErrorCode FNEvaluateFunctionMat_Basic(FN fn,Mat A,Mat F)
     592             : {
     593        1862 :   PetscBool iscuda;
     594             : 
     595        1862 :   PetscFunctionBegin;
     596        1862 :   PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSECUDA,&iscuda));
     597        1862 :   if (iscuda && !fn->ops->evaluatefunctionmatcuda[fn->method]) PetscCall(PetscInfo(fn,"The method %" PetscInt_FMT " is not implemented for CUDA, falling back to CPU version\n",fn->method));
     598        1862 :   if (iscuda && fn->ops->evaluatefunctionmatcuda[fn->method]) PetscUseTypeMethod(fn,evaluatefunctionmatcuda[fn->method],A,F);
     599        1862 :   else if (fn->ops->evaluatefunctionmat[fn->method]) PetscUseTypeMethod(fn,evaluatefunctionmat[fn->method],A,F);
     600             :   else {
     601           0 :     PetscCheck(fn->method,PetscObjectComm((PetscObject)fn),PETSC_ERR_SUP,"Matrix functions not implemented in this FN type");
     602           0 :     PetscCheck(!fn->method,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_OUTOFRANGE,"The specified method number does not exist for this FN type");
     603             :   }
     604        1862 :   PetscFunctionReturn(PETSC_SUCCESS);
     605             : }
     606             : 
     607        1622 : PetscErrorCode FNEvaluateFunctionMat_Private(FN fn,Mat A,Mat B,PetscBool sync)
     608             : {
     609        1622 :   PetscBool      set,flg,symm=PETSC_FALSE,iscuda,hasspecificmeth;
     610        1622 :   PetscInt       m,n;
     611        1622 :   PetscMPIInt    size,rank,n2;
     612        1622 :   PetscScalar    *pF;
     613        1622 :   Mat            M,F;
     614             : 
     615        1622 :   PetscFunctionBegin;
     616             :   /* destination matrix */
     617        1622 :   F = B?B:A;
     618             : 
     619             :   /* check symmetry of A */
     620        1622 :   PetscCall(MatIsHermitianKnown(A,&set,&flg));
     621        1622 :   symm = set? flg: PETSC_FALSE;
     622             : 
     623        1622 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)fn),&size));
     624        1622 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)fn),&rank));
     625        1622 :   if (size==1 || fn->pmode==FN_PARALLEL_REDUNDANT || (fn->pmode==FN_PARALLEL_SYNCHRONIZED && !rank)) {
     626        1610 :     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
     627        1610 :     PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSECUDA,&iscuda));
     628        1610 :     hasspecificmeth = ((iscuda && fn->ops->evaluatefunctionmatcuda[fn->method]) || (!iscuda && fn->method && fn->ops->evaluatefunctionmat[fn->method]))? PETSC_TRUE: PETSC_FALSE;
     629        1610 :     if (!hasspecificmeth && symm && !fn->method) {  /* prefer diagonalization */
     630          19 :       PetscCall(PetscInfo(fn,"Computing matrix function via diagonalization\n"));
     631          19 :       PetscCall(FNEvaluateFunctionMat_Sym_Default(fn,A,F));
     632             :     } else {
     633             :       /* scale argument */
     634        1591 :       if (fn->alpha!=(PetscScalar)1.0) {
     635         298 :         PetscCall(FN_AllocateWorkMat(fn,A,&M));
     636         298 :         PetscCall(MatScale(M,fn->alpha));
     637        1293 :       } else M = A;
     638        1591 :       PetscCall(FNEvaluateFunctionMat_Basic(fn,M,F));
     639        1591 :       if (fn->alpha!=(PetscScalar)1.0) PetscCall(FN_FreeWorkMat(fn,&M));
     640             :       /* scale result */
     641        1591 :       PetscCall(MatScale(F,fn->beta));
     642             :     }
     643        1610 :     PetscCall(PetscFPTrapPop());
     644             :   }
     645        1622 :   if (size>1 && fn->pmode==FN_PARALLEL_SYNCHRONIZED && sync) {  /* synchronize */
     646          18 :     PetscCall(MatGetSize(A,&m,&n));
     647          18 :     PetscCall(MatDenseGetArray(F,&pF));
     648          18 :     PetscCall(PetscMPIIntCast(n*n,&n2));
     649          36 :     PetscCallMPI(MPI_Bcast(pF,n2,MPIU_SCALAR,0,PetscObjectComm((PetscObject)fn)));
     650          18 :     PetscCall(MatDenseRestoreArray(F,&pF));
     651             :   }
     652        1622 :   PetscFunctionReturn(PETSC_SUCCESS);
     653             : }
     654             : 
     655             : /*@
     656             :    FNEvaluateFunctionMat - Computes the value of the function f(A) for a given
     657             :    matrix A, where the result is also a matrix.
     658             : 
     659             :    Logically Collective
     660             : 
     661             :    Input Parameters:
     662             : +  fn - the math function context
     663             : -  A  - matrix on which the function must be evaluated
     664             : 
     665             :    Output Parameter:
     666             : .  B  - (optional) matrix resulting from evaluating f(A)
     667             : 
     668             :    Notes:
     669             :    Matrix A must be a square sequential dense Mat, with all entries equal on
     670             :    all processes (otherwise each process will compute different results).
     671             :    If matrix B is provided, it must also be a square sequential dense Mat, and
     672             :    both matrices must have the same dimensions. If B is NULL (or B=A) then the
     673             :    function will perform an in-place computation, overwriting A with f(A).
     674             : 
     675             :    If A is known to be real symmetric or complex Hermitian then it is
     676             :    recommended to set the appropriate flag with MatSetOption(), because
     677             :    symmetry can sometimes be exploited by the algorithm.
     678             : 
     679             :    Scaling factors are taken into account, so the actual function evaluation
     680             :    will return beta*f(alpha*A).
     681             : 
     682             :    Level: advanced
     683             : 
     684             : .seealso: FNEvaluateFunction(), FNEvaluateFunctionMatVec(), FNSetMethod()
     685             : @*/
     686        1576 : PetscErrorCode FNEvaluateFunctionMat(FN fn,Mat A,Mat B)
     687             : {
     688        1576 :   PetscBool      inplace=PETSC_FALSE;
     689        1576 :   PetscInt       m,n,n1;
     690        1576 :   MatType        type;
     691             : 
     692        1576 :   PetscFunctionBegin;
     693        1576 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     694        1576 :   PetscValidHeaderSpecific(A,MAT_CLASSID,2);
     695        1576 :   PetscValidType(fn,1);
     696        1576 :   PetscValidType(A,2);
     697        1576 :   if (B) {
     698        1526 :     PetscValidHeaderSpecific(B,MAT_CLASSID,3);
     699        1526 :     PetscValidType(B,3);
     700             :   } else inplace = PETSC_TRUE;
     701        1576 :   PetscCheckTypeNames(A,MATSEQDENSE,MATSEQDENSECUDA);   //SlepcMatCheckSeq(A);
     702        1576 :   PetscCall(MatGetSize(A,&m,&n));
     703        1576 :   PetscCheck(m==n,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_SIZ,"Mat A is not square (has %" PetscInt_FMT " rows, %" PetscInt_FMT " cols)",m,n);
     704        1576 :   if (!inplace) {
     705        1526 :     PetscCall(MatGetType(A,&type));
     706        1526 :     PetscCheckTypeName(B,type);
     707        1526 :     n1 = n;
     708        1526 :     PetscCall(MatGetSize(B,&m,&n));
     709        1526 :     PetscCheck(m==n,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_SIZ,"Mat B is not square (has %" PetscInt_FMT " rows, %" PetscInt_FMT " cols)",m,n);
     710        1526 :     PetscCheck(n1==n,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_SIZ,"Matrices A and B must have the same dimension");
     711             :   }
     712             : 
     713             :   /* evaluate matrix function */
     714        1576 :   PetscCall(PetscLogEventBegin(FN_Evaluate,fn,0,0,0));
     715        1576 :   PetscCall(FNEvaluateFunctionMat_Private(fn,A,B,PETSC_TRUE));
     716        1576 :   PetscCall(PetscLogEventEnd(FN_Evaluate,fn,0,0,0));
     717        1576 :   PetscFunctionReturn(PETSC_SUCCESS);
     718             : }
     719             : 
     720             : /*
     721             :    FNEvaluateFunctionMatVec_Default - computes the full matrix f(A)
     722             :    and then copies the first column.
     723             : */
     724         271 : static PetscErrorCode FNEvaluateFunctionMatVec_Default(FN fn,Mat A,Vec v)
     725             : {
     726         271 :   Mat            F;
     727             : 
     728         271 :   PetscFunctionBegin;
     729         271 :   PetscCall(FN_AllocateWorkMat(fn,A,&F));
     730         271 :   PetscCall(FNEvaluateFunctionMat_Basic(fn,A,F));
     731         271 :   PetscCall(MatGetColumnVector(F,v,0));
     732         271 :   PetscCall(FN_FreeWorkMat(fn,&F));
     733         271 :   PetscFunctionReturn(PETSC_SUCCESS);
     734             : }
     735             : 
     736             : /*
     737             :    FNEvaluateFunctionMatVec_Sym_Default - given a symmetric matrix A,
     738             :    compute the matrix function as f(A)=Q*f(D)*Q' where the spectral
     739             :    decomposition of A is A=Q*D*Q'. Only the first column is computed.
     740             : */
     741          23 : static PetscErrorCode FNEvaluateFunctionMatVec_Sym_Default(FN fn,Mat A,Vec v)
     742             : {
     743          23 :   PetscInt          m;
     744          23 :   const PetscScalar *As;
     745          23 :   PetscScalar       *vs;
     746             : 
     747          23 :   PetscFunctionBegin;
     748          23 :   PetscCall(MatDenseGetArrayRead(A,&As));
     749          23 :   PetscCall(VecGetArray(v,&vs));
     750          23 :   PetscCall(MatGetSize(A,&m,NULL));
     751          23 :   PetscCall(FNEvaluateFunctionMat_Sym_Private(fn,As,vs,m,PETSC_TRUE));
     752          23 :   PetscCall(MatDenseRestoreArrayRead(A,&As));
     753          23 :   PetscCall(VecRestoreArray(v,&vs));
     754          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     755             : }
     756             : 
     757         422 : PetscErrorCode FNEvaluateFunctionMatVec_Private(FN fn,Mat A,Vec v,PetscBool sync)
     758             : {
     759         422 :   PetscBool      set,flg,symm=PETSC_FALSE,iscuda,hasspecificmeth;
     760         422 :   PetscInt       m,n;
     761         422 :   Mat            M;
     762         422 :   PetscMPIInt    size,rank,n_;
     763         422 :   PetscScalar    *pv;
     764             : 
     765         422 :   PetscFunctionBegin;
     766             :   /* check symmetry of A */
     767         422 :   PetscCall(MatIsHermitianKnown(A,&set,&flg));
     768         422 :   symm = set? flg: PETSC_FALSE;
     769             : 
     770             :   /* evaluate matrix function */
     771         422 :   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)fn),&size));
     772         422 :   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)fn),&rank));
     773         422 :   if (size==1 || fn->pmode==FN_PARALLEL_REDUNDANT || (fn->pmode==FN_PARALLEL_SYNCHRONIZED && !rank)) {
     774         410 :     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
     775         410 :     PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSECUDA,&iscuda));
     776         410 :     hasspecificmeth = ((iscuda && fn->ops->evaluatefunctionmatcuda[fn->method]) || (!iscuda && fn->method && fn->ops->evaluatefunctionmat[fn->method]))? PETSC_TRUE: PETSC_FALSE;
     777         410 :     if (!hasspecificmeth && symm && !fn->method) {  /* prefer diagonalization */
     778          23 :       PetscCall(PetscInfo(fn,"Computing matrix function via diagonalization\n"));
     779          23 :       PetscCall(FNEvaluateFunctionMatVec_Sym_Default(fn,A,v));
     780             :     } else {
     781             :       /* scale argument */
     782         387 :       if (fn->alpha!=(PetscScalar)1.0) {
     783         289 :         PetscCall(FN_AllocateWorkMat(fn,A,&M));
     784         289 :         PetscCall(MatScale(M,fn->alpha));
     785          98 :       } else M = A;
     786         387 :       if (iscuda && fn->ops->evaluatefunctionmatveccuda[fn->method]) PetscUseTypeMethod(fn,evaluatefunctionmatveccuda[fn->method],M,v);
     787         387 :       else if (fn->ops->evaluatefunctionmatvec[fn->method]) PetscUseTypeMethod(fn,evaluatefunctionmatvec[fn->method],M,v);
     788         271 :       else PetscCall(FNEvaluateFunctionMatVec_Default(fn,M,v));
     789         387 :       if (fn->alpha!=(PetscScalar)1.0) PetscCall(FN_FreeWorkMat(fn,&M));
     790             :       /* scale result */
     791         387 :       PetscCall(VecScale(v,fn->beta));
     792             :     }
     793         410 :     PetscCall(PetscFPTrapPop());
     794             :   }
     795             : 
     796             :   /* synchronize */
     797         422 :   if (size>1 && fn->pmode==FN_PARALLEL_SYNCHRONIZED && sync) {
     798          18 :     PetscCall(MatGetSize(A,&m,&n));
     799          18 :     PetscCall(VecGetArray(v,&pv));
     800          18 :     PetscCall(PetscMPIIntCast(n,&n_));
     801          36 :     PetscCallMPI(MPI_Bcast(pv,n_,MPIU_SCALAR,0,PetscObjectComm((PetscObject)fn)));
     802          18 :     PetscCall(VecRestoreArray(v,&pv));
     803             :   }
     804         422 :   PetscFunctionReturn(PETSC_SUCCESS);
     805             : }
     806             : 
     807             : /*@
     808             :    FNEvaluateFunctionMatVec - Computes the first column of the matrix f(A)
     809             :    for a given matrix A.
     810             : 
     811             :    Logically Collective
     812             : 
     813             :    Input Parameters:
     814             : +  fn - the math function context
     815             : -  A  - matrix on which the function must be evaluated
     816             : 
     817             :    Output Parameter:
     818             : .  v  - vector to hold the first column of f(A)
     819             : 
     820             :    Notes:
     821             :    This operation is similar to FNEvaluateFunctionMat() but returns only
     822             :    the first column of f(A), hence saving computations in most cases.
     823             : 
     824             :    Level: advanced
     825             : 
     826             : .seealso: FNEvaluateFunction(), FNEvaluateFunctionMat(), FNSetMethod()
     827             : @*/
     828         352 : PetscErrorCode FNEvaluateFunctionMatVec(FN fn,Mat A,Vec v)
     829             : {
     830         352 :   PetscInt       m,n;
     831         352 :   PetscBool      iscuda;
     832             : 
     833         352 :   PetscFunctionBegin;
     834         352 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     835         352 :   PetscValidHeaderSpecific(A,MAT_CLASSID,2);
     836         352 :   PetscValidHeaderSpecific(v,VEC_CLASSID,3);
     837         352 :   PetscValidType(fn,1);
     838         352 :   PetscValidType(A,2);
     839         352 :   PetscValidType(v,3);
     840         352 :   PetscCheckTypeNames(A,MATSEQDENSE,MATSEQDENSECUDA);   //SlepcMatCheckSeq(A);
     841         352 :   PetscCall(MatGetSize(A,&m,&n));
     842         352 :   PetscCheck(m==n,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_SIZ,"Mat A is not square (has %" PetscInt_FMT " rows, %" PetscInt_FMT " cols)",m,n);
     843         352 :   PetscCall(PetscObjectTypeCompare((PetscObject)A,MATSEQDENSECUDA,&iscuda));
     844         704 :   PetscCheckTypeName(v,iscuda?VECSEQCUDA:VECSEQ);
     845         352 :   PetscCall(VecGetSize(v,&m));
     846         352 :   PetscCheck(m==n,PetscObjectComm((PetscObject)fn),PETSC_ERR_ARG_SIZ,"Matrix A and vector v must have the same size");
     847         352 :   PetscCall(PetscLogEventBegin(FN_Evaluate,fn,0,0,0));
     848         352 :   PetscCall(FNEvaluateFunctionMatVec_Private(fn,A,v,PETSC_TRUE));
     849         352 :   PetscCall(PetscLogEventEnd(FN_Evaluate,fn,0,0,0));
     850         352 :   PetscFunctionReturn(PETSC_SUCCESS);
     851             : }
     852             : 
     853             : /*@
     854             :    FNSetFromOptions - Sets FN options from the options database.
     855             : 
     856             :    Collective
     857             : 
     858             :    Input Parameters:
     859             : .  fn - the math function context
     860             : 
     861             :    Notes:
     862             :    To see all options, run your program with the -help option.
     863             : 
     864             :    Level: beginner
     865             : 
     866             : .seealso: FNSetOptionsPrefix()
     867             : @*/
     868         375 : PetscErrorCode FNSetFromOptions(FN fn)
     869             : {
     870         375 :   char           type[256];
     871         375 :   PetscScalar    array[2];
     872         375 :   PetscInt       k,meth;
     873         375 :   PetscBool      flg;
     874         375 :   FNParallelType pmode;
     875             : 
     876         375 :   PetscFunctionBegin;
     877         375 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     878         375 :   PetscCall(FNRegisterAll());
     879        1125 :   PetscObjectOptionsBegin((PetscObject)fn);
     880         747 :     PetscCall(PetscOptionsFList("-fn_type","Math function type","FNSetType",FNList,(char*)(((PetscObject)fn)->type_name?((PetscObject)fn)->type_name:FNRATIONAL),type,sizeof(type),&flg));
     881         375 :     if (flg) PetscCall(FNSetType(fn,type));
     882         370 :     else if (!((PetscObject)fn)->type_name) PetscCall(FNSetType(fn,FNRATIONAL));
     883             : 
     884         375 :     k = 2;
     885         375 :     array[0] = 0.0; array[1] = 0.0;
     886         375 :     PetscCall(PetscOptionsScalarArray("-fn_scale","Scale factors (one or two scalar values separated with a comma without spaces)","FNSetScale",array,&k,&flg));
     887         375 :     if (flg) {
     888          38 :       if (k<2) array[1] = 1.0;
     889          38 :       PetscCall(FNSetScale(fn,array[0],array[1]));
     890             :     }
     891             : 
     892         375 :     PetscCall(PetscOptionsInt("-fn_method","Method to be used for computing matrix functions","FNSetMethod",fn->method,&meth,&flg));
     893         375 :     if (flg) PetscCall(FNSetMethod(fn,meth));
     894             : 
     895         375 :     PetscCall(PetscOptionsEnum("-fn_parallel","Operation mode in parallel runs","FNSetParallel",FNParallelTypes,(PetscEnum)fn->pmode,(PetscEnum*)&pmode,&flg));
     896         375 :     if (flg) PetscCall(FNSetParallel(fn,pmode));
     897             : 
     898         375 :     PetscTryTypeMethod(fn,setfromoptions,PetscOptionsObject);
     899         375 :     PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)fn,PetscOptionsObject));
     900         375 :   PetscOptionsEnd();
     901         375 :   PetscFunctionReturn(PETSC_SUCCESS);
     902             : }
     903             : 
     904             : /*@
     905             :    FNView - Prints the FN data structure.
     906             : 
     907             :    Collective
     908             : 
     909             :    Input Parameters:
     910             : +  fn - the math function context
     911             : -  viewer - optional visualization context
     912             : 
     913             :    Note:
     914             :    The available visualization contexts include
     915             : +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
     916             : -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
     917             :          output where only the first processor opens
     918             :          the file.  All other processors send their
     919             :          data to the first processor to print.
     920             : 
     921             :    The user can open an alternative visualization context with
     922             :    PetscViewerASCIIOpen() - output to a specified file.
     923             : 
     924             :    Level: beginner
     925             : 
     926             : .seealso: FNCreate()
     927             : @*/
     928          87 : PetscErrorCode FNView(FN fn,PetscViewer viewer)
     929             : {
     930          87 :   PetscBool      isascii;
     931          87 :   PetscMPIInt    size;
     932             : 
     933          87 :   PetscFunctionBegin;
     934          87 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     935          87 :   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)fn),&viewer));
     936          87 :   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
     937          87 :   PetscCheckSameComm(fn,1,viewer,2);
     938          87 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     939          87 :   if (isascii) {
     940          87 :     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)fn,viewer));
     941          87 :     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)fn),&size));
     942          87 :     if (size>1) PetscCall(PetscViewerASCIIPrintf(viewer,"  parallel operation mode: %s\n",FNParallelTypes[fn->pmode]));
     943          87 :     PetscCall(PetscViewerASCIIPushTab(viewer));
     944          87 :     PetscTryTypeMethod(fn,view,viewer);
     945          87 :     PetscCall(PetscViewerASCIIPopTab(viewer));
     946             :   }
     947          87 :   PetscFunctionReturn(PETSC_SUCCESS);
     948             : }
     949             : 
     950             : /*@
     951             :    FNViewFromOptions - View from options
     952             : 
     953             :    Collective
     954             : 
     955             :    Input Parameters:
     956             : +  fn   - the math function context
     957             : .  obj  - optional object
     958             : -  name - command line option
     959             : 
     960             :    Level: intermediate
     961             : 
     962             : .seealso: FNView(), FNCreate()
     963             : @*/
     964         326 : PetscErrorCode FNViewFromOptions(FN fn,PetscObject obj,const char name[])
     965             : {
     966         326 :   PetscFunctionBegin;
     967         326 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
     968         326 :   PetscCall(PetscObjectViewFromOptions((PetscObject)fn,obj,name));
     969         326 :   PetscFunctionReturn(PETSC_SUCCESS);
     970             : }
     971             : 
     972             : /*@
     973             :    FNDuplicate - Duplicates a math function, copying all parameters, possibly with a
     974             :    different communicator.
     975             : 
     976             :    Collective
     977             : 
     978             :    Input Parameters:
     979             : +  fn   - the math function context
     980             : -  comm - MPI communicator
     981             : 
     982             :    Output Parameter:
     983             : .  newfn - location to put the new FN context
     984             : 
     985             :    Note:
     986             :    In order to use the same MPI communicator as in the original object,
     987             :    use PetscObjectComm((PetscObject)fn).
     988             : 
     989             :    Level: developer
     990             : 
     991             : .seealso: FNCreate()
     992             : @*/
     993          44 : PetscErrorCode FNDuplicate(FN fn,MPI_Comm comm,FN *newfn)
     994             : {
     995          44 :   FNType         type;
     996          44 :   PetscScalar    alpha,beta;
     997          44 :   PetscInt       meth;
     998          44 :   FNParallelType ptype;
     999             : 
    1000          44 :   PetscFunctionBegin;
    1001          44 :   PetscValidHeaderSpecific(fn,FN_CLASSID,1);
    1002          44 :   PetscValidType(fn,1);
    1003          44 :   PetscAssertPointer(newfn,3);
    1004          44 :   PetscCall(FNCreate(comm,newfn));
    1005          44 :   PetscCall(FNGetType(fn,&type));
    1006          44 :   PetscCall(FNSetType(*newfn,type));
    1007          44 :   PetscCall(FNGetScale(fn,&alpha,&beta));
    1008          44 :   PetscCall(FNSetScale(*newfn,alpha,beta));
    1009          44 :   PetscCall(FNGetMethod(fn,&meth));
    1010          44 :   PetscCall(FNSetMethod(*newfn,meth));
    1011          44 :   PetscCall(FNGetParallel(fn,&ptype));
    1012          44 :   PetscCall(FNSetParallel(*newfn,ptype));
    1013          44 :   PetscTryTypeMethod(fn,duplicate,comm,newfn);
    1014          44 :   PetscFunctionReturn(PETSC_SUCCESS);
    1015             : }
    1016             : 
    1017             : /*@
    1018             :    FNDestroy - Destroys FN context that was created with FNCreate().
    1019             : 
    1020             :    Collective
    1021             : 
    1022             :    Input Parameter:
    1023             : .  fn - the math function context
    1024             : 
    1025             :    Level: beginner
    1026             : 
    1027             : .seealso: FNCreate()
    1028             : @*/
    1029         948 : PetscErrorCode FNDestroy(FN *fn)
    1030             : {
    1031         948 :   PetscInt       i;
    1032             : 
    1033         948 :   PetscFunctionBegin;
    1034         948 :   if (!*fn) PetscFunctionReturn(PETSC_SUCCESS);
    1035         920 :   PetscValidHeaderSpecific(*fn,FN_CLASSID,1);
    1036         920 :   if (--((PetscObject)*fn)->refct > 0) { *fn = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
    1037         447 :   PetscTryTypeMethod(*fn,destroy);
    1038         579 :   for (i=0;i<(*fn)->nw;i++) PetscCall(MatDestroy(&(*fn)->W[i]));
    1039         447 :   PetscCall(PetscHeaderDestroy(fn));
    1040         447 :   PetscFunctionReturn(PETSC_SUCCESS);
    1041             : }
    1042             : 
    1043             : /*@C
    1044             :    FNRegister - Adds a mathematical function to the FN package.
    1045             : 
    1046             :    Not Collective
    1047             : 
    1048             :    Input Parameters:
    1049             : +  name - name of a new user-defined FN
    1050             : -  function - routine to create context
    1051             : 
    1052             :    Notes:
    1053             :    FNRegister() may be called multiple times to add several user-defined functions.
    1054             : 
    1055             :    Level: advanced
    1056             : 
    1057             : .seealso: FNRegisterAll()
    1058             : @*/
    1059        1246 : PetscErrorCode FNRegister(const char *name,PetscErrorCode (*function)(FN))
    1060             : {
    1061        1246 :   PetscFunctionBegin;
    1062        1246 :   PetscCall(FNInitializePackage());
    1063        1246 :   PetscCall(PetscFunctionListAdd(&FNList,name,function));
    1064        1246 :   PetscFunctionReturn(PETSC_SUCCESS);
    1065             : }

Generated by: LCOV version 1.14