/* examples/C/ssmfe/precond_expert.c */ /* Laplacian on a square grid (using SPRAL_SSMFE_EXPERT routines) */ #include "spral.h" #include #include #include #include /* Header that implements Laplacian and preconditioners */ #include "laplace2d.h" int main(void) { const int ngrid = 20; /* grid points along each side */ const int n = ngrid*ngrid; /* problem size */ const int nep = 5; /* eigenpairs wanted */ const int m = 3; /* dimension of the iterated subspace */ int state = SPRAL_RANDOM_INITIAL_SEED; /* PRNG state */ int *ind = malloc(m * sizeof(*ind)); /* permutation index */ double *lambda = malloc(n * sizeof(*lambda)); /* eigenvalues */ double (*X)[n][n] = malloc(sizeof(*X)); /* eigenvectors */ /* Work arrays */ double (*rr)[3][2*m][2*m] = malloc(sizeof(*rr)); double (*W)[6][m][n] = malloc(sizeof(*W)); double (*U)[m][n] = malloc(sizeof(*U)); /* Derived types */ struct spral_ssmfe_rcid rci; /* reverse communication data */ struct spral_ssmfe_options options; /* options */ void *keep; /* private data */ struct spral_ssmfe_inform inform; /* information */ /* Initialize options to default values */ spral_ssmfe_default_options(&options); /* gap between the last converged eigenvalue and the rest of the spectrum * must be at least 0.1 times average gap between computed eigenvalues */ options.left_gap = -0.1; /* block size is small, convergence may be slow, allow more iterations */ options.max_iterations = 200; /* Initialize W to lin indep vectors by randomizing */ for(int i=0; i rci.jy ) { cblas_dcopy(n*rci.nx, &(*W)[rci.kx][rci.jx][0], 1, &(*W)[rci.ky][rci.jy][0], 1); } else if ( rci.jx < rci.jy ) { for(int j=rci.nx-1; j>=0; j--) cblas_dcopy(n, &(*W)[rci.kx][rci.jx+j][0], 1, &(*W)[rci.ky][rci.jy+j][0], 1); } } else { for(int i=0; i 0 ) cblas_dscal(n, 1/s, &(*W)[rci.kx][rci.jx+i][0], 1); } else { double s = sqrt(fabs(cblas_ddot( n, &(*W)[rci.kx][rci.jx+i][0], 1, &(*W)[rci.ky][rci.jy+i][0], 1) )); if ( s > 0 ) { cblas_dscal(n, 1/s, &(*W)[rci.kx][rci.jx+i][0], 1); cblas_dscal(n, 1/s, &(*W)[rci.ky][rci.jy+i][0], 1); } else { for(int j=0; j 0 && rci.ny > 0 ) cblas_dgemm( CblasColMajor, CblasTrans, CblasNoTrans, rci.nx, rci.ny, n, rci.alpha, &(*W)[rci.kx][rci.jx][0], n, &(*W)[rci.ky][rci.jy][0], n, rci.beta, &(*rr)[rci.k][rci.j][rci.i], 2*m ); break; case 16: // Fall through to 17 case 17: if( rci.ny < 1 ) continue; if( rci.nx < 1 ) { if( rci.job == 17 ) continue; if( rci.beta == 1.0 ) continue; for(int j=rci.jy; j 0 ) { cblas_dgemm( CblasColMajor, CblasTrans, CblasNoTrans, ncon, rci.nx, n, 1.0, &(*X)[0][0], n, &(*W)[rci.ky][rci.jy][0], n, 0.0, &(*U)[0][0], n ); cblas_dgemm( CblasColMajor, CblasNoTrans, CblasNoTrans, n, rci.nx, ncon, -1.0, &(*X)[0][0], n, &(*U)[0][0], n, 1.0, &(*W)[rci.kx][rci.jx][0], n ); } break; case 999: if( rci.k == 0 ) { if( rci.jx > 1 ) { for(int j=0; j