PCSTEIN(l)
β¨ PCSTEIN(l) β LAPACK routine (version 1.5) β¨
okay bestie, sit down, hydrate, because we're about to talk about PCSTEIN and she is a lot but also lowkey iconic π
πΈ NAME πΈ
PCSTEIN β computes the eigenvectors of a symmetric tridiagonal matrix in parallel, using inverse iteration. no cap.
π SYNOPSIS π
SUBROUTINE PCSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, ORFAC, Z, IZ, JZ,
DESCZ, WORK, LWORK, IWORK, LIWORK, IFAIL, ICLUSTR,
GAP, INFO )
INTEGER INFO, IZ, JZ, LIWORK, LWORK, M, N
REAL ORFAC
INTEGER DESCZ( * ), IBLOCK( * ), ICLUSTR( * ), IFAIL( * ),
ISPLIT( * ), IWORK( * )
REAL D( * ), E( * ), GAP( * ), W( * ), WORK( * )
COMPLEX Z( * )
likeβ¦ look at her. all those args. main character energy fr fr π
π PURPOSE π
PCSTEIN computes the eigenvectors of a symmetric tridiagonal matrix in parallel, using inverse iteration. the eigenvectors it finds correspond to user specified eigenvalues β you pick 'em, she finds 'em π¦
important: PCSTEIN does not orthogonalize vectors that are on different processes. the extent of orthogonalization is controlled by the input parameter LWORK. eigenvectors that are to be orthogonalized are computed by the same process. PCSTEIN decides on the allocation of work among the processes and then calls SSTEIN2 (a modified LAPACK routine) on each individual process. and likeβ¦ if insufficient workspace is allocated, the expected orthogonalization may not be done. sad but true π
Note : If the eigenvectors obtained are not orthogonal, increase LWORK and run the code again. that's it, that's the fix, bestie.
β Notes β
Each global data object is described by an associated description vector. this vector stores the information required to establish the mapping between an object element and its corresponding process and memory location. π«Ά
Let A be a generic term for any 2D block cyclicly distributed array. such a global array has an associated description vector DESCA. in the following comments, the character _ should be read as "of the global array".
DTYPE_A(global), stored inDESCA( DTYPE_ )β the descriptor type. in this case,DTYPE_A = 1.CTXT_A(global), stored inDESCA( CTXT_ )β the BLACS context handle, indicating the BLACS process gridAis distributed over. the context itself is global, but the handle (the integer value) may vary.M_A(global), stored inDESCA( M_ )β the number of rows in the global arrayA.N_A(global), stored inDESCA( N_ )β the number of columns in the global arrayA.MB_A(global), stored inDESCA( MB_ )β the blocking factor used to distribute the rows of the array.NB_A(global), stored inDESCA( NB_ )β the blocking factor used to distribute the columns of the array.RSRC_A(global), stored inDESCA( RSRC_ )β the process row over which the first row of the arrayAis distributed.CSRC_A(global), stored inDESCA( CSRC_ )β the process column over which the first column of the arrayAis distributed.LLD_A(local), stored inDESCA( LLD_ )β the leading dimension of the local array.LLD_A >= MAX(1,LOCr(M_A)).
Let K be the number of rows or columns of a distributed matrix, and assume that its process grid has dimension p x q.
LOCr( K ) denotes the number of elements of K that a process would receive if K were distributed over the p processes of its process column.
Similarly, LOCc( K ) denotes the number of elements of K that a process would receive if K were distributed over the q processes of its process row.
The values of LOCr() and LOCc() may be determined via a call to the ScaLAPACK tool function, NUMROC:
LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
An upper bound for these quantities may be computed by:
LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
bestie we are SO not done yet β more parts incoming, don't go anywhere π
β¨ ARGUMENTS β¨
okay bestie, this is the part where we go through every single argument one by one. no skipping, no summarizing, we're doing the whole thing π and yes, every type, dimension, default, and weird edge case is staying. periodt.
P = NPROW * NPCOLβ this is literally the total number of processes, bestie. like, that's the whole vibe. πN(global input,INTEGER) β the order of the tridiagonal matrixT.N >= 0. that's it, that's the tea. β¨D(global input,REAL array, dimension(N)) β thendiagonal elements of the tridiagonal matrixT. yes, lowercasenenergy. πE(global input,REAL array, dimension(N-1)) β the(n-1)off-diagonal elements of the tridiagonal matrixT. the way it's justN-1... iconic. π¦M(global input,INTEGER) β the total number of eigenvectors to be found.0 <= M <= N. no cap. πΈW(global input/global output,REAL array, dim(M)) β on input, the firstMelements ofWcontain all the eigenvalues for which eigenvectors are to be computed. The eigenvalues should be grouped by split-off block and ordered from smallest to largest within the block (the output arrayWfromPSSTEBZwithORDER='b'is expected here). This array should be replicated on all processes. On output, the firstMelements contain the input eigenvalues in ascending order.
Note: To obtain orthogonal vectors, it is best if eigenvalues are computed to highest accuracy (this can be done by setting ABSTOL to the underflow threshold = SLAMCH('U') --- ABSTOL is an input parameter to PSSTEBZ). π
IBLOCK(global input,INTEGER array, dimension(N)) β the submatrix indices associated with the corresponding eigenvalues inW--1for eigenvalues belonging to the first submatrix from the top,2for those belonging to the second submatrix, etc. (the output arrayIBLOCKfromPSSTEBZis expected here). slay. πISPLIT(global input,INTEGER array, dimension(N)) β the splitting points, at whichTbreaks up into submatrices. The first submatrix consists of rows/columns1toISPLIT(1), the second of rows/columnsISPLIT(1)+1throughISPLIT(2), etc., and theNSPLIT-th consists of rows/columnsISPLIT(NSPLIT-1)+1throughISPLIT(NSPLIT)=N(the output arrayISPLITfromPSSTEBZis expected here). the math is mathing. π₯ORFAC(global input,REAL) βORFACspecifies which eigenvectors should be orthogonalized. Eigenvectors that correspond to eigenvalues which are withinORFAC*||T||of each other are to be orthogonalized. However, if the workspace is insufficient (seeLWORK), this tolerance may be decreased until all eigenvectors to be orthogonalized can be stored in one process. No orthogonalization will be done ifORFACequals zero. A default value of10^-3is used ifORFACis negative.ORFACshould be identical on all processes. bestie, keep it consistent. πZ(local output,COMPLEX array, dimension(DESCZ(DLEN_), N/npcol + NB)) βZcontains the computed eigenvectors associated with the specified eigenvalues. Any vector which fails to converge is set to its current iterate afterMAXITSiterations (seeSSTEIN2). On output,Zis distributed across thePprocesses in block cyclic format. it's giving distributed realness. πIZ(global input,INTEGER) βZ's global row index, which points to the beginning of the submatrix which is to be operated on. okurrr. πJZ(global input,INTEGER) βZ's global column index, which points to the beginning of the submatrix which is to be operated on. twin. πDESCZ(global and local input,INTEGER arrayof dimensionDLEN_) β the array descriptor for the distributed matrixZ. iconic descriptor energy. πWORK(local workspace/global output,REAL array, dimension( LWORK )) β on output,WORK(1)gives a lower bound on the workspace (LWORK) that guarantees the user desired orthogonalization (seeORFAC). Note that this may overestimate the minimum workspace needed. lowkey important. βLWORK(local input,integer) βLWORKcontrols the extent of orthogonalization which can be done. The number of eigenvectors for which storage is allocated on each process isNVEC = floor(( LWORK- max(5*N,NP00*MQ00) )/N). Eigenvectors corresponding to eigenvalue clusters of sizeNVEC - ceil(M/P) + 1are guaranteed to be orthogonal (the orthogonality is similar to that obtained fromCSTEIN2). Note:LWORKmust be no smaller than:max(5*N,NP00*MQ00) + ceil(M/P)*N, and should have the same input value on all processes. It is the minimum value ofLWORKinput on different processes that is significant.
If LWORK = -1, then LWORK is global input and a workspace query is assumed; the routine only calculates the minimum and optimal size for all work arrays. Each of these values is returned in the first entry of the corresponding work array, and no error message is issued by PXERBLA. periodt. π
IWORK(local workspace/global output,INTEGER array, dimension( 3*N+P+1 )) β on return,IWORK(1)contains the amount of integer workspace required. On return, theIWORK(2)throughIWORK(P+2)indicate the eigenvectors computed by each process. ProcessIcomputes eigenvectors indexedIWORK(I+2)+1thru'IWORK(I+3). the indexing is giving. π¦LIWORK(local input,INTEGER) β size of arrayIWORK. Must be>= 3*N + P + 1. IfLIWORK = -1, thenLIWORKis global input and a workspace query is assumed; the routine only calculates the minimum and optimal size for all work arrays. Each of these values is returned in the first entry of the corresponding work array, and no error message is issued byPXERBLA. same energy asLWORK. β¨IFAIL(global output,integer array, dimension(M)) β on normal exit, all elements ofIFAILare zero. If one or more eigenvectors fail to converge afterMAXITSiterations (as inCSTEIN), thenINFO > 0is returned. Ifmod(INFO,M+1)>0, then forI=1tomod(INFO,M+1), the eigenvector corresponding to the eigenvalueW(IFAIL(I))failed to converge (Wrefers to the array of eigenvalues on output). bestie, if this happens, it's not a vibe. πICLUSTR(global output,integer array, dimension(2*P)) β this output array contains indices of eigenvectors corresponding to a cluster of eigenvalues that could not be orthogonalized due to insufficient workspace (seeLWORK,ORFACandINFO). Eigenvectors corresponding to clusters of eigenvalues indexedICLUSTR(2*I-1)toICLUSTR(2*I),I = 1toINFO/(M+1), could not be orthogonalized due to lack of workspace. Hence the eigenvectors corresponding to these clusters may not be orthogonal.ICLUSTRis a zero terminated array --- (ICLUSTR(2*K).NE.0 .AND. ICLUSTR(2*K+1).EQ.0) if and only ifKis the number of clusters. the way it's zero terminated... iconic. πGAP(global output,REAL array, dimension(P)) β this output array contains the gap between eigenvalues whose eigenvectors could not be orthogonalized. TheINFO/Moutput values in this array correspond to theINFO/(M+1)clusters indicated by the arrayICLUSTR. As a result, the dot product between eigenvectors corresponding to theI^th cluster may be as high as( O(n)*macheps ) / GAP(I). math queen. πINFO(global output,INTEGER) β= 0: successful exit.< 0: If thei-th argument is an array and thej-entry had an illegal value, thenINFO = -(i*100+j), if thei-th argument is a scalar and had an illegal value, thenINFO = -i.< 0: ifINFO = -I, theI-th argument had an illegal value.> 0: ifmod(INFO,M+1) = I, thenIeigenvectors failed to converge inMAXITSiterations. Their indices are stored in the arrayIFAIL. ifINFO/(M+1) = I, then eigenvectors corresponding toIclusters of eigenvalues could not be orthogonalized due to insufficient workspace. The indices of the clusters are stored in the arrayICLUSTR. so basically, zero is good, negative is bad, positive is also bad but in a different way. π
and that's the whole page, bestie π this iconic manual is from LAPACK version 1.5, dated 12 May 1997, and it's literally PCSTEIN(l) π«Ά no cap.
π¦ where this page comes from
- ubuntu jammy: scalapack-doc 1.5-11
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms