LCOV - code coverage report
Current view: top level - sys/classes/ds/interface - dspriv.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 333 357 93.3 %
Date: 2024-12-18 00:51:33 Functions: 13 14 92.9 %
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             :    Private DS routines
      12             : */
      13             : 
      14             : #include <slepc/private/dsimpl.h>      /*I "slepcds.h" I*/
      15             : #include <slepcblaslapack.h>
      16             : 
      17        7700 : PetscErrorCode DSAllocateMat_Private(DS ds,DSMatType m)
      18             : {
      19        7700 :   PetscInt       n,d,rows=0,cols;
      20        7700 :   PetscBool      ispep,isnep;
      21             : 
      22        7700 :   PetscFunctionBegin;
      23        7700 :   n = ds->ld;
      24        7700 :   PetscCall(PetscObjectTypeCompare((PetscObject)ds,DSPEP,&ispep));
      25        7700 :   if (ispep) {
      26        1389 :     if (m==DS_MAT_A || m==DS_MAT_B || m==DS_MAT_W || m==DS_MAT_U || m==DS_MAT_X || m==DS_MAT_Y) {
      27        1304 :       PetscCall(DSPEPGetDegree(ds,&d));
      28        1304 :       n = d*ds->ld;
      29             :     }
      30             :   } else {
      31        6311 :     PetscCall(PetscObjectTypeCompare((PetscObject)ds,DSNEP,&isnep));
      32        6311 :     if (isnep) {
      33         775 :       if (m==DS_MAT_Q || m==DS_MAT_Z || m==DS_MAT_U || m==DS_MAT_V || m==DS_MAT_X || m==DS_MAT_Y) {
      34         152 :         PetscCall(DSNEPGetMinimality(ds,&d));
      35         152 :         n = d*ds->ld;
      36             :       }
      37             :     }
      38             :   }
      39        7700 :   cols = n;
      40             : 
      41        7700 :   switch (m) {
      42             :     case DS_MAT_T:
      43             :       cols = PetscDefined(USE_COMPLEX)? 2: 3;
      44             :       rows = n;
      45             :       break;
      46         140 :     case DS_MAT_D:
      47         140 :       cols = 1;
      48         140 :       rows = n;
      49         140 :       break;
      50        1216 :     case DS_MAT_X:
      51        1216 :       rows = ds->ld;
      52        1216 :       break;
      53          94 :     case DS_MAT_Y:
      54          94 :       rows = ds->ld;
      55          94 :       break;
      56        5708 :     default:
      57        5708 :       rows = n;
      58             :   }
      59        7700 :   if (ds->omat[m]) PetscCall(MatZeroEntries(ds->omat[m]));
      60             :   else {
      61        4467 :     PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,rows,cols,NULL,&ds->omat[m]));
      62             :   }
      63        7700 :   PetscFunctionReturn(PETSC_SUCCESS);
      64             : }
      65             : 
      66          30 : PetscErrorCode DSReallocateMat_Private(DS ds,DSMatType mat,PetscInt ld)
      67             : {
      68          30 :   Mat               M;
      69          30 :   PetscInt          i,m,n,rows,cols;
      70          30 :   PetscScalar       *dst;
      71          30 :   PetscReal         *rdst;
      72          30 :   const PetscScalar *src;
      73          30 :   const PetscReal   *rsrc;
      74             : 
      75          30 :   PetscFunctionBegin;
      76          30 :   PetscCall(MatGetSize(ds->omat[mat],&m,&n));
      77          30 :   rows = ld;
      78          30 :   cols = m==n? ld: n;
      79          30 :   PetscCall(MatCreateSeqDense(PETSC_COMM_SELF,rows,cols,NULL,&M));
      80          30 :   PetscCall(MatDenseGetArrayRead(ds->omat[mat],&src));
      81          30 :   PetscCall(MatDenseGetArray(M,&dst));
      82          30 :   if (mat==DS_MAT_T && PetscDefined(USE_COMPLEX)) {
      83          11 :     rsrc = (const PetscReal*)src;
      84          11 :     rdst = (PetscReal*)dst;
      85          44 :     for (i=0;i<3;i++) PetscCall(PetscArraycpy(rdst+i*ld,rsrc+i*ds->ld,ds->ld));
      86             :   } else {
      87         242 :     for (i=0;i<n;i++) PetscCall(PetscArraycpy(dst+i*ld,src+i*ds->ld,ds->ld));
      88             :   }
      89          30 :   PetscCall(MatDenseRestoreArrayRead(ds->omat[mat],&src));
      90          30 :   PetscCall(MatDenseRestoreArray(M,&dst));
      91          30 :   PetscCall(MatDestroy(&ds->omat[mat]));
      92          30 :   ds->omat[mat] = M;
      93          30 :   PetscFunctionReturn(PETSC_SUCCESS);
      94             : }
      95             : 
      96       79407 : PetscErrorCode DSAllocateWork_Private(DS ds,PetscInt s,PetscInt r,PetscInt i)
      97             : {
      98       79407 :   PetscFunctionBegin;
      99       79407 :   if (s>ds->lwork) {
     100        1611 :     PetscCall(PetscFree(ds->work));
     101        1611 :     PetscCall(PetscMalloc1(s,&ds->work));
     102        1611 :     ds->lwork = s;
     103             :   }
     104       79407 :   if (r>ds->lrwork) {
     105        1354 :     PetscCall(PetscFree(ds->rwork));
     106        1354 :     PetscCall(PetscMalloc1(r,&ds->rwork));
     107        1354 :     ds->lrwork = r;
     108             :   }
     109       79407 :   if (i>ds->liwork) {
     110         651 :     PetscCall(PetscFree(ds->iwork));
     111         651 :     PetscCall(PetscMalloc1(i,&ds->iwork));
     112         651 :     ds->liwork = i;
     113             :   }
     114       79407 :   PetscFunctionReturn(PETSC_SUCCESS);
     115             : }
     116             : 
     117             : /*@
     118             :    DSViewMat - Prints one of the internal DS matrices.
     119             : 
     120             :    Collective
     121             : 
     122             :    Input Parameters:
     123             : +  ds     - the direct solver context
     124             : .  viewer - visualization context
     125             : -  m      - matrix to display
     126             : 
     127             :    Note:
     128             :    Works only for ascii viewers. Set the viewer in Matlab format if
     129             :    want to paste into Matlab.
     130             : 
     131             :    Level: developer
     132             : 
     133             : .seealso: DSView()
     134             : @*/
     135          30 : PetscErrorCode DSViewMat(DS ds,PetscViewer viewer,DSMatType m)
     136             : {
     137          30 :   PetscInt          i,j,rows,cols;
     138          30 :   const PetscScalar *M=NULL,*v;
     139          30 :   PetscViewerFormat format;
     140             : #if defined(PETSC_USE_COMPLEX)
     141          30 :   PetscBool         allreal = PETSC_TRUE;
     142          30 :   const PetscReal   *vr;
     143             : #endif
     144             : 
     145          30 :   PetscFunctionBegin;
     146          30 :   PetscValidHeaderSpecific(ds,DS_CLASSID,1);
     147          90 :   PetscValidLogicalCollectiveEnum(ds,m,3);
     148          30 :   DSCheckValidMat(ds,m,3);
     149          30 :   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ds),&viewer));
     150          30 :   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
     151          30 :   PetscCheckSameComm(ds,1,viewer,2);
     152          30 :   PetscCall(PetscViewerGetFormat(viewer,&format));
     153          30 :   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
     154          30 :   PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
     155          30 :   PetscCall(DSMatGetSize(ds,m,&rows,&cols));
     156          30 :   PetscCall(MatDenseGetArrayRead(ds->omat[m],&M));
     157             : #if defined(PETSC_USE_COMPLEX)
     158             :   /* determine if matrix has all real values */
     159          30 :   if (m!=DS_MAT_T && m!=DS_MAT_D) {
     160             :     /* determine if matrix has all real values */
     161          29 :     v = M;
     162         404 :     for (i=0;i<rows;i++)
     163        4155 :       for (j=0;j<cols;j++)
     164        3780 :         if (PetscImaginaryPart(v[i+j*ds->ld])) { allreal = PETSC_FALSE; break; }
     165             :   }
     166          30 :   if (m==DS_MAT_T) cols=3;
     167             : #endif
     168          30 :   if (format == PETSC_VIEWER_ASCII_MATLAB) {
     169           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"%% Size = %" PetscInt_FMT " %" PetscInt_FMT "\n",rows,cols));
     170           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"%s = [\n",DSMatName[m]));
     171          30 :   } else PetscCall(PetscViewerASCIIPrintf(viewer,"Matrix %s =\n",DSMatName[m]));
     172             : 
     173         420 :   for (i=0;i<rows;i++) {
     174         390 :     v = M+i;
     175             : #if defined(PETSC_USE_COMPLEX)
     176         390 :     vr = (const PetscReal*)M+i;   /* handle compact storage, 2nd column is in imaginary part of 1st column */
     177             : #endif
     178        4185 :     for (j=0;j<cols;j++) {
     179             : #if defined(PETSC_USE_COMPLEX)
     180        3795 :       if (m!=DS_MAT_T && m!=DS_MAT_D) {
     181        3780 :         if (allreal) PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)PetscRealPart(*v)));
     182           0 :         else PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e%+18.16ei ",(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v)));
     183          15 :       } else PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*vr));
     184             : #else
     185             :       PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*v));
     186             : #endif
     187        3795 :       v += ds->ld;
     188             : #if defined(PETSC_USE_COMPLEX)
     189        3795 :       if (m==DS_MAT_T) vr += ds->ld;
     190             : #endif
     191             :     }
     192         390 :     PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
     193             :   }
     194          30 :   PetscCall(MatDenseRestoreArrayRead(ds->omat[m],&M));
     195             : 
     196          30 :   if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer,"];\n"));
     197          30 :   PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
     198          30 :   PetscCall(PetscViewerFlush(viewer));
     199          30 :   PetscFunctionReturn(PETSC_SUCCESS);
     200             : }
     201             : 
     202       19032 : PetscErrorCode DSSortEigenvalues_Private(DS ds,PetscScalar *wr,PetscScalar *wi,PetscInt *perm,PetscBool isghiep)
     203             : {
     204       19032 :   PetscScalar    re,im,wi0;
     205       19032 :   PetscInt       n,i,j,result,tmp1,tmp2=0,d=1;
     206             : 
     207       19032 :   PetscFunctionBegin;
     208       19032 :   n = ds->t;   /* sort only first t pairs if truncated */
     209             :   /* insertion sort */
     210       19032 :   i=ds->l+1;
     211             : #if !defined(PETSC_USE_COMPLEX)
     212             :   if (wi && wi[perm[i-1]]!=0.0) i++; /* initial value is complex */
     213             : #else
     214       19032 :   if (isghiep && PetscImaginaryPart(wr[perm[i-1]])!=0.0) i++;
     215             : #endif
     216      221965 :   for (;i<n;i+=d) {
     217      202933 :     re = wr[perm[i]];
     218      202933 :     if (wi) im = wi[perm[i]];
     219             :     else im = 0.0;
     220      202933 :     tmp1 = perm[i];
     221             : #if !defined(PETSC_USE_COMPLEX)
     222             :     if (im!=0.0) { d = 2; tmp2 = perm[i+1]; }
     223             :     else d = 1;
     224             : #else
     225      202933 :     if (isghiep && PetscImaginaryPart(re)!=0.0) { d = 2; tmp2 = perm[i+1]; }
     226             :     else d = 1;
     227             : #endif
     228      202933 :     j = i-1;
     229      202933 :     if (wi) wi0 = wi[perm[j]];
     230             :     else wi0 = 0.0;
     231      202933 :     PetscCall(SlepcSCCompare(ds->sc,re,im,wr[perm[j]],wi0,&result));
     232      622030 :     while (result<0 && j>=ds->l) {
     233      568800 :       perm[j+d] = perm[j];
     234      568800 :       j--;
     235             : #if !defined(PETSC_USE_COMPLEX)
     236             :       if (wi && wi[perm[j+1]]!=0)
     237             : #else
     238      568800 :       if (isghiep && PetscImaginaryPart(wr[perm[j+1]])!=0)
     239             : #endif
     240        3911 :         { perm[j+d] = perm[j]; j--; }
     241             : 
     242      568800 :       if (j>=ds->l) {
     243      515570 :         if (wi) wi0 = wi[perm[j]];
     244             :         else wi0 = 0.0;
     245     1287303 :         PetscCall(SlepcSCCompare(ds->sc,re,im,wr[perm[j]],wi0,&result));
     246             :       }
     247             :     }
     248      202933 :     perm[j+1] = tmp1;
     249      202933 :     if (d==2) perm[j+2] = tmp2;
     250             :   }
     251       19032 :   PetscFunctionReturn(PETSC_SUCCESS);
     252             : }
     253             : 
     254        5492 : PetscErrorCode DSSortEigenvaluesReal_Private(DS ds,PetscReal *eig,PetscInt *perm)
     255             : {
     256        5492 :   PetscScalar    re;
     257        5492 :   PetscInt       i,j,result,tmp,l,n;
     258             : 
     259        5492 :   PetscFunctionBegin;
     260        5492 :   n = ds->t;   /* sort only first t pairs if truncated */
     261        5492 :   l = ds->l;
     262             :   /* insertion sort */
     263       73768 :   for (i=l+1;i<n;i++) {
     264       68276 :     re = eig[perm[i]];
     265       68276 :     j = i-1;
     266       68276 :     PetscCall(SlepcSCCompare(ds->sc,re,0.0,eig[perm[j]],0.0,&result));
     267      525598 :     while (result<0 && j>=l) {
     268      498369 :       tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
     269     1065014 :       if (j>=l) PetscCall(SlepcSCCompare(ds->sc,re,0.0,eig[perm[j]],0.0,&result));
     270             :     }
     271             :   }
     272        5492 :   PetscFunctionReturn(PETSC_SUCCESS);
     273             : }
     274             : 
     275             : /*
     276             :   Permute comumns [istart..iend-1] of [mat] according to perm. Columns have length n
     277             :  */
     278       20369 : PetscErrorCode DSPermuteColumns_Private(DS ds,PetscInt istart,PetscInt iend,PetscInt n,DSMatType mat,PetscInt *perm)
     279             : {
     280       20369 :   PetscInt    i,j,k,p,ld;
     281       20369 :   PetscScalar *Q,rtmp;
     282             : 
     283       20369 :   PetscFunctionBegin;
     284       20369 :   ld = ds->ld;
     285       20369 :   PetscCall(MatDenseGetArray(ds->omat[mat],&Q));
     286      263344 :   for (i=istart;i<iend;i++) {
     287      242975 :     p = perm[i];
     288      242975 :     if (p != i) {
     289       72605 :       j = i + 1;
     290      571246 :       while (perm[j] != i) j++;
     291       72605 :       perm[j] = p; perm[i] = i;
     292             :       /* swap columns i and j */
     293     1982440 :       for (k=0;k<n;k++) {
     294     1909835 :         rtmp = Q[k+p*ld]; Q[k+p*ld] = Q[k+i*ld]; Q[k+i*ld] = rtmp;
     295             :       }
     296             :     }
     297             :   }
     298       20369 :   PetscCall(MatDenseRestoreArray(ds->omat[mat],&Q));
     299       20369 :   PetscFunctionReturn(PETSC_SUCCESS);
     300             : }
     301             : 
     302             : /*
     303             :   The same as DSPermuteColumns_Private but for two matrices [mat1] and [mat2]
     304             :  */
     305         314 : PetscErrorCode DSPermuteColumnsTwo_Private(DS ds,PetscInt istart,PetscInt iend,PetscInt n,DSMatType mat1,DSMatType mat2,PetscInt *perm)
     306             : {
     307         314 :   PetscInt    i,j,k,p,ld;
     308         314 :   PetscScalar *Q,*Z,rtmp,rtmp2;
     309             : 
     310         314 :   PetscFunctionBegin;
     311         314 :   ld = ds->ld;
     312         314 :   PetscCall(MatDenseGetArray(ds->omat[mat1],&Q));
     313         314 :   PetscCall(MatDenseGetArray(ds->omat[mat2],&Z));
     314        7963 :   for (i=istart;i<iend;i++) {
     315        7649 :     p = perm[i];
     316        7649 :     if (p != i) {
     317        5395 :       j = i + 1;
     318       51762 :       while (perm[j] != i) j++;
     319        5395 :       perm[j] = p; perm[i] = i;
     320             :       /* swap columns i and j */
     321       95509 :       for (k=0;k<n;k++) {
     322       90114 :         rtmp  = Q[k+p*ld]; Q[k+p*ld] = Q[k+i*ld]; Q[k+i*ld] = rtmp;
     323       90114 :         rtmp2 = Z[k+p*ld]; Z[k+p*ld] = Z[k+i*ld]; Z[k+i*ld] = rtmp2;
     324             :       }
     325             :     }
     326             :   }
     327         314 :   PetscCall(MatDenseRestoreArray(ds->omat[mat1],&Q));
     328         314 :   PetscCall(MatDenseRestoreArray(ds->omat[mat2],&Z));
     329         314 :   PetscFunctionReturn(PETSC_SUCCESS);
     330             : }
     331             : 
     332             : /*
     333             :   Permute rows [istart..iend-1] of [mat] according to perm. Rows have length m
     334             :  */
     335           0 : PetscErrorCode DSPermuteRows_Private(DS ds,PetscInt istart,PetscInt iend,PetscInt m,DSMatType mat,PetscInt *perm)
     336             : {
     337           0 :   PetscInt    i,j,k,p,ld;
     338           0 :   PetscScalar *Q,rtmp;
     339             : 
     340           0 :   PetscFunctionBegin;
     341           0 :   ld = ds->ld;
     342           0 :   PetscCall(MatDenseGetArray(ds->omat[mat],&Q));
     343           0 :   for (i=istart;i<iend;i++) {
     344           0 :     p = perm[i];
     345           0 :     if (p != i) {
     346           0 :       j = i + 1;
     347           0 :       while (perm[j] != i) j++;
     348           0 :       perm[j] = p; perm[i] = i;
     349             :       /* swap rows i and j */
     350           0 :       for (k=0;k<m;k++) {
     351           0 :         rtmp = Q[p+k*ld]; Q[p+k*ld] = Q[i+k*ld]; Q[i+k*ld] = rtmp;
     352             :       }
     353             :     }
     354             :   }
     355           0 :   PetscCall(MatDenseRestoreArray(ds->omat[mat],&Q));
     356           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     357             : }
     358             : 
     359             : /*
     360             :   Permute columns [istart..iend-1] of [mat1] and [mat2] according to perm.
     361             :   Columns of [mat1] have length n, columns of [mat2] have length m
     362             :  */
     363        1885 : PetscErrorCode DSPermuteBoth_Private(DS ds,PetscInt istart,PetscInt iend,PetscInt n,PetscInt m,DSMatType mat1,DSMatType mat2,PetscInt *perm)
     364             : {
     365        1885 :   PetscInt    i,j,k,p,ld;
     366        1885 :   PetscScalar *U,*V,rtmp;
     367             : 
     368        1885 :   PetscFunctionBegin;
     369        1885 :   ld = ds->ld;
     370        1885 :   PetscCall(MatDenseGetArray(ds->omat[mat1],&U));
     371        1885 :   PetscCall(MatDenseGetArray(ds->omat[mat2],&V));
     372       21428 :   for (i=istart;i<iend;i++) {
     373       19543 :     p = perm[i];
     374       19543 :     if (p != i) {
     375        4088 :       j = i + 1;
     376       66926 :       while (perm[j] != i) j++;
     377        4088 :       perm[j] = p; perm[i] = i;
     378             :       /* swap columns i and j of U */
     379      433052 :       for (k=0;k<n;k++) {
     380      428964 :         rtmp = U[k+p*ld]; U[k+p*ld] = U[k+i*ld]; U[k+i*ld] = rtmp;
     381             :       }
     382             :       /* swap columns i and j of V */
     383      230520 :       for (k=0;k<m;k++) {
     384      226432 :         rtmp = V[k+p*ld]; V[k+p*ld] = V[k+i*ld]; V[k+i*ld] = rtmp;
     385             :       }
     386             :     }
     387             :   }
     388        1885 :   PetscCall(MatDenseRestoreArray(ds->omat[mat1],&U));
     389        1885 :   PetscCall(MatDenseRestoreArray(ds->omat[mat2],&V));
     390        1885 :   PetscFunctionReturn(PETSC_SUCCESS);
     391             : }
     392             : 
     393             : /*@
     394             :    DSSetIdentity - Copy the identity (a diagonal matrix with ones) on the
     395             :    active part of a matrix.
     396             : 
     397             :    Logically Collective
     398             : 
     399             :    Input Parameters:
     400             : +  ds  - the direct solver context
     401             : -  mat - the matrix to modify
     402             : 
     403             :    Level: intermediate
     404             : 
     405             : .seealso: DSGetMat()
     406             : @*/
     407       10110 : PetscErrorCode DSSetIdentity(DS ds,DSMatType mat)
     408             : {
     409       10110 :   PetscScalar    *A;
     410       10110 :   PetscInt       i,ld,n,l;
     411             : 
     412       10110 :   PetscFunctionBegin;
     413       10110 :   PetscValidHeaderSpecific(ds,DS_CLASSID,1);
     414       30330 :   PetscValidLogicalCollectiveEnum(ds,mat,2);
     415       10110 :   DSCheckValidMat(ds,mat,2);
     416             : 
     417       10110 :   PetscCall(DSGetDimensions(ds,&n,&l,NULL,NULL));
     418       10110 :   PetscCall(DSGetLeadingDimension(ds,&ld));
     419       10110 :   PetscCall(PetscLogEventBegin(DS_Other,ds,0,0,0));
     420       10110 :   PetscCall(MatDenseGetArray(ds->omat[mat],&A));
     421       10110 :   PetscCall(PetscArrayzero(A+l*ld,ld*(n-l)));
     422      137644 :   for (i=l;i<n;i++) A[i+i*ld] = 1.0;
     423       10110 :   PetscCall(MatDenseRestoreArray(ds->omat[mat],&A));
     424       10110 :   PetscCall(PetscLogEventEnd(DS_Other,ds,0,0,0));
     425       10110 :   PetscFunctionReturn(PETSC_SUCCESS);
     426             : }
     427             : 
     428             : /*@
     429             :    DSOrthogonalize - Orthogonalize the columns of a matrix.
     430             : 
     431             :    Logically Collective
     432             : 
     433             :    Input Parameters:
     434             : +  ds   - the direct solver context
     435             : .  mat  - a matrix
     436             : -  cols - number of columns to orthogonalize (starting from column zero)
     437             : 
     438             :    Output Parameter:
     439             : .  lindcols - (optional) number of linearly independent columns of the matrix
     440             : 
     441             :    Level: developer
     442             : 
     443             : .seealso: DSPseudoOrthogonalize()
     444             : @*/
     445        1778 : PetscErrorCode DSOrthogonalize(DS ds,DSMatType mat,PetscInt cols,PetscInt *lindcols)
     446             : {
     447        1778 :   PetscInt       n,l,ld;
     448        1778 :   PetscBLASInt   ld_,rA,cA,info,ltau,lw;
     449        1778 :   PetscScalar    *A,*tau,*w,saux,dummy;
     450             : 
     451        1778 :   PetscFunctionBegin;
     452        1778 :   PetscValidHeaderSpecific(ds,DS_CLASSID,1);
     453        1778 :   DSCheckAlloc(ds,1);
     454        5334 :   PetscValidLogicalCollectiveEnum(ds,mat,2);
     455        1778 :   DSCheckValidMat(ds,mat,2);
     456        5334 :   PetscValidLogicalCollectiveInt(ds,cols,3);
     457             : 
     458        1778 :   PetscCall(DSGetDimensions(ds,&n,&l,NULL,NULL));
     459        1778 :   PetscCall(DSGetLeadingDimension(ds,&ld));
     460        1778 :   n = n - l;
     461        1778 :   PetscCheck(cols<=n,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_WRONG,"Invalid number of columns");
     462        1778 :   if (n == 0 || cols == 0) PetscFunctionReturn(PETSC_SUCCESS);
     463             : 
     464        1778 :   PetscCall(PetscLogEventBegin(DS_Other,ds,0,0,0));
     465        1778 :   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
     466        1778 :   PetscCall(MatDenseGetArray(ds->omat[mat],&A));
     467        1778 :   PetscCall(PetscBLASIntCast(PetscMin(cols,n),&ltau));
     468        1778 :   PetscCall(PetscBLASIntCast(ld,&ld_));
     469        1778 :   PetscCall(PetscBLASIntCast(n,&rA));
     470        1778 :   PetscCall(PetscBLASIntCast(cols,&cA));
     471        1778 :   lw = -1;
     472        1778 :   PetscCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&rA,&cA,A,&ld_,&dummy,&saux,&lw,&info));
     473        1778 :   SlepcCheckLapackInfo("geqrf",info);
     474        1778 :   lw = (PetscBLASInt)PetscRealPart(saux);
     475        1778 :   PetscCall(DSAllocateWork_Private(ds,lw+ltau,0,0));
     476        1778 :   tau = ds->work;
     477        1778 :   w = &tau[ltau];
     478        1778 :   PetscCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&rA,&cA,&A[ld*l+l],&ld_,tau,w,&lw,&info));
     479        1778 :   SlepcCheckLapackInfo("geqrf",info);
     480        1778 :   PetscCallBLAS("LAPACKorgqr",LAPACKorgqr_(&rA,&ltau,&ltau,&A[ld*l+l],&ld_,tau,w,&lw,&info));
     481        1778 :   SlepcCheckLapackInfo("orgqr",info);
     482        1778 :   if (lindcols) *lindcols = ltau;
     483        1778 :   PetscCall(PetscFPTrapPop());
     484        1778 :   PetscCall(MatDenseRestoreArray(ds->omat[mat],&A));
     485        1778 :   PetscCall(PetscLogEventEnd(DS_Other,ds,0,0,0));
     486        1778 :   PetscCall(PetscObjectStateIncrease((PetscObject)ds));
     487        1778 :   PetscFunctionReturn(PETSC_SUCCESS);
     488             : }
     489             : 
     490             : /*
     491             :   Compute C <- a*A*B + b*C, where
     492             :     ldC, the leading dimension of C,
     493             :     ldA, the leading dimension of A,
     494             :     rA, cA, rows and columns of A,
     495             :     At, if true use the transpose of A instead,
     496             :     ldB, the leading dimension of B,
     497             :     rB, cB, rows and columns of B,
     498             :     Bt, if true use the transpose of B instead
     499             : */
     500          55 : static PetscErrorCode SlepcMatDenseMult(PetscScalar *C,PetscInt _ldC,PetscScalar b,PetscScalar a,const PetscScalar *A,PetscInt _ldA,PetscInt rA,PetscInt cA,PetscBool At,const PetscScalar *B,PetscInt _ldB,PetscInt rB,PetscInt cB,PetscBool Bt)
     501             : {
     502          55 :   PetscInt       tmp;
     503          55 :   PetscBLASInt   m, n, k, ldA, ldB, ldC;
     504          55 :   const char     *N = "N", *T = "C", *qA = N, *qB = N;
     505             : 
     506          55 :   PetscFunctionBegin;
     507          55 :   if ((rA == 0) || (cB == 0)) PetscFunctionReturn(PETSC_SUCCESS);
     508          55 :   PetscAssertPointer(C,1);
     509          55 :   PetscAssertPointer(A,5);
     510          55 :   PetscAssertPointer(B,10);
     511          55 :   PetscCall(PetscBLASIntCast(_ldA,&ldA));
     512          55 :   PetscCall(PetscBLASIntCast(_ldB,&ldB));
     513          55 :   PetscCall(PetscBLASIntCast(_ldC,&ldC));
     514             : 
     515             :   /* Transpose if needed */
     516          55 :   if (At) tmp = rA, rA = cA, cA = tmp, qA = T;
     517          55 :   if (Bt) tmp = rB, rB = cB, cB = tmp, qB = T;
     518             : 
     519             :   /* Check size */
     520          55 :   PetscCheck(cA==rB,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Matrix dimensions do not match");
     521             : 
     522             :   /* Do stub */
     523          55 :   if ((rA == 1) && (cA == 1) && (cB == 1)) {
     524           0 :     if (!At && !Bt) *C = *A * *B;
     525           0 :     else if (At && !Bt) *C = PetscConj(*A) * *B;
     526           0 :     else if (!At && Bt) *C = *A * PetscConj(*B);
     527           0 :     else *C = PetscConj(*A) * PetscConj(*B);
     528           0 :     m = n = k = 1;
     529             :   } else {
     530          55 :     PetscCall(PetscBLASIntCast(rA,&m));
     531          55 :     PetscCall(PetscBLASIntCast(cB,&n));
     532          55 :     PetscCall(PetscBLASIntCast(cA,&k));
     533          55 :     PetscCallBLAS("BLASgemm",BLASgemm_(qA,qB,&m,&n,&k,&a,(PetscScalar*)A,&ldA,(PetscScalar*)B,&ldB,&b,C,&ldC));
     534             :   }
     535             : 
     536          55 :   PetscCall(PetscLogFlops(2.0*m*n*k));
     537          55 :   PetscFunctionReturn(PETSC_SUCCESS);
     538             : }
     539             : 
     540             : /*@
     541             :    DSPseudoOrthogonalize - Orthogonalize the columns of a matrix with Modified
     542             :    Gram-Schmidt in an indefinite inner product space defined by a signature.
     543             : 
     544             :    Logically Collective
     545             : 
     546             :    Input Parameters:
     547             : +  ds   - the direct solver context
     548             : .  mat  - the matrix
     549             : .  cols - number of columns to orthogonalize (starting from column zero)
     550             : -  s    - the signature that defines the inner product
     551             : 
     552             :    Output Parameters:
     553             : +  lindcols - (optional) linearly independent columns of the matrix
     554             : -  ns   - (optional) the new signature of the vectors
     555             : 
     556             :    Note:
     557             :    After the call the matrix satisfies A'*s*A = ns.
     558             : 
     559             :    Level: developer
     560             : 
     561             : .seealso: DSOrthogonalize()
     562             : @*/
     563           1 : PetscErrorCode DSPseudoOrthogonalize(DS ds,DSMatType mat,PetscInt cols,PetscReal s[],PetscInt *lindcols,PetscReal ns[])
     564             : {
     565           1 :   PetscInt       i,j,k,l,n,ld;
     566           1 :   PetscBLASInt   info,one=1,zero=0,rA_,ld_;
     567           1 :   PetscScalar    *A,*A_,*m,*h,nr0;
     568           1 :   PetscReal      nr_o,nr,nr_abs,*ns_,done=1.0;
     569             : 
     570           1 :   PetscFunctionBegin;
     571           1 :   PetscValidHeaderSpecific(ds,DS_CLASSID,1);
     572           1 :   DSCheckAlloc(ds,1);
     573           3 :   PetscValidLogicalCollectiveEnum(ds,mat,2);
     574           1 :   DSCheckValidMat(ds,mat,2);
     575           3 :   PetscValidLogicalCollectiveInt(ds,cols,3);
     576           1 :   PetscAssertPointer(s,4);
     577           1 :   PetscCall(DSGetDimensions(ds,&n,&l,NULL,NULL));
     578           1 :   PetscCall(DSGetLeadingDimension(ds,&ld));
     579           1 :   n = n - l;
     580           1 :   PetscCheck(cols<=n,PetscObjectComm((PetscObject)ds),PETSC_ERR_ARG_WRONG,"Invalid number of columns");
     581           1 :   if (n == 0 || cols == 0) PetscFunctionReturn(PETSC_SUCCESS);
     582           1 :   PetscCall(PetscLogEventBegin(DS_Other,ds,0,0,0));
     583           1 :   PetscCall(PetscBLASIntCast(n,&rA_));
     584           1 :   PetscCall(PetscBLASIntCast(ld,&ld_));
     585           1 :   PetscCall(MatDenseGetArray(ds->omat[mat],&A_));
     586           1 :   A = &A_[ld*l+l];
     587           2 :   PetscCall(DSAllocateWork_Private(ds,n+cols,ns?0:cols,0));
     588           1 :   m = ds->work;
     589           1 :   h = &m[n];
     590           1 :   ns_ = ns ? ns : ds->rwork;
     591          11 :   for (i=0; i<cols; i++) {
     592             :     /* m <- diag(s)*A[i] */
     593         110 :     for (k=0; k<n; k++) m[k] = s[k]*A[k+i*ld];
     594             :     /* nr_o <- mynorm(A[i]'*m), mynorm(x) = sign(x)*sqrt(|x|) */
     595          10 :     PetscCall(SlepcMatDenseMult(&nr0,1,0.0,1.0,&A[ld*i],ld,n,1,PETSC_TRUE,m,n,n,1,PETSC_FALSE));
     596          10 :     nr = nr_o = PetscSign(PetscRealPart(nr0))*PetscSqrtReal(PetscAbsScalar(nr0));
     597          16 :     for (j=0; j<3 && i>0; j++) {
     598             :       /* h <- A[0:i-1]'*m */
     599          15 :       PetscCall(SlepcMatDenseMult(h,i,0.0,1.0,A,ld,n,i,PETSC_TRUE,m,n,n,1,PETSC_FALSE));
     600             :       /* h <- diag(ns)*h */
     601          99 :       for (k=0; k<i; k++) h[k] *= ns_[k];
     602             :       /* A[i] <- A[i] - A[0:i-1]*h */
     603          15 :       PetscCall(SlepcMatDenseMult(&A[ld*i],ld,1.0,-1.0,A,ld,n,i,PETSC_FALSE,h,i,i,1,PETSC_FALSE));
     604             :       /* m <- diag(s)*A[i] */
     605         165 :       for (k=0; k<n; k++) m[k] = s[k]*A[k+i*ld];
     606             :       /* nr_o <- mynorm(A[i]'*m) */
     607          15 :       PetscCall(SlepcMatDenseMult(&nr0,1,0.0,1.0,&A[ld*i],ld,n,1,PETSC_TRUE,m,n,n,1,PETSC_FALSE));
     608          15 :       nr = PetscSign(PetscRealPart(nr0))*PetscSqrtReal(PetscAbsScalar(nr0));
     609          15 :       PetscCheck(PetscAbs(nr)>PETSC_MACHINE_EPSILON,PETSC_COMM_SELF,PETSC_ERR_CONV_FAILED,"Linear dependency detected");
     610          15 :       if (PetscAbs(nr) > 0.7*PetscAbs(nr_o)) break;
     611           6 :       nr_o = nr;
     612             :     }
     613          10 :     ns_[i] = PetscSign(nr);
     614             :     /* A[i] <- A[i]/|nr| */
     615          10 :     nr_abs = PetscAbs(nr);
     616          10 :     PetscCallBLAS("LAPACKlascl",LAPACKlascl_("G",&zero,&zero,&nr_abs,&done,&rA_,&one,A+i*ld,&ld_,&info));
     617          10 :     SlepcCheckLapackInfo("lascl",info);
     618             :   }
     619           1 :   PetscCall(MatDenseRestoreArray(ds->omat[mat],&A_));
     620           1 :   PetscCall(PetscLogEventEnd(DS_Other,ds,0,0,0));
     621           1 :   PetscCall(PetscObjectStateIncrease((PetscObject)ds));
     622           1 :   if (lindcols) *lindcols = cols;
     623           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     624             : }

Generated by: LCOV version 1.14