Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new struct to hold convergence parameters for the Krylov solvers. #1172

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/krylov/conv_params.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/******************************************************************************
* Copyright (c) 1998 Lawrence Livermore National Security, LLC and other
* HYPRE Project Developers. See the top-level COPYRIGHT file for details.
*
* SPDX-License-Identifier: (Apache-2.0 OR MIT)
******************************************************************************/

/******************************************************************************
*
* Krylov convergence parameters header
*
*****************************************************************************/

#ifndef hypre_CONV_PARAMS_HEADER
#define hypre_CONV_PARAMS_HEADER


/**
* The {\tt hypre\_conv\_params} object ...
**/

/*
Summary of Parameters to Control Stopping Test:
- tol = relative error tolerance, as above
-a_tol = absolute convergence tolerance (default is 0.0)
If one desires the convergence test to check the absolute
convergence tolerance *only*, then set the relative convergence
tolerance to 0.0. (The default convergence test is <C*r,r> <=
max(relative_tolerance^2 * <C*b, b>, absolute_tolerance^2)
- cf_tol = convergence factor tolerance; if >0 used for special test
for slow convergence
- atolf = absolute error tolerance factor to be used _together_ with the
relative error tolerance, |delta-residual| / ( atolf + |right-hand-side| ) < tol
(To BE PHASED OUT)
*/

typedef struct
{
HYPRE_Real tol;
HYPRE_Real atolf;
HYPRE_Real cf_tol;
HYPRE_Real a_tol;
HYPRE_Real rtol;

HYPRE_Real rel_residual_norm;

} hypre_conv_params;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't conform to our naming conventions. Should be hypre_ConvParams.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rfalgout yes, I agree. I expected to change this at some point.


#endif
50 changes: 45 additions & 5 deletions src/krylov/krylov.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,49 @@
extern "C" {
#endif

/******************************************************************************
*
* Krylov convergence parameters header
*
*****************************************************************************/

#ifndef hypre_CONV_PARAMS_HEADER
#define hypre_CONV_PARAMS_HEADER


/**
* The {\tt hypre\_conv\_params} object ...
**/

/*
Summary of Parameters to Control Stopping Test:
- tol = relative error tolerance, as above
-a_tol = absolute convergence tolerance (default is 0.0)
If one desires the convergence test to check the absolute
convergence tolerance *only*, then set the relative convergence
tolerance to 0.0. (The default convergence test is <C*r,r> <=
max(relative_tolerance^2 * <C*b, b>, absolute_tolerance^2)
- cf_tol = convergence factor tolerance; if >0 used for special test
for slow convergence
- atolf = absolute error tolerance factor to be used _together_ with the
relative error tolerance, |delta-residual| / ( atolf + |right-hand-side| ) < tol
(To BE PHASED OUT)
*/

typedef struct
{
HYPRE_Real tol;
HYPRE_Real atolf;
HYPRE_Real cf_tol;
HYPRE_Real a_tol;
HYPRE_Real rtol;

HYPRE_Real rel_residual_norm;

} hypre_conv_params;

#endif

/******************************************************************************
*
* BiCGSTAB bicgstab
Expand Down Expand Up @@ -1109,11 +1152,8 @@ typedef struct

typedef struct
{
HYPRE_Real tol;
HYPRE_Real atolf;
HYPRE_Real cf_tol;
HYPRE_Real a_tol;
HYPRE_Real rtol;
void *conv_params;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this have to be void *? I think we should be able to make this opaque to this header file while still retaining some type checking by doing something similar to hypre_SStructGrid_struct in sstruct_mv/HYPRE_sstruct_mv.h for example. In that header file, HYPRE_SStructGrid is used in many of the function prototypes, but it's definition is opaque in that header file. We give it a specific definition in the C source files by way of the lower-case header file. It looks like you need to know the type of the void * once you get into the pcg.c file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rfalgout indeed I can do something similar for this. The type of the struct will be inferred by the precision in which we are building functions in pcg.c. So the struct's precision type will be the same as the function's.


HYPRE_Int max_iter;
HYPRE_Int two_norm;
HYPRE_Int rel_change;
Expand Down
66 changes: 42 additions & 24 deletions src/krylov/pcg.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,15 @@ hypre_PCGCreate( hypre_PCGFunctions *pcg_functions )
pcg_data -> functions = pcg_functions;

/* set defaults */
(pcg_data -> tol) = 1.0e-06;
(pcg_data -> atolf) = 0.0;
(pcg_data -> cf_tol) = 0.0;
(pcg_data -> a_tol) = 0.0;
(pcg_data -> rtol) = 0.0;
hypre_conv_params *pcg_conv_params;
pcg_conv_params = hypre_CTAllocF(hypre_conv_params, 1, pcg_functions, HYPRE_MEMORY_HOST);
pcg_conv_params->tol = 1.0e-6;
pcg_conv_params->atolf = 0.0;
pcg_conv_params->cf_tol = 0.0;
pcg_conv_params->a_tol = 0.0;
pcg_conv_params->rtol = 0.0;

(pcg_data -> conv_params) = pcg_conv_params;
(pcg_data -> max_iter) = 1000;
(pcg_data -> two_norm) = 0;
(pcg_data -> rel_change) = 0;
Expand Down Expand Up @@ -174,6 +178,7 @@ hypre_PCGDestroy( void *pcg_vdata )
(*(pcg_functions->DestroyVector))(pcg_data -> v);
pcg_data -> v = NULL;
}
hypre_TFreeF( pcg_data->conv_params, pcg_functions );
hypre_TFreeF( pcg_data, pcg_functions );
hypre_TFreeF( pcg_functions, pcg_functions );
}
Expand Down Expand Up @@ -208,9 +213,10 @@ hypre_PCGSetup( void *pcg_vdata,
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_PCGFunctions *pcg_functions = pcg_data->functions;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);
HYPRE_Int max_iter = (pcg_data -> max_iter);
HYPRE_Int recompute_residual_p = (pcg_data -> recompute_residual_p);
HYPRE_Real rtol = (pcg_data -> rtol);
HYPRE_Real rtol = (pcg_conv_params -> rtol);
HYPRE_Int two_norm = (pcg_data -> two_norm);
HYPRE_Int flex = (pcg_data -> flex);
HYPRE_Int (*precond_setup)(void*, void*, void*, void*) = (pcg_functions -> precond_setup);
Expand Down Expand Up @@ -322,12 +328,13 @@ hypre_PCGSolve( void *pcg_vdata,
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_PCGFunctions *pcg_functions = pcg_data->functions;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

HYPRE_Real r_tol = (pcg_data -> tol);
HYPRE_Real a_tol = (pcg_data -> a_tol);
HYPRE_Real atolf = (pcg_data -> atolf);
HYPRE_Real cf_tol = (pcg_data -> cf_tol);
HYPRE_Real rtol = (pcg_data -> rtol);
HYPRE_Real r_tol = (pcg_conv_params -> tol);
HYPRE_Real a_tol = (pcg_conv_params -> a_tol);
HYPRE_Real atolf = (pcg_conv_params -> atolf);
HYPRE_Real cf_tol = (pcg_conv_params -> cf_tol);
HYPRE_Real rtol = (pcg_conv_params -> rtol);
HYPRE_Int max_iter = (pcg_data -> max_iter);
HYPRE_Int two_norm = (pcg_data -> two_norm);
HYPRE_Int rel_change = (pcg_data -> rel_change);
Expand Down Expand Up @@ -995,11 +1002,11 @@ hypre_PCGSolve( void *pcg_vdata,
(pcg_data -> num_iterations) = i;
if (bi_prod > 0.0)
{
(pcg_data -> rel_residual_norm) = hypre_sqrt(i_prod / bi_prod);
(pcg_conv_params -> rel_residual_norm) = hypre_sqrt(i_prod / bi_prod);
}
else /* actually, we'll never get here... */
{
(pcg_data -> rel_residual_norm) = 0.0;
(pcg_conv_params -> rel_residual_norm) = 0.0;
}

HYPRE_ANNOTATE_FUNC_END;
Expand All @@ -1016,8 +1023,9 @@ hypre_PCGSetTol( void *pcg_vdata,
HYPRE_Real tol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

(pcg_data -> tol) = tol;
(pcg_conv_params -> tol) = tol;

return hypre_error_flag;
}
Expand All @@ -1027,8 +1035,9 @@ hypre_PCGGetTol( void *pcg_vdata,
HYPRE_Real * tol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

*tol = (pcg_data -> tol);
*tol = (pcg_conv_params -> tol);

return hypre_error_flag;
}
Expand All @@ -1041,8 +1050,9 @@ hypre_PCGSetAbsoluteTol( void *pcg_vdata,
HYPRE_Real a_tol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

(pcg_data -> a_tol) = a_tol;
(pcg_conv_params -> a_tol) = a_tol;

return hypre_error_flag;
}
Expand All @@ -1052,8 +1062,9 @@ hypre_PCGGetAbsoluteTol( void *pcg_vdata,
HYPRE_Real * a_tol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

*a_tol = (pcg_data -> a_tol);
*a_tol = (pcg_conv_params -> a_tol);

return hypre_error_flag;
}
Expand All @@ -1067,8 +1078,9 @@ hypre_PCGSetAbsoluteTolFactor( void *pcg_vdata,
HYPRE_Real atolf )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

(pcg_data -> atolf) = atolf;
(pcg_conv_params -> atolf) = atolf;

return hypre_error_flag;
}
Expand All @@ -1078,8 +1090,9 @@ hypre_PCGGetAbsoluteTolFactor( void *pcg_vdata,
HYPRE_Real * atolf )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

*atolf = (pcg_data -> atolf);
*atolf = (pcg_conv_params -> atolf);

return hypre_error_flag;
}
Expand All @@ -1093,8 +1106,9 @@ hypre_PCGSetResidualTol( void *pcg_vdata,
HYPRE_Real rtol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

(pcg_data -> rtol) = rtol;
(pcg_conv_params -> rtol) = rtol;

return hypre_error_flag;
}
Expand All @@ -1104,8 +1118,9 @@ hypre_PCGGetResidualTol( void *pcg_vdata,
HYPRE_Real * rtol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

*rtol = (pcg_data -> rtol);
*rtol = (pcg_conv_params -> rtol);

return hypre_error_flag;
}
Expand All @@ -1119,8 +1134,9 @@ hypre_PCGSetConvergenceFactorTol( void *pcg_vdata,
HYPRE_Real cf_tol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

(pcg_data -> cf_tol) = cf_tol;
(pcg_conv_params -> cf_tol) = cf_tol;

return hypre_error_flag;
}
Expand All @@ -1130,8 +1146,9 @@ hypre_PCGGetConvergenceFactorTol( void *pcg_vdata,
HYPRE_Real * cf_tol )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

*cf_tol = (pcg_data -> cf_tol);
*cf_tol = (pcg_conv_params -> cf_tol);

return hypre_error_flag;
}
Expand Down Expand Up @@ -1550,8 +1567,9 @@ hypre_PCGGetFinalRelativeResidualNorm( void *pcg_vdata,
HYPRE_Real *relative_residual_norm )
{
hypre_PCGData *pcg_data = (hypre_PCGData *)pcg_vdata;
hypre_conv_params *pcg_conv_params = (hypre_conv_params *)(pcg_data->conv_params);

HYPRE_Real rel_residual_norm = (pcg_data -> rel_residual_norm);
HYPRE_Real rel_residual_norm = (pcg_conv_params -> rel_residual_norm);

*relative_residual_norm = rel_residual_norm;

Expand Down
8 changes: 2 additions & 6 deletions src/krylov/pcg.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,7 @@ typedef struct

typedef struct
{
HYPRE_Real tol;
HYPRE_Real atolf;
HYPRE_Real cf_tol;
HYPRE_Real a_tol;
HYPRE_Real rtol;
void *conv_params;
HYPRE_Int max_iter;
HYPRE_Int two_norm;
HYPRE_Int rel_change;
Expand Down Expand Up @@ -139,7 +135,7 @@ typedef struct

/* log info (always logged) */
HYPRE_Int num_iterations;
HYPRE_Real rel_residual_norm;
// HYPRE_Real rel_residual_norm;

HYPRE_Int print_level; /* printing when print_level>0 */
HYPRE_Int logging; /* extra computations for logging when logging>0 */
Expand Down