aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortradke <tradke@ff385933-4943-42dc-877b-ffc776028de6>2002-03-08 10:47:14 +0000
committertradke <tradke@ff385933-4943-42dc-877b-ffc776028de6>2002-03-08 10:47:14 +0000
commitff49258b74bf1420fdd01e39b3071bed337a9f10 (patch)
tree020605bf04247c4606659c97d0181616daa7e177
parentaa6e128a99109b9f5d2c22d3af46e3c69ff6cbb6 (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.tex21
-rw-r--r--param.ccl7
-rw-r--r--src/NaNCheck.c58
-rw-r--r--src/NaNCheck.h1
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.
%
diff --git a/param.ccl b/param.ccl
index 7f06643..1edb15f 100644
--- a/param.ccl
+++ b/param.ccl
@@ -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);