//, ref double[] D, ref double[] T)///Add 'D' term, for distance traveled laterally before exit. One number for each direction.
            public static Complex[][] Transfer_Matrix_Explicit_Alpha(bool freq_log, bool Rigid_Backed, int sample_Freq, double c_sound, List<ABS_Layer> LayerList, ref double[] frequency, ref Complex[] anglesdeg)
            {
                if (freq_log)
                {
                    //3rd octave band frequencies...
                    List<double> freq = new List<double>();
                    double f = 15.625;
                    int ct = 1;
                    while (f < sample_Freq / 2)
                    {
                        ct++;
                        f = 15.625 * Math.Pow(2, ct / 3);
                        freq.Add(f);
                    }
                    frequency = freq.ToArray();
                }
                else
                {
                    //Linear frequency scale
                    frequency = new double[4096];
                    double step = (sample_Freq / 2) / 4096;
                    for (int i = 0; i < frequency.Length; i++) frequency[i] = (i + .5) * step;
                }

                anglesdeg = new Complex[(int)(180 / 5)];

                double[] Angle = new double[anglesdeg.Length];
                Complex[][] sintheta_inc = new Complex[36][];
                Complex[][][] Angle_Inc = new Complex[LayerList.Count][][];
                Complex[] K_Air = AbsorptionModels.Operations.Air_Wavenumber(c_sound, frequency);
                Complex[] Zc_Air = AbsorptionModels.Operations.Air_CharImpedance(1.2, c_sound, frequency);

                for (double a = 2.5, i = 0; a <= 180; a += 5, i++)
                {
                    sintheta_inc[(int)i] = new Complex[frequency.Length];
                    anglesdeg[(int)i] = 90 - a;
                    if (a <= 90) Angle[(int)i] = (90 - a) * Utilities.Numerics.Pi_180;
                    sintheta_inc[(int)i][0] = Complex.Sin(a <= 90 ? Angle[(int)i] : Angle[36 - (int)i]);
                    for (int j = 1; j < sintheta_inc[(int)i].Length; j++) sintheta_inc[(int)i][j] = sintheta_inc[(int)i][0];
                }

                SparseMatrix[][][] T = new SparseMatrix[LayerList.Count][][];

                for (int a = 0; a < anglesdeg.Length; a++)
                {

                    //sintheta_trans[i][j] = K0[j] * sintheta_inc[i][j] / K[j];
                    //Kxi[i][j] = Complex.Sqrt(K[j] * K[j] * (1 - sintheta_trans[i][j] * sintheta_trans[i][j]));

                }

                for (int i = LayerList.Count - 1; i >= 0; i--)
                {
                    ABS_Layer Layer_i = (LayerList[i] as ABS_Layer);
                    T[i] = new SparseMatrix[anglesdeg.Length][];
                    for(int a = 0; a < anglesdeg.Length; a++)
                    {
                        T[i][a] = new SparseMatrix[4096];
                        double sintheta =  Math.Sin(Angle[a]);

                            switch (Layer_i.T)
                            {
                                case ABS_Layer.LayerType.AirSpace:
                                    for(int f = 0; f < 4096; f++)
                                    {
                                        Complex Ksintheta = K_Air[f] * sintheta;
                                        T[i][a][f] = Explicit_TMM.FluidMatrix(Layer_i.depth * 1000, Complex.Sqrt(K_Air[f] * K_Air[f] - Ksintheta * Ksintheta), frequency[f], 1.2);
                                    }
                                    break;
                                case ABS_Layer.LayerType.PorousDB:
                                    Complex[] Kdb = Equivalent_Fluids.DelaneyBazley_WNumber(1.2, c_sound, Layer_i.Flow_Resist, frequency);
                                    for(int f = 0; f < 4096; f++)
                                    {
                                        Complex Ksintheta = K_Air[f] * sintheta;
                                        T[i][a][f] = Explicit_TMM.FluidMatrix(Layer_i.depth, Complex.Sqrt(Kdb[f] * Kdb[f] - Ksintheta * Ksintheta), frequency[f], 1.2);
                                    }
                                    break;
                                case ABS_Layer.LayerType.PorousCA:
                                    Complex[] Kca = Equivalent_Fluids.DBAllardChampoux_WNumber(1.2, c_sound, Layer_i.Flow_Resist, frequency);
                                    for(int f = 0; f < 4096; f++)
                                    {
                                        Complex Ksintheta = K_Air[f] * sintheta;
                                        T[i][a][f] = Explicit_TMM.FluidMatrix(Layer_i.depth, Complex.Sqrt(Kca[f] * Kca[f] - Ksintheta * Ksintheta), frequency[f], 1.2);
                                    }
                                    break;
                                case ABS_Layer.LayerType.PorousM:
                                    Complex[] Km = Equivalent_Fluids.DB_Miki_WNumber(1.2, c_sound, Layer_i.Flow_Resist, frequency);
                                    for(int f = 0; f < 4096; f++)
                                    {
                                        //Complex Ksintheta = K_Air[f] * sintheta;
                                        T[i][a][f] = Explicit_TMM.FluidMatrix(Layer_i.depth, Complex.Sqrt(Km[f] * Km[f] * (1 - sintheta * sintheta)), frequency[f], 1.2);
                                    }
                                    break;
                                //case ABS_Layer.LayerType.Perforated_Modal:

                                //case ABS_Layer.LayerType.Slotted_Modal:

                                //case ABS_Layer.LayerType.CircularPerforations:

                                //case ABS_Layer.LayerType.SquarePerforations:

                                //case ABS_Layer.LayerType.Slots:

                                //case ABS_Layer.LayerType.MicroPerforated:

                                //case ABS_Layer.LayerType.Microslit:

                                default:
                                    throw new Exception("Unknown Layer Type");
                            }
                        }
                    }

                SparseMatrix[] I = new SparseMatrix[LayerList.Count];
                SparseMatrix[] J = new SparseMatrix[LayerList.Count];

                //SparseMatrix Yterm;

                //if ((int)LayerList[0].T <= 10)
                //{
                //    //Fluid Layer
                //    Yterm = Explicit_TMM.RigidTerminationF();
                //}
                //else if ((int)LayerList[0].T == 15 || (int)LayerList[0].T == 16)
                //{
                //    //Biot Porous absorbers
                //    Yterm = Explicit_TMM.RigidTerminationP();
                //}
                //else
                //{
                //    //Solid Layer
                //    Yterm = Explicit_TMM.RigidTerminationS();
                //}

                //Get Interface Matrices

                for (int i = 0; i < LayerList.Count; i++)
                {
                    if (i == LayerList.Count - 1)
                    {
                        if ((int)LayerList[i].T <= 10)
                        {
                            //Fluid Layer
                            I[i] = MathNet.Numerics.LinearAlgebra.Complex.SparseMatrix.CreateIdentity(2);
                            J[i] = MathNet.Numerics.LinearAlgebra.Complex.SparseMatrix.CreateIdentity(2);
                        }
                        else if ((int)LayerList[i].T == 15 || (int)LayerList[i].T == 16)
                        {
                            //Biot Porous absorbers
                            I[i] = Explicit_TMM.Interfacepf_Porous(LayerList[i].porosity);
                            J[i] = Explicit_TMM.Interfacepf_Fluid(LayerList[i].porosity);
                        }
                        else
                        {
                            //Solid Layer
                            I[i] = Explicit_TMM.InterfaceSF_Solid();
                            J[i] = Explicit_TMM.InterfaceSF_Fluid();
                        }
                        continue;
                    }

                    if ((int)LayerList[i].T <= 10)
                    {
                        //Fluid Layer
                        if ((int)LayerList[i + 1].T <= 10)
                        {
                            //Fluid Layer
                            I[i] = MathNet.Numerics.LinearAlgebra.Complex.SparseMatrix.CreateIdentity(2);
                            J[i] = MathNet.Numerics.LinearAlgebra.Complex.SparseMatrix.CreateIdentity(2);
                        }
                        else if ((int)LayerList[i + 1].T == 15 || (int)LayerList[i + 1].T == 16)
                        {
                            //Biot Porous absorbers
                            I[i] = Explicit_TMM.Interfacepf_Fluid(LayerList[i + 1].porosity) as SparseMatrix;
                            J[i] = Explicit_TMM.Interfacepf_Porous(LayerList[i + 1].porosity);
                        }
                        else
                        {
                            //Solid Layer
                            I[i] = SparseMatrix.CreateIdentity(4);
                            J[i] = SparseMatrix.CreateIdentity(4);
                        }
                    }
                    else if ((int)LayerList[i].T == 15 || (int)LayerList[i + 1].T == 16)
                    {
                        //Biot Porous absorbers
                        if ((int)LayerList[i + 1].T <= 10)
                        {
                            //Fluid Layer
                            I[i] = Explicit_TMM.Interfacepf_Porous(LayerList[i].porosity);
                            J[i] = Explicit_TMM.Interfacepf_Fluid(LayerList[i].porosity);
                        }
                        else if ((int)LayerList[i + 1].T == 15 || (int)LayerList[i + 1].T == 16)
                        {
                            //Biot Porous absorbers
                            I[i] = Explicit_TMM.InterfacePP(LayerList[i].porosity, LayerList[i + 1].porosity);//TODO: Check that we have the right porosities in the right places...
                            J[i] = SparseMatrix.CreateIdentity(6);
                        }
                        else
                        {
                            //Solid Layer
                            I[i] = Explicit_TMM.Interfacesp_Porous();
                            J[i] = Explicit_TMM.Interfacesp_Solid();
                        }

                    }
                    else
                    {
                        //Solid Layer
                        if ((int)LayerList[i + 1].T <= 10)
                        {
                            //Fluid Layer
                            I[i] = Explicit_TMM.InterfaceSF_Solid();
                            J[i] = Explicit_TMM.InterfaceSF_Fluid();
                        }
                        else if ((int)LayerList[i + 1].T == 15 || (int)LayerList[i + 1].T == 16)
                        {
                            //Biot Porous absorbers
                            I[i] = Explicit_TMM.Interfacesp_Solid();
                            J[i] = Explicit_TMM.Interfacesp_Porous();
                        }
                        else
                        {
                            //Solid Layer
                            I[i] = Explicit_TMM.InterfaceSF_Fluid() as SparseMatrix;
                            J[i] = Explicit_TMM.InterfaceSF_Solid();
                        }
                    }
                }
                //List<SparseMatrix[][]> T = Layer(LayerList.Count - 1, LayerList, K_Air, sintheta_inc, K_Air, c_sound, frequency);

                Complex[][] Z = new Complex[sintheta_inc.Length][];
                for (int a = 0; a < sintheta_inc.Length; a++)
                {
                    Z[a] = new Complex[sintheta_inc[a].Length];
                    for(int f = 0; f < sintheta_inc[a].Length; f++)
                    {
                        SparseMatrix V;
                        if (T.First()[a][f].RowCount == 2)
                        {
                            V = new SparseMatrix(2, 1);
                            V[0, 0] = 1;
                        }
                        else if (T.First()[a][f].RowCount == 4)
                        {
                            V = new SparseMatrix(4, 1);
                            V[0, 0] = 1;
                            V[1, 0] = 1;
                        }
                        else
                        {
                            V = new SparseMatrix(6, 1);
                            V[0, 0] = 1;
                            V[1, 0] = 1;
                            V[2, 0] = 1;
                        }

                        for (int i = 0; i < T.Length; i++)
                        {
                            V = -((J[i] * T[i][a][f]) * I[i].Inverse() as SparseMatrix) * V;
                            //V = T[i][a][f] * V;
                        }

                        V = -(J.Last() * I.Last().Inverse() as SparseMatrix) * V;

                        Z[a][f] = V[0, 0] * 100000 / V[1, 0];
                    }
                }

                return Z;
            }