/// <summary>
            ///
            /// </summary>
            /// <param name="Temp">temperature in Celsius</param>
            /// <param name="hr">relative humidity in percent</param>
            /// <param name="Pa">Pressure in Pascals</param>
            /// <param name="Air_Choice"></param>
            /// <param name="EdgeCorrection"></param>
            /// <param name="IsAcoustic"></param>
            public Scene(double Temp, double hr, double Pa, int Air_Choice, bool EdgeCorrection, bool IsAcoustic)
            {
                Custom_Method = IsAcoustic;
                Valid         = false;
                TempC_S       = Temp;
                Pa_S          = Pa; //TODO: Check that the pressure is in the correct units... hpa, kpa, pa.
                hr_S          = hr;
                AC_S          = Air_Choice;
                EdgeFC        = EdgeCorrection;
                R_Seed        = new Random();

                double TK = Temp + 273.15;
                //convert to Kelvins
                //Psat = Pr * 10 ^ (-6.8346 * (To1 / T) ^ 1.261 + 4.6151)
                double Psat = 101.325 * Math.Pow(10, (-6.8346 * Math.Pow((273.16 / TK), 1.261) + 4.6151));
                //6.1121 * Math.Exp((18.678 - T / 234.5) * TC / (257.14 + T))
                double h = hr * (Psat / Pa);

                Env_Prop = new Uniform_Medium(Air_Choice, Pa, TK, hr, EdgeCorrection);

                // Saturation water vapor pressure:
                // psv = exp(aa(1,1)*T^2 + aa(2,1)*T + aa(3,1) + aa(4,1)/T); % Formula Giacomo
                double psv = 101325 * Math.Pow(10, (4.6151 - 6.8346 * Math.Pow(((273.15 + 0.01) / (Temp + 273.15)), 1.261)));     // Formula ISO 9613-1:1993

                // Enhancement factor:
                double fpst = 1.00062 + 3.14e-8 * Atmospheric_Pressure + 5.6e-7 * Temp * Temp;

                // Mole fraction of water vapor in air:
                double xw = Relative_Humidity * psv * fpst / (100 * Atmospheric_Pressure);

                // Compressibility factor:
                double Z = 1 - Atmospheric_Pressure / (Temp + 273.15) * (1.58123e-6 + -2.9331e-8 * +1.1043e-10 * Temp * Temp + (5.707e-6 + -2.051e-8) * xw + (1.9898e-4 + -2.376e-6) * xw * xw) + Math.Pow((Atmospheric_Pressure / (Temp + 273.15)), 2) * (1.83e-11 + -0.765e-8 * xw * xw);

                //// Density of air:
                //rho = 3.48349 * 1e-3 * Atmospheric_Pressure / (Z * (Temp + 273.15)) * (1 - 0.3780 * xw);
            }
            public Finite_Material(Smart_Material Mat, Rhino.Geometry.Brep Br, Rhino.Geometry.Mesh M, int face_id, Medium_Properties med)
            {
                //Strictly for the flat X,Y case - oversimplified for now.
                Inf_Mat = Mat;
                Azimuth = new double[36];
                Altitude = new double[Mat.Angles.Length/2];
                alpha = new double[Altitude.Length][][];
                for(int i = 0; i < Altitude.Length; i++) Altitude[i] = Mat.Angles[i].Magnitude;
                for(int i = 0; i < Azimuth.Length; i++) Azimuth[i] = i * 360f / Azimuth.Length;

                    //Set up a frequency interpolated Zr for each direction individually.
                    Rhino.Geometry.Point3d pt = M.Faces.GetFaceCenter(face_id);

                    double[][][] ZrR = new double[Altitude.Length][][], ZrI = new double[Altitude.Length][][];
                    double[] fr = new double[9];
                    for (int k = 0; k < Altitude.Length; k++)
                    {
                        ZrR[k] = new double[Azimuth.Length][];
                        ZrI[k] = new double[Azimuth.Length][];
                        alpha[k] = new double[Azimuth.Length][];
                        for (int j = 0; j < Azimuth.Length; j++)
                        {
                            ZrR[k][j] = new double[9];
                            ZrI[k][j] = new double[9];
                            alpha[k][j] = new double[8];
                        }
                    }

                    for (int oct = 0; oct < 9; oct++)
                    {
                        fr[oct] = 62.5 * Math.Pow(2, oct) / Utilities.Numerics.rt2;
                        System.Numerics.Complex[][] Zr = AbsorptionModels.Operations.Finite_Radiation_Impedance_Rect_Longhand(pt.X, pt.Y, Br, fr[oct], Altitude, Azimuth, med.Sound_Speed(pt));

                        for (int k = 0; k < Zr.Length; k++)
                        {
                            for (int j = 0; j < Zr[k].Length; j++)
                            {
                                ZrR[k][j][oct] = Zr[k][j].Real;
                                ZrI[k][j][oct] = Zr[k][j].Imaginary;
                            }
                        }
                    }

                    MathNet.Numerics.Interpolation.CubicSpline[][] Zr_r = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];
                    MathNet.Numerics.Interpolation.CubicSpline[][] Zr_i = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];

                    for (int k = 0; k < Zr_r.Length; k++)
                    {
                        Zr_r[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                        Zr_i[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                        for (int j = 0; j < Zr_r[k].Length; j++)
                        {
                            //Interpolate over curve real and imaginary Zr here...
                            Zr_r[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrR[k][j]);
                            Zr_i[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrI[k][j]);
                        }
                    }

                    for (int k = 0; k < Zr_r.Length; k++)
                    {
                        for (int j = 0; j < Zr_r[k].Length; j++)
                        {
                            List<double> freq = new List<double>();
                            List<double> alpha_interp = new List<double>();
                            for (int l = 0; l < Mat.frequency.Length; l++)
                            {
                                if (Mat.frequency[l] > 10000) break;
                                freq.Add(Mat.frequency[l]);
                                alpha_interp.Add(AbsorptionModels.Operations.Finite_Unit_Absorption_Coefficient(Mat.Z[k][j], new System.Numerics.Complex(Zr_r[k][j].Interpolate(Mat.frequency[l]), Zr_i[k][j].Interpolate(Mat.frequency[l])), med.Rho(Utilities.PachTools.RPttoHPt(pt)), med.Sound_Speed(pt)));
                            }
                            MathNet.Numerics.Interpolation.CubicSpline a = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, alpha_interp);
                            for (int oct = 0; oct < 8; oct++)
                            {
                                alpha[k][j][oct] = 1 - a.Integrate(fr[oct], fr[oct + 1]) / (fr[oct + 1] - fr[oct]);
                            }
                        }
                    }
            }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="Temp">temperature in Celsius</param>
            /// <param name="hr">relative humidity in percent</param>
            /// <param name="Pa">Pressure in Pascals</param>
            /// <param name="Air_Choice"></param>
            /// <param name="EdgeCorrection"></param>
            /// <param name="IsAcoustic"></param>
            public Scene(double Temp, double hr, double Pa, int Air_Choice, bool EdgeCorrection, bool IsAcoustic)
            {
                Custom_Method = IsAcoustic;
                Valid = false;
                TempC_S = Temp;
                Pa_S = Pa;          //TODO: Check that the pressure is in the correct units... hpa, kpa, pa.
                hr_S = hr;
                AC_S = Air_Choice;
                EdgeFC = EdgeCorrection;
                R_Seed = new Random();

                double TK = Temp + 273.15;
                //convert to Kelvins
                //Psat = Pr * 10 ^ (-6.8346 * (To1 / T) ^ 1.261 + 4.6151)
                double Psat = 101.325 * Math.Pow(10, (-6.8346 * Math.Pow((273.16 / TK), 1.261) + 4.6151));
                //6.1121 * Math.Exp((18.678 - T / 234.5) * TC / (257.14 + T))
                double h = hr * (Psat / Pa);

                //C_Sound = Utilities.AcousticalMath.SoundSpeed(Temp);

                Env_Prop = new Uniform_Medium(Air_Choice, Pa, TK, hr, EdgeCorrection);

                // Saturation water vapor pressure:
                // psv = exp(aa(1,1)*T^2 + aa(2,1)*T + aa(3,1) + aa(4,1)/T); % Formula Giacomo
                double psv = 101325 * Math.Pow(10, (4.6151 - 6.8346 * Math.Pow(((273.15 + 0.01) / (Temp + 273.15)), 1.261)));     // Formula ISO 9613-1:1993

                // Enhancement factor:
                double fpst = 1.00062 + 3.14e-8 * Atmospheric_Pressure + 5.6e-7 * Temp * Temp;

                // Mole fraction of water vapor in air:
                double xw = Relative_Humidity * psv * fpst / (100 * Atmospheric_Pressure);

                // Compressibility factor:
                double Z = 1 - Atmospheric_Pressure / (Temp + 273.15) * (1.58123e-6 + -2.9331e-8 * +1.1043e-10 * Temp * Temp + (5.707e-6 + -2.051e-8) * xw + (1.9898e-4 + -2.376e-6) * xw * xw) + Math.Pow((Atmospheric_Pressure / (Temp + 273.15)), 2) * (1.83e-11 + -0.765e-8 * xw * xw);

                //// Density of air:
                //rho = 3.48349 * 1e-3 * Atmospheric_Pressure / (Z * (Temp + 273.15)) * (1 - 0.3780 * xw);

                //Get_Edges();
            }
            public Finite_Material(Smart_Material Mat, Rhino.Geometry.Brep Br, Rhino.Geometry.Mesh M, int face_id, Medium_Properties med)
            {
                //Strictly for the flat X,Y case - oversimplified for now.
                Inf_Mat  = Mat;
                Azimuth  = new double[36];
                Altitude = new double[Mat.Angles.Length / 2];
                alpha    = new double[Altitude.Length][][];
                for (int i = 0; i < Altitude.Length; i++)
                {
                    Altitude[i] = Mat.Angles[i].Magnitude;
                }
                for (int i = 0; i < Azimuth.Length; i++)
                {
                    Azimuth[i] = i * 360f / Azimuth.Length;
                }

                //Set up a frequency interpolated Zr for each direction individually.
                Rhino.Geometry.Point3d pt = M.Faces.GetFaceCenter(face_id);

                double[][][] ZrR = new double[Altitude.Length][][], ZrI = new double[Altitude.Length][][];
                double[]     fr  = new double[9];
                for (int k = 0; k < Altitude.Length; k++)
                {
                    ZrR[k]   = new double[Azimuth.Length][];
                    ZrI[k]   = new double[Azimuth.Length][];
                    alpha[k] = new double[Azimuth.Length][];
                    for (int j = 0; j < Azimuth.Length; j++)
                    {
                        ZrR[k][j]   = new double[9];
                        ZrI[k][j]   = new double[9];
                        alpha[k][j] = new double[8];
                    }
                }

                for (int oct = 0; oct < 9; oct++)
                {
                    fr[oct] = 62.5 * Math.Pow(2, oct) / Utilities.Numerics.rt2;
                    System.Numerics.Complex[][] Zr = AbsorptionModels.Operations.Finite_Radiation_Impedance_Rect_Longhand(pt.X, pt.Y, Br, fr[oct], Altitude, Azimuth, med.Sound_Speed(pt));

                    for (int k = 0; k < Zr.Length; k++)
                    {
                        for (int j = 0; j < Zr[k].Length; j++)
                        {
                            ZrR[k][j][oct] = Zr[k][j].Real;
                            ZrI[k][j][oct] = Zr[k][j].Imaginary;
                        }
                    }
                }

                MathNet.Numerics.Interpolation.CubicSpline[][] Zr_r = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];
                MathNet.Numerics.Interpolation.CubicSpline[][] Zr_i = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];

                for (int k = 0; k < Zr_r.Length; k++)
                {
                    Zr_r[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                    Zr_i[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                    for (int j = 0; j < Zr_r[k].Length; j++)
                    {
                        //Interpolate over curve real and imaginary Zr here...
                        Zr_r[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrR[k][j]);
                        Zr_i[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrI[k][j]);
                    }
                }

                for (int k = 0; k < Zr_r.Length; k++)
                {
                    for (int j = 0; j < Zr_r[k].Length; j++)
                    {
                        List <double> freq         = new List <double>();
                        List <double> alpha_interp = new List <double>();
                        for (int l = 0; l < Mat.frequency.Length; l++)
                        {
                            if (Mat.frequency[l] > 10000)
                            {
                                break;
                            }
                            freq.Add(Mat.frequency[l]);
                            alpha_interp.Add(AbsorptionModels.Operations.Finite_Unit_Absorption_Coefficient(Mat.Z[k][j], new System.Numerics.Complex(Zr_r[k][j].Interpolate(Mat.frequency[l]), Zr_i[k][j].Interpolate(Mat.frequency[l])), med.Rho(Utilities.PachTools.RPttoHPt(pt)), med.Sound_Speed(pt)));
                        }
                        MathNet.Numerics.Interpolation.CubicSpline a = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, alpha_interp);
                        for (int oct = 0; oct < 8; oct++)
                        {
                            alpha[k][j][oct] = 1 - a.Integrate(fr[oct], fr[oct + 1]) / (fr[oct + 1] - fr[oct]);
                        }
                    }
                }
            }