98 Expanded Syntax and Capacity for User-Defined Functions (FUNCA) (NM74)
Introduction to NONMEM 7.6.0
For the several past versions to NONMEM, user-defined functions may be incorporated into the NONMEM problem, and made available particularly for use in the classical NONMEM estimation methods, so long as the function also returns first and second derivatives. More information can be obtained from Guide VIII as to how this is done. Before nm74, at most 9 functions could be used, they had to be called FUNCA through FUNCI, each of which could be specified at most 9 times, and each function could accommodate only a maximum of 9 input variables.
In addition to returning the main result as a function of these input arguments, the function is also to return up to 9 partial derivatives of the result with respect to each variable, and their second derivatives. For example, a function FUNCA may be defined in a file called myfunc.f90, with the following header information:
FUNCTION FUNCA(X,X1,X2)
REAL*8 FUNCA,X(9),X1(9),X2(9,9)
…
…
FUNCA=…
RETURN
ENDand the user may reference this function in the control stream file, as:
$SUB OTHER=myfunc.f90
…
$PK
…
…
VECTRA(1)=CL
VECTRA(2)=V
VECTR(3)=Q
VECTR(4)=V2
…
W=FUNCA(VECTRA)
…The user function FUNCA will accept the input vector VECTRA() as the first argument, which maps to X() in the FUNCA routine itself. The user function then calculates the result, as well as packages the first derivatives of the result with respect to each element in VECTRA(), placing them in the array X1(). So the partial derivative of result with respect to VECTRA(2) is to be placed in X1(2). Similarly, second partial derivative of result with respect to VECTRA(i), VECTR(j) is to be packaged in X2(i,j).
As of nm74, a function may have more than 9 input variables, each function may be specified in abbreviated code more than 9 times, and up to 100 different functions may be used (although this can be increased in SIZES by changing NFUNCX and NVECX). Furthermore, the functions need not be named FUNCA, FUNCB, etc. in the function file.
To use this more versatile feature, the function must be defined as follows:
$ABBR FUNCTION function_name(input_vector_name,dimension,usage)where function_name is the name of the function as it appears in the source file specified in OTHER, input_vector_name is the name of the input vector you will use in the control stream file when passing the first argument, dimension is the vector and matrix sizes, and usage is the maximum number of times you will be calling this function in the control stream file. The maximum usage need not be entered, and is 999 by default. However, you may wish to set a lower maximum usage boundary for NMTRAN to flag, if you desire.
For example,
$ABBR FUNCTION BIVARIATE(VBI,5,3)means there is a function in the OTHER source code file with the following header:
FUNCTION BIVARIATE(X,X1,X2,NDIM)
INTEGER NDIM
REAL*8 X(NDIM),X1(NDIM),X2(NDIM,NDIM)In the control stream file, the input vector VBI is to be used to load into the function:
$PK
…
VBI(1)=RHO
VBI(2)=5
VBI(3)=6
VBI(4)=1 ;***0 = Upper tail as in Drezner & Wesolowsky; 1 = Bottom tail***;
VBI(5)=1 ;***0 = 3 pt approximation; 1 = 5 point approximation***;
BV=BIVARIATE(VBI)Notice that in the control stream file only the first argument is given, that of the input vector X. NMTRAN will add the additional arguments, for first derivative vector (X1), second derivative matrix (x2), and dimension (NDIM, in this case equaling, 5). The maximum number of times BIVARIATE may be specified is 3, for this example. Notice that functions declared in the $ABBR FUNCTION option must allow for passing the dimension number NDIM, which the function should use to dynamically size and shape the arguments.
Usually you want to associate a specific vector to each function such as:
$ABBR FUNCTION BIVARIATE(VBI,5)
$ABBR FUNCTION BIVARIATEQ(VQI,10)to assure that each vector-function pair are set up with comparable dimensions. However, it is not essential to have vectors and functions paire up like this, it is more a convenience, and avoids confusion. The vectors and functions need not be defined on the same $ABBR FUNCTION line, and you can use different vectors for different functions in the abbreviated code. Use the asterisk as a place holder, for example:
$ABBR FUNCTION BIVARIATE(*,5)
$ABBR FUNCTION BIVARIATEQ(*,10)
$ABBR VECTOR VQI(15)In the above code, functions BIVARIATE and BIVARIATEQ are defined separately from vector VQI, whose use will be shared with both functions. Notice VQI is dimensioned differently (15) from BIVARIATE (5) and BIVARATEQ (10), which as a precaution the dimension of VQI should be at least the dimension for all the functions for which it will be used. Then VQI may be used with BIVARIATE or BIVARIATEQ:
…
VQI(1)=RHO
VQI(2)=MX
BVAL=BIVARIATE(VQI)
RVAL=BIVARIATEQ(VQI)
VECTRA(1)=RHO
VECTRA(2)=MX2
YVAL=FUNCB(VECTRA)
QVAL=BIVARIATEQ(VECTRA)Furthermore, you may still use the FUNCxyz and VECTRxyz nomenclature for functions and vectors not declared by $ABBR FUNCTION, as shown above, and use any vector with any function. Keep in mind, that vector VECTRA not pre-defined in $ABBR FUNCTION, and used in code, as shown above, will have the implicit dimension of 9, and the FUNCB defined in the OTHER source code file cannot have the additional NDIM argument, and must be set up with a dimension of 9.