diff options
author | tradke <tradke@ff385933-4943-42dc-877b-ffc776028de6> | 2002-03-08 10:47:14 +0000 |
---|---|---|
committer | tradke <tradke@ff385933-4943-42dc-877b-ffc776028de6> | 2002-03-08 10:47:14 +0000 |
commit | ff49258b74bf1420fdd01e39b3071bed337a9f10 (patch) | |
tree | 020605bf04247c4606659c97d0181616daa7e177 | |
parent | aa6e128a99109b9f5d2c22d3af46e3c69ff6cbb6 (diff) |
Added a new parameter 'NaNChecker::check_for' by which you can choose whether
to check for NaN and/or infinite values (default is check for both).
This is only evaluated if finite(3) is available.
Sorry for changing the API again.
git-svn-id: http://svn.cactuscode.org/arrangements/CactusUtils/NaNChecker/trunk@26 ff385933-4943-42dc-877b-ffc776028de6
-rw-r--r-- | doc/documentation.tex | 21 | ||||
-rw-r--r-- | param.ccl | 7 | ||||
-rw-r--r-- | src/NaNCheck.c | 58 | ||||
-rw-r--r-- | src/NaNCheck.h | 1 |
4 files changed, 69 insertions, 18 deletions
diff --git a/doc/documentation.tex b/doc/documentation.tex index 02342b5..725ebd9 100644 --- a/doc/documentation.tex +++ b/doc/documentation.tex @@ -45,17 +45,18 @@ respectively). The NaNChecker then registers a routine at {\bf CCTK\_POSTSTEP} which checks at every {\tt NanChecker::check\_every} iteration all the variables listed in -{\tt NaNChecker::check\_vars} and -- in the case a NaN is found -- performs an +{\tt NaNChecker::check\_vars} for NaN or infinite values (depending on {\tt +NaNChecker::check\_for}) and -- if such a value is found -- performs an action as specified in {\tt NaNChecker::action\_if\_found}.\\ Currently these actions can be to \begin{itemize} \item{\tt just\_warn} (the default) - just print a level 1 warning message telling you where NaNs were found + just print a level 1 warning message telling you where NaNs/Infs were found and how many (for grid array variables).\\ For grid arrays it will also print level 2 warnings with the array index - (in fortran order) for all NaN elements. You can limit the number of + (in fortran order) for all NaN/Inf elements. You can limit the number of such warnings by setting the {\tt NanChecker::report\_max} parameter. \item{\tt terminate} @@ -84,8 +85,8 @@ of the variable grid::x, timelevel 1 of {\tt grid::y} and timelevel 2 of \section{NaNChecker API} % Thorn NaNChecker also provides a function API which can be used by other code -to invoke the NaNChecker routines to test for NaN values or to set NaN values -for a list of variables: +to invoke the NaNChecker routines to test for NaN/Inf values or to set NaN +values for a list of variables: \vskip .2cm \noindent{\bf C API} @@ -94,6 +95,7 @@ for a list of variables: int NaNChecker_CheckVarsForNaN (const cGH *cctkGH, int report_max, const char *vars, + const char *check_for, const char *action_if_found); int NaNChecker_SetVarsToNaN (const cGH *cctkGH, @@ -106,12 +108,13 @@ for a list of variables: \begin{verbatim} call NaNChecker_CheckVarsForNaN (ierror, cctkGH, report_max, - vars, action_if_found) + vars, check_for, action_if_found) integer ierror CCTK_POINTER cctkGH integer report_max character*(*) vars + character*(*) check_for character*(*) action_if_found call NaNChecker_SetVarsToNaN (ierror, cctkGH, vars) @@ -121,14 +124,14 @@ for a list of variables: character*(*) vars \end{verbatim} -The {\tt report\_max, check\_vars,} and {\tt action\_if\_found} arguments -have the same semantics as their parameter counterparts.\\ +The {\tt report\_max, check\_vars, check\_for} and {\tt action\_if\_found} +arguments have the same semantics as their parameter counterparts.\\ If {\tt action\_if\_found} is given as a NULL pointer (C API) or as an empty string (Fortran API) the routine will be quiet and just return the number of NaN values found.\\ The C function {\tt NaNChecker\_CheckVarsForNaN()} returns the total number of -NaN values found, {\tt NaNChecker\_SetToNaN()} returns the total number of +NaN/Inf values found, {\tt NaNChecker\_SetToNaN()} returns the total number of variables set to NaN; this return value is stored in the {\tt ierror} argument for the corresponding fortran wrapper routines. % @@ -23,6 +23,13 @@ STRING check_vars "Groups and/or variables to check for NaN's" STEERABLE = ALWAY .* :: "List of full group and/or variable names, or 'all' for everything" } "" +KEYWORD check_for "Check for NaN's and/or infinite numbers (only evaluated if finite(3) is available)" STEERABLE = ALWAYS +{ + "NaN" :: "Check only for NaN's" + "Inf" :: "Check only for infinite numbers" + "both" :: "Check for both NaN's and infinite numbers" +} "both" + KEYWORD action_if_found "What to do if a NaN was found" STEERABLE = ALWAYS { "just warn" :: "Just print a level 1 warning" diff --git a/src/NaNCheck.c b/src/NaNCheck.c index ba5fba4..acef501 100644 --- a/src/NaNCheck.c +++ b/src/NaNCheck.c @@ -40,7 +40,7 @@ void CCTK_FCALL CCTK_FNAME (NaNChecker_CheckVarsForNaN) (int *ierror, const cGH *GH, const int *report_max, - TWO_FORTSTRING_ARG); + THREE_FORTSTRING_ARG); void CCTK_FCALL CCTK_FNAME (NaNChecker_SetVarsToNaN) (int *ierror, const cGH *GH, @@ -68,6 +68,9 @@ typedef struct int report_max; const char *action_if_found; int count; +#ifdef HAVE_FINITE + enum {CHECK_FOR_NAN = 0, CHECK_FOR_INF = 1, CHECK_FOR_BOTH = 2} check_for; +#endif } t_nanchecker_info; @@ -106,6 +109,20 @@ int NaNChecker_NaNCheck (const cGH *GH) info.GH = GH; info.report_max = report_max; info.action_if_found = action_if_found; +#ifdef HAVE_FINITE + if (CCTK_Equals (check_for, "NaN")) + { + info.check_for = CHECK_FOR_NAN; + } + else if (CCTK_Equals (check_for, "Inf")) + { + info.check_for = CHECK_FOR_INF; + } + else + { + info.check_for = CHECK_FOR_BOTH; + } +#endif retval = CCTK_TraverseString (check_vars, CheckForNaN, &info, CCTK_GROUP_OR_VAR); } @@ -144,6 +161,12 @@ int NaNChecker_NaNCheck (const cGH *GH) @vtype const char * @vio in @endvar + @var check_for + @vdesc Whether to check for NaN's and/or infinite numbers + This is only evaluated if finite(3) is available. + @vtype const char * + @vio in + @endvar @var action_if_found @vdesc What do do if a NaN was found This is treated the same as the KEYWORD parameter @@ -165,6 +188,7 @@ int NaNChecker_NaNCheck (const cGH *GH) int NaNChecker_CheckVarsForNaN (const cGH *GH, int report_max, const char *vars, + const char *check_for, const char *action_if_found) { t_nanchecker_info info; @@ -191,6 +215,20 @@ int NaNChecker_CheckVarsForNaN (const cGH *GH, info.report_max = report_max; info.action_if_found = action_if_found; info.count = 0; +#ifdef HAVE_FINITE + if (CCTK_Equals (check_for, "NaN")) + { + info.check_for = CHECK_FOR_NAN; + } + else if (CCTK_Equals (check_for, "Inf")) + { + info.check_for = CHECK_FOR_INF; + } + else + { + info.check_for = CHECK_FOR_BOTH; + } +#endif if (CCTK_TraverseString (vars, CheckForNaN, &info, CCTK_GROUP_OR_VAR) < 0) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, @@ -205,12 +243,13 @@ void CCTK_FCALL CCTK_FNAME (NaNChecker_CheckVarsForNaN) (int *ierror, const cGH *GH, const int *report_max, - TWO_FORTSTRING_ARG) + THREE_FORTSTRING_ARG) { - TWO_FORTSTRING_CREATE (vars, action_if_found); - *ierror = NaNChecker_CheckVarsForNaN (GH, *report_max, vars, + THREE_FORTSTRING_CREATE (vars, check_for, action_if_found); + *ierror = NaNChecker_CheckVarsForNaN (GH, *report_max, vars, check_for, *action_if_found ? action_if_found : NULL); free (vars); + free (check_for); free (action_if_found); } @@ -422,19 +461,20 @@ static void PrintWarning (const char *error_type, #define CHECK_DATA(cctk_type) \ { \ int _i; \ - const cctk_type *_typed_data = (const cctk_type *) data; \ + const cctk_type *_data = (const cctk_type *) data; \ \ \ /* now loop over all elements and check against NaN's */ \ for (_i = 0; _i < nelems; _i++) \ { \ - if (! finite ((double) _typed_data[_i])) \ + if (! finite ((double) _data[_i]) && (info->check_for == CHECK_FOR_BOTH ||\ + ((isnan ((double) _data[_i]) & 1) ^ info->check_for))) \ { \ nans_found++; \ if (info->action_if_found && \ (info->report_max < 0 || nans_found <= info->report_max)) \ { \ - PrintWarning (isnan ((double) _typed_data[_i]) ? "NaN" : "Inf", \ + PrintWarning (isnan ((double) _data[_i]) ? "NaN" : "Inf", \ _i, fp_type, coords, fullname, &gdata); \ } \ } \ @@ -446,13 +486,13 @@ static void PrintWarning (const char *error_type, #define CHECK_DATA(cctk_type) \ { \ int _i; \ - const cctk_type *_typed_data = (const cctk_type *) data; \ + const cctk_type *_data = (const cctk_type *) data; \ \ \ /* now loop over all elements and check against NaN's */ \ for (_i = 0; _i < nelems; _i++) \ { \ - if (isnan ((double) _typed_data[_i])) \ + if (isnan ((double) _data[_i])) \ { \ nans_found++; \ if (info->action_if_found && \ diff --git a/src/NaNCheck.h b/src/NaNCheck.h index 0de3282..b3ee8de 100644 --- a/src/NaNCheck.h +++ b/src/NaNCheck.h @@ -16,6 +16,7 @@ int NaNChecker_CheckVarsForNaN (const cGH *GH, int report_max, const char *vars, + const char *check_for, const char *action_if_found); int NaNChecker_SetVarsToNaN (const cGH *GH, const char *vars); |