public void ODEImplicitRungeKutta5Jacobian() { //VAN DER POL'S EQUATION //In this example the OdeImplicitRungeKutta5 class is used to solve the van der Pol equation: //y''-mu*(1-y^2)*y'+y=0 //If y0=y and y1=y' then: //y'0 = y1, y0(0)= 2 //y'1 = ((1 - y0 ^2) * y1 - y0)/rpar, y1(0)=-0.66 //using DotNumerics.ODE OdeFunction YDot = new OdeFunction(VPol); OdeJacobian Jac = new OdeJacobian(JacVPol); OdeImplicitRungeKutta5 rungeKutta = new OdeImplicitRungeKutta5(YDot, Jac, 2); double[,] sol; double[] y0 = new double[2]; y0[0] = 2.0E0; y0[1] = -0.66E0; double x0 = 0; double xf = 2; sol = rungeKutta.Solve(y0, x0, 0.2, xf); for (int i = 0; i < sol.GetLength(0); i++) { ObjectDumper.Write("X = " + sol[i, 0].ToString() + " Y1 = " + sol[i, 1].ToString() + " Y2 = " + sol[i, 2].ToString()); } //private double[] VPol(double T, double[] Y) //{ // double[] ydot = new double[2]; // double rpar = 1.0E-6; // ydot[0] = Y[1]; // ydot[1] = ((1 - Math.Pow(Y[0], 2)) * Y[1] - Y[0]) / rpar; // return ydot; //} //public double[,] JacVPol(double T, double[] Y) //{ // double[,] jacobian = new double[2, 2]; // double rpar = 1.0E-6; // jacobian[0, 0] = 0.0E0; // jacobian[0, 1] = 1.0E0; // jacobian[1, 0] = (-2.0E0 * Y[0] * Y[1] - 1.0E0) / rpar; // jacobian[1, 1] = (1.0E0 - Math.Pow(Y[0], 2)) / rpar; // return jacobian; //} }
private void button_Run_Click(object sender, EventArgs e) { /***************** Defining initial conditions **************/ d_p_i = Convert.ToDouble(textBox_d_p_i.Text) * Math.Pow(10, -6); // Initial droplet diameter [m]: T_d_i = Convert.ToDouble(textBox_T_d_i.Text); // Initial temperature of the droplet [K]: T_inf_i = Convert.ToDouble(textBox_T_inf_i.Text); // Initial temperature of the surrounding air [K]: phi_inf_i = Convert.ToDouble(textBox_phi_inf_i.Text); // Initial relative humidity of surrounding air [RH]: double V_a = Convert.ToDouble(textBox_V_a.Text) * Math.Pow(10, -3); // Volume flow rate of air [m^3/s]: double V_w = Convert.ToDouble(textBox_V_w.Text) * Math.Pow(10, -6); // Volume flow rate of water [m^3/s]: double tf = Convert.ToDouble(textBox_tf.Text); // Evaluation time double delta_t = Convert.ToDouble(textBox_delta_t.Text); // Time step /***************** Calculation of initial water vapour pressure **************/ // Saturation pressure calculation (2007, P.T. Tsilingiris) [Pa]: double p_s_i = (0.7073 - 2.7036E-2 * (T_inf_i - 273.15) + 4.3609E-3 * Math.Pow(T_inf_i - 273.15, 2) - 4.6626E-5 * Math.Pow(T_inf_i - 273.15, 3) + 1.0347E-6 * Math.Pow(T_inf_i - 273.15, 4) ) * Math.Pow(10, 3); p_inf_i = phi_inf_i * p_s_i / 100; // Initial water vapour pressure in the surrounding air [Pa]: /***************ODE Solver*********************/ OdeFunction YDot = new OdeFunction(Equation); OdeImplicitRungeKutta5 rungeKutta = new OdeImplicitRungeKutta5(YDot, 4); double[] y0 = new double[4]; y0[0] = d_p_i; y0[1] = T_d_i; y0[2] = p_inf_i; y0[3] = T_inf_i; double x0 = 0; double xf = tf; /**************Solution out********************/ /*************Error handler*********************/ this.label_Error.Text = "Error: no error"; try { sol = rungeKutta.Solve(y0, x0, delta_t, xf); //Solution identifier which is 0 if the droplets do not fully evaporate droplet_evaporated = 0; } catch { //Error lable this.label_Error.Text = "Error: Droplet evaporated"; //Solution identifier which is 1 if the droplets do fully evaporate droplet_evaporated = 1; } if (droplet_evaporated == 0) { /***************Printing number of datapoints**********/ solLength = sol.GetLength(0); string input1 = solLength.ToString(); this.textBox_number_of_data_points.Text = ""; this.textBox_number_of_data_points.Text = input1; /*********************Converting data*******************/ //Creating arrays to store datapoints tValues = new double[solLength]; d_pValues = new double[solLength]; t_dValues = new double[solLength]; p_infValues = new double[solLength]; T_infValues = new double[solLength]; //Storing datapoints in arrays for (int i = 0; i < solLength; i++) { tValues[i] = sol[i, 0]; d_pValues[i] = sol[i, 1]; t_dValues[i] = sol[i, 2]; p_infValues[i] = sol[i, 3]; T_infValues[i] = sol[i, 4]; } //Claculating evaporation percentage double evaporation = 100 - ((4 / 3 * Math.PI * Math.Pow((d_pValues[solLength - 1] * Math.Pow(10, 6)) / 2, 3)) / (4 / 3 * Math.PI * Math.Pow((d_p_i * Math.Pow(10, 6)) / 2, 3)) * 100); //Calculating relative humidity double relativeHumidity = (p_infValues[solLength - 1] / ( (0.7073 - 2.7036E-2 * (T_infValues[solLength - 1] - 273.15) + 4.3609E-3 * Math.Pow(T_infValues[solLength - 1] - 273.15, 2) - 4.6626E-5 * Math.Pow(T_infValues[solLength - 1] - 273.15, 3) + 1.0347E-6 * Math.Pow(T_infValues[solLength - 1] - 273.15, 4) ) * Math.Pow(10, 3) )) * 100; //phi_inf = (Y[2] / p_s) * 100; // Data with two decimal points double d_p_end = Math.Truncate(d_pValues[solLength - 1] * Math.Pow(10, 8)) / 100; double t_d_end = Math.Truncate(t_dValues[solLength - 1] * 100) / 100; double T_inf_end = Math.Truncate(T_infValues[solLength - 1] * 100) / 100; double T_inf_diff = Math.Truncate((T_infValues[0] - T_infValues[solLength - 1]) * 100) / 100; double p_inf_end = Math.Truncate(p_infValues[solLength - 1] * 100) / 100; double evap_end = Math.Truncate(evaporation * 100) / 100; double phi_inf_end = Math.Truncate(relativeHumidity * 100) / 100; // Printing end result string d_p_end_str = d_p_end.ToString(); string t_d_end_str = t_d_end.ToString(); string T_inf_end_str = T_inf_end.ToString(); string T_inf_diff_str = T_inf_diff.ToString(); string p_inf_end_str = p_inf_end.ToString(); string evap_end_str = evap_end.ToString(); string phi_inf_end_str = phi_inf_end.ToString(); this.textBox_d_p_end.Text = ""; this.textBox_d_p_end.Text = d_p_end_str; this.textBox_T_d_end.Text = ""; this.textBox_T_d_end.Text = t_d_end_str; this.textBox_T_inf_end.Text = ""; this.textBox_T_inf_end.Text = T_inf_end_str; this.textBox_T_inf_diff.Text = ""; this.textBox_T_inf_diff.Text = T_inf_diff_str; this.textBox_p_inf_end.Text = ""; this.textBox_p_inf_end.Text = p_inf_end_str; this.textBox_evap_end.Text = ""; this.textBox_evap_end.Text = evap_end_str; this.textBox_phi_inf_end.Text = ""; this.textBox_phi_inf_end.Text = phi_inf_end_str; //Converting datapoints to input units d_pValues_mum = new double[solLength]; multi = 1000000; for (int i = 0; i < solLength; i++) { d_pValues_mum[i] = d_pValues[i] * multi; } // Clearing charts foreach (var series in chart_all.Series) { series.Points.Clear(); } // Populating chart with datapoints for (int i = 0; i < solLength; i++) { chart_all.Series["Droplet diameter"].Points.AddXY(tValues[i], d_pValues_mum[i]); chart_all.Series["Droplet temperature"].Points.AddXY(tValues[i], t_dValues[i]); } // Setting Y-axis values on upper chart chart_all.ChartAreas[0].AxisY.Maximum = d_pValues_mum[0] + (d_pValues_mum[0] / 10); chart_all.ChartAreas[0].AxisY.Minimum = d_pValues_mum[solLength - 1] - (d_pValues_mum[solLength - 1] / 10); // Setting Y-axis values on lower chart chart_all.ChartAreas[1].AxisY.Maximum = T_inf_i + (T_inf_i / 100); chart_all.ChartAreas[1].AxisY.Minimum = t_dValues[solLength - 1] - (t_dValues[solLength - 1] / 100); // Setting axis decimals and lable on upper chart chart_all.ChartAreas[0].AxisX.LabelStyle.Format = "#.#"; chart_all.ChartAreas[0].AxisY.LabelStyle.Format = "#"; chart_all.ChartAreas[0].AxisX.Title = "Time [s]"; chart_all.ChartAreas[0].AxisY.Title = "Droplet diameter [μm]"; // Setting axis decimals and lable on lower chart chart_all.ChartAreas[1].AxisX.LabelStyle.Format = "#.#"; chart_all.ChartAreas[1].AxisY.LabelStyle.Format = "#"; chart_all.ChartAreas[1].AxisX.Title = "Time [s]"; chart_all.ChartAreas[1].AxisY.Title = "Droplet temperature [K]"; } else { //Printing N/A in the result boxes this.textBox_d_p_end.Text = ""; this.textBox_d_p_end.Text = "N/A"; this.textBox_T_d_end.Text = ""; this.textBox_T_d_end.Text = "N/A"; this.textBox_T_inf_end.Text = ""; this.textBox_T_inf_end.Text = "N/A"; this.textBox_p_inf_end.Text = ""; this.textBox_p_inf_end.Text = "N/A"; this.textBox_evap_end.Text = ""; this.textBox_evap_end.Text = "N/A"; this.textBox_phi_inf_end.Text = ""; this.textBox_phi_inf_end.Text = "N/A"; this.textBox_number_of_data_points.Text = ""; this.textBox_number_of_data_points.Text = "N/A"; // Clearing charts foreach (var series in chart_all.Series) { series.Points.Clear(); } } }