Пример #1
0
HYPRE_Int
hypre_HybridSolve( void               *hybrid_vdata,
                   hypre_StructMatrix *A,
                   hypre_StructVector *b,
                   hypre_StructVector *x            )
{
   hypre_HybridData  *hybrid_data    = hybrid_vdata;

   MPI_Comm           comm           = (hybrid_data -> comm);

   HYPRE_Real         tol            = (hybrid_data -> tol);
   HYPRE_Real         cf_tol         = (hybrid_data -> cf_tol);
   HYPRE_Real         pcg_atolf      = (hybrid_data -> pcg_atolf);
   HYPRE_Int          dscg_max_its   = (hybrid_data -> dscg_max_its);
   HYPRE_Int          pcg_max_its    = (hybrid_data -> pcg_max_its);
   HYPRE_Int          two_norm       = (hybrid_data -> two_norm);
   HYPRE_Int          stop_crit      = (hybrid_data -> stop_crit);
   HYPRE_Int          rel_change     = (hybrid_data -> rel_change);
   HYPRE_Int          logging        = (hybrid_data -> logging);
   HYPRE_Int          print_level    = (hybrid_data -> print_level);
   HYPRE_Int          solver_type    = (hybrid_data -> solver_type);
   HYPRE_Int          k_dim          = (hybrid_data -> k_dim);
  
   HYPRE_Int          pcg_default    = (hybrid_data -> pcg_default);
   HYPRE_Int        (*pcg_precond_solve)();
   HYPRE_Int        (*pcg_precond_setup)();
   void              *pcg_precond;

   void              *pcg_solver;
   hypre_PCGFunctions * pcg_functions;
   hypre_GMRESFunctions * gmres_functions;
   hypre_BiCGSTABFunctions * bicgstab_functions;

   HYPRE_Int          dscg_num_its;
   HYPRE_Int          pcg_num_its;
   HYPRE_Int          converged;

   HYPRE_Real         res_norm;
   HYPRE_Int          myid;

   if (solver_type == 1)
   {
      /*--------------------------------------------------------------------
       * Setup DSCG.
       *--------------------------------------------------------------------*/
      pcg_functions =
         hypre_PCGFunctionsCreate(
            hypre_CAlloc, hypre_StructKrylovFree,
            hypre_StructKrylovCommInfo,
            hypre_StructKrylovCreateVector,
            hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate,
            hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy,
            hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector,
            hypre_StructKrylovClearVector,
            hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy,
            hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity );
      pcg_solver = hypre_PCGCreate( pcg_functions );

      hypre_PCGSetMaxIter(pcg_solver, dscg_max_its);
      hypre_PCGSetTol(pcg_solver, tol);
      hypre_PCGSetAbsoluteTolFactor(pcg_solver, pcg_atolf);
      hypre_PCGSetConvergenceFactorTol(pcg_solver, cf_tol);
      hypre_PCGSetTwoNorm(pcg_solver, two_norm);
      hypre_PCGSetStopCrit(pcg_solver, stop_crit);
      hypre_PCGSetRelChange(pcg_solver, rel_change);
      hypre_PCGSetPrintLevel(pcg_solver, print_level);
      hypre_PCGSetLogging(pcg_solver, logging);

      pcg_precond = NULL;

      hypre_PCGSetPrecond(pcg_solver,
                          HYPRE_StructDiagScale,
                          HYPRE_StructDiagScaleSetup,
                          pcg_precond);
      hypre_PCGSetup(pcg_solver, (void*) A, (void*) b, (void*) x);


      /*--------------------------------------------------------------------
       * Solve with DSCG.
       *--------------------------------------------------------------------*/
      hypre_PCGSolve(pcg_solver, (void*) A, (void*) b, (void*) x);

      /*--------------------------------------------------------------------
       * Get information for DSCG.
       *--------------------------------------------------------------------*/
      hypre_PCGGetNumIterations(pcg_solver, &dscg_num_its);
      (hybrid_data -> dscg_num_its) = dscg_num_its;
      hypre_PCGGetFinalRelativeResidualNorm(pcg_solver, &res_norm);

      /*--------------------------------------------------------------------
       * Get additional information from PCG if logging on for hybrid solver.
       * Currently used as debugging flag to print norms.
       *--------------------------------------------------------------------*/
      if( logging > 1 )
      {
         hypre_MPI_Comm_rank(comm, &myid );
         hypre_PCGPrintLogging(pcg_solver, myid);
      }

      /*--------------------------------------------------------------------
       * check if converged.
       *--------------------------------------------------------------------*/
      hypre_PCGGetConverged(pcg_solver, &converged);
   }
   else if (solver_type == 2)
   {
      /*--------------------------------------------------------------------
       * Setup GMRES
       *--------------------------------------------------------------------*/
      gmres_functions =
         hypre_GMRESFunctionsCreate(
            hypre_CAlloc, hypre_StructKrylovFree,
            hypre_StructKrylovCommInfo,
            hypre_StructKrylovCreateVector,
            hypre_StructKrylovCreateVectorArray,
            hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate,
            hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy,
            hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector,
            hypre_StructKrylovClearVector,
            hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy,
            hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity );
      pcg_solver = hypre_GMRESCreate( gmres_functions );

      hypre_GMRESSetMaxIter(pcg_solver, dscg_max_its);
      hypre_GMRESSetTol(pcg_solver, tol);
      hypre_GMRESSetKDim(pcg_solver, k_dim);
      hypre_GMRESSetConvergenceFactorTol(pcg_solver, cf_tol);
      hypre_GMRESSetStopCrit(pcg_solver, stop_crit);
      hypre_GMRESSetRelChange(pcg_solver, rel_change);
      hypre_GMRESSetPrintLevel(pcg_solver, print_level);
      hypre_GMRESSetPrintLevel(pcg_solver, print_level);
      hypre_GMRESSetLogging(pcg_solver, logging);

      pcg_precond = NULL;

      hypre_GMRESSetPrecond(pcg_solver,
                            HYPRE_StructDiagScale,
                            HYPRE_StructDiagScaleSetup,
                            pcg_precond);
      hypre_GMRESSetup(pcg_solver, (void*) A, (void*) b, (void*) x);


      /*--------------------------------------------------------------------
       * Solve with GMRES
       *--------------------------------------------------------------------*/
      hypre_GMRESSolve(pcg_solver, (void*) A, (void*) b, (void*) x);

      /*--------------------------------------------------------------------
       * Get information for GMRES
       *--------------------------------------------------------------------*/
      hypre_GMRESGetNumIterations(pcg_solver, &dscg_num_its);
      (hybrid_data -> dscg_num_its) = dscg_num_its;
      hypre_GMRESGetFinalRelativeResidualNorm(pcg_solver, &res_norm);

      /*--------------------------------------------------------------------
       * check if converged.
       *--------------------------------------------------------------------*/
      hypre_GMRESGetConverged(pcg_solver, &converged);
   }

   else 
   {
      /*--------------------------------------------------------------------
       * Setup BiCGSTAB
       *--------------------------------------------------------------------*/
      bicgstab_functions =
         hypre_BiCGSTABFunctionsCreate(
            hypre_StructKrylovCreateVector,
            hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate,
            hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy,
            hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector,
            hypre_StructKrylovClearVector,
            hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy,
            hypre_StructKrylovCommInfo,
            hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity );
      pcg_solver = hypre_BiCGSTABCreate( bicgstab_functions );

      hypre_BiCGSTABSetMaxIter(pcg_solver, dscg_max_its);
      hypre_BiCGSTABSetTol(pcg_solver, tol);
      hypre_BiCGSTABSetConvergenceFactorTol(pcg_solver, cf_tol);
      hypre_BiCGSTABSetStopCrit(pcg_solver, stop_crit);
      hypre_BiCGSTABSetPrintLevel(pcg_solver, print_level);
      hypre_BiCGSTABSetLogging(pcg_solver, logging);

      pcg_precond = NULL;

      hypre_BiCGSTABSetPrecond(pcg_solver,
                               HYPRE_StructDiagScale,
                               HYPRE_StructDiagScaleSetup,
                               pcg_precond);
      hypre_BiCGSTABSetup(pcg_solver, (void*) A, (void*) b, (void*) x);


      /*--------------------------------------------------------------------
       * Solve with BiCGSTAB
       *--------------------------------------------------------------------*/
      hypre_BiCGSTABSolve(pcg_solver, (void*) A, (void*) b, (void*) x);

      /*--------------------------------------------------------------------
       * Get information for BiCGSTAB
       *--------------------------------------------------------------------*/
      hypre_BiCGSTABGetNumIterations(pcg_solver, &dscg_num_its);
      (hybrid_data -> dscg_num_its) = dscg_num_its;
      hypre_BiCGSTABGetFinalRelativeResidualNorm(pcg_solver, &res_norm);

      /*--------------------------------------------------------------------
       * check if converged.
       *--------------------------------------------------------------------*/
      hypre_BiCGSTABGetConverged(pcg_solver, &converged);
   }


   /*-----------------------------------------------------------------------
    * if converged, done... 
    *-----------------------------------------------------------------------*/
   if( converged )
   {
      (hybrid_data -> final_rel_res_norm) = res_norm;
      if (solver_type == 1)
	 hypre_PCGDestroy(pcg_solver);
      else if (solver_type == 2)
	 hypre_GMRESDestroy(pcg_solver);
      else
	 hypre_BiCGSTABDestroy(pcg_solver);
   }

   /*-----------------------------------------------------------------------
    * ... otherwise, use SMG+solver
    *-----------------------------------------------------------------------*/
   else
   {
      /*--------------------------------------------------------------------
       * Free up previous PCG solver structure and set up a new one.
       *--------------------------------------------------------------------*/
      if (solver_type == 1)
      {
         hypre_PCGDestroy(pcg_solver);

         pcg_functions =
            hypre_PCGFunctionsCreate(
               hypre_CAlloc, hypre_StructKrylovFree,
               hypre_StructKrylovCommInfo,
               hypre_StructKrylovCreateVector,
               hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate,
               hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy,
               hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector,
               hypre_StructKrylovClearVector,
               hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy,
               hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity );
         pcg_solver = hypre_PCGCreate( pcg_functions );

         hypre_PCGSetMaxIter(pcg_solver, pcg_max_its);
         hypre_PCGSetTol(pcg_solver, tol);
         hypre_PCGSetAbsoluteTolFactor(pcg_solver, pcg_atolf);
         hypre_PCGSetTwoNorm(pcg_solver, two_norm);
         hypre_PCGSetStopCrit(pcg_solver, stop_crit);
         hypre_PCGSetRelChange(pcg_solver, rel_change);
         hypre_PCGSetPrintLevel(pcg_solver, print_level);
         hypre_PCGSetLogging(pcg_solver, logging);
      }
      else if (solver_type == 2)
      {
         hypre_GMRESDestroy(pcg_solver);

         gmres_functions =
            hypre_GMRESFunctionsCreate(
               hypre_CAlloc, hypre_StructKrylovFree,
               hypre_StructKrylovCommInfo,
               hypre_StructKrylovCreateVector,
               hypre_StructKrylovCreateVectorArray,
               hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate,
               hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy,
               hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector,
               hypre_StructKrylovClearVector,
               hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy,
               hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity );
         pcg_solver = hypre_GMRESCreate( gmres_functions );

         hypre_GMRESSetMaxIter(pcg_solver, pcg_max_its);
         hypre_GMRESSetTol(pcg_solver, tol);
         hypre_GMRESSetKDim(pcg_solver, k_dim);
         hypre_GMRESSetStopCrit(pcg_solver, stop_crit);
         hypre_GMRESSetRelChange(pcg_solver, rel_change);
         hypre_GMRESSetPrintLevel(pcg_solver, print_level);
         hypre_GMRESSetLogging(pcg_solver, logging);
         hypre_GMRESSetConvergenceFactorTol(pcg_solver, 0.0);
      }
      else
      {
         hypre_BiCGSTABDestroy(pcg_solver);

         bicgstab_functions =
            hypre_BiCGSTABFunctionsCreate(
               hypre_StructKrylovCreateVector,
               hypre_StructKrylovDestroyVector, hypre_StructKrylovMatvecCreate,
               hypre_StructKrylovMatvec, hypre_StructKrylovMatvecDestroy,
               hypre_StructKrylovInnerProd, hypre_StructKrylovCopyVector,
               hypre_StructKrylovClearVector,
               hypre_StructKrylovScaleVector, hypre_StructKrylovAxpy,
               hypre_StructKrylovCommInfo,
               hypre_StructKrylovIdentitySetup, hypre_StructKrylovIdentity );
         pcg_solver = hypre_BiCGSTABCreate( bicgstab_functions );

         hypre_BiCGSTABSetMaxIter(pcg_solver, pcg_max_its);
         hypre_BiCGSTABSetTol(pcg_solver, tol);
         hypre_BiCGSTABSetStopCrit(pcg_solver, stop_crit);
         hypre_BiCGSTABSetPrintLevel(pcg_solver, print_level);
         hypre_BiCGSTABSetLogging(pcg_solver, logging);
         hypre_BiCGSTABSetConvergenceFactorTol(pcg_solver, 0.0);
      }

      /* Setup preconditioner */
      if (pcg_default)
      {
         pcg_precond = hypre_SMGCreate(comm);
         hypre_SMGSetMaxIter(pcg_precond, 1);
         hypre_SMGSetTol(pcg_precond, 0.0);
         hypre_SMGSetNumPreRelax(pcg_precond, 1);
         hypre_SMGSetNumPostRelax(pcg_precond, 1);
         hypre_SMGSetLogging(pcg_precond, 0);
         pcg_precond_solve = hypre_SMGSolve;
         pcg_precond_setup = hypre_SMGSetup;
      }
      else
      {
         pcg_precond       = (hybrid_data -> pcg_precond);
         pcg_precond_solve = (hybrid_data -> pcg_precond_solve);
         pcg_precond_setup = (hybrid_data -> pcg_precond_setup);
      }

      /* Complete setup of solver+SMG */
      if (solver_type == 1)
      {
         hypre_PCGSetPrecond(pcg_solver,
                             pcg_precond_solve, pcg_precond_setup, pcg_precond);
         hypre_PCGSetup(pcg_solver, (void*) A, (void*) b, (void*) x);

         /* Solve */
         hypre_PCGSolve(pcg_solver, (void*) A, (void*) b, (void*) x);

         /* Get information from PCG that is always logged in hybrid solver*/
         hypre_PCGGetNumIterations(pcg_solver, &pcg_num_its);
         (hybrid_data -> pcg_num_its)  = pcg_num_its;
         hypre_PCGGetFinalRelativeResidualNorm(pcg_solver, &res_norm);
         (hybrid_data -> final_rel_res_norm) = res_norm;

         /*-----------------------------------------------------------------
          * Get additional information from PCG if logging on for hybrid solver.
          * Currently used as debugging flag to print norms.
          *-----------------------------------------------------------------*/
         if( logging > 1 )
         {
            hypre_MPI_Comm_rank(comm, &myid );
            hypre_PCGPrintLogging(pcg_solver, myid);
         }

         /* Free PCG and preconditioner */
         hypre_PCGDestroy(pcg_solver);
      }
      else if (solver_type == 2)
      {
         hypre_GMRESSetPrecond(pcg_solver,
                               pcg_precond_solve, pcg_precond_setup, pcg_precond);
         hypre_GMRESSetup(pcg_solver, (void*) A, (void*) b, (void*) x);

         /* Solve */
         hypre_GMRESSolve(pcg_solver, (void*) A, (void*) b, (void*) x);

         /* Get information from GMRES that is always logged in hybrid solver*/
         hypre_GMRESGetNumIterations(pcg_solver, &pcg_num_its);
         (hybrid_data -> pcg_num_its)  = pcg_num_its;
         hypre_GMRESGetFinalRelativeResidualNorm(pcg_solver, &res_norm);
         (hybrid_data -> final_rel_res_norm) = res_norm;

         /* Free GMRES and preconditioner */
         hypre_GMRESDestroy(pcg_solver);
      }
      else
      {
         hypre_BiCGSTABSetPrecond(pcg_solver, pcg_precond_solve,
                                  pcg_precond_setup, pcg_precond);
         hypre_BiCGSTABSetup(pcg_solver, (void*) A, (void*) b, (void*) x);

         /* Solve */
         hypre_BiCGSTABSolve(pcg_solver, (void*) A, (void*) b, (void*) x);

         /* Get information from BiCGSTAB that is always logged in hybrid solver*/
         hypre_BiCGSTABGetNumIterations(pcg_solver, &pcg_num_its);
         (hybrid_data -> pcg_num_its)  = pcg_num_its;
         hypre_BiCGSTABGetFinalRelativeResidualNorm(pcg_solver, &res_norm);
         (hybrid_data -> final_rel_res_norm) = res_norm;

         /* Free BiCGSTAB and preconditioner */
         hypre_BiCGSTABDestroy(pcg_solver);
      }

      if (pcg_default)
      {
         hypre_SMGDestroy(pcg_precond);
      }
   }

   return hypre_error_flag;
}
Пример #2
0
int
HYPRE_PCGSetStopCrit( HYPRE_Solver solver,
                      int          stop_crit )
{
   return( hypre_PCGSetStopCrit( (void *) solver, stop_crit ) );
}