LCOV - code coverage report
Current view: top level - sys/vec - vecutil.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 108 124 87.1 %
Date: 2024-11-21 00:40:22 Functions: 6 6 100.0 %
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             : #include <slepc/private/vecimplslepc.h>       /*I "slepcvec.h" I*/
      12             : 
      13             : /*@
      14             :    VecNormalizeComplex - Normalizes a possibly complex vector by the 2-norm.
      15             : 
      16             :    Collective
      17             : 
      18             :    Input Parameters:
      19             : +  xr - the real part of the vector (overwritten on output)
      20             : .  xi - the imaginary part of the vector (not referenced if iscomplex is false)
      21             : -  iscomplex - a flag indicating if the vector is complex
      22             : 
      23             :    Output Parameter:
      24             : .  norm - the vector norm before normalization (can be set to NULL)
      25             : 
      26             :    Level: developer
      27             : 
      28             : .seealso: BVNormalize()
      29             : @*/
      30          34 : PetscErrorCode VecNormalizeComplex(Vec xr,Vec xi,PetscBool iscomplex,PetscReal *norm)
      31             : {
      32             : #if !defined(PETSC_USE_COMPLEX)
      33             :   PetscReal      normr,normi,alpha;
      34             : #endif
      35             : 
      36          34 :   PetscFunctionBegin;
      37          34 :   PetscValidHeaderSpecific(xr,VEC_CLASSID,1);
      38             : #if !defined(PETSC_USE_COMPLEX)
      39             :   if (iscomplex) {
      40             :     PetscValidHeaderSpecific(xi,VEC_CLASSID,2);
      41             :     PetscCall(VecNormBegin(xr,NORM_2,&normr));
      42             :     PetscCall(VecNormBegin(xi,NORM_2,&normi));
      43             :     PetscCall(VecNormEnd(xr,NORM_2,&normr));
      44             :     PetscCall(VecNormEnd(xi,NORM_2,&normi));
      45             :     alpha = SlepcAbsEigenvalue(normr,normi);
      46             :     if (norm) *norm = alpha;
      47             :     alpha = 1.0 / alpha;
      48             :     PetscCall(VecScale(xr,alpha));
      49             :     PetscCall(VecScale(xi,alpha));
      50             :   } else
      51             : #endif
      52          34 :     PetscCall(VecNormalize(xr,norm));
      53          34 :   PetscFunctionReturn(PETSC_SUCCESS);
      54             : }
      55             : 
      56         252 : static PetscErrorCode VecCheckOrthogonality_Private(Vec V[],PetscInt nv,Vec W[],PetscInt nw,Mat B,PetscViewer viewer,PetscReal *lev,PetscBool norm)
      57             : {
      58         252 :   PetscInt       i,j;
      59         252 :   PetscScalar    *vals;
      60         252 :   PetscBool      isascii;
      61         252 :   Vec            w;
      62             : 
      63         252 :   PetscFunctionBegin;
      64         252 :   if (!lev) {
      65           0 :     if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)*V),&viewer));
      66           0 :     PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,6);
      67           0 :     PetscCheckSameComm(*V,1,viewer,6);
      68           0 :     PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
      69           0 :     if (!isascii) PetscFunctionReturn(PETSC_SUCCESS);
      70             :   }
      71             : 
      72         252 :   PetscCall(PetscMalloc1(nv,&vals));
      73         252 :   if (B) PetscCall(VecDuplicate(V[0],&w));
      74         252 :   if (lev) *lev = 0.0;
      75        3044 :   for (i=0;i<nw;i++) {
      76        2792 :     if (B) {
      77        1208 :       if (W) PetscCall(MatMultTranspose(B,W[i],w));
      78        1202 :       else PetscCall(MatMultTranspose(B,V[i],w));
      79             :     } else {
      80        1584 :       if (W) w = W[i];
      81        1479 :       else w = V[i];
      82             :     }
      83        2792 :     PetscCall(VecMDot(w,nv,V,vals));
      84      182104 :     for (j=0;j<nv;j++) {
      85      179312 :       if (lev) {
      86      355380 :         if (i!=j) *lev = PetscMax(*lev,PetscAbsScalar(vals[j]));
      87        2792 :         else if (norm) {
      88        2681 :           if (PetscRealPart(vals[j])<0.0) *lev = PetscMax(*lev,PetscAbsScalar(vals[j]+PetscRealConstant(1.0)));  /* indefinite case */
      89        4932 :           else *lev = PetscMax(*lev,PetscAbsScalar(vals[j]-PetscRealConstant(1.0)));
      90             :         }
      91             :       } else {
      92             : #if !defined(PETSC_USE_COMPLEX)
      93             :         PetscCall(PetscViewerASCIIPrintf(viewer," %12g  ",(double)vals[j]));
      94             : #else
      95      179312 :         PetscCall(PetscViewerASCIIPrintf(viewer," %12g%+12gi ",(double)PetscRealPart(vals[j]),(double)PetscImaginaryPart(vals[j])));
      96             : #endif
      97             :       }
      98             :     }
      99        2792 :     if (!lev) PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
     100             :   }
     101         252 :   PetscCall(PetscFree(vals));
     102         252 :   if (B) PetscCall(VecDestroy(&w));
     103         252 :   PetscFunctionReturn(PETSC_SUCCESS);
     104             : }
     105             : 
     106             : /*@
     107             :    VecCheckOrthogonality - Checks (or prints) the level of (bi-)orthogonality
     108             :    of a set of vectors.
     109             : 
     110             :    Collective
     111             : 
     112             :    Input Parameters:
     113             : +  V  - a set of vectors
     114             : .  nv - number of V vectors
     115             : .  W  - an alternative set of vectors (optional)
     116             : .  nw - number of W vectors
     117             : .  B  - matrix defining the inner product (optional)
     118             : -  viewer - optional visualization context
     119             : 
     120             :    Output Parameter:
     121             : .  lev - level of orthogonality (optional)
     122             : 
     123             :    Notes:
     124             :    This function computes W'*V and prints the result. It is intended to check
     125             :    the level of bi-orthogonality of the vectors in the two sets. If W is equal
     126             :    to NULL then V is used, thus checking the orthogonality of the V vectors.
     127             : 
     128             :    If matrix B is provided then the check uses the B-inner product, W'*B*V.
     129             : 
     130             :    If lev is not NULL, it will contain the maximum entry of matrix
     131             :    W'*V - I (in absolute value) omitting the diagonal. Otherwise, the matrix W'*V
     132             :    is printed.
     133             : 
     134             :    Level: developer
     135             : 
     136             : .seealso: VecCheckOrthonormality()
     137             : @*/
     138          16 : PetscErrorCode VecCheckOrthogonality(Vec V[],PetscInt nv,Vec W[],PetscInt nw,Mat B,PetscViewer viewer,PetscReal *lev)
     139             : {
     140          16 :   PetscFunctionBegin;
     141          16 :   PetscAssertPointer(V,1);
     142          16 :   PetscValidHeaderSpecific(*V,VEC_CLASSID,1);
     143          48 :   PetscValidLogicalCollectiveInt(*V,nv,2);
     144          48 :   PetscValidLogicalCollectiveInt(*V,nw,4);
     145          16 :   if (nv<=0 || nw<=0) PetscFunctionReturn(PETSC_SUCCESS);
     146          16 :   if (W) {
     147          16 :     PetscAssertPointer(W,3);
     148          16 :     PetscValidHeaderSpecific(*W,VEC_CLASSID,3);
     149          16 :     PetscCheckSameComm(*V,1,*W,3);
     150             :   }
     151          16 :   PetscCall(VecCheckOrthogonality_Private(V,nv,W,nw,B,viewer,lev,PETSC_FALSE));
     152          16 :   PetscFunctionReturn(PETSC_SUCCESS);
     153             : }
     154             : 
     155             : /*@
     156             :    VecCheckOrthonormality - Checks (or prints) the level of (bi-)orthonormality
     157             :    of a set of vectors.
     158             : 
     159             :    Collective
     160             : 
     161             :    Input Parameters:
     162             : +  V  - a set of vectors
     163             : .  nv - number of V vectors
     164             : .  W  - an alternative set of vectors (optional)
     165             : .  nw - number of W vectors
     166             : .  B  - matrix defining the inner product (optional)
     167             : -  viewer - optional visualization context
     168             : 
     169             :    Output Parameter:
     170             : .  lev - level of orthogonality (optional)
     171             : 
     172             :    Notes:
     173             :    This function is equivalent to VecCheckOrthonormality(), but in addition it checks
     174             :    that the diagonal of W'*V (or W'*B*V) is equal to all ones.
     175             : 
     176             :    Level: developer
     177             : 
     178             : .seealso: VecCheckOrthogonality()
     179             : @*/
     180         236 : PetscErrorCode VecCheckOrthonormality(Vec V[],PetscInt nv,Vec W[],PetscInt nw,Mat B,PetscViewer viewer,PetscReal *lev)
     181             : {
     182         236 :   PetscFunctionBegin;
     183         236 :   PetscAssertPointer(V,1);
     184         236 :   PetscValidHeaderSpecific(*V,VEC_CLASSID,1);
     185         708 :   PetscValidLogicalCollectiveInt(*V,nv,2);
     186         708 :   PetscValidLogicalCollectiveInt(*V,nw,4);
     187         236 :   if (nv<=0 || nw<=0) PetscFunctionReturn(PETSC_SUCCESS);
     188         236 :   if (W) {
     189           0 :     PetscAssertPointer(W,3);
     190           0 :     PetscValidHeaderSpecific(*W,VEC_CLASSID,3);
     191           0 :     PetscCheckSameComm(*V,1,*W,3);
     192             :   }
     193         236 :   PetscCall(VecCheckOrthogonality_Private(V,nv,W,nw,B,viewer,lev,PETSC_TRUE));
     194         236 :   PetscFunctionReturn(PETSC_SUCCESS);
     195             : }
     196             : 
     197             : /*@
     198             :    VecDuplicateEmpty - Creates a new vector of the same type as an existing vector,
     199             :    but without internal array.
     200             : 
     201             :    Collective
     202             : 
     203             :    Input Parameters:
     204             : .  v - a vector to mimic
     205             : 
     206             :    Output Parameter:
     207             : .  newv - location to put new vector
     208             : 
     209             :    Note:
     210             :    This is similar to VecDuplicate(), but the new vector does not have an internal
     211             :    array, so the intended usage is with VecPlaceArray().
     212             : 
     213             :    Level: developer
     214             : 
     215             : .seealso: MatCreateVecsEmpty()
     216             : @*/
     217          10 : PetscErrorCode VecDuplicateEmpty(Vec v,Vec *newv)
     218             : {
     219          10 :   PetscBool      standard,cuda,hip,mpi;
     220          10 :   PetscInt       N,nloc,bs;
     221             : 
     222          10 :   PetscFunctionBegin;
     223          10 :   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
     224          10 :   PetscAssertPointer(newv,2);
     225          10 :   PetscValidType(v,1);
     226             : 
     227          10 :   PetscCall(PetscObjectTypeCompareAny((PetscObject)v,&standard,VECSEQ,VECMPI,""));
     228          10 :   PetscCall(PetscObjectTypeCompareAny((PetscObject)v,&cuda,VECSEQCUDA,VECMPICUDA,""));
     229          10 :   PetscCall(PetscObjectTypeCompareAny((PetscObject)v,&hip,VECSEQHIP,VECMPIHIP,""));
     230          10 :   if (standard || cuda || hip) {
     231          10 :     PetscCall(PetscObjectTypeCompareAny((PetscObject)v,&mpi,VECMPI,VECMPICUDA,VECMPIHIP,""));
     232          10 :     PetscCall(VecGetLocalSize(v,&nloc));
     233          10 :     PetscCall(VecGetSize(v,&N));
     234          10 :     PetscCall(VecGetBlockSize(v,&bs));
     235          10 :     if (cuda) {
     236             : #if defined(PETSC_HAVE_CUDA)
     237             :       if (mpi) PetscCall(VecCreateMPICUDAWithArray(PetscObjectComm((PetscObject)v),bs,nloc,N,NULL,newv));
     238             :       else PetscCall(VecCreateSeqCUDAWithArray(PetscObjectComm((PetscObject)v),bs,N,NULL,newv));
     239             : #endif
     240          10 :     } else if (hip) {
     241             : #if defined(PETSC_HAVE_HIP)
     242             :       if (mpi) PetscCall(VecCreateMPIHIPWithArray(PetscObjectComm((PetscObject)v),bs,nloc,N,NULL,newv));
     243             :       else PetscCall(VecCreateSeqHIPWithArray(PetscObjectComm((PetscObject)v),bs,N,NULL,newv));
     244             : #endif
     245             :     } else {
     246          10 :       if (mpi) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)v),bs,nloc,N,NULL,newv));
     247          10 :       else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)v),bs,N,NULL,newv));
     248             :     }
     249           0 :   } else PetscCall(VecDuplicate(v,newv)); /* standard duplicate, with internal array */
     250          10 :   PetscFunctionReturn(PETSC_SUCCESS);
     251             : }
     252             : 
     253             : /*@
     254             :    VecSetRandomNormal - Sets all components of a vector to normally distributed random values.
     255             : 
     256             :    Logically Collective
     257             : 
     258             :    Input Parameters:
     259             : +  v    - the vector to be filled with random values
     260             : .  rctx - the random number context (can be NULL)
     261             : .  w1   - first work vector (can be NULL)
     262             : -  w2   - second work vector (can be NULL)
     263             : 
     264             :    Notes:
     265             :    Fills the two work vectors with uniformly distributed random values (VecSetRandom)
     266             :    and then applies the Box-Muller transform to get normally distributed values on v.
     267             : 
     268             :    Level: developer
     269             : 
     270             : .seealso: VecSetRandom()
     271             : @*/
     272         109 : PetscErrorCode VecSetRandomNormal(Vec v,PetscRandom rctx,Vec w1,Vec w2)
     273             : {
     274         109 :   const PetscScalar *x,*y;
     275         109 :   PetscScalar       *z;
     276         109 :   PetscInt          n,i;
     277         109 :   PetscRandom       rand=NULL;
     278         109 :   Vec               v1=NULL,v2=NULL;
     279             : 
     280         109 :   PetscFunctionBegin;
     281         109 :   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
     282         109 :   PetscValidType(v,1);
     283         109 :   if (rctx) PetscValidHeaderSpecific(rctx,PETSC_RANDOM_CLASSID,2);
     284         109 :   if (w1) PetscValidHeaderSpecific(w1,VEC_CLASSID,3);
     285         109 :   if (w2) PetscValidHeaderSpecific(w2,VEC_CLASSID,4);
     286             : 
     287         109 :   if (!rctx) {
     288           0 :     PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)v),&rand));
     289           0 :     PetscCall(PetscRandomSetFromOptions(rand));
     290           0 :     rctx = rand;
     291             :   }
     292         109 :   if (!w1) {
     293           0 :     PetscCall(VecDuplicate(v,&v1));
     294           0 :     w1 = v1;
     295             :   }
     296         109 :   if (!w2) {
     297           0 :     PetscCall(VecDuplicate(v,&v2));
     298           0 :     w2 = v2;
     299             :   }
     300         109 :   PetscCheckSameTypeAndComm(v,1,w1,3);
     301         109 :   PetscCheckSameTypeAndComm(v,1,w2,4);
     302             : 
     303         109 :   PetscCall(VecSetRandom(w1,rctx));
     304         109 :   PetscCall(VecSetRandom(w2,rctx));
     305         109 :   PetscCall(VecGetLocalSize(v,&n));
     306         109 :   PetscCall(VecGetArrayWrite(v,&z));
     307         109 :   PetscCall(VecGetArrayRead(w1,&x));
     308         109 :   PetscCall(VecGetArrayRead(w2,&y));
     309        6513 :   for (i=0;i<n;i++) {
     310             : #if defined(PETSC_USE_COMPLEX)
     311        6404 :     z[i] = PetscCMPLX(PetscSqrtReal(-2.0*PetscLogReal(PetscRealPart(x[i])))*PetscCosReal(2.0*PETSC_PI*PetscRealPart(y[i])),PetscSqrtReal(-2.0*PetscLogReal(PetscImaginaryPart(x[i])))*PetscCosReal(2.0*PETSC_PI*PetscImaginaryPart(y[i])));
     312             : #else
     313             :     z[i] = PetscSqrtReal(-2.0*PetscLogReal(x[i]))*PetscCosReal(2.0*PETSC_PI*y[i]);
     314             : #endif
     315             :   }
     316         109 :   PetscCall(VecRestoreArrayWrite(v,&z));
     317         109 :   PetscCall(VecRestoreArrayRead(w1,&x));
     318         109 :   PetscCall(VecRestoreArrayRead(w2,&y));
     319             : 
     320         109 :   PetscCall(VecDestroy(&v1));
     321         109 :   PetscCall(VecDestroy(&v2));
     322         109 :   if (!rctx) PetscCall(PetscRandomDestroy(&rand));
     323         109 :   PetscFunctionReturn(PETSC_SUCCESS);
     324             : }

Generated by: LCOV version 1.14