// // rkckStep takes a Cash-Karp Runge-Kutta step // to estimate the error and the substance levels // after the attempted step. // private void rkckStep(double h) { double t = timer.getTime(); // step 1 for (int i = 0; i < numberOfSubstances; i++) { // // get the substance values before this step // y1[i] = s[i].getValue(); // // k1 = h * f(t, y); // k1[i] = h * s[i].getRate(); } // step 2 // // k2 = h * f (t + a2 * h, y + b21 * k1) // timer.setTime(t + a2 * h); for (int i = 0; i < numberOfSubstances; i++) { s[i].setValue(y1[i] + k1[i] * b21); k2[i] = h * s[i].getRate(); } // step 3 // // k3 = h * f (t + a3 * h, y + b31 * k1 + b32 * k2) // timer.setTime(t + a3 * h); for (int i = 0; i < numberOfSubstances; i++) { s[i].setValue(y1[i] + b31 * k1[i] + b32 * k2[i]); k3[i] = h * s[i].getRate(); } // step 4 // // k4 = h * f (t + a4 * h, y + b41 * k1 + b42 * k2 + b43 * k3) // timer.setTime(t + a4 * h); for (int i = 0; i < numberOfSubstances; i++) { s[i].setValue(y1[i] + b41 * k1[i] + b42 * k2[i] + b43 * k3[i]); k4[i] = h * s[i].getRate(); } // step 5 // k5 = h * f (t + a5 * h, y + b51 * k1 + b52 * k2 + b53 * k3 + b54 * // k4) // timer.setTime(t + a5 * h); for (int i = 0; i < numberOfSubstances; i++) { s[i].setValue(y1[i] + b51 * k1[i] + b52 * k2[i] + b53 * k3[i] + b54 * k4[i]); k5[i] = h * s[i].getRate(); } // step 6 // k6 = h * f (t + a6 * h, y + b61 * k1 + b62 * k2 + b63 * k3 + b64 * k4 // + k65 * k5) // timer.setTime(t + a5 * h); for (int i = 0; i < numberOfSubstances; i++) { s[i].setValue(y1[i] + b61 * k1[i] + b62 * k2[i] + b63 * k3[i] + b64 * k4[i] + b65 * k5[i]); k6[i] = h * s[i].getRate(); } for (int i = 0; i < numberOfSubstances; i++) { y2[i] = y1[i] + c1 * k1[i] + c3 * k3[i] + c4 * k4[i] + c6 * k6[i]; // fifth // order // estimate // // error between 4th and 5th // // note that the errors are scaled with respect to estimated new // values // if the new values are smaller than 1e-8, scale to 1e-8. This // number is // used to avoid scaling with respect to a number that is too small. // yerr[i] = Math.abs( (dc1 * k1[i] + dc3 * k3[i] + dc4 * k4[i] + dc5 * k5[i] + dc6 * k6[i]) / Math.max(Math.abs(y2[i]), 1e-8)); } }