PROTECT

Since NONMEM 7.4, a series of routines are available that protect against domain violations, divide by zero, and floating point overflows. Each of these routines start with the letter P, followed by the name of the mathematical operation they are to perform. For example, PLOG is the protective code routine that performs the LOG operation. In addition, there are first derivative (such as PLOGD1), and second derivative (such as PLOGD2) companion routines available which NMTRAN uses for computing analytical derivatives. The source code of these routines are available in ..\source\PROTECT.f90. If you wish to modify their behavior, then copy PROTECT.f90 to your run directory as (say) myprotect.f90, modify it, then refer to this modified code with $SUBROUTINES OTHER=myprotect.f90 (The OTHER option is not needed if the P functions are coded explicitly or implicitly via $ABBR PROTECT.)

The following protective code routines are available. For all routines, if X=not a number, X is converted to machine precision value, which is about 1.0E-15, before performing an operation on it. If X>INFNTY (where INFNTY is approximately 1.0E+154), then X is converted to INFNTY before an operation is performed on it.

  • PLOG(x): returns LOG of x. If x<SMALLZ, where SMALLZ is approximately 2.8E-103, then LOG(SMALLZ) is returned.
  • PLOG10(x): returns LOG10 of x. If x<SMALLZ, where SMALLZ is approximately 2.8E-103, then LOG10(SMALLZ) is returned.
  • PSQRT(x): returns SQRT of x. If x=0.0d+00, then 0 is returned.
  • PEXP(x): returns EXP of x. If x>40.0, then PEXP(100.0) is returned (avoids overflow).
  • PDZ(x): returns 1/x . Protects against divide by zero. If abs(x)<SMALLZ, then 1/SMALLZ is returned.
  • PZR(x): returns x. protects against zero. If abs(x)<SMALLZ, then SMALLZ is returned.
  • PNP(x): returns x. Protects against non-positive. If X<SMALLZ, then SMALLZ is returned.
  • PHE(x): returns x. Protects against high exponent. If X>100, then 100 is returned. Thus PEXP(x)=EXP(PHE(x)).
  • PNG(x): returns x. Protects against negative. If X<0.0, then 0.0 is returned.
  • PTAN(x): returns tan(x). Protects against returning infinity on inputs near pi/2.
  • PATAN(x): returns atan(x). Protects against large intputs.
  • PACOS(x), PASIN(x): returns acos(x), asin(x), respectively. If |X| is between 1.0 and 1+10**(-08), then x is submitted as 1 or -1. So, "dirty ones" are cleaned up, but values clearly beyond 1 are allowed to trip up the function, so the user is aware of the logical error in the code, and fix the issue.

Instead of replacing various operations with protected code operations by hand, you can ask NMTRAN to automatically convert your code to protected code with the following statement:

1
$ABBR PROTECT

NMTRAN will automatically replace all LOG (or DLOG) with PLOG, EXP (or DEXP) with PEXP, SQRT (or DSQRT) with PSQRT, / operations with *PDZ(), and B**E operations with PEXP(E*PLOG(B)), and so on.

Note that the any P function name that is used explicitly or implicitly via $ABBR PROTECT may not be used for a user-defined variable name.

REFERENCES: Guide Introduction_7