/// <param name="N"> /// DIMENSION OF THE SYSTEM ///</param> /// <param name="FCN"> /// NAME (EXTERNAL) OF SUBROUTINE COMPUTING THE /// VALUE OF F(X,Y): /// SUBROUTINE FCN(N,X,Y,F,RPAR,IPAR) /// DOUBLE PRECISION X,Y(N),F(N) /// F(1)=... ETC. /// RPAR, IPAR (SEE BELOW) ///</param> /// <param name="X"> /// INITIAL X-VALUE ///</param> /// <param name="XEND"> /// FINAL X-VALUE (XEND-X MAY BE POSITIVE OR NEGATIVE) ///</param> /// <param name="H"> /// INITIAL STEP SIZE GUESS; /// FOR STIFF EQUATIONS WITH INITIAL TRANSIENT, /// H=1.D0/(NORM OF F'), USUALLY 1.D-3 OR 1.D-5, IS GOOD. /// THIS CHOICE IS NOT VERY IMPORTANT, THE STEP SIZE IS /// QUICKLY ADAPTED. (IF H=0.D0, THE CODE PUTS H=1.D-6). ///</param> /// <param name="ITOL"> /// SWITCH FOR RTOL AND ATOL: /// ITOL=0: BOTH RTOL AND ATOL ARE SCALARS. /// THE CODE KEEPS, ROUGHLY, THE LOCAL ERROR OF /// Y(I) BELOW RTOL*ABS(Y(I))+ATOL /// ITOL=1: BOTH RTOL AND ATOL ARE VECTORS. /// THE CODE KEEPS THE LOCAL ERROR OF Y(I) BELOW /// RTOL(I)*ABS(Y(I))+ATOL(I). ///</param> /// <param name="JAC"> /// NAME (EXTERNAL) OF THE SUBROUTINE WHICH COMPUTES /// THE PARTIAL DERIVATIVES OF F(X,Y) WITH RESPECT TO Y /// (THIS ROUTINE IS ONLY CALLED IF IJAC=1; SUPPLY /// A DUMMY SUBROUTINE IN THE CASE IJAC=0). /// FOR IJAC=1, THIS SUBROUTINE MUST HAVE THE FORM /// SUBROUTINE JAC(N,X,Y,DFY,LDFY,RPAR,IPAR) /// DOUBLE PRECISION X,Y(N),DFY(LDFY,N) /// DFY(1,1)= ... /// LDFY, THE COLUMN-LENGTH OF THE ARRAY, IS /// FURNISHED BY THE CALLING PROGRAM. /// IF (MLJAC.EQ.N) THE JACOBIAN IS SUPPOSED TO /// BE FULL AND THE PARTIAL DERIVATIVES ARE /// STORED IN DFY AS /// DFY(I,J) = PARTIAL F(I) / PARTIAL Y(J) /// ELSE, THE JACOBIAN IS TAKEN AS BANDED AND /// THE PARTIAL DERIVATIVES ARE STORED /// DIAGONAL-WISE AS /// DFY(I-J+MUJAC+1,J) = PARTIAL F(I) / PARTIAL Y(J). ///</param> /// <param name="IJAC"> /// SWITCH FOR THE COMPUTATION OF THE JACOBIAN: /// IJAC=0: JACOBIAN IS COMPUTED INTERNALLY BY FINITE /// DIFFERENCES, SUBROUTINE "JAC" IS NEVER CALLED. /// IJAC=1: JACOBIAN IS SUPPLIED BY SUBROUTINE JAC. ///</param> /// <param name="MLJAC"> /// SWITCH FOR THE BANDED STRUCTURE OF THE JACOBIAN: /// MLJAC=N: JACOBIAN IS A FULL MATRIX. THE LINEAR /// ALGEBRA IS DONE BY FULL-MATRIX GAUSS-ELIMINATION. /// 0.LE.MLJAC.LT.N: MLJAC IS THE LOWER BANDWITH OF JACOBIAN /// MATRIX (.GE. NUMBER OF NON-ZERO DIAGONALS BELOW /// THE MAIN DIAGONAL). ///</param> /// <param name="MUJAC"> /// UPPER BANDWITH OF JACOBIAN MATRIX (.GE. NUMBER OF NON- /// ZERO DIAGONALS ABOVE THE MAIN DIAGONAL). /// NEED NOT BE DEFINED IF MLJAC=N. ///</param> /// <param name="MAS"> /// NAME (EXTERNAL) OF SUBROUTINE COMPUTING THE MASS- /// MATRIX M. /// IF IMAS=0, THIS MATRIX IS ASSUMED TO BE THE IDENTITY /// MATRIX AND NEEDS NOT TO BE DEFINED; /// SUPPLY A DUMMY SUBROUTINE IN THIS CASE. /// IF IMAS=1, THE SUBROUTINE MAS IS OF THE FORM /// SUBROUTINE MAS(N,AM,LMAS,RPAR,IPAR) /// DOUBLE PRECISION AM(LMAS,N) /// AM(1,1)= .... /// IF (MLMAS.EQ.N) THE MASS-MATRIX IS STORED /// AS FULL MATRIX LIKE /// AM(I,J) = M(I,J) /// ELSE, THE MATRIX IS TAKEN AS BANDED AND STORED /// DIAGONAL-WISE AS /// AM(I-J+MUMAS+1,J) = M(I,J). ///</param> /// <param name="IMAS"> /// GIVES INFORMATION ON THE MASS-MATRIX: /// IMAS=0: M IS SUPPOSED TO BE THE IDENTITY /// MATRIX, MAS IS NEVER CALLED. /// IMAS=1: MASS-MATRIX IS SUPPLIED. ///</param> /// <param name="MLMAS"> /// SWITCH FOR THE BANDED STRUCTURE OF THE MASS-MATRIX: /// MLMAS=N: THE FULL MATRIX CASE. THE LINEAR /// ALGEBRA IS DONE BY FULL-MATRIX GAUSS-ELIMINATION. /// 0.LE.MLMAS.LT.N: MLMAS IS THE LOWER BANDWITH OF THE /// MATRIX (.GE. NUMBER OF NON-ZERO DIAGONALS BELOW /// THE MAIN DIAGONAL). /// MLMAS IS SUPPOSED TO BE .LE. MLJAC. ///</param> /// <param name="MUMAS"> /// UPPER BANDWITH OF MASS-MATRIX (.GE. NUMBER OF NON- /// ZERO DIAGONALS ABOVE THE MAIN DIAGONAL). /// NEED NOT BE DEFINED IF MLMAS=N. /// MUMAS IS SUPPOSED TO BE .LE. MUJAC. ///</param> /// <param name="SOLOUT"> /// NAME (EXTERNAL) OF SUBROUTINE PROVIDING THE /// NUMERICAL SOLUTION DURING INTEGRATION. /// IF IOUT=1, IT IS CALLED AFTER EVERY SUCCESSFUL STEP. /// SUPPLY A DUMMY SUBROUTINE IF IOUT=0. /// IT MUST HAVE THE FORM /// SUBROUTINE SOLOUT (NR,XOLD,X,Y,CONT,LRC,N, /// RPAR,IPAR,IRTRN) /// DOUBLE PRECISION X,Y(N),CONT(LRC) /// .... /// SOLOUT FURNISHES THE SOLUTION "Y" AT THE NR-TH /// GRID-POINT "X" (THEREBY THE INITIAL VALUE IS /// THE FIRST GRID-POINT). /// "XOLD" IS THE PRECEEDING GRID-POINT. /// "IRTRN" SERVES TO INTERRUPT THE INTEGRATION. IF IRTRN /// IS SET .LT.0, RADAU5 RETURNS TO THE CALLING PROGRAM. /// /// ----- CONTINUOUS OUTPUT: ----- /// DURING CALLS TO "SOLOUT", A CONTINUOUS SOLUTION /// FOR THE INTERVAL [XOLD,X] IS AVAILABLE THROUGH /// THE FUNCTION /// .GT..GT..GT. CONTR5(I,S,CONT,LRC) .LT..LT..LT. /// WHICH PROVIDES AN APPROXIMATION TO THE I-TH /// COMPONENT OF THE SOLUTION AT THE POINT S. THE VALUE /// S SHOULD LIE IN THE INTERVAL [XOLD,X]. /// DO NOT CHANGE THE ENTRIES OF CONT(LRC), IF THE /// DENSE OUTPUT FUNCTION IS USED. ///</param> /// <param name="IOUT"> /// SWITCH FOR CALLING THE SUBROUTINE SOLOUT: /// IOUT=0: SUBROUTINE IS NEVER CALLED /// IOUT=1: SUBROUTINE IS AVAILABLE FOR OUTPUT. ///</param> /// <param name="WORK"> /// ARRAY OF WORKING SPACE OF LENGTH "LWORK". /// WORK(1), WORK(2),.., WORK(20) SERVE AS PARAMETERS /// FOR THE CODE. FOR STANDARD USE OF THE CODE /// WORK(1),..,WORK(20) MUST BE SET TO ZERO BEFORE /// CALLING. SEE BELOW FOR A MORE SOPHISTICATED USE. /// WORK(21),..,WORK(LWORK) SERVE AS WORKING SPACE /// FOR ALL VECTORS AND MATRICES. /// "LWORK" MUST BE AT LEAST /// N*(LJAC+LMAS+3*LE+12)+20 /// WHERE /// LJAC=N IF MLJAC=N (FULL JACOBIAN) /// LJAC=MLJAC+MUJAC+1 IF MLJAC.LT.N (BANDED JAC.) /// AND /// LMAS=0 IF IMAS=0 /// LMAS=N IF IMAS=1 AND MLMAS=N (FULL) /// LMAS=MLMAS+MUMAS+1 IF MLMAS.LT.N (BANDED MASS-M.) /// AND /// LE=N IF MLJAC=N (FULL JACOBIAN) /// LE=2*MLJAC+MUJAC+1 IF MLJAC.LT.N (BANDED JAC.) /// /// IN THE USUAL CASE WHERE THE JACOBIAN IS FULL AND THE /// MASS-MATRIX IS THE INDENTITY (IMAS=0), THE MINIMUM /// STORAGE REQUIREMENT IS /// LWORK = 4*N*N+12*N+20. /// IF IWORK(9)=M1.GT.0 THEN "LWORK" MUST BE AT LEAST /// N*(LJAC+12)+(N-M1)*(LMAS+3*LE)+20 /// WHERE IN THE DEFINITIONS OF LJAC, LMAS AND LE THE /// NUMBER N CAN BE REPLACED BY N-M1. ///</param> /// <param name="LWORK"> /// DECLARED LENGTH OF ARRAY "WORK". ///</param> /// <param name="IWORK"> /// INTEGER WORKING SPACE OF LENGTH "LIWORK". /// IWORK(1),IWORK(2),...,IWORK(20) SERVE AS PARAMETERS /// FOR THE CODE. FOR STANDARD USE, SET IWORK(1),.., /// IWORK(20) TO ZERO BEFORE CALLING. /// IWORK(21),...,IWORK(LIWORK) SERVE AS WORKING AREA. /// "LIWORK" MUST BE AT LEAST 3*N+20. ///</param> /// <param name="LIWORK"> /// DECLARED LENGTH OF ARRAY "IWORK". ///</param> /// <param name="IDID"> /// REPORTS ON SUCCESSFULNESS UPON RETURN: /// IDID= 1 COMPUTATION SUCCESSFUL, /// IDID= 2 COMPUT. SUCCESSFUL (INTERRUPTED BY SOLOUT) /// IDID=-1 INPUT IS NOT CONSISTENT, /// IDID=-2 LARGER NMAX IS NEEDED, /// IDID=-3 STEP SIZE BECOMES TOO SMALL, /// IDID=-4 MATRIX IS REPEATEDLY SINGULAR. ///</param> public void Run(int N, IFVPOL FCN, ref double X, ref double[] Y, int offset_y, double XEND, ref double H , ref double[] RTOL, int offset_rtol, ref double[] ATOL, int offset_atol, int ITOL, IJVPOL JAC, int IJAC, ref int MLJAC , ref int MUJAC, IBBAMPL MAS, int IMAS, int MLMAS, ref int MUMAS, ISOLOUTR SOLOUT , int IOUT, ref double[] WORK, int offset_work, int LWORK, ref int[] IWORK, int offset_iwork, int LIWORK, double[] RPAR, int offset_rpar , int[] IPAR, int offset_ipar, ref int IDID) { #region Variables bool IMPLCT = false; bool JBAND = false; bool ARRET = false; bool STARTN = false; bool PRED = false; #endregion Variables #region Implicit Variables int NFCN = 0; int NJAC = 0; int NSTEP = 0; int NACCPT = 0; int NREJCT = 0; int NDEC = 0; int NSOL = 0; double UROUND = 0; double EXPM = 0; double QUOT = 0; int I = 0; int NMAX = 0; int NIT = 0; int NIND1 = 0; int NIND2 = 0; int NIND3 = 0; int M1 = 0; int M2 = 0; int NM1 = 0; double SAFE = 0; double THET = 0; double TOLST = 0; double FNEWT = 0; double QUOT1 = 0; double QUOT2 = 0; double HMAX = 0; double FACL = 0; double FACR = 0; int LDJAC = 0; int LDE1 = 0; int LDMAS = 0; int IJOB = 0; int LDMAS2 = 0; int IEZ1 = 0; int IEZ2 = 0; int IEZ3 = 0; int IEY0 = 0; int IESCAL = 0; int IEF1 = 0; int IEF2 = 0; int IEF3 = 0; int IECON = 0; int IEJAC = 0; int IEMAS = 0; int IEE1 = 0; int IEE2R = 0; int IEE2I = 0; int ISTORE = 0; int IEIP1 = 0; int IEIP2 = 0; int IEIPH = 0; #endregion Implicit Variables #region Array Index Correction int o_y = -1 + offset_y; int o_rtol = -1 + offset_rtol; int o_atol = -1 + offset_atol; int o_work = -1 + offset_work; int o_iwork = -1 + offset_iwork; int o_rpar = -1 + offset_rpar; int o_ipar = -1 + offset_ipar; #endregion Array Index Correction #region Prolog // C ---------------------------------------------------------- // C NUMERICAL SOLUTION OF A STIFF (OR DIFFERENTIAL ALGEBRAIC) // C SYSTEM OF FIRST 0RDER ORDINARY DIFFERENTIAL EQUATIONS // C M*Y'=F(X,Y). // C THE SYSTEM CAN BE (LINEARLY) IMPLICIT (MASS-MATRIX M .NE. I) // C OR EXPLICIT (M=I). // C THE METHOD USED IS AN IMPLICIT RUNGE-KUTTA METHOD (RADAU IIA) // C OF ORDER 5 WITH STEP SIZE CONTROL AND CONTINUOUS OUTPUT. // C CF. SECTION IV.8 // C // C AUTHORS: E. HAIRER AND G. WANNER // C UNIVERSITE DE GENEVE, DEPT. DE MATHEMATIQUES // C CH-1211 GENEVE 24, SWITZERLAND // C E-MAIL: [email protected] // C [email protected] // C // C THIS CODE IS PART OF THE BOOK: // C E. HAIRER AND G. WANNER, SOLVING ORDINARY DIFFERENTIAL // C EQUATIONS II. STIFF AND DIFFERENTIAL-ALGEBRAIC PROBLEMS. // C SPRINGER SERIES IN COMPUTATIONAL MATHEMATICS 14, // C SPRINGER-VERLAG 1991, SECOND EDITION 1996. // C // C VERSION OF JULY 9, 1996 // C (latest small correction: January 18, 2002) // C // C INPUT PARAMETERS // C ---------------- // C N DIMENSION OF THE SYSTEM // C // C FCN NAME (EXTERNAL) OF SUBROUTINE COMPUTING THE // C VALUE OF F(X,Y): // C SUBROUTINE FCN(N,X,Y,F,RPAR,IPAR) // C DOUBLE PRECISION X,Y(N),F(N) // C F(1)=... ETC. // C RPAR, IPAR (SEE BELOW) // C // C X INITIAL X-VALUE // C // C Y(N) INITIAL VALUES FOR Y // C // C XEND FINAL X-VALUE (XEND-X MAY BE POSITIVE OR NEGATIVE) // C // C H INITIAL STEP SIZE GUESS; // C FOR STIFF EQUATIONS WITH INITIAL TRANSIENT, // C H=1.D0/(NORM OF F'), USUALLY 1.D-3 OR 1.D-5, IS GOOD. // C THIS CHOICE IS NOT VERY IMPORTANT, THE STEP SIZE IS // C QUICKLY ADAPTED. (IF H=0.D0, THE CODE PUTS H=1.D-6). // C // C RTOL,ATOL RELATIVE AND ABSOLUTE ERROR TOLERANCES. THEY // C CAN BE BOTH SCALARS OR ELSE BOTH VECTORS OF LENGTH N. // C // C ITOL SWITCH FOR RTOL AND ATOL: // C ITOL=0: BOTH RTOL AND ATOL ARE SCALARS. // C THE CODE KEEPS, ROUGHLY, THE LOCAL ERROR OF // C Y(I) BELOW RTOL*ABS(Y(I))+ATOL // C ITOL=1: BOTH RTOL AND ATOL ARE VECTORS. // C THE CODE KEEPS THE LOCAL ERROR OF Y(I) BELOW // C RTOL(I)*ABS(Y(I))+ATOL(I). // C // C JAC NAME (EXTERNAL) OF THE SUBROUTINE WHICH COMPUTES // C THE PARTIAL DERIVATIVES OF F(X,Y) WITH RESPECT TO Y // C (THIS ROUTINE IS ONLY CALLED IF IJAC=1; SUPPLY // C A DUMMY SUBROUTINE IN THE CASE IJAC=0). // C FOR IJAC=1, THIS SUBROUTINE MUST HAVE THE FORM // C SUBROUTINE JAC(N,X,Y,DFY,LDFY,RPAR,IPAR) // C DOUBLE PRECISION X,Y(N),DFY(LDFY,N) // C DFY(1,1)= ... // C LDFY, THE COLUMN-LENGTH OF THE ARRAY, IS // C FURNISHED BY THE CALLING PROGRAM. // C IF (MLJAC.EQ.N) THE JACOBIAN IS SUPPOSED TO // C BE FULL AND THE PARTIAL DERIVATIVES ARE // C STORED IN DFY AS // C DFY(I,J) = PARTIAL F(I) / PARTIAL Y(J) // C ELSE, THE JACOBIAN IS TAKEN AS BANDED AND // C THE PARTIAL DERIVATIVES ARE STORED // C DIAGONAL-WISE AS // C DFY(I-J+MUJAC+1,J) = PARTIAL F(I) / PARTIAL Y(J). // C // C IJAC SWITCH FOR THE COMPUTATION OF THE JACOBIAN: // C IJAC=0: JACOBIAN IS COMPUTED INTERNALLY BY FINITE // C DIFFERENCES, SUBROUTINE "JAC" IS NEVER CALLED. // C IJAC=1: JACOBIAN IS SUPPLIED BY SUBROUTINE JAC. // C // C MLJAC SWITCH FOR THE BANDED STRUCTURE OF THE JACOBIAN: // C MLJAC=N: JACOBIAN IS A FULL MATRIX. THE LINEAR // C ALGEBRA IS DONE BY FULL-MATRIX GAUSS-ELIMINATION. // C 0<=MLJAC<N: MLJAC IS THE LOWER BANDWITH OF JACOBIAN // C MATRIX (>= NUMBER OF NON-ZERO DIAGONALS BELOW // C THE MAIN DIAGONAL). // C // C MUJAC UPPER BANDWITH OF JACOBIAN MATRIX (>= NUMBER OF NON- // C ZERO DIAGONALS ABOVE THE MAIN DIAGONAL). // C NEED NOT BE DEFINED IF MLJAC=N. // C // C ---- MAS,IMAS,MLMAS, AND MUMAS HAVE ANALOG MEANINGS ----- // C ---- FOR THE "MASS MATRIX" (THE MATRIX "M" OF SECTION IV.8): - // C // C MAS NAME (EXTERNAL) OF SUBROUTINE COMPUTING THE MASS- // C MATRIX M. // C IF IMAS=0, THIS MATRIX IS ASSUMED TO BE THE IDENTITY // C MATRIX AND NEEDS NOT TO BE DEFINED; // C SUPPLY A DUMMY SUBROUTINE IN THIS CASE. // C IF IMAS=1, THE SUBROUTINE MAS IS OF THE FORM // C SUBROUTINE MAS(N,AM,LMAS,RPAR,IPAR) // C DOUBLE PRECISION AM(LMAS,N) // C AM(1,1)= .... // C IF (MLMAS.EQ.N) THE MASS-MATRIX IS STORED // C AS FULL MATRIX LIKE // C AM(I,J) = M(I,J) // C ELSE, THE MATRIX IS TAKEN AS BANDED AND STORED // C DIAGONAL-WISE AS // C AM(I-J+MUMAS+1,J) = M(I,J). // C // C IMAS GIVES INFORMATION ON THE MASS-MATRIX: // C IMAS=0: M IS SUPPOSED TO BE THE IDENTITY // C MATRIX, MAS IS NEVER CALLED. // C IMAS=1: MASS-MATRIX IS SUPPLIED. // C // C MLMAS SWITCH FOR THE BANDED STRUCTURE OF THE MASS-MATRIX: // C MLMAS=N: THE FULL MATRIX CASE. THE LINEAR // C ALGEBRA IS DONE BY FULL-MATRIX GAUSS-ELIMINATION. // C 0<=MLMAS<N: MLMAS IS THE LOWER BANDWITH OF THE // C MATRIX (>= NUMBER OF NON-ZERO DIAGONALS BELOW // C THE MAIN DIAGONAL). // C MLMAS IS SUPPOSED TO BE .LE. MLJAC. // C // C MUMAS UPPER BANDWITH OF MASS-MATRIX (>= NUMBER OF NON- // C ZERO DIAGONALS ABOVE THE MAIN DIAGONAL). // C NEED NOT BE DEFINED IF MLMAS=N. // C MUMAS IS SUPPOSED TO BE .LE. MUJAC. // C // C SOLOUT NAME (EXTERNAL) OF SUBROUTINE PROVIDING THE // C NUMERICAL SOLUTION DURING INTEGRATION. // C IF IOUT=1, IT IS CALLED AFTER EVERY SUCCESSFUL STEP. // C SUPPLY A DUMMY SUBROUTINE IF IOUT=0. // C IT MUST HAVE THE FORM // C SUBROUTINE SOLOUT (NR,XOLD,X,Y,CONT,LRC,N, // C RPAR,IPAR,IRTRN) // C DOUBLE PRECISION X,Y(N),CONT(LRC) // C .... // C SOLOUT FURNISHES THE SOLUTION "Y" AT THE NR-TH // C GRID-POINT "X" (THEREBY THE INITIAL VALUE IS // C THE FIRST GRID-POINT). // C "XOLD" IS THE PRECEEDING GRID-POINT. // C "IRTRN" SERVES TO INTERRUPT THE INTEGRATION. IF IRTRN // C IS SET <0, RADAU5 RETURNS TO THE CALLING PROGRAM. // C // C ----- CONTINUOUS OUTPUT: ----- // C DURING CALLS TO "SOLOUT", A CONTINUOUS SOLUTION // C FOR THE INTERVAL [XOLD,X] IS AVAILABLE THROUGH // C THE FUNCTION // C >>> CONTR5(I,S,CONT,LRC) <<< // C WHICH PROVIDES AN APPROXIMATION TO THE I-TH // C COMPONENT OF THE SOLUTION AT THE POINT S. THE VALUE // C S SHOULD LIE IN THE INTERVAL [XOLD,X]. // C DO NOT CHANGE THE ENTRIES OF CONT(LRC), IF THE // C DENSE OUTPUT FUNCTION IS USED. // C // C IOUT SWITCH FOR CALLING THE SUBROUTINE SOLOUT: // C IOUT=0: SUBROUTINE IS NEVER CALLED // C IOUT=1: SUBROUTINE IS AVAILABLE FOR OUTPUT. // C // C WORK ARRAY OF WORKING SPACE OF LENGTH "LWORK". // C WORK(1), WORK(2),.., WORK(20) SERVE AS PARAMETERS // C FOR THE CODE. FOR STANDARD USE OF THE CODE // C WORK(1),..,WORK(20) MUST BE SET TO ZERO BEFORE // C CALLING. SEE BELOW FOR A MORE SOPHISTICATED USE. // C WORK(21),..,WORK(LWORK) SERVE AS WORKING SPACE // C FOR ALL VECTORS AND MATRICES. // C "LWORK" MUST BE AT LEAST // C N*(LJAC+LMAS+3*LE+12)+20 // C WHERE // C LJAC=N IF MLJAC=N (FULL JACOBIAN) // C LJAC=MLJAC+MUJAC+1 IF MLJAC<N (BANDED JAC.) // C AND // C LMAS=0 IF IMAS=0 // C LMAS=N IF IMAS=1 AND MLMAS=N (FULL) // C LMAS=MLMAS+MUMAS+1 IF MLMAS<N (BANDED MASS-M.) // C AND // C LE=N IF MLJAC=N (FULL JACOBIAN) // C LE=2*MLJAC+MUJAC+1 IF MLJAC<N (BANDED JAC.) // C // C IN THE USUAL CASE WHERE THE JACOBIAN IS FULL AND THE // C MASS-MATRIX IS THE INDENTITY (IMAS=0), THE MINIMUM // C STORAGE REQUIREMENT IS // C LWORK = 4*N*N+12*N+20. // C IF IWORK(9)=M1>0 THEN "LWORK" MUST BE AT LEAST // C N*(LJAC+12)+(N-M1)*(LMAS+3*LE)+20 // C WHERE IN THE DEFINITIONS OF LJAC, LMAS AND LE THE // C NUMBER N CAN BE REPLACED BY N-M1. // C // C LWORK DECLARED LENGTH OF ARRAY "WORK". // C // C IWORK INTEGER WORKING SPACE OF LENGTH "LIWORK". // C IWORK(1),IWORK(2),...,IWORK(20) SERVE AS PARAMETERS // C FOR THE CODE. FOR STANDARD USE, SET IWORK(1),.., // C IWORK(20) TO ZERO BEFORE CALLING. // C IWORK(21),...,IWORK(LIWORK) SERVE AS WORKING AREA. // C "LIWORK" MUST BE AT LEAST 3*N+20. // C // C LIWORK DECLARED LENGTH OF ARRAY "IWORK". // C // C RPAR, IPAR REAL AND INTEGER PARAMETERS (OR PARAMETER ARRAYS) WHICH // C CAN BE USED FOR COMMUNICATION BETWEEN YOUR CALLING // C PROGRAM AND THE FCN, JAC, MAS, SOLOUT SUBROUTINES. // C // C ---------------------------------------------------------------------- // C // C SOPHISTICATED SETTING OF PARAMETERS // C ----------------------------------- // C SEVERAL PARAMETERS OF THE CODE ARE TUNED TO MAKE IT WORK // C WELL. THEY MAY BE DEFINED BY SETTING WORK(1),... // C AS WELL AS IWORK(1),... DIFFERENT FROM ZERO. // C FOR ZERO INPUT, THE CODE CHOOSES DEFAULT VALUES: // C // C IWORK(1) IF IWORK(1).NE.0, THE CODE TRANSFORMS THE JACOBIAN // C MATRIX TO HESSENBERG FORM. THIS IS PARTICULARLY // C ADVANTAGEOUS FOR LARGE SYSTEMS WITH FULL JACOBIAN. // C IT DOES NOT WORK FOR BANDED JACOBIAN (MLJAC<N) // C AND NOT FOR IMPLICIT SYSTEMS (IMAS=1). // C // C IWORK(2) THIS IS THE MAXIMAL NUMBER OF ALLOWED STEPS. // C THE DEFAULT VALUE (FOR IWORK(2)=0) IS 100000. // C // C IWORK(3) THE MAXIMUM NUMBER OF NEWTON ITERATIONS FOR THE // C SOLUTION OF THE IMPLICIT SYSTEM IN EACH STEP. // C THE DEFAULT VALUE (FOR IWORK(3)=0) IS 7. // C // C IWORK(4) IF IWORK(4).EQ.0 THE EXTRAPOLATED COLLOCATION SOLUTION // C IS TAKEN AS STARTING VALUE FOR NEWTON'S METHOD. // C IF IWORK(4).NE.0 ZERO STARTING VALUES ARE USED. // C THE LATTER IS RECOMMENDED IF NEWTON'S METHOD HAS // C DIFFICULTIES WITH CONVERGENCE (THIS IS THE CASE WHEN // C NSTEP IS LARGER THAN NACCPT + NREJCT; SEE OUTPUT PARAM.). // C DEFAULT IS IWORK(4)=0. // C // C THE FOLLOWING 3 PARAMETERS ARE IMPORTANT FOR // C DIFFERENTIAL-ALGEBRAIC SYSTEMS OF INDEX > 1. // C THE FUNCTION-SUBROUTINE SHOULD BE WRITTEN SUCH THAT // C THE INDEX 1,2,3 VARIABLES APPEAR IN THIS ORDER. // C IN ESTIMATING THE ERROR THE INDEX 2 VARIABLES ARE // C MULTIPLIED BY H, THE INDEX 3 VARIABLES BY H**2. // C // C IWORK(5) DIMENSION OF THE INDEX 1 VARIABLES (MUST BE > 0). FOR // C ODE'S THIS EQUALS THE DIMENSION OF THE SYSTEM. // C DEFAULT IWORK(5)=N. // C // C IWORK(6) DIMENSION OF THE INDEX 2 VARIABLES. DEFAULT IWORK(6)=0. // C // C IWORK(7) DIMENSION OF THE INDEX 3 VARIABLES. DEFAULT IWORK(7)=0. // C // C IWORK(8) SWITCH FOR STEP SIZE STRATEGY // C IF IWORK(8).EQ.1 MOD. PREDICTIVE CONTROLLER (GUSTAFSSON) // C IF IWORK(8).EQ.2 CLASSICAL STEP SIZE CONTROL // C THE DEFAULT VALUE (FOR IWORK(8)=0) IS IWORK(8)=1. // C THE CHOICE IWORK(8).EQ.1 SEEMS TO PRODUCE SAFER RESULTS; // C FOR SIMPLE PROBLEMS, THE CHOICE IWORK(8).EQ.2 PRODUCES // C OFTEN SLIGHTLY FASTER RUNS // C // C IF THE DIFFERENTIAL SYSTEM HAS THE SPECIAL STRUCTURE THAT // C Y(I)' = Y(I+M2) FOR I=1,...,M1, // C WITH M1 A MULTIPLE OF M2, A SUBSTANTIAL GAIN IN COMPUTERTIME // C CAN BE ACHIEVED BY SETTING THE PARAMETERS IWORK(9) AND IWORK(10). // C E.G., FOR SECOND ORDER SYSTEMS P'=V, V'=G(P,V), WHERE P AND V ARE // C VECTORS OF DIMENSION N/2, ONE HAS TO PUT M1=M2=N/2. // C FOR M1>0 SOME OF THE INPUT PARAMETERS HAVE DIFFERENT MEANINGS: // C - JAC: ONLY THE ELEMENTS OF THE NON-TRIVIAL PART OF THE // C JACOBIAN HAVE TO BE STORED // C IF (MLJAC.EQ.N-M1) THE JACOBIAN IS SUPPOSED TO BE FULL // C DFY(I,J) = PARTIAL F(I+M1) / PARTIAL Y(J) // C FOR I=1,N-M1 AND J=1,N. // C ELSE, THE JACOBIAN IS BANDED ( M1 = M2 * MM ) // C DFY(I-J+MUJAC+1,J+K*M2) = PARTIAL F(I+M1) / PARTIAL Y(J+K*M2) // C FOR I=1,MLJAC+MUJAC+1 AND J=1,M2 AND K=0,MM. // C - MLJAC: MLJAC=N-M1: IF THE NON-TRIVIAL PART OF THE JACOBIAN IS FULL // C 0<=MLJAC<N-M1: IF THE (MM+1) SUBMATRICES (FOR K=0,MM) // C PARTIAL F(I+M1) / PARTIAL Y(J+K*M2), I,J=1,M2 // C ARE BANDED, MLJAC IS THE MAXIMAL LOWER BANDWIDTH // C OF THESE MM+1 SUBMATRICES // C - MUJAC: MAXIMAL UPPER BANDWIDTH OF THESE MM+1 SUBMATRICES // C NEED NOT BE DEFINED IF MLJAC=N-M1 // C - MAS: IF IMAS=0 THIS MATRIX IS ASSUMED TO BE THE IDENTITY AND // C NEED NOT BE DEFINED. SUPPLY A DUMMY SUBROUTINE IN THIS CASE. // C IT IS ASSUMED THAT ONLY THE ELEMENTS OF RIGHT LOWER BLOCK OF // C DIMENSION N-M1 DIFFER FROM THAT OF THE IDENTITY MATRIX. // C IF (MLMAS.EQ.N-M1) THIS SUBMATRIX IS SUPPOSED TO BE FULL // C AM(I,J) = M(I+M1,J+M1) FOR I=1,N-M1 AND J=1,N-M1. // C ELSE, THE MASS MATRIX IS BANDED // C AM(I-J+MUMAS+1,J) = M(I+M1,J+M1) // C - MLMAS: MLMAS=N-M1: IF THE NON-TRIVIAL PART OF M IS FULL // C 0<=MLMAS<N-M1: LOWER BANDWIDTH OF THE MASS MATRIX // C - MUMAS: UPPER BANDWIDTH OF THE MASS MATRIX // C NEED NOT BE DEFINED IF MLMAS=N-M1 // C // C IWORK(9) THE VALUE OF M1. DEFAULT M1=0. // C // C IWORK(10) THE VALUE OF M2. DEFAULT M2=M1. // C // C ---------- // C // C WORK(1) UROUND, THE ROUNDING UNIT, DEFAULT 1.D-16. // C // C WORK(2) THE SAFETY FACTOR IN STEP SIZE PREDICTION, // C DEFAULT 0.9D0. // C // C WORK(3) DECIDES WHETHER THE JACOBIAN SHOULD BE RECOMPUTED; // C INCREASE WORK(3), TO 0.1 SAY, WHEN JACOBIAN EVALUATIONS // C ARE COSTLY. FOR SMALL SYSTEMS WORK(3) SHOULD BE SMALLER // C (0.001D0, SAY). NEGATIV WORK(3) FORCES THE CODE TO // C COMPUTE THE JACOBIAN AFTER EVERY ACCEPTED STEP. // C DEFAULT 0.001D0. // C // C WORK(4) STOPPING CRITERION FOR NEWTON'S METHOD, USUALLY CHOSEN <1. // C SMALLER VALUES OF WORK(4) MAKE THE CODE SLOWER, BUT SAFER. // C DEFAULT MIN(0.03D0,RTOL(1)**0.5D0) // C // C WORK(5) AND WORK(6) : IF WORK(5) < HNEW/HOLD < WORK(6), THEN THE // C STEP SIZE IS NOT CHANGED. THIS SAVES, TOGETHER WITH A // C LARGE WORK(3), LU-DECOMPOSITIONS AND COMPUTING TIME FOR // C LARGE SYSTEMS. FOR SMALL SYSTEMS ONE MAY HAVE // C WORK(5)=1.D0, WORK(6)=1.2D0, FOR LARGE FULL SYSTEMS // C WORK(5)=0.99D0, WORK(6)=2.D0 MIGHT BE GOOD. // C DEFAULTS WORK(5)=1.D0, WORK(6)=1.2D0 . // C // C WORK(7) MAXIMAL STEP SIZE, DEFAULT XEND-X. // C // C WORK(8), WORK(9) PARAMETERS FOR STEP SIZE SELECTION // C THE NEW STEP SIZE IS CHOSEN SUBJECT TO THE RESTRICTION // C WORK(8) <= HNEW/HOLD <= WORK(9) // C DEFAULT VALUES: WORK(8)=0.2D0, WORK(9)=8.D0 // C // C----------------------------------------------------------------------- // C // C OUTPUT PARAMETERS // C ----------------- // C X X-VALUE FOR WHICH THE SOLUTION HAS BEEN COMPUTED // C (AFTER SUCCESSFUL RETURN X=XEND). // C // C Y(N) NUMERICAL SOLUTION AT X // C // C H PREDICTED STEP SIZE OF THE LAST ACCEPTED STEP // C // C IDID REPORTS ON SUCCESSFULNESS UPON RETURN: // C IDID= 1 COMPUTATION SUCCESSFUL, // C IDID= 2 COMPUT. SUCCESSFUL (INTERRUPTED BY SOLOUT) // C IDID=-1 INPUT IS NOT CONSISTENT, // C IDID=-2 LARGER NMAX IS NEEDED, // C IDID=-3 STEP SIZE BECOMES TOO SMALL, // C IDID=-4 MATRIX IS REPEATEDLY SINGULAR. // C // C IWORK(14) NFCN NUMBER OF FUNCTION EVALUATIONS (THOSE FOR NUMERICAL // C EVALUATION OF THE JACOBIAN ARE NOT COUNTED) // C IWORK(15) NJAC NUMBER OF JACOBIAN EVALUATIONS (EITHER ANALYTICALLY // C OR NUMERICALLY) // C IWORK(16) NSTEP NUMBER OF COMPUTED STEPS // C IWORK(17) NACCPT NUMBER OF ACCEPTED STEPS // C IWORK(18) NREJCT NUMBER OF REJECTED STEPS (DUE TO ERROR TEST), // C (STEP REJECTIONS IN THE FIRST STEP ARE NOT COUNTED) // C IWORK(19) NDEC NUMBER OF LU-DECOMPOSITIONS OF BOTH MATRICES // C IWORK(20) NSOL NUMBER OF FORWARD-BACKWARD SUBSTITUTIONS, OF BOTH // C SYSTEMS; THE NSTEP FORWARD-BACKWARD SUBSTITUTIONS, // C NEEDED FOR STEP SIZE SELECTION, ARE NOT COUNTED // C----------------------------------------------------------------------- // C *** *** *** *** *** *** *** *** *** *** *** *** *** // C DECLARATIONS // C *** *** *** *** *** *** *** *** *** *** *** *** *** // C *** *** *** *** *** *** *** // C SETTING THE PARAMETERS // C *** *** *** *** *** *** *** #endregion Prolog #region Body NFCN = 0; NJAC = 0; NSTEP = 0; NACCPT = 0; NREJCT = 0; NDEC = 0; NSOL = 0; ARRET = false; // C -------- UROUND SMALLEST NUMBER SATISFYING 1.0D0+UROUND>1.0D0 if (WORK[1 + o_work] == 0.0E0) { UROUND = 1.0E-16; } else { UROUND = WORK[1 + o_work]; if (UROUND <= 1.0E-19 || UROUND >= 1.0E0) { //ERROR-ERROR WRITE(6,*)' COEFFICIENTS HAVE 20 DIGITS, UROUND=',WORK(1); ARRET = true; } } // C -------- CHECK AND CHANGE THE TOLERANCES EXPM = 2.0E0 / 3.0E0; if (ITOL == 0) { if (ATOL[1 + o_atol] <= 0.0E0 || RTOL[1 + o_rtol] <= 10.0E0 * UROUND) { //ERROR-ERROR WRITE (6,*) ' TOLERANCES ARE TOO SMALL'; ARRET = true; } else { QUOT = ATOL[1 + o_atol] / RTOL[1 + o_rtol]; RTOL[1 + o_rtol] = 0.1E0 * Math.Pow(RTOL[1 + o_rtol], EXPM); ATOL[1 + o_atol] = RTOL[1 + o_rtol] * QUOT; } } else { for (I = 1; I <= N; I++) { if (ATOL[I + o_atol] <= 0.0E0 || RTOL[I + o_rtol] <= 10.0E0 * UROUND) { //ERROR-ERROR WRITE (6,*) ' TOLERANCES(',I,') ARE TOO SMALL'; ARRET = true; } else { QUOT = ATOL[I + o_atol] / RTOL[I + o_rtol]; RTOL[I + o_rtol] = 0.1E0 * Math.Pow(RTOL[I + o_rtol], EXPM); ATOL[I + o_atol] = RTOL[I + o_rtol] * QUOT; } } } // C -------- NMAX , THE MAXIMAL NUMBER OF STEPS ----- if (IWORK[2 + o_iwork] == 0) { NMAX = 100000; } else { NMAX = IWORK[2 + o_iwork]; if (NMAX <= 0) { //ERROR-ERROR WRITE(6,*)' WRONG INPUT IWORK(2)=',IWORK(2); ARRET = true; } } // C -------- NIT MAXIMAL NUMBER OF NEWTON ITERATIONS if (IWORK[3 + o_iwork] == 0) { NIT = 7; } else { NIT = IWORK[3 + o_iwork]; if (NIT <= 0) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT IWORK(3)=',IWORK(3); ARRET = true; } } // C -------- STARTN SWITCH FOR STARTING VALUES OF NEWTON ITERATIONS if (IWORK[4 + o_iwork] == 0) { STARTN = false; } else { STARTN = true; } // C -------- PARAMETER FOR DIFFERENTIAL-ALGEBRAIC COMPONENTS NIND1 = IWORK[5 + o_iwork]; NIND2 = IWORK[6 + o_iwork]; NIND3 = IWORK[7 + o_iwork]; if (NIND1 == 0) NIND1 = N; if (NIND1 + NIND2 + NIND3 != N) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT FOR IWORK(5,6,7)=',NIND1,NIND2,NIND3; ARRET = true; } // C -------- PRED STEP SIZE CONTROL if (IWORK[8 + o_iwork] <= 1) { PRED = true; } else { PRED = false; } // C -------- PARAMETER FOR SECOND ORDER EQUATIONS M1 = IWORK[9 + o_iwork]; M2 = IWORK[10 + o_iwork]; NM1 = N - M1; if (M1 == 0) M2 = N; if (M2 == 0) M2 = M1; if (M1 < 0 || M2 < 0 || M1 + M2 > N) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT FOR IWORK(9,10)=',M1,M2; ARRET = true; } // C --------- SAFE SAFETY FACTOR IN STEP SIZE PREDICTION if (WORK[2 + o_work] == 0.0E0) { SAFE = 0.9E0; } else { SAFE = WORK[2 + o_work]; if (SAFE <= 0.001E0 || SAFE >= 1.0E0) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT FOR WORK(2)=',WORK(2); ARRET = true; } } // C ------ THET DECIDES WHETHER THE JACOBIAN SHOULD BE RECOMPUTED; if (WORK[3 + o_work] == 0.0E0) { THET = 0.001E0; } else { THET = WORK[3 + o_work]; if (THET >= 1.0E0) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT FOR WORK(3)=',WORK(3); ARRET = true; } } // C --- FNEWT STOPPING CRITERION FOR NEWTON'S METHOD, USUALLY CHOSEN <1. TOLST = RTOL[1 + o_rtol]; if (WORK[4 + o_work] == 0.0E0) { FNEWT = Math.Max(10 * UROUND / TOLST, Math.Min(0.03E0, Math.Pow(TOLST, 0.5E0))); } else { FNEWT = WORK[4 + o_work]; if (FNEWT <= UROUND / TOLST) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT FOR WORK(4)=',WORK(4); ARRET = true; } } // C --- QUOT1 AND QUOT2: IF QUOT1 < HNEW/HOLD < QUOT2, STEP SIZE = CONST. if (WORK[5 + o_work] == 0.0E0) { QUOT1 = 1.0E0; } else { QUOT1 = WORK[5 + o_work]; } if (WORK[6 + o_work] == 0.0E0) { QUOT2 = 1.2E0; } else { QUOT2 = WORK[6 + o_work]; } if (QUOT1 > 1.0E0 || QUOT2 < 1.0E0) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT FOR WORK(5,6)=',QUOT1,QUOT2; ARRET = true; } // C -------- MAXIMAL STEP SIZE if (WORK[7 + o_work] == 0.0E0) { HMAX = XEND - X; } else { HMAX = WORK[7 + o_work]; } // C ------- FACL,FACR PARAMETERS FOR STEP SIZE SELECTION if (WORK[8 + o_work] == 0.0E0) { FACL = 5.0E0; } else { FACL = 1.0E0 / WORK[8 + o_work]; } if (WORK[9 + o_work] == 0.0E0) { FACR = 1.0E0 / 8.0E0; } else { FACR = 1.0E0 / WORK[9 + o_work]; } if (FACL < 1.0E0 || FACR > 1.0E0) { //ERROR-ERROR WRITE(6,*)' CURIOUS INPUT WORK(8,9)=',WORK(8),WORK(9); ARRET = true; } // C *** *** *** *** *** *** *** *** *** *** *** *** *** // C COMPUTATION OF ARRAY ENTRIES // C *** *** *** *** *** *** *** *** *** *** *** *** *** // C ---- IMPLICIT, BANDED OR NOT ? IMPLCT = IMAS != 0; JBAND = MLJAC < NM1; // C -------- COMPUTATION OF THE ROW-DIMENSIONS OF THE 2-ARRAYS --- // C -- JACOBIAN AND MATRICES E1, E2 if (JBAND) { LDJAC = MLJAC + MUJAC + 1; LDE1 = MLJAC + LDJAC; } else { MLJAC = NM1; MUJAC = NM1; LDJAC = NM1; LDE1 = NM1; } // C -- MASS MATRIX if (IMPLCT) { if (MLMAS != NM1) { LDMAS = MLMAS + MUMAS + 1; if (JBAND) { IJOB = 4; } else { IJOB = 3; } } else { MUMAS = NM1; LDMAS = NM1; IJOB = 5; } // C ------ BANDWITH OF "MAS" NOT SMALLER THAN BANDWITH OF "JAC" if (MLMAS > MLJAC || MUMAS > MUJAC) { //ERROR-ERROR WRITE (6,*) 'BANDWITH OF "MAS" NOT SMALLER THAN BANDWITH OF"JAC"'; ARRET = true; } } else { LDMAS = 0; if (JBAND) { IJOB = 2; } else { IJOB = 1; if (N > 2 && IWORK[1 + o_iwork] != 0) IJOB = 7; } } LDMAS2 = Math.Max(1, LDMAS); // C ------ HESSENBERG OPTION ONLY FOR EXPLICIT EQU. WITH FULL JACOBIAN if ((IMPLCT || JBAND) && IJOB == 7) { //ERROR-ERROR WRITE(6,*)' HESSENBERG OPTION ONLY FOR EXPLICIT EQUATIONS WITH FULL JACOBIAN'; ARRET = true; } // C ------- PREPARE THE ENTRY-POINTS FOR THE ARRAYS IN WORK ----- IEZ1 = 21; IEZ2 = IEZ1 + N; IEZ3 = IEZ2 + N; IEY0 = IEZ3 + N; IESCAL = IEY0 + N; IEF1 = IESCAL + N; IEF2 = IEF1 + N; IEF3 = IEF2 + N; IECON = IEF3 + N; IEJAC = IECON + 4 * N; IEMAS = IEJAC + N * LDJAC; IEE1 = IEMAS + NM1 * LDMAS; IEE2R = IEE1 + NM1 * LDE1; IEE2I = IEE2R + NM1 * LDE1; // C ------ TOTAL STORAGE REQUIREMENT ----------- ISTORE = IEE2I + NM1 * LDE1 - 1; if (ISTORE > LWORK) { //ERROR-ERROR WRITE(6,*)' INSUFFICIENT STORAGE FOR WORK, MIN. LWORK=',ISTORE; ARRET = true; } // C ------- ENTRY POINTS FOR INTEGER WORKSPACE ----- IEIP1 = 21; IEIP2 = IEIP1 + NM1; IEIPH = IEIP2 + NM1; // C --------- TOTAL REQUIREMENT --------------- ISTORE = IEIPH + NM1 - 1; if (ISTORE > LIWORK) { //ERROR-ERROR WRITE(6,*)' INSUFF. STORAGE FOR IWORK, MIN. LIWORK=',ISTORE; ARRET = true; } // C ------ WHEN A FAIL HAS OCCURED, WE RETURN WITH IDID=-1 if (ARRET) { IDID = -1; return; } // C -------- CALL TO CORE INTEGRATOR ------------ this._radcor.Run(N, FCN, ref X, ref Y, offset_y, XEND, HMAX , ref H, RTOL, offset_rtol, ATOL, offset_atol, ITOL, JAC, IJAC , MLJAC, MUJAC, MAS, MLMAS, MUMAS, SOLOUT , IOUT, ref IDID, NMAX, UROUND, SAFE, THET , FNEWT, QUOT1, QUOT2, NIT, ref IJOB, STARTN , NIND1, NIND2, NIND3, PRED, FACL, FACR , M1, M2, NM1, IMPLCT, JBAND, LDJAC , LDE1, LDMAS2, ref WORK, IEZ1 + o_work, ref WORK, IEZ2 + o_work, ref WORK, IEZ3 + o_work, ref WORK, IEY0 + o_work , ref WORK, IESCAL + o_work, ref WORK, IEF1 + o_work, ref WORK, IEF2 + o_work, ref WORK, IEF3 + o_work, ref WORK, IEJAC + o_work, ref WORK, IEE1 + o_work , ref WORK, IEE2R + o_work, ref WORK, IEE2I + o_work, ref WORK, IEMAS + o_work, ref IWORK, IEIP1 + o_iwork, ref IWORK, IEIP2 + o_iwork, ref IWORK, IEIPH + o_iwork , ref WORK, IECON + o_work, ref NFCN, ref NJAC, ref NSTEP, ref NACCPT, ref NREJCT , ref NDEC, ref NSOL, RPAR, offset_rpar, IPAR, offset_ipar); IWORK[14 + o_iwork] = NFCN; IWORK[15 + o_iwork] = NJAC; IWORK[16 + o_iwork] = NSTEP; IWORK[17 + o_iwork] = NACCPT; IWORK[18 + o_iwork] = NREJCT; IWORK[19 + o_iwork] = NDEC; IWORK[20 + o_iwork] = NSOL; // C -------- RESTORE TOLERANCES EXPM = 1.0E0 / EXPM; if (ITOL == 0) { QUOT = ATOL[1 + o_atol] / RTOL[1 + o_rtol]; RTOL[1 + o_rtol] = Math.Pow(10.0E0 * RTOL[1 + o_rtol], EXPM); ATOL[1 + o_atol] = RTOL[1 + o_rtol] * QUOT; } else { for (I = 1; I <= N; I++) { QUOT = ATOL[I + o_atol] / RTOL[I + o_rtol]; RTOL[I + o_rtol] = Math.Pow(10.0E0 * RTOL[I + o_rtol], EXPM); ATOL[I + o_atol] = RTOL[I + o_rtol] * QUOT; } } // C ----------- RETURN ----------- return; #endregion Body }
public void Run(int N, IFVPOL FCN, ref double X, ref double[] Y, int offset_y, double XEND, double HMAX , ref double H, double[] RTOL, int offset_rtol, double[] ATOL, int offset_atol, int ITOL, IJVPOL JAC, int IJAC , int MLJAC, int MUJAC, IBBAMPL MAS, int MLMAS, int MUMAS, ISOLOUTR SOLOUT , int IOUT, ref int IDID, int NMAX, double UROUND, double SAFE, double THET , double FNEWT, double QUOT1, double QUOT2, int NIT, ref int IJOB, bool STARTN , int NIND1, int NIND2, int NIND3, bool PRED, double FACL, double FACR , int M1, int M2, int NM1, bool IMPLCT, bool BANDED, int LDJAC , int LDE1, int LDMAS, ref double[] Z1, int offset_z1, ref double[] Z2, int offset_z2, ref double[] Z3, int offset_z3, ref double[] Y0, int offset_y0 , ref double[] SCAL, int offset_scal, ref double[] F1, int offset_f1, ref double[] F2, int offset_f2, ref double[] F3, int offset_f3, ref double[] FJAC, int offset_fjac, ref double[] E1, int offset_e1 , ref double[] E2R, int offset_e2r, ref double[] E2I, int offset_e2i, ref double[] FMAS, int offset_fmas, ref int[] IP1, int offset_ip1, ref int[] IP2, int offset_ip2, ref int[] IPHES, int offset_iphes , ref double[] CONT, int offset_cont, ref int NFCN, ref int NJAC, ref int NSTEP, ref int NACCPT, ref int NREJCT , ref int NDEC, ref int NSOL, double[] RPAR, int offset_rpar, int[] IPAR, int offset_ipar) { #region Variables bool REJECT = false; bool FIRST = false; bool CALJAC = false; bool CALHES = false; bool INDEX1 = false; bool INDEX2 = false; bool INDEX3 = false; bool LAST = false; #endregion Variables #region Implicit Variables int LRC = 0; double SQ6 = 0; double C1 = 0; double C2 = 0; double C1MC2 = 0; double DD1 = 0; double DD2 = 0; double DD3 = 0; double U1 = 0; double ALPH = 0; double BETA = 0; double CNO = 0; double T11 = 0; double T12 = 0; double T13 = 0; double T21 = 0; double T22 = 0; double T23 = 0; double T31 = 0; double TI11 = 0; double TI12 = 0; double TI13 = 0; double TI21 = 0; double TI22 = 0; double TI23 = 0; double TI31 = 0; double TI32 = 0; double TI33 = 0; double POSNEG = 0; double HMAXN = 0; double HOLD = 0; double HOPT = 0; double FACCON = 0; double CFAC = 0; int NSING = 0; double XOLD = 0; int IRTRN = 0; int NRSOL = 0; double XOSOL = 0; int I = 0; int NSOLU = 0; int N2 = 0; int N3 = 0; double HHFAC = 0; int MUJACP = 0; int MD = 0; int J = 0; int K = 0; int MM = 0; int J1 = 0; int LBEG = 0; int LEND = 0; int MUJACJ = 0; int L = 0; int FJAC_J = 0; double YSAFE = 0; double DELT = 0; int FJAC_I = 0; double FAC1 = 0; double ALPHN = 0; double BETAN = 0; int IER = 0; double XPH = 0; double C3Q = 0; double C1Q = 0; double C2Q = 0; double AK1 = 0; double AK2 = 0; double AK3 = 0; double Z1I = 0; double Z2I = 0; double Z3I = 0; int NEWT = 0; double THETA = 0; double A1 = 0; double A2 = 0; double A3 = 0; double DYNO = 0; double DENOM = 0; double THQ = 0; double DYNOLD = 0; double THQOLD = 0; double DYTH = 0; double QNEWT = 0; double F1I = 0; double F2I = 0; double F3I = 0; double FAC = 0; double QUOT = 0; double ERR = 0; double HNEW = 0; double FACGUS = 0; double HACC = 0; double ERRACC = 0; double AK = 0; double ACONT3 = 0; double QT = 0; #endregion Implicit Variables #region Array Index Correction int o_y = -1 + offset_y; int o_rtol = -1 + offset_rtol; int o_atol = -1 + offset_atol; int o_z1 = -1 + offset_z1; int o_z2 = -1 + offset_z2; int o_z3 = -1 + offset_z3; int o_y0 = -1 + offset_y0; int o_scal = -1 + offset_scal; int o_f1 = -1 + offset_f1; int o_f2 = -1 + offset_f2; int o_f3 = -1 + offset_f3; int o_fjac = -1 - LDJAC + offset_fjac; int o_e1 = -1 - LDE1 + offset_e1; int o_e2r = -1 - LDE1 + offset_e2r; int o_e2i = -1 - LDE1 + offset_e2i; int o_fmas = -1 - LDMAS + offset_fmas; int o_ip1 = -1 + offset_ip1; int o_ip2 = -1 + offset_ip2; int o_iphes = -1 + offset_iphes; int o_cont = -1 + offset_cont; int o_rpar = -1 + offset_rpar; int o_ipar = -1 + offset_ipar; #endregion Array Index Correction // C ---------------------------------------------------------- // C CORE INTEGRATOR FOR RADAU5 // C PARAMETERS SAME AS IN RADAU5 WITH WORKSPACE ADDED // C ---------------------------------------------------------- // C DECLARATIONS // C ---------------------------------------------------------- // C *** *** *** *** *** *** *** // C INITIALISATIONS // C *** *** *** *** *** *** *** // C --------- DUPLIFY N FOR COMMON BLOCK CONT ----- #region Body NN.v = N; NN2.v = 2 * N; NN3.v = 3 * N; LRC = 4 * N; // C -------- CHECK THE INDEX OF THE PROBLEM ----- INDEX1 = NIND1 != 0; INDEX2 = NIND2 != 0; INDEX3 = NIND3 != 0; // C ------- COMPUTE MASS MATRIX FOR IMPLICIT CASE ---------- if (IMPLCT) MAS.Run(NM1, ref FMAS, offset_fmas, LDMAS, RPAR, offset_rpar, IPAR[1 + o_ipar]); // C ---------- CONSTANTS --------- SQ6 = Math.Sqrt(6.0E0); C1 = (4.0E0 - SQ6) / 10.0E0; C2 = (4.0E0 + SQ6) / 10.0E0; C1M1.v = C1 - 1.0E0; C2M1.v = C2 - 1.0E0; C1MC2 = C1 - C2; DD1 = -(13.0E0 + 7.0E0 * SQ6) / 3.0E0; DD2 = (-13.0E0 + 7.0E0 * SQ6) / 3.0E0; DD3 = -1.0E0 / 3.0E0; U1 = (6.0E0 + Math.Pow(81.0E0, 1.0E0 / 3.0E0) - Math.Pow(9.0E0, 1.0E0 / 3.0E0)) / 30.0E0; ALPH = (12.0E0 - Math.Pow(81.0E0, 1.0E0 / 3.0E0) + Math.Pow(9.0E0, 1.0E0 / 3.0E0)) / 60.0E0; BETA = (Math.Pow(81.0E0, 1.0E0 / 3.0E0) + Math.Pow(9.0E0, 1.0E0 / 3.0E0)) * Math.Sqrt(3.0E0) / 60.0E0; CNO = Math.Pow(ALPH, 2) + Math.Pow(BETA, 2); U1 = 1.0E0 / U1; ALPH /= CNO; BETA /= CNO; T11 = 9.1232394870892942792E-02; T12 = -0.14125529502095420843E0; T13 = -3.0029194105147424492E-02; T21 = 0.24171793270710701896E0; T22 = 0.20412935229379993199E0; T23 = 0.38294211275726193779E0; T31 = 0.96604818261509293619E0; TI11 = 4.3255798900631553510E0; TI12 = 0.33919925181580986954E0; TI13 = 0.54177053993587487119E0; TI21 = -4.1787185915519047273E0; TI22 = -0.32768282076106238708E0; TI23 = 0.47662355450055045196E0; TI31 = -0.50287263494578687595E0; TI32 = 2.5719269498556054292E0; TI33 = -0.59603920482822492497E0; if (M1 > 0) IJOB += 10; POSNEG = FortranLib.Sign(1.0E0, XEND - X); HMAXN = Math.Min(Math.Abs(HMAX), Math.Abs(XEND - X)); if (Math.Abs(H) <= 10.0E0 * UROUND) H = 1.0E-6; H = Math.Min(Math.Abs(H), HMAXN); H = FortranLib.Sign(H, POSNEG); HOLD = H; REJECT = false; FIRST = true; LAST = false; if ((X + H * 1.0001E0 - XEND) * POSNEG >= 0.0E0) { H = XEND - X; LAST = true; } HOPT = H; FACCON = 1.0E0; CFAC = SAFE * (1 + 2 * NIT); NSING = 0; XOLD = X; if (IOUT != 0) { IRTRN = 1; NRSOL = 1; XOSOL = XOLD; XSOL.v = X; for (I = 1; I <= N; I++) { CONT[I + o_cont] = Y[I + o_y]; } NSOLU = N; HSOL.v = HOLD; SOLOUT.Run(NRSOL, XOSOL, XSOL.v, Y, offset_y, CONT, offset_cont, LRC , NSOLU, RPAR[1 + o_rpar], IPAR[1 + o_ipar], IRTRN); if (IRTRN < 0) goto LABEL179; } MLE.v = MLJAC; MUE.v = MUJAC; MBJAC.v = MLJAC + MUJAC + 1; MBB.v = MLMAS + MUMAS + 1; MDIAG.v = MLE.v + MUE.v + 1; MDIFF.v = MLE.v + MUE.v - MUMAS; MBDIAG.v = MUMAS + 1; N2 = 2 * N; N3 = 3 * N; if (ITOL == 0) { for (I = 1; I <= N; I++) { SCAL[I + o_scal] = ATOL[1 + o_atol] + RTOL[1 + o_rtol] * Math.Abs(Y[I + o_y]); } } else { for (I = 1; I <= N; I++) { SCAL[I + o_scal] = ATOL[I + o_atol] + RTOL[I + o_rtol] * Math.Abs(Y[I + o_y]); } } HHFAC = H; FCN.Run(N, X, Y, offset_y, ref Y0, offset_y0, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); NFCN += 1; // C --- BASIC INTEGRATION STEP LABEL10:; // C *** *** *** *** *** *** *** // C COMPUTATION OF THE JACOBIAN // C *** *** *** *** *** *** *** NJAC += 1; if (IJAC == 0) { // C --- COMPUTE JACOBIAN MATRIX NUMERICALLY if (BANDED) { // C --- JACOBIAN IS BANDED MUJACP = MUJAC + 1; MD = Math.Min(MBJAC.v, M2); for (MM = 1; MM <= M1 / M2 + 1; MM++) { for (K = 1; K <= MD; K++) { J = K + (MM - 1) * M2; LABEL12: F1[J + o_f1] = Y[J + o_y]; F2[J + o_f2] = Math.Sqrt(UROUND * Math.Max(1.0E-5, Math.Abs(Y[J + o_y]))); Y[J + o_y] += F2[J + o_f2]; J += MD; if (J <= MM * M2) goto LABEL12; FCN.Run(N, X, Y, offset_y, ref CONT, offset_cont, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); J = K + (MM - 1) * M2; J1 = K; LBEG = Math.Max(1, J1 - MUJAC) + M1; LABEL14: LEND = Math.Min(M2, J1 + MLJAC) + M1; Y[J + o_y] = F1[J + o_f1]; MUJACJ = MUJACP - J1 - M1; FJAC_J = J * LDJAC + o_fjac; for (L = LBEG; L <= LEND; L++) { FJAC[L + MUJACJ + FJAC_J] = (CONT[L + o_cont] - Y0[L + o_y0]) / F2[J + o_f2]; } J += MD; J1 += MD; LBEG = LEND + 1; if (J <= MM * M2) goto LABEL14; } } } else { // C --- JACOBIAN IS FULL for (I = 1; I <= N; I++) { YSAFE = Y[I + o_y]; DELT = Math.Sqrt(UROUND * Math.Max(1.0E-5, Math.Abs(YSAFE))); Y[I + o_y] = YSAFE + DELT; FCN.Run(N, X, Y, offset_y, ref CONT, offset_cont, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); FJAC_I = I * LDJAC + o_fjac; for (J = M1 + 1; J <= N; J++) { FJAC[J - M1 + FJAC_I] = (CONT[J + o_cont] - Y0[J + o_y0]) / DELT; } Y[I + o_y] = YSAFE; } } } else { // C --- COMPUTE JACOBIAN MATRIX ANALYTICALLY JAC.Run(N, X, Y, offset_y, ref FJAC, offset_fjac, LDJAC, RPAR[1 + o_rpar] , IPAR[1 + o_ipar]); } CALJAC = true; CALHES = true; LABEL20:; // C --- COMPUTE THE MATRICES E1 AND E2 AND THEIR DECOMPOSITIONS FAC1 = U1 / H; ALPHN = ALPH / H; BETAN = BETA / H; this._decomr.Run(N, ref FJAC, offset_fjac, LDJAC, FMAS, offset_fmas, LDMAS, MLMAS , MUMAS, M1, M2, NM1, FAC1, ref E1, offset_e1 , LDE1, ref IP1, offset_ip1, ref IER, IJOB, ref CALHES, ref IPHES, offset_iphes); if (IER != 0) goto LABEL78; this._decomc.Run(N, FJAC, offset_fjac, LDJAC, FMAS, offset_fmas, LDMAS, MLMAS , MUMAS, M1, M2, NM1, ALPHN, BETAN , ref E2R, offset_e2r, ref E2I, offset_e2i, LDE1, ref IP2, offset_ip2, ref IER, IJOB); if (IER != 0) goto LABEL78; NDEC += 1; LABEL30:; NSTEP += 1; if (NSTEP > NMAX) goto LABEL178; if (0.1E0 * Math.Abs(H) <= Math.Abs(X) * UROUND) goto LABEL177; if (INDEX2) { for (I = NIND1 + 1; I <= NIND1 + NIND2; I++) { SCAL[I + o_scal] /= HHFAC; } } if (INDEX3) { for (I = NIND1 + NIND2 + 1; I <= NIND1 + NIND2 + NIND3; I++) { SCAL[I + o_scal] = SCAL[I + o_scal] / (HHFAC * HHFAC); } } XPH = X + H; // C *** *** *** *** *** *** *** // C STARTING VALUES FOR NEWTON ITERATION // C *** *** *** *** *** *** *** if (FIRST || STARTN) { for (I = 1; I <= N; I++) { Z1[I + o_z1] = 0.0E0; Z2[I + o_z2] = 0.0E0; Z3[I + o_z3] = 0.0E0; F1[I + o_f1] = 0.0E0; F2[I + o_f2] = 0.0E0; F3[I + o_f3] = 0.0E0; } } else { C3Q = H / HOLD; C1Q = C1 * C3Q; C2Q = C2 * C3Q; for (I = 1; I <= N; I++) { AK1 = CONT[I + N + o_cont]; AK2 = CONT[I + N2 + o_cont]; AK3 = CONT[I + N3 + o_cont]; Z1I = C1Q * (AK1 + (C1Q - C2M1.v) * (AK2 + (C1Q - C1M1.v) * AK3)); Z2I = C2Q * (AK1 + (C2Q - C2M1.v) * (AK2 + (C2Q - C1M1.v) * AK3)); Z3I = C3Q * (AK1 + (C3Q - C2M1.v) * (AK2 + (C3Q - C1M1.v) * AK3)); Z1[I + o_z1] = Z1I; Z2[I + o_z2] = Z2I; Z3[I + o_z3] = Z3I; F1[I + o_f1] = TI11 * Z1I + TI12 * Z2I + TI13 * Z3I; F2[I + o_f2] = TI21 * Z1I + TI22 * Z2I + TI23 * Z3I; F3[I + o_f3] = TI31 * Z1I + TI32 * Z2I + TI33 * Z3I; } } // C *** *** *** *** *** *** *** // C LOOP FOR THE SIMPLIFIED NEWTON ITERATION // C *** *** *** *** *** *** *** NEWT = 0; FACCON = Math.Pow(Math.Max(FACCON, UROUND), 0.8E0); THETA = Math.Abs(THET); LABEL40:; if (NEWT >= NIT) goto LABEL78; // C --- COMPUTE THE RIGHT-HAND SIDE for (I = 1; I <= N; I++) { CONT[I + o_cont] = Y[I + o_y] + Z1[I + o_z1]; } FCN.Run(N, X + C1 * H, CONT, offset_cont, ref Z1, offset_z1, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); for (I = 1; I <= N; I++) { CONT[I + o_cont] = Y[I + o_y] + Z2[I + o_z2]; } FCN.Run(N, X + C2 * H, CONT, offset_cont, ref Z2, offset_z2, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); for (I = 1; I <= N; I++) { CONT[I + o_cont] = Y[I + o_y] + Z3[I + o_z3]; } FCN.Run(N, XPH, CONT, offset_cont, ref Z3, offset_z3, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); NFCN += 3; // C --- SOLVE THE LINEAR SYSTEMS for (I = 1; I <= N; I++) { A1 = Z1[I + o_z1]; A2 = Z2[I + o_z2]; A3 = Z3[I + o_z3]; Z1[I + o_z1] = TI11 * A1 + TI12 * A2 + TI13 * A3; Z2[I + o_z2] = TI21 * A1 + TI22 * A2 + TI23 * A3; Z3[I + o_z3] = TI31 * A1 + TI32 * A2 + TI33 * A3; } this._slvrad.Run(N, FJAC, offset_fjac, LDJAC, MLJAC, MUJAC, FMAS, offset_fmas , LDMAS, MLMAS, MUMAS, M1, M2, NM1 , FAC1, ALPHN, BETAN, E1, offset_e1, E2R, offset_e2r, E2I, offset_e2i , LDE1, ref Z1, offset_z1, ref Z2, offset_z2, ref Z3, offset_z3, F1, offset_f1, F2, offset_f2 , F3, offset_f3, CONT[1 + o_cont], IP1, offset_ip1, IP2, offset_ip2, IPHES, offset_iphes, IER , IJOB); NSOL += 1; NEWT += 1; DYNO = 0.0E0; for (I = 1; I <= N; I++) { DENOM = SCAL[I + o_scal]; DYNO += Math.Pow(Z1[I + o_z1] / DENOM, 2) + Math.Pow(Z2[I + o_z2] / DENOM, 2) + Math.Pow(Z3[I + o_z3] / DENOM, 2); } DYNO = Math.Sqrt(DYNO / N3); // C --- BAD CONVERGENCE OR NUMBER OF ITERATIONS TO LARGE if (NEWT > 1 && NEWT < NIT) { THQ = DYNO / DYNOLD; if (NEWT == 2) { THETA = THQ; } else { THETA = Math.Sqrt(THQ * THQOLD); } THQOLD = THQ; if (THETA < 0.99E0) { FACCON = THETA / (1.0E0 - THETA); DYTH = FACCON * DYNO * Math.Pow(THETA, NIT - 1 - NEWT) / FNEWT; if (DYTH >= 1.0E0) { QNEWT = Math.Max(1.0E-4, Math.Min(20.0E0, DYTH)); HHFAC = .8E0 * Math.Pow(QNEWT, -1.0E0 / (4.0E0 + NIT - 1 - NEWT)); H *= HHFAC; REJECT = true; LAST = false; if (CALJAC) goto LABEL20; goto LABEL10; } } else { goto LABEL78; } } DYNOLD = Math.Max(DYNO, UROUND); for (I = 1; I <= N; I++) { F1I = F1[I + o_f1] + Z1[I + o_z1]; F2I = F2[I + o_f2] + Z2[I + o_z2]; F3I = F3[I + o_f3] + Z3[I + o_z3]; F1[I + o_f1] = F1I; F2[I + o_f2] = F2I; F3[I + o_f3] = F3I; Z1[I + o_z1] = T11 * F1I + T12 * F2I + T13 * F3I; Z2[I + o_z2] = T21 * F1I + T22 * F2I + T23 * F3I; Z3[I + o_z3] = T31 * F1I + F2I; } if (FACCON * DYNO > FNEWT) goto LABEL40; // C --- ERROR ESTIMATION this._estrad.Run(N, FJAC, offset_fjac, LDJAC, MLJAC, MUJAC, FMAS, offset_fmas , LDMAS, MLMAS, MUMAS, H, DD1, DD2 , DD3, FCN, ref NFCN, Y0, offset_y0, Y, offset_y, IJOB , X, M1, M2, NM1, E1, offset_e1, LDE1 , Z1, offset_z1, Z2, offset_z2, Z3, offset_z3, ref CONT, offset_cont, ref F1, offset_f1, ref F2, offset_f2 , IP1, offset_ip1, IPHES, offset_iphes, SCAL, offset_scal, ref ERR, FIRST, REJECT , FAC1, RPAR, offset_rpar, IPAR, offset_ipar); // C --- COMPUTATION OF HNEW // C --- WE REQUIRE .2<=HNEW/H<=8. FAC = Math.Min(SAFE, CFAC / (NEWT + 2 * NIT)); QUOT = Math.Max(FACR, Math.Min(FACL, Math.Pow(ERR, .25E0) / FAC)); HNEW = H / QUOT; // C *** *** *** *** *** *** *** // C IS THE ERROR SMALL ENOUGH ? // C *** *** *** *** *** *** *** if (ERR < 1.0E0) { // C --- STEP IS ACCEPTED FIRST = false; NACCPT += 1; if (PRED) { // C --- PREDICTIVE CONTROLLER OF GUSTAFSSON if (NACCPT > 1) { FACGUS = (HACC / H) * Math.Pow(Math.Pow(ERR, 2) / ERRACC, 0.25E0) / SAFE; FACGUS = Math.Max(FACR, Math.Min(FACL, FACGUS)); QUOT = Math.Max(QUOT, FACGUS); HNEW = H / QUOT; } HACC = H; ERRACC = Math.Max(1.0E-2, ERR); } XOLD = X; HOLD = H; X = XPH; for (I = 1; I <= N; I++) { Y[I + o_y] += Z3[I + o_z3]; Z2I = Z2[I + o_z2]; Z1I = Z1[I + o_z1]; CONT[I + N + o_cont] = (Z2I - Z3[I + o_z3]) / C2M1.v; AK = (Z1I - Z2I) / C1MC2; ACONT3 = Z1I / C1; ACONT3 = (AK - ACONT3) / C2; CONT[I + N2 + o_cont] = (AK - CONT[I + N + o_cont]) / C1M1.v; CONT[I + N3 + o_cont] = CONT[I + N2 + o_cont] - ACONT3; } if (ITOL == 0) { for (I = 1; I <= N; I++) { SCAL[I + o_scal] = ATOL[1 + o_atol] + RTOL[1 + o_rtol] * Math.Abs(Y[I + o_y]); } } else { for (I = 1; I <= N; I++) { SCAL[I + o_scal] = ATOL[I + o_atol] + RTOL[I + o_rtol] * Math.Abs(Y[I + o_y]); } } if (IOUT != 0) { NRSOL = NACCPT + 1; XSOL.v = X; XOSOL = XOLD; for (I = 1; I <= N; I++) { CONT[I + o_cont] = Y[I + o_y]; } NSOLU = N; HSOL.v = HOLD; SOLOUT.Run(NRSOL, XOSOL, XSOL.v, Y, offset_y, CONT, offset_cont, LRC , NSOLU, RPAR[1 + o_rpar], IPAR[1 + o_ipar], IRTRN); if (IRTRN < 0) goto LABEL179; } CALJAC = false; if (LAST) { H = HOPT; IDID = 1; return; } FCN.Run(N, X, Y, offset_y, ref Y0, offset_y0, RPAR[1 + o_rpar], IPAR[1 + o_ipar]); NFCN += 1; HNEW = POSNEG * Math.Min(Math.Abs(HNEW), HMAXN); HOPT = HNEW; HOPT = Math.Min(H, HNEW); if (REJECT) HNEW = POSNEG * Math.Min(Math.Abs(HNEW), Math.Abs(H)); REJECT = false; if ((X + HNEW / QUOT1 - XEND) * POSNEG >= 0.0E0) { H = XEND - X; LAST = true; } else { QT = HNEW / H; HHFAC = H; if (THETA <= THET && QT >= QUOT1 && QT <= QUOT2) goto LABEL30; H = HNEW; } HHFAC = H; if (THETA <= THET) goto LABEL20; goto LABEL10; } else { // C --- STEP IS REJECTED REJECT = true; LAST = false; if (FIRST) { H *= 0.1E0; HHFAC = 0.1E0; } else { HHFAC = HNEW / H; H = HNEW; } if (NACCPT >= 1) NREJCT += 1; if (CALJAC) goto LABEL20; goto LABEL10; } // C --- UNEXPECTED STEP-REJECTION LABEL78:; if (IER != 0) { NSING += 1; if (NSING >= 5) goto LABEL176; } H *= 0.5E0; HHFAC = 0.5E0; REJECT = true; LAST = false; if (CALJAC) goto LABEL20; goto LABEL10; // C --- FAIL EXIT LABEL176:; //ERROR-ERROR WRITE(6,979)X ; //ERROR-ERROR WRITE(6,*) ' MATRIX IS REPEATEDLY SINGULAR, IER=',IER; IDID = -4; return; LABEL177:; //ERROR-ERROR WRITE(6,979)X ; //ERROR-ERROR WRITE(6,*) ' STEP SIZE T0O SMALL, H=',H; IDID = -3; return; LABEL178:; //ERROR-ERROR WRITE(6,979)X ; //ERROR-ERROR WRITE(6,*) ' MORE THAN NMAX =',NMAX,'STEPS ARE NEEDED' ; IDID = -2; return; // C --- EXIT CAUSED BY SOLOUT LABEL179:; //ERROR-ERROR WRITE(6,979)X; IDID = 2; return; #endregion Body }