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();
                }
            }
        }