Esempio n. 1
0
		/// <param name="Y">
		/// = Vector containing predicted values on entry.
		///</param>
		/// <param name="YH">
		/// = The Nordsieck array, an LDYH by LMAX array, input.
		///</param>
		/// <param name="LDYH">
		/// = A constant .ge. N, the first dimension of YH, input.
		///</param>
		/// <param name="EWT">
		/// = An error weight vector of length N.
		///</param>
		/// <param name="SAVF">
		/// = Array containing f evaluated at predicted y, input.
		///</param>
		/// <param name="WM">
		/// = Real work space for matrices.  In the output, it containS
		/// the inverse diagonal matrix if MITER = 3 and the LU
		/// decomposition of P if MITER is 1, 2 , 4, or 5.
		/// Storage of matrix elements starts at WM(3).
		/// Storage of the saved Jacobian starts at WM(LOCJS).
		/// WM also contains the following matrix-related data:
		/// WM(1) = SQRT(UROUND), used in numerical Jacobian step.
		/// WM(2) = H*RL1, saved for later use if MITER = 3.
		///</param>
		/// <param name="IWM">
		/// = Integer work space containing pivot information,
		/// starting at IWM(31), if MITER is 1, 2, 4, or 5.
		/// IWM also contains band parameters ML = IWM(1) and
		/// MU = IWM(2) if MITER is 4 or 5.
		///</param>
		/// <param name="F">
		/// = Dummy name for the user supplied subroutine for f.
		///</param>
		/// <param name="JAC">
		/// = Dummy name for the user supplied Jacobian subroutine.
		///</param>
		/// <param name="IERPJ">
		/// = Output error flag,  = 0 if no trouble, 1 if the P
		/// matrix is found to be singular.
		///</param>
		public void Run(ref double[] Y, int offset_y, double[] YH, int offset_yh, int LDYH, double[] EWT, int offset_ewt, ref double[] FTEM, int offset_ftem, double[] SAVF, int offset_savf
										 , ref double[] WM, int offset_wm, ref int[] IWM, int offset_iwm, IFEX F, IJEX JAC, ref int IERPJ, double[] RPAR, int offset_rpar
										 , int[] IPAR, int offset_ipar)
		{
			#region Variables

			double CON = 0; double DI = 0; double FAC = 0; double HRL1 = 0; double R = 0; double R0 = 0; double SRUR = 0;
			double YI = 0; double YJ = 0; double YJJ = 0; int I = 0; int I1 = 0; int I2 = 0; int IER = 0; int II = 0; int J = 0;
			int J1 = 0; int JJ = 0; int JOK = 0; int LENP = 0; int MBA = 0; int MBAND = 0; int MEB1 = 0; int MEBAND = 0;
			int ML = 0; int ML3 = 0; int MU = 0; int NP1 = 0;

			#endregion Variables

			#region Implicit Variables

			int YH_2 = 0; int YH_1 = 0;

			#endregion Implicit Variables

			#region Array Index Correction

			int o_y = -1 + offset_y; int o_yh = -1 - LDYH + offset_yh; int o_ewt = -1 + offset_ewt;
			int o_ftem = -1 + offset_ftem; int o_savf = -1 + offset_savf; int o_wm = -1 + offset_wm;
			int o_iwm = -1 + offset_iwm; int o_rpar = -1 + offset_rpar; int o_ipar = -1 + offset_ipar;

			#endregion Array Index Correction

			#region Prolog

			// C-----------------------------------------------------------------------
			// C Call sequence input -- Y, YH, LDYH, EWT, FTEM, SAVF, WM, IWM,
			// C                        F, JAC, RPAR, IPAR
			// C Call sequence output -- WM, IWM, IERPJ
			// C COMMON block variables accessed:
			// C     /DVOD01/  CCMXJ, DRC, H, RL1, TN, UROUND, ICF, JCUR, LOCJS,
			// C               MITER, MSBJ, N, NSLJ
			// C     /DVOD02/  NFE, NST, NJE, NLU
			// C
			// C Subroutines called by DVJAC: F, JAC, DACOPY, DCOPY, DGBFA, DGEFA,
			// C                              DSCAL
			// C Function routines called by DVJAC: DVNORM
			// C-----------------------------------------------------------------------
			// C DVJAC is called by DVNLSD to compute and process the matrix
			// C P = I - h*rl1*J , where J is an approximation to the Jacobian.
			// C Here J is computed by the user-supplied routine JAC if
			// C MITER = 1 or 4, or by finite differencing if MITER = 2, 3, or 5.
			// C If MITER = 3, a diagonal approximation to J is used.
			// C If JSV = -1, J is computed from scratch in all cases.
			// C If JSV = 1 and MITER = 1, 2, 4, or 5, and if the saved value of J is
			// C considered acceptable, then P is constructed from the saved J.
			// C J is stored in wm and replaced by P.  If MITER .ne. 3, P is then
			// C subjected to LU decomposition in preparation for later solution
			// C of linear systems with P as coefficient matrix. This is done
			// C by DGEFA if MITER = 1 or 2, and by DGBFA if MITER = 4 or 5.
			// C
			// C Communication with DVJAC is done with the following variables.  (For
			// C more details, please see the comments in the driver subroutine.)
			// C Y          = Vector containing predicted values on entry.
			// C YH         = The Nordsieck array, an LDYH by LMAX array, input.
			// C LDYH       = A constant .ge. N, the first dimension of YH, input.
			// C EWT        = An error weight vector of length N.
			// C SAVF       = Array containing f evaluated at predicted y, input.
			// C WM         = Real work space for matrices.  In the output, it containS
			// C              the inverse diagonal matrix if MITER = 3 and the LU
			// C              decomposition of P if MITER is 1, 2 , 4, or 5.
			// C              Storage of matrix elements starts at WM(3).
			// C              Storage of the saved Jacobian starts at WM(LOCJS).
			// C              WM also contains the following matrix-related data:
			// C              WM(1) = SQRT(UROUND), used in numerical Jacobian step.
			// C              WM(2) = H*RL1, saved for later use if MITER = 3.
			// C IWM        = Integer work space containing pivot information,
			// C              starting at IWM(31), if MITER is 1, 2, 4, or 5.
			// C              IWM also contains band parameters ML = IWM(1) and
			// C              MU = IWM(2) if MITER is 4 or 5.
			// C F          = Dummy name for the user supplied subroutine for f.
			// C JAC        = Dummy name for the user supplied Jacobian subroutine.
			// C RPAR, IPAR = Dummy names for user's real and integer work arrays.
			// C RL1        = 1/EL(2) (input).
			// C IERPJ      = Output error flag,  = 0 if no trouble, 1 if the P
			// C              matrix is found to be singular.
			// C JCUR       = Output flag to indicate whether the Jacobian matrix
			// C              (or approximation) is now current.
			// C              JCUR = 0 means J is not current.
			// C              JCUR = 1 means J is current.
			// C-----------------------------------------------------------------------
			// C
			// C Type declarations for labeled COMMON block DVOD01 --------------------
			// C
			// C
			// C Type declarations for labeled COMMON block DVOD02 --------------------
			// C
			// C
			// C Type declarations for local variables --------------------------------
			// C
			// C
			// C Type declaration for function subroutines called ---------------------
			// C
			// C-----------------------------------------------------------------------
			// C The following Fortran-77 declaration is to cause the values of the
			// C listed (local) variables to be saved between calls to this subroutine.
			// C-----------------------------------------------------------------------
			// C-----------------------------------------------------------------------
			// C
			// C

			#endregion Prolog

			#region Body

			IERPJ = 0;
			HRL1 = H.v * RL1.v;
			// C See whether J should be evaluated (JOK = -1) or not (JOK = 1). -------
			JOK = JSV.v;
			if (JSV.v == 1)
			{
				if (NST.v == 0 || NST.v > NSLJ.v + MSBJ.v) JOK = -1;
				if (ICF.v == 1 && DRC.v < CCMXJ.v) JOK = -1;
				if (ICF.v == 2) JOK = -1;
			}
			// C End of setting JOK. --------------------------------------------------
			// C
			if (JOK == -1 && MITER.v == 1)
			{
				// C If JOK = -1 and MITER = 1, call JAC to evaluate Jacobian. ------------
				NJE.v += 1;
				NSLJ.v = NST.v;
				JCUR.v = 1;
				LENP = N.v * N.v;
				for (I = 1; I <= LENP; I++)
				{
					WM[I + 2 + o_wm] = ZERO;
				}
				JAC.Run(N.v, TN.v, Y, offset_y, 0, 0, ref WM, 3 + o_wm
								, N.v, RPAR[1 + o_rpar], IPAR[1 + o_ipar]);
				if (JSV.v == 1) this._dcopy.Run(LENP, WM, 3 + o_wm, 1, ref WM, LOCJS.v + o_wm, 1);
			}
			// C
			if (JOK == -1 && MITER.v == 2)
			{
				// C If MITER = 2, make N calls to F to approximate the Jacobian. ---------
				NJE.v += 1;
				NSLJ.v = NST.v;
				JCUR.v = 1;
				FAC = this._dvnorm.Run(N.v, SAVF, offset_savf, EWT, offset_ewt);
				R0 = THOU * Math.Abs(H.v) * UROUND.v * Convert.ToSingle(N.v) * FAC;
				if (R0 == ZERO) R0 = ONE;
				SRUR = WM[1 + o_wm];
				J1 = 2;
				for (J = 1; J <= N.v; J++)
				{
					YJ = Y[J + o_y];
					R = Math.Max(SRUR * Math.Abs(YJ), R0 / EWT[J + o_ewt]);
					Y[J + o_y] += R;
					FAC = ONE / R;
					F.Run(N.v, TN.v, Y, offset_y, ref FTEM, offset_ftem, RPAR[1 + o_rpar], IPAR[1 + o_ipar]);
					for (I = 1; I <= N.v; I++)
					{
						WM[I + J1 + o_wm] = (FTEM[I + o_ftem] - SAVF[I + o_savf]) * FAC;
					}
					Y[J + o_y] = YJ;
					J1 += N.v;
				}
				NFE.v += N.v;
				LENP = N.v * N.v;
				if (JSV.v == 1) this._dcopy.Run(LENP, WM, 3 + o_wm, 1, ref WM, LOCJS.v + o_wm, 1);
			}
			// C
			if (JOK == 1 && (MITER.v == 1 || MITER.v == 2))
			{
				JCUR.v = 0;
				LENP = N.v * N.v;
				this._dcopy.Run(LENP, WM, LOCJS.v + o_wm, 1, ref WM, 3 + o_wm, 1);
			}
			// C
			if (MITER.v == 1 || MITER.v == 2)
			{
				// C Multiply Jacobian by scalar, add identity, and do LU decomposition. --
				CON = -HRL1;
				this._dscal.Run(LENP, CON, ref WM, 3 + o_wm, 1);
				J = 3;
				NP1 = N.v + 1;
				for (I = 1; I <= N.v; I++)
				{
					WM[J + o_wm] += ONE;
					J += NP1;
				}
				NLU.v += 1;
				this._dgefa.Run(ref WM, 3 + o_wm, N.v, N.v, ref IWM, 31 + o_iwm, ref IER);
				if (IER != 0) IERPJ = 1;
				return;
			}
			// C End of code block for MITER = 1 or 2. --------------------------------
			// C
			if (MITER.v == 3)
			{
				// C If MITER = 3, construct a diagonal approximation to J and P. ---------
				NJE.v += 1;
				JCUR.v = 1;
				WM[2 + o_wm] = HRL1;
				R = RL1.v * PT1;
				for (I = 1; I <= N.v; I++)
				{
					Y[I + o_y] += R * (H.v * SAVF[I + o_savf] - YH[I + 2 * LDYH + o_yh]);
				}
				F.Run(N.v, TN.v, Y, offset_y, ref WM, 3 + o_wm, RPAR[1 + o_rpar], IPAR[1 + o_ipar]);
				NFE.v += 1;
				YH_2 = 2 * LDYH + o_yh;
				for (I = 1; I <= N.v; I++)
				{
					R0 = H.v * SAVF[I + o_savf] - YH[I + YH_2];
					DI = PT1 * R0 - H.v * (WM[I + 2 + o_wm] - SAVF[I + o_savf]);
					WM[I + 2 + o_wm] = ONE;
					if (Math.Abs(R0) < UROUND.v / EWT[I + o_ewt]) goto LABEL320;
					if (Math.Abs(DI) == ZERO) goto LABEL330;
					WM[I + 2 + o_wm] = PT1 * R0 / DI;
				LABEL320:;
				}
				return;
			LABEL330: IERPJ = 1;
				return;
			}
			// C End of code block for MITER = 3. -------------------------------------
			// C
			// C Set constants for MITER = 4 or 5. ------------------------------------
			ML = IWM[1 + o_iwm];
			MU = IWM[2 + o_iwm];
			ML3 = ML + 3;
			MBAND = ML + MU + 1;
			MEBAND = MBAND + ML;
			LENP = MEBAND * N.v;
			// C
			if (JOK == -1 && MITER.v == 4)
			{
				// C If JOK = -1 and MITER = 4, call JAC to evaluate Jacobian. ------------
				NJE.v += 1;
				NSLJ.v = NST.v;
				JCUR.v = 1;
				for (I = 1; I <= LENP; I++)
				{
					WM[I + 2 + o_wm] = ZERO;
				}
				JAC.Run(N.v, TN.v, Y, offset_y, ML, MU, ref WM, ML3 + o_wm
								, MEBAND, RPAR[1 + o_rpar], IPAR[1 + o_ipar]);
				if (JSV.v == 1) this._dacopy.Run(MBAND, N.v, WM, ML3 + o_wm, MEBAND, ref WM, LOCJS.v + o_wm, MBAND);
			}
			// C
			if (JOK == -1 && MITER.v == 5)
			{
				// C If MITER = 5, make ML+MU+1 calls to F to approximate the Jacobian. ---
				NJE.v += 1;
				NSLJ.v = NST.v;
				JCUR.v = 1;
				MBA = Math.Min(MBAND, N.v);
				MEB1 = MEBAND - 1;
				SRUR = WM[1 + o_wm];
				FAC = this._dvnorm.Run(N.v, SAVF, offset_savf, EWT, offset_ewt);
				R0 = THOU * Math.Abs(H.v) * UROUND.v * Convert.ToSingle(N.v) * FAC;
				if (R0 == ZERO) R0 = ONE;
				for (J = 1; J <= MBA; J++)
				{
					for (I = J; (MBAND >= 0) ? (I <= N.v) : (I >= N.v); I += MBAND)
					{
						YI = Y[I + o_y];
						R = Math.Max(SRUR * Math.Abs(YI), R0 / EWT[I + o_ewt]);
						Y[I + o_y] += R;
					}
					F.Run(N.v, TN.v, Y, offset_y, ref FTEM, offset_ftem, RPAR[1 + o_rpar], IPAR[1 + o_ipar]);
					YH_1 = 1 * LDYH + o_yh;
					for (JJ = J; (MBAND >= 0) ? (JJ <= N.v) : (JJ >= N.v); JJ += MBAND)
					{
						Y[JJ + o_y] = YH[JJ + YH_1];
						YJJ = Y[JJ + o_y];
						R = Math.Max(SRUR * Math.Abs(YJJ), R0 / EWT[JJ + o_ewt]);
						FAC = ONE / R;
						I1 = Math.Max(JJ - MU, 1);
						I2 = Math.Min(JJ + ML, N.v);
						II = JJ * MEB1 - ML + 2;
						for (I = I1; I <= I2; I++)
						{
							WM[II + I + o_wm] = (FTEM[I + o_ftem] - SAVF[I + o_savf]) * FAC;
						}
					}
				}
				NFE.v += MBA;
				if (JSV.v == 1) this._dacopy.Run(MBAND, N.v, WM, ML3 + o_wm, MEBAND, ref WM, LOCJS.v + o_wm, MBAND);
			}
			// C
			if (JOK == 1)
			{
				JCUR.v = 0;
				this._dacopy.Run(MBAND, N.v, WM, LOCJS.v + o_wm, MBAND, ref WM, ML3 + o_wm, MEBAND);
			}
			// C
			// C Multiply Jacobian by scalar, add identity, and do LU decomposition.
			CON = -HRL1;
			this._dscal.Run(LENP, CON, ref WM, 3 + o_wm, 1);
			II = MBAND + 2;
			for (I = 1; I <= N.v; I++)
			{
				WM[II + o_wm] += ONE;
				II += MEBAND;
			}
			NLU.v += 1;
			this._dgbfa.Run(ref WM, 3 + o_wm, MEBAND, N.v, ML, MU, ref IWM, 31 + o_iwm
											, ref IER);
			if (IER != 0) IERPJ = 1;
			return;
			// C End of code block for MITER = 4 or 5. --------------------------------
			// C
			// C----------------------- End of Subroutine DVJAC -----------------------

			#endregion Body
		}