The structure of the CLIPS file is as follows:
Global variables
Sub-functions
UDF
Note: The numerical values and the UDF functions are not relevant and must be adapted.
Also, the order of the global variable definitions
(defglobal
) and the functions
(deffunction
) are important because they first
must be defined before being used.
; 1. GLOBAL VARIABLES. ; 1.1. Parameters of the UDF's FA and FB. (defglobal ; Parameter A0 of FA. ?*A0* = 1.23E+3 ; Parameter A1 of FA. ?*A1* = 1.007 ; Parameter A2 of FA. ?*A2* = 0.00236 ; Parameter A3 of FA. ?*A3* = -4.687E-2 ; Parameter A4 of FA. ?*A4* = -9.7423E-6 ; Parameter B0 of FB. ?*B0* = 151.2 ; Parameter B1 of FB. ?*B1* = 9.876E+4 )
; 1.2. U values and associated data (defglobal ; Number of points ?*nX* = 2000 ; Length of the interval ?*deltaX* = 0.0005428414207103552 ; Minimum value of X ?*xMin* = 0. ; Maximum value of X ?*xMax* = (+ ?*xMin* (* (- ?*nX* 1) ?*deltaX*)) ; U values corresponding to the multi-ramp function ; NOTE THE FOLLOWING STATEMENT HAS BEEN TRUNCATED ?*UValues* = (create$ 1000.0 999.9999705323207 999.99988212 …) ; Number of U values in ?*UValues* (for test) ?*nUValues* = (length ?*UValues*) ; Estimated range of UValue (for test) ?*UValueMax* = 1000. ?*UValueMin* = 900. )
; 1.3.Interval values (defglobal ; Interval index corresponding to X ?*i* = 0 ; X values of interval ?*X1* = 0. ?*X2* = 0. ; U values of interval ?*U1* = 0. ?*U2* = 0. )
; 1.4. Working variables. (defglobal ; Error code. In case of error, always return this with ; the value T; in case of success, don’t return this variable. ?*Error* = F ; Flag to execute huge test only once ?*TestValidData* = F )
; 2. SUB-FUNCTIONS ; 2.1. Sub-functions to manage the error. (deffunction InitError () (bind ?*Error* F)) (deffunction DeclareError () (bind ?*Error* T)) ; 2.2. Sub-function to check the validity of U values: number ; of values, type and order to magnitude. ; It is not need to call it from all UDF, and this test is ; done only once. ; The call to this sub-function can be commented in the UDF ; once you are sure the U values validity. (deffunction IsDataValid () ; Return if the test is already done. (if (eq ?*TestValidData* T) then (return)) ;Do the test (bind ?*TestValidData* T) ; Check the number of data in UValues. (if (neq ?*nX* ?*nUValues*) then (printout t "Data are not valid: number of values in ?*UValues* (" (length ?*UValues*) ")" crlf "are not the expected one ?*nX* (" ?*nX* ")." crlf ) (DeclareError) ) ;Check if the values in UValues are numeric values and ranged ;between UValueMin and UValueMax. (loop-for-count (?i 1 ?*nUValues*) do (bind ?U (nth$ ?i ?*UValues*)) (if (eq (numberp ?U) FALSE) then (printout t "Data are not valid: the value " ?i " (" ?U ")" crlf "in ?*nUValues* is not a number ." crlf ) (DeclareError) else (if (or (< ?U ?*UValueMin*) (> ?U ?*UValueMax*)) then (printout t "Data are not valid: the value " ?i " (" ?U ") in ?*nUValues*" crlf "is out of expected range [" ?*UValueMin* ", " ?*UValueMax*"]." crlf ) (DeclareError) ) ) ) (if (eq ?*Error* T ) then (bind ?*TestValidData* F) ; Other process have to do the test ) ) ; 2.3. Sub-function to check if X is valid ; (ranged between xMin and xMax). (deffunction IsXValid (?X) (if (or (< ?X ?*xMin*) (> ?X ?*xMax*)) then (DeclareError) (printout t "Error in IsXValid: " crlf " ?X=" ?X " is not ranged between xMin=" ?*xMin* " and xMax=" ?*xMax* crlf ) ) )
; 2.4. Sub-function to get the interval index (deffunction GetIntervalValues (?X) (bind ?*i* (+ 1 (integer (/ (- ?X ?*xMin*) ?*deltaX*)))) ; If X is the last point equal to xMax then, I equal nX-1 (if (eq ?*i* ?*nX*) then (bind ?*i* (- ?*i* 1))) ; U and X at beginning of the interval i. (bind ?*U1* (nth ?*i* ?*UValues*)) (bind ?*X1* (+ ?*xMin* (* (- ?*i* 1) ?*deltaX*))) ; U and X at end of the interval i. (bind ?*U2* (nth (+ ?*i* 1) ?*UValues*)) (bind ?*X2* (+ ?*xMin* (* ?*i* ?*deltaX*))) ) ; 2.5. Sub-function to get the U values (deffunction GetTValue ( ?X) (bind ?p (/ (- ?*U2* ?*U1*) ?*deltaX*)) (bind ?q (/ (- (* ?*U1* ?*X2*) (* ?*U2* ?*X1*)) ?*deltaX*)) (bind ?R (+ (* ?p ?X) ?q)) ?R )
; 3. UDF CALLED FROM POLYFLOW. ; Those functions must return ?*Error* = T if its evaluation fails. ; 3.1. UDF for the function FA(X) (deffunction FA (?X) ; Initialize the error code. (InitError) ; Check if data are valid. : Already check during setup of UDF, commented in order to do not call it. (IsDataValid) ; Check if X is valid (IsXValid ?X) (if (eq ?*Error* T) then (printout t "Error in FA(X) UDF, see above message." crlf) (return ?*Error*) ; Return a non-numeric value ) (GetIntervalValues ?X) (bind ?U (GetTValue ?X)) ; R = A0 + U*(A1 + U*(A2 + U*(A3 + U*A4))) (bind ?R (+ ?*A0* (* ?U (+ ?*A1* (* ?U (+ ?*A2* (* ?U (+ ?*A3* (* ?U ?*A4*) )))))))) ?R ; Return a numeric value ) ; 3.2. UDF for the function FB(X) (deffunction FB (?X) ; Initialize the error code. (InitError) ; Check if X is valid (IsXValid ?X) (if (eq ?*Error* T) then (printout t "Error in FB(X) UDF, see above message." crlf) (return ?*Error*) ; Return a non-numeric value ) (GetIntervalValues ?X) (bind ?U (GetTValue ?X)) ; R = B1 * (U – B0) (bind ?R (* ?*B1* (- ?U ?*B0*))) ?R ; Return a numeric value )