示例#1
0
void petsc_lobpcg_solve_c_(
   Vec* u,                           /* prototype of a vector, not used   */
   int* num_eval,                    /* number of eigenvalues to compute  */
   int* maxit,                       /* maximum number of iterations      */
   int* niter,                       /* actual number of iterations       */
   double* atol,                     /* absolute error tolerance          */
   double* rtol,                     /* relative error tolerance          */
   double* eigenvalues,              /* computed eigenvalues              */
   void *matmult_opA,                /* Fortran Routine for operator A    */
   void *matmult_opB,                /* Fortran routine for operator B    */
   void *matmult_opT,                /* Fortran routine for operator T    */
   void *petsc_lobpcg_return_evec,  /* Fortran routine gets eigenvectors */
   void *petsc_lobpcg_initial_guess, /* Fortran routine for initial guess */
   int* info)                        /* error code                        */
{

   PetscErrorCode             ierr;         /* for PETSc return code        */
   mv_MultiVectorPtr          eigenvectors; /* the eigenvectors             */
   PetscScalar *              eigs;         /* the eigenvalues              */
   PetscScalar *              eigs_hist;    /* history of eigenvalues       */
   double *                   resid;        /* the residuals                */
   double *                   resid_hist;   /* history of residuals         */
   int                        iterations;   /* number of iterations         */
   int                        n_eigs;       /* number of eigenvalues        */
   int                        i;
   PetscTruth                 outpt=PETSC_FALSE; /* print evals and resids  */
   lobpcg_Tolerance           lobpcg_tol;   /* residual tolerance           */
   mv_InterfaceInterpreter    ii;           /* Interface Interpreter        */
   lobpcg_BLASLAPACKFunctions blap_fn;      /* BLAS functions               */
   aux_data_struct            aux_data;     /* auxillary data               */

/* set the number of eigenvalues to compute */

   n_eigs = *num_eval;

/* set pointers to the Fortran callback functions */
/* type casting added  For Ver 1.1 */
   hold_matmult_opA =(void (*)(void *,void *,void *))  matmult_opA;
   hold_matmult_opB =(void (*)(void *,void *,void *))  matmult_opB;
   hold_matmult_opT =(void (*)(void *,void *,void *))  matmult_opT;
   hold_petsc_lobpcg_initial_guess =(void (*)(void *)) petsc_lobpcg_initial_guess;
   hold_petsc_lobpcg_return_evec = (void (*)(void *)) petsc_lobpcg_return_evec;

/* allocate memory for the eigenvalues, residuals and histories */

   ierr = PetscMalloc(sizeof(PetscScalar)*n_eigs,&eigs);
   ierr = PetscMalloc(sizeof(PetscScalar)*n_eigs*(*maxit+1),&eigs_hist);
   ierr = PetscMalloc(sizeof(double)*n_eigs,&resid);
   ierr = PetscMalloc(sizeof(double)*n_eigs*(*maxit+1),&resid_hist);

/* create the Interface Interpreter and put it in auxillary data */

   PETSCSetupInterpreter( &ii );
   aux_data.ii = ii;

/* set tolerances and BLAS routines */

   lobpcg_tol.absolute = *atol;
   lobpcg_tol.relative = *rtol;

   #ifdef PETSC_USE_COMPLEX  /* complex check added for Ver 1.1 */
      blap_fn.zpotrf = PETSC_zpotrf_interface;
      blap_fn.zhegv = PETSC_zsygv_interface;
   #else
      blap_fn.dpotrf = PETSC_dpotrf_interface;
      blap_fn.dsygv = PETSC_dsygv_interface;
   #endif
/* create the multivector for eigenvectors */

   eigenvectors = mv_MultiVectorCreateFromSampleVector(&ii, n_eigs,*u);

/* set the initial guess.  The second instance of eigenvectors in this
   call isn't actually used, but something has to be passed in */

   petsc_lobpcg_initial_guess_MultiVector(&aux_data,
                                          mv_MultiVectorGetData(eigenvectors),
                                          mv_MultiVectorGetData(eigenvectors));

/* call the lobpcg solver from BLOPEX */
   #ifdef PETSC_USE_COMPLEX   /* complex check added for Ver 1.1 */
   ierr = lobpcg_solve_complex( eigenvectors,
                        &aux_data,
                        OperatorAMultiVector,
                        &aux_data,
                        OperatorBMultiVector,
                        &aux_data,
                        OperatorTMultiVector,
                        NULL,
                        blap_fn,
                        lobpcg_tol,
                        *maxit,
                        0, /* verbosity, use 2 for debugging */
                        &iterations,
                        (komplex *) eigs,
                        (komplex *) eigs_hist,
                        n_eigs,
                        resid,
                        resid_hist,
                        n_eigs
   );
   #else
   ierr = lobpcg_solve_double( eigenvectors,
                        &aux_data,
                        OperatorAMultiVector,
                        &aux_data,
                        OperatorBMultiVector,
                        &aux_data,
                        OperatorTMultiVector,
                        NULL,
                        blap_fn,
                        lobpcg_tol,
                        *maxit,
                        0, /* verbosity, use 2 for debugging */
                        &iterations,
                        eigs,
                        eigs_hist,
                        n_eigs,
                        resid,
                        resid_hist,
                        n_eigs
   );
   #endif

/* set the return error code to lobpcg's error code */

   *info = ierr;

/* set the number of iterations used */

   *niter = iterations;

/* copy the eigenvalues to the return variable */

   #ifdef PETSC_USE_COMPLEX  /* complex check added for Ver 1.1 */
      for (i=0;i<n_eigs;i++) eigenvalues[i] = PetscRealPart(eigs[i]);
   #else
      for (i=0;i<n_eigs;i++) eigenvalues[i] = eigs[i];
   #endif

/* return the eigenvectors.  The second instance of eigenvectors isn't used
   here either */

   petsc_lobpcg_return_evec_MultiVector(&aux_data,
                                        mv_MultiVectorGetData(eigenvectors),
                                        mv_MultiVectorGetData(eigenvectors));

/* printed output, for debugging */

  if (outpt)
  {
      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG driver\n");
      PetscPrintf(PETSC_COMM_WORLD,"   iterations: %d\n",iterations);
      PetscPrintf(PETSC_COMM_WORLD,"   eigenvalues and residuals:\n");
      for (i=0;i<n_eigs;i++)
        {
                ierr = PetscPrintf(PETSC_COMM_WORLD,"%e %e\n",PetscRealPart(eigs[i]),resid[i]);
        }

/*
      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, eigenvalues history:\n");
      for (j=0; j<iterations+1; j++)
         for (i=0;i<n_eigs;i++)
         {
            ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",*(eigs_hist+j*n_eigs+i));
         }
      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, residual norms:\n");
      for (i=0;i<n_eigs;i++)
        {
                ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",resid[i]);
        }

      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, residual norms history:\n");
      for (j=0; j<iterations+1; j++)
         for (i=0;i<n_eigs;i++)
         {
            ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",*(resid_hist+j*n_eigs+i));
         }
*/

   }

/* free work space */

   mv_MultiVectorDestroy(eigenvectors);
   ierr = PetscFree(eigs);
   ierr = PetscFree(eigs_hist);
   ierr = PetscFree(resid);
   ierr = PetscFree(resid_hist);
}
示例#2
0
int main(int argc,char **args)
{
   Vec            u;
   Mat            A;

   PetscErrorCode ierr;

   mv_MultiVectorPtr          eigenvectors;
   PetscScalar  *             eigs;
   PetscScalar  *             eigs_hist;
   double *                   resid;
   double *                   resid_hist;
   int                        iterations;
   PetscMPIInt                rank;
   int                        n_eigs = 1;
   int                         seed = 1;
   int                         i,j;
   PetscLogDouble              t1,t2,elapsed_time;
   DA                          da;
   double                      tol=1e-08;
   PetscTruth                  option_present;
   PetscTruth                  freepart=PETSC_FALSE;
   PetscTruth                  full_output=PETSC_FALSE;
   PetscInt                    m,n,p;
   KSP                        ksp;
   lobpcg_Tolerance           lobpcg_tol;
   int                        maxIt = 100;
   mv_InterfaceInterpreter    ii;
   lobpcg_BLASLAPACKFunctions blap_fn;
   aux_data_struct            aux_data;
/*
   PetscViewer                viewer;
*/
   PetscInt                   tmp_int;
   mv_TempMultiVector * xe;
   PetscInt  N;
   PetscScalar * xx;

   PetscInitialize(&argc,&args,(char *)0,help);
   ierr = PetscOptionsGetInt(PETSC_NULL,"-n_eigs",&tmp_int,&option_present);CHKERRQ(ierr);
   if (option_present)
      n_eigs = tmp_int;
   ierr = PetscOptionsGetReal(PETSC_NULL,"-tol", &tol,PETSC_NULL); CHKERRQ(ierr);
   ierr = PetscOptionsHasName(PETSC_NULL,"-freepart",&freepart); CHKERRQ(ierr);
   ierr = PetscOptionsHasName(PETSC_NULL,"-full_out",&full_output); CHKERRQ(ierr);
   ierr = PetscOptionsGetInt(PETSC_NULL,"-seed",&tmp_int,&option_present);CHKERRQ(ierr);
   if (option_present)
      seed = tmp_int;
   ierr = PetscOptionsGetInt(PETSC_NULL,"-itr",&tmp_int,&option_present);CHKERRQ(ierr);
   if (option_present)
      maxIt = tmp_int;

   if (seed<1)
    seed=1;

  /* we actually run our code twice: first time we solve small problem just to make sure
    that all program code is actually loaded into memory; then we solve the problem
    we are interested in; this trick is done for accurate timing
  */
  PreLoadBegin(PETSC_TRUE,"grid and matrix assembly");

  /* "create" the grid and stencil data; on first run we form small problem */
  if (PreLoadIt==0)
  {
      /* small problem */
      ierr=DACreate3d(PETSC_COMM_WORLD,DA_NONPERIODIC,DA_STENCIL_STAR,10,10,10,
            1,PETSC_DECIDE,1,1,1,0,0,0,&da); CHKERRQ(ierr);
  }
  else
  {
     /* actual problem */
      if (freepart)     /* petsc determines partitioning */
      {
        ierr=DACreate3d(PETSC_COMM_WORLD,DA_NONPERIODIC,DA_STENCIL_STAR,-10,-10,-10,
            PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,1,1,0,0,0,&da); CHKERRQ(ierr);
      }
      else             /* (1,NP,1) partitioning */
      {
        ierr=DACreate3d(PETSC_COMM_WORLD,DA_NONPERIODIC,DA_STENCIL_STAR,-10,-10,-10,
            1,PETSC_DECIDE,1,1,1,0,0,0,&da); CHKERRQ(ierr);
      }

      /* now we print what partitioning is chosen */
      ierr=DAGetInfo(da,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,&m,
                      &n,&p,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr);
      PetscPrintf(PETSC_COMM_WORLD,"Partitioning: %u %u %u\n",m,n,p);
  }

  /* create matrix, whose nonzero structure and probably partitioning corresponds to
  grid and stencil structure */
  ierr=DAGetMatrix(da,MATMPIAIJ,&A); CHKERRQ(ierr);

  /* fill the matrix with values. I intend to build 7-pt Laplas */
  /* this procedure includes matrix assembly */
  ierr=FillMatrix(da,A); CHKERRQ(ierr);

  /*
  PetscViewerBinaryOpen(PETSC_COMM_WORLD,"matrix.dat",FILE_MODE_WRITE,&viewer);
  MatView(A,PETSC_VIEWER_STDOUT_WORLD);
  PetscViewerDestroy(viewer);
  */

  /*
     Create parallel vectors.
      - We form 1 vector from scratch and then duplicate as needed.
  */

  ierr = DACreateGlobalVector(da,&u); CHKERRQ(ierr);
  /* ierr = VecSetFromOptions(u);CHKERRQ(ierr); */

  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                Create the linear solver and set various options
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

/* Here we START measuring time for preconditioner setup */
  PreLoadStage("preconditioner setup");
  ierr = PetscGetTime(&t1);CHKERRQ(ierr);

  /*
     Create linear solver context
  */
  ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr);

  /*
     Set operators. Here the matrix that defines the linear system
     also serves as the preconditioning matrix.
  */
  ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);

  /*
    Set runtime options, e.g.,
        -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol>
    These options will override those specified above as long as
    KSPSetFromOptions() is called _after_ any other customization
    routines.
  */
   ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr);

   /* probably this call actually builds the preconditioner */
   ierr = KSPSetUp(ksp);CHKERRQ(ierr);

/* Here we STOP measuring time for preconditioner setup */
   PreLoadStage("solution");

   ierr = PetscGetTime(&t2);CHKERRQ(ierr);
   elapsed_time=t2-t1;
   if (PreLoadIt==1)
    PetscPrintf(PETSC_COMM_WORLD,"Preconditioner setup, seconds: %f\n",elapsed_time);

   /* request memory for eig-vals */
   ierr = PetscMalloc(sizeof(PetscScalar)*n_eigs,&eigs); CHKERRQ(ierr);

   /* request memory for eig-vals history */
   ierr = PetscMalloc(sizeof(PetscScalar)*n_eigs*(maxIt+1),&eigs_hist); CHKERRQ(ierr);

   /* request memory for resid. norms */
   ierr = PetscMalloc(sizeof(double)*n_eigs,&resid); CHKERRQ(ierr);

   /* request memory for resid. norms hist. */
   ierr = PetscMalloc(sizeof(double)*n_eigs*(maxIt+1),&resid_hist); CHKERRQ(ierr);

   LOBPCG_InitRandomContext();

   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);


   PETSCSetupInterpreter( &ii );
   eigenvectors = mv_MultiVectorCreateFromSampleVector(&ii, n_eigs,u);


   xe = (mv_TempMultiVector *) mv_MultiVectorGetData( eigenvectors );
   /*
   VecView( (Vec)xe->vector[0],PETSC_VIEWER_STDOUT_WORLD);
   */

   for (i=0; i<seed; i++) /* this cycle is to imitate changing random seed */
      mv_MultiVectorSetRandom (eigenvectors, 1234);
   /*
   VecView( (Vec)xe->vector[0],PETSC_VIEWER_STDOUT_WORLD);
   */

   VecGetSize( (Vec)xe->vector[0], &N );
   N=mv_TempMultiVectorHeight( xe );
   VecGetArray( (Vec)xe->vector[0],&xx);

   lobpcg_tol.absolute = tol;
   lobpcg_tol.relative = 1e-50;

   #ifdef PETSC_USE_COMPLEX
      blap_fn.zpotrf = PETSC_zpotrf_interface;
      blap_fn.zhegv = PETSC_zsygv_interface;
   #else
      blap_fn.dpotrf = PETSC_dpotrf_interface;
      blap_fn.dsygv = PETSC_dsygv_interface;
   #endif

   aux_data.A = A;
   aux_data.ksp = ksp;
   aux_data.ii = ii;

/* Here we START measuring time for solution process */
   ierr = PetscGetTime(&t1);CHKERRQ(ierr);

  #ifdef PETSC_USE_COMPLEX
   lobpcg_solve_complex(
              eigenvectors,             /*input-initial guess of e-vectors */
              &aux_data,                /*input-matrix A */
              OperatorAMultiVector,     /*input-operator A */
              NULL,                     /*input-matrix B */
              NULL,                     /*input-operator B */
              &aux_data,                /*input-matrix T */
              Precond_FnMultiVector,    /*input-operator T */
              NULL,                     /*input-matrix Y */
              blap_fn,                  /*input-lapack functions */
              lobpcg_tol,               /*input-tolerances */
              PreLoadIt? maxIt:1,       /*input-max iterations */
              !rank && PreLoadIt,       /*input-verbosity level */

              &iterations,              /*output-actual iterations */
              (komplex *) eigs,                     /*output-eigenvalues */
              (komplex *) eigs_hist,                /*output-eigenvalues history */
              n_eigs,                   /*output-history global height */
              resid,                    /*output-residual norms */
              resid_hist ,              /*output-residual norms history */
              n_eigs                    /*output-history global height  */
    );

   #else

   lobpcg_solve_double( eigenvectors,
                 &aux_data,
              OperatorAMultiVector,
              NULL,
              NULL,
              &aux_data,
              Precond_FnMultiVector,
              NULL,
              blap_fn,
              lobpcg_tol,
              PreLoadIt? maxIt:1,
              !rank && PreLoadIt,
              &iterations,

          eigs,                    /* eigenvalues; "lambda_values" should point to array
                                       containing <blocksize> doubles where <blocksize> is the
                                       width of multivector "blockVectorX" */

          eigs_hist,
                                      /* eigenvalues history; a pointer to the entries of the
                                         <blocksize>-by-(<maxIterations>+1) matrix stored in
                                         fortran-style. (i.e. column-wise) The matrix may be
                                         a submatrix of a larger matrix, see next argument */

              n_eigs,                  /* global height of the matrix (stored in fotran-style)
                                         specified by previous argument */

          resid,
                                      /* residual norms; argument should point to
                                         array of <blocksize> doubles */

          resid_hist ,
                                      /* residual norms history; a pointer to the entries of the
                                         <blocksize>-by-(<maxIterations>+1) matrix stored in
                                         fortran-style. (i.e. column-wise) The matrix may be
                                         a submatrix of a larger matrix, see next argument */
              n_eigs
                                      /* global height of the matrix (stored in fotran-style)
                                         specified by previous argument */
   );

   #endif

/* Here we STOP measuring time for solution process */
  ierr = PetscGetTime(&t2);CHKERRQ(ierr);
  elapsed_time=t2-t1;
  if (PreLoadIt)
   PetscPrintf(PETSC_COMM_WORLD,"Solution process, seconds: %e\n",elapsed_time);

  if (PreLoadIt && full_output)
  {
      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, eigenvalues:\n");
      for (i=0;i<n_eigs;i++)
    {
        ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",PetscRealPart(eigs[i]));
        CHKERRQ(ierr);
    }

      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, eigenvalues history:\n");
      for (j=0; j<iterations+1; j++)
         for (i=0;i<n_eigs;i++)
         {
            ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",PetscRealPart(*(eigs_hist+j*n_eigs+i)));
            CHKERRQ(ierr);
     }
      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, residual norms:\n");
      for (i=0;i<n_eigs;i++)
    {
        ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",resid[i]);
        CHKERRQ(ierr);
    }

      PetscPrintf(PETSC_COMM_WORLD,"Output from LOBPCG, residual norms history:\n");
      for (j=0; j<iterations+1; j++)
         for (i=0;i<n_eigs;i++)
         {
            ierr = PetscPrintf(PETSC_COMM_WORLD,"%e\n",*(resid_hist+j*n_eigs+i));
            CHKERRQ(ierr);
     }
   }
  /*
     Free work space.  All PETSc objects should be destroyed when they
     are no longer needed.
  */
   ierr = VecDestroy(u);CHKERRQ(ierr);
   ierr = MatDestroy(A);CHKERRQ(ierr);
   ierr = KSPDestroy(ksp);CHKERRQ(ierr);
   ierr = DADestroy(da); CHKERRQ(ierr);

   LOBPCG_DestroyRandomContext();
   mv_MultiVectorDestroy(eigenvectors);

   /* free memory used for eig-vals */
   ierr = PetscFree(eigs); CHKERRQ(ierr);
   ierr = PetscFree(eigs_hist); CHKERRQ(ierr);
   ierr = PetscFree(resid); CHKERRQ(ierr);
   ierr = PetscFree(resid_hist); CHKERRQ(ierr);

  /*
     Always call PetscFinalize() before exiting a program.  This routine
       - finalizes the PETSc libraries as well as MPI
       - provides summary and diagnostic information if certain runtime
         options are chosen (e.g., -log_summary).
  */

  PreLoadEnd();
  ierr = PetscFinalize();CHKERRQ(ierr);
  return 0;
}
示例#3
0
int
hypre_LOBPCGSolve( void *vdata, 
		   mv_MultiVectorPtr con, 
		   mv_MultiVectorPtr vec, 
		   double* val )
{
   hypre_LOBPCGData* data = vdata;
   int (*precond)() = (data->precondFunctions).Precond;
   void* opB = data->B;
  
   void (*prec)( void*, void*, void* );
   void (*operatorA)( void*, void*, void* );
   void (*operatorB)( void*, void*, void* );

   int maxit = lobpcg_maxIterations(data->lobpcgData);
   int verb  = lobpcg_verbosityLevel(data->lobpcgData);

   int n	= mv_MultiVectorWidth( vec );
   lobpcg_BLASLAPACKFunctions blap_fn;
   
   utilities_FortranMatrix* lambdaHistory;
   utilities_FortranMatrix* residuals;
   utilities_FortranMatrix* residualsHistory;
  
   lambdaHistory	= lobpcg_eigenvaluesHistory(data->lobpcgData);
   residuals = lobpcg_residualNorms(data->lobpcgData);
   residualsHistory = lobpcg_residualNormsHistory(data->lobpcgData);

   utilities_FortranMatrixAllocateData( n, maxit + 1,	lambdaHistory );
   utilities_FortranMatrixAllocateData( n, 1,		residuals );
   utilities_FortranMatrixAllocateData( n, maxit + 1,	residualsHistory );

   if ( precond != NULL )
      prec = hypre_LOBPCGMultiPreconditioner;
   else
      prec = NULL;

   operatorA = hypre_LOBPCGMultiOperatorA;

   if ( opB != NULL )
      operatorB = hypre_LOBPCGMultiOperatorB;
   else
      operatorB = NULL;

   blap_fn.dsygv = dsygv_interface;
   blap_fn.dpotrf = dpotrf_interface;
  
   lobpcg_solve_double( vec, 
                 vdata, operatorA, 
                 vdata, operatorB,
                 vdata, prec,
                 con,
                 blap_fn,
                 lobpcg_tolerance(data->lobpcgData), maxit, verb,
                 &(lobpcg_iterationNumber(data->lobpcgData)),
                 val, 
                 utilities_FortranMatrixValues(lambdaHistory),
                 utilities_FortranMatrixGlobalHeight(lambdaHistory),
                 utilities_FortranMatrixValues(residuals),
                 utilities_FortranMatrixValues(residualsHistory),
                 utilities_FortranMatrixGlobalHeight(residualsHistory)
      );

   return hypre_error_flag;
}