Beispiel #1
0
        // Wake Code - Matlab
        // Rasmus Christensen
        // Control and Automation, Aalborg University

        // N_turb = number of turbines.
        // X_turb = x-position of turbine.
        // Y_turb = y-position of turbine.
        #endregion
        internal static void ROTATE_corrd(out ILArray<double> out_x, out ILArray<double> out_y, ILArray<double> xTurb, ILArray<double> yTurb, double rotA)
        {
            #region "Used variables declaration"
            ILArray<double> x_out;
            ILArray<double> y_out;
            int i;
            #endregion

            x_out = zeros(1, length(xTurb)); // Initialization x-coordinates
            y_out = zeros(1, length(yTurb)); // Initialization y-coordinates
    
            rotA = rotA * pi / 180; // Conversion to radians

            for (i = 1; i <= length(xTurb); i++)
            {
                x_out._(i, '=', xTurb._(i) * cos(rotA) - xTurb._(i) * sin(rotA));
                y_out._(i, '=', xTurb._(i) * sin(rotA) + yTurb._(i) * cos(rotA));
            }

            if (min_(x_out) < 0) // Moves the x-points if these are negative.
            {
                x_out = x_out + 500 + abs(min_(x_out));
            }

            if (min_(y_out) < 0) // Moves the y-points if these are negative.
            {
                y_out = y_out + 500 + abs(min_(y_out));
            }
    
	        out_x = x_out;
	        out_y = y_out;
        }
Beispiel #2
0
        // Wake Code - Matlab
        // Rasmus Christensen
        // Control and Automation, Aalborg University

        // N_turb = number of turbines.
        // X_turb = x-position of turbine.
        // Y_turb = y-position of turbine.
        #endregion
        internal static void ROTATE_corrd(out ILArray <double> out_x, out ILArray <double> out_y, ILArray <double> xTurb, ILArray <double> yTurb, double rotA)
        {
            #region "Used variables declaration"
            ILArray <double> x_out;
            ILArray <double> y_out;
            int i;
            #endregion

            x_out = zeros(1, length(xTurb)); // Initialization x-coordinates
            y_out = zeros(1, length(yTurb)); // Initialization y-coordinates

            rotA = rotA * pi / 180;          // Conversion to radians

            for (i = 1; i <= length(xTurb); i++)
            {
                x_out._(i, '=', xTurb._(i) * cos(rotA) - xTurb._(i) * sin(rotA));
                y_out._(i, '=', xTurb._(i) * sin(rotA) + yTurb._(i) * cos(rotA));
            }

            if (min_(x_out) < 0) // Moves the x-points if these are negative.
            {
                x_out = x_out + 500 + abs(min_(x_out));
            }

            if (min_(y_out) < 0) // Moves the y-points if these are negative.
            {
                y_out = y_out + 500 + abs(min_(y_out));
            }

            out_x = x_out;
            out_y = y_out;
        }
Beispiel #3
0
        //P_ref is a vector of power refenreces for tehe wind turbine with dimension 1xN
        //v_nac is a vector of wind speed at each wind turbine with dimension 1xN
        //P_demand is a scale of the wind farm power demand.
        //parm is a struct of wind turbine parameters e.g. NREL5MW
        #endregion
        internal static void powerDistributionControl(out ILArray <double> P_ref, out ILArray <double> P_a, double[] v_nac, double P_demand, WindTurbineParameters parm)
        {
            #region "Used variables declaration"
            double           rho;
            ILArray <double> R;
            ILArray <double> rated;
            ILArray <double> Cp;
            int i;
            #endregion

            rho   = parm.rho;               //air density for each wind turbine(probably the same for all)
            R     = parm.radius.C;          //rotor radius for each wind turbine(NREL.r=63m)
            rated = parm.rated.C;           //Rated power for each wind turbine(NREL.Prated=5MW)
            Cp    = parm.Cp.C;              // Max cp of the turbines for each wind turbine(NREL.Cp.max=0.45)

            P_a   = zeros(parm.N, 1);
            P_ref = zeros(parm.N, 1);

            // Compute available power at each turbine
            for (i = 1; i <= parm.N; i++)
            {
                P_a._(i, '=', min_(__[rated._(i), (pi / 2) * rho * _p(R._(i), 2) * _p(v_nac[i - 1], 3) * Cp._(i)]));
            }

            var sum_P_a_ = sum_(P_a);

            //Distribute power according to availibility
            for (i = 1; i <= parm.N; i++)
            {
                if (P_demand < sum_P_a_)
                {
                    P_ref._(i, '=', max_(__[0, min_(__[rated._(i), P_demand * P_a._(i) / sum_P_a_])]));
                }
                else
                {
                    P_ref._(i, '=', P_a._(i));
                }
            }
        }
        //P_ref is a vector of power refenreces for tehe wind turbine with dimension 1xN
        //v_nac is a vector of wind speed at each wind turbine with dimension 1xN
        //P_demand is a scale of the wind farm power demand.
        //parm is a struct of wind turbine parameters e.g. NREL5MW
        #endregion
        internal static void powerDistributionControl(out ILArray<double> P_ref, out ILArray<double> P_a, double[] v_nac, double P_demand, WindTurbineParameters parm)
        {
            #region "Used variables declaration"
            double rho;
            ILArray<double> R;
            ILArray<double> rated;
            ILArray<double> Cp;
            int i;
            #endregion

            rho = parm.rho;                 //air density for each wind turbine(probably the same for all)
            R = parm.radius.C;              //rotor radius for each wind turbine(NREL.r=63m)
            rated = parm.rated.C;           //Rated power for each wind turbine(NREL.Prated=5MW)
            Cp = parm.Cp.C;                 // Max cp of the turbines for each wind turbine(NREL.Cp.max=0.45)

            P_a = zeros(parm.N, 1);
            P_ref = zeros(parm.N, 1);

            // Compute available power at each turbine
            for (i = 1; i <= parm.N; i++)
            {
                P_a._(i, '=', min_(__[ rated._(i), (pi / 2) * rho * _p(R._(i), 2) * _p(v_nac[i - 1], 3) * Cp._(i) ]));
            }

            var sum_P_a_ = sum_(P_a);

            //Distribute power according to availibility
            for (i = 1; i <= parm.N; i++)
            {
                if (P_demand < sum_P_a_)
                {
                    P_ref._(i, '=', max_(__[ 0, min_(__[ rated._(i), P_demand * P_a._(i) / sum_P_a_ ]) ]));
                }
                else
                {
                    P_ref._(i, '=', P_a._(i));
                }
            }
        }
        // Wake Code - Matlab
        // Rasmus Christensen
        // Control and Automation, Aalborg University
        #endregion
        internal static void Turb_centr_coord(out ILArray<int> output, int nTurb, int iMax, ILArray<double> x, ILArray<double> xTurb, int gridRes)
        {
            #region "Used variables declaration"
            ILArray<int> xxcTurb;
            int i;
            int ii;
            #endregion

            xxcTurb = zeros_(1, nTurb);

            for (i = 1; i <= nTurb; i++)
            {
                for (ii = 1; ii <= iMax - 1; ii++)
                {
                    if (abs(x._(ii)) <= abs(xTurb._(i)) && abs(xTurb._(i)) < abs(x._(ii + 1)))
                    {
                        xxcTurb._(i, '=', ii * sign(xTurb._(i)));
                        break;
                    }
                }
            }
            output = xxcTurb;
        }
Beispiel #6
0
        // Wake Code - Matlab
        // Rasmus Christensen
        // Control and Automation, Aalborg University
        #endregion
        internal static void Turb_centr_coord(out ILArray <int> output, int nTurb, int iMax, ILArray <double> x, ILArray <double> xTurb, int gridRes)
        {
            #region "Used variables declaration"
            ILArray <int> xxcTurb;
            int           i;
            int           ii;
            #endregion

            xxcTurb = zeros_(1, nTurb);

            for (i = 1; i <= nTurb; i++)
            {
                for (ii = 1; ii <= iMax - 1; ii++)
                {
                    if (abs(x._(ii)) <= abs(xTurb._(i)) && abs(xTurb._(i)) < abs(x._(ii + 1)))
                    {
                        xxcTurb._(i, '=', ii * sign(xTurb._(i)));
                        break;
                    }
                }
            }
            output = xxcTurb;
        }
Beispiel #7
0
        internal static void wakeCalculation(out ILArray <double> v_nac, ILArray <double> Ct, int i, ILArray <double> wind)
        {
            #region "Original function comments"
            //% v_nac = WAKECALCULATION(Ct,i,wind)
            //This function calculates the wake
            //Currently it is a very very simplified wake calculation. It just serves as
            //a placeholder for a correct wake calculation that will come later
            #endregion

            #region "Used variables declaration"
            ILArray <double> scaling;
            #endregion

            scaling = linspace(0.5, 0.9, length(Ct));
            v_nac   = scaling * wind._(i, 2);
        }
        internal static void wakeCalculation(out ILArray<double> v_nac, ILArray<double> Ct, int i, ILArray<double> wind)
        {
            #region "Original function comments"
            //% v_nac = WAKECALCULATION(Ct,i,wind)
            //This function calculates the wake
            //Currently it is a very very simplified wake calculation. It just serves as
            //a placeholder for a correct wake calculation that will come later
            #endregion

            #region "Used variables declaration"
            ILArray<double> scaling;
            #endregion

            scaling = linspace(0.5, 0.9, length(Ct));
            v_nac = scaling * wind._(i, 2);
        }
        //% v_nac = WAKECALCULATION(Ct,i,wind)
        // RLC, Aalborg
        // The below is based on the .F90 code developed by ?, and will give a
        // better estimate of the actual wake the individual turbines experience.
        #endregion
        internal static void wakeCalculationsRLC(out ILArray <double> vNac, double dTurb, int nTurb, double kWake, ILArray <double> x, int gridX, int gridY, ILArray <double> yOrder, double dy, ILArray <int> xTurbC, ILArray <int> yTurbC, ILArray <double> Ct, ILArray <double> wField, double[] vHub, WindTurbineParameters parm, SimParm simParm)
        {
            #region "Used variables declaration"
            double[,] Velocity;
            int j;
            #endregion

            // Velocity Computation
            Compute_Vell(out Velocity, yOrder, xTurbC, yTurbC, x, wField, vHub, kWake, gridX, gridY, nTurb, dTurb, Ct, dy);

            // Extracting the individual Nacelle Wind Speeds from the wind velocity matrix.
            //Velocity = Velocity';
            vNac = zeros(nTurb, 1);

            for (j = 1; j <= length(xTurbC); j++)
            {
                vNac._(j, '=', Velocity[yTurbC._(j) - 1, xTurbC._(j) - 1]);
            }
        }
        //% v_nac = WAKECALCULATION(Ct,i,wind)
        // RLC, Aalborg
        // The below is based on the .F90 code developed by ?, and will give a
        // better estimate of the actual wake the individual turbines experience. 
        #endregion
        internal static void wakeCalculationsRLC(out ILArray<double> vNac, double dTurb, int nTurb, double kWake, ILArray<double> x, int gridX, int gridY, ILArray<double> yOrder, double dy, ILArray<int> xTurbC, ILArray<int> yTurbC, ILArray<double> Ct, ILArray<double> wField, double[] vHub, WindTurbineParameters parm, SimParm simParm)
        {
            #region "Used variables declaration"
            double[,] Velocity;
            int j;
            #endregion

            // Velocity Computation
            Compute_Vell(out Velocity, yOrder, xTurbC, yTurbC, x, wField, vHub, kWake, gridX, gridY, nTurb, dTurb, Ct, dy);

            // Extracting the individual Nacelle Wind Speeds from the wind velocity matrix.
            //Velocity = Velocity';
            vNac = zeros(nTurb, 1);

            for (j = 1; j <= length(xTurbC); j++)
            {
                vNac._(j, '=', Velocity[yTurbC._(j) - 1, xTurbC._(j) - 1]);
            }
        }
Beispiel #11
0
        //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        // DESCRIPTION:
        // RLC - 8/9/2014, interpolation, for getting an accurate CP/CT value. The
        // reason for a standalone script, is that the built in MATLAB script
        // (interp) includes a lot of redundancy checks that are not necessary, and
        // not feasible for embedded solutions.
        // Based on the NREL5MW Turbine.
        // Uses Linear Polynomial Extrapolation, to get a value for CP, given a Beta
        // (Revolutional speed) and Lambda (Tip-Speed-Ratio) of the Turbine.
        // The interpolation is computed as:
        // y = y0 + (y1 - y0)*(x-x0)/(x1-x0)
        //
        // Beta is the revolutional entry.
        // Lambda is the TSR entry ratio.
        // turbineTable defines the table to lookup in.
        // negYes defines wether the CP value should be allowed to be negative.
        //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        #endregion
        internal static void interpTable(out double interpValue, double Beta, double Lambda, ILArray <double> table, ILArray <double> turbineTableBeta, ILArray <double> turbineTableLambda, bool negYes)
        {
            #region "Used variables declaration"
            ILArray <double> turbineTable;
            int sizeBt;
            int sizeLa;
            int Bt0;
            int Bt1;
            int La0;
            int La1;
            ILArray <double> tableLookup;
            ILArray <double> lambdaIntervals;
            double           betaIntervals;
            #endregion

            //% Setup, loads the table, and stores it.
            //persistent turbineTable tableLoad

            //if isempty(tableLoad)
            turbineTable = table.C;
            //    tableLoad           = 1;
            //end

            size(out sizeBt, out sizeLa, turbineTable);

            //% Index Interpolation
            // Finds the beta-point of the interpolation.
            min(out Bt0, abs(turbineTableBeta - Beta));  // Determines the index of the closest point.

            if (Beta > turbineTableBeta._(Bt0))
            {
                if (Bt0 == sizeBt) //length(turbineTableBeta)
                {
                    Bt1 = Bt0;
                    Bt0 = Bt0 - 1;
                }
                else
                {
                    Bt1 = Bt0 + 1;
                }
            }
            else
            {
                if (Bt0 == 1)
                {
                    Bt1 = Bt0 + 1;
                }
                else
                {
                    Bt1 = Bt0;
                    Bt0 = Bt1 - 1;
                }
            }

            // Finds the Lambda-point of the interpolation.
            min(out La0, abs(turbineTableLambda - Lambda)); // Determines the index of the closest point.

            if (Lambda > turbineTableLambda._(La0))
            {
                if (La0 == sizeLa) //length(turbineTableLambda)
                {
                    La1 = La0;
                    La0 = La1 - 1;
                }
                else
                {
                    La1 = La0 + 1;
                }
            }
            else
            {
                if (La0 == 1)
                {
                    La1 = La0 + 1;
                }
                else
                {
                    La1 = La0;
                    La0 = La1 - 1;
                }
            }

            //% Table Interpolation
            // Table lookup using indexes obtained previously:
            tableLookup = __[turbineTable._(Bt0, La0), turbineTable._(Bt0, La1), ';',
                             turbineTable._(Bt1, La0), turbineTable._(Bt1, La1)];

            // Interpolating, using the Lambda values first, then the Betas.
            lambdaIntervals = __[((tableLookup._(1, 2) - tableLookup._(1, 1)) / (turbineTableLambda._(La1) - turbineTableLambda._(La0))) * (Lambda - turbineTableLambda._(La0)) + tableLookup._(1, 1), ';',
                                 ((tableLookup._(2, 2) - tableLookup._(2, 1)) / (turbineTableLambda._(La1) - turbineTableLambda._(La0))) * (Lambda - turbineTableLambda._(La0)) + tableLookup._(1, 2)];

            // Interpolation, using the Beta values (using the intervales computed above).
            betaIntervals = ((lambdaIntervals._(2) - lambdaIntervals._(1)) / (turbineTableBeta._(Bt1) - turbineTableBeta._(Bt0))) * (Beta - turbineTableBeta._(Bt0)) + lambdaIntervals._(1);

            //% Negativity Handling
            // If the negYes value is set as true in the system, the functino will only
            // give an absolute value of Ct and Cp - have to be modified so it does this
            // correctly.

            if (negYes)
            {
                interpValue = 0;
            }
            else
            {
                interpValue = betaIntervals;
            }
        }
Beispiel #12
0
        // Wake Simulation
        // (C) Rasmus Christensen
        // Control and Automation, Aalborg University 2014

        // Compute the velocity in front of each wind-turbine, with respect to the wind input.
        #endregion
        internal static void Compute_Vell(out double[,] vel_output, ILArray <double> yTurb, ILArray <int> xTurbC, ILArray <int> yTurbC, ILArray <double> x, ILArray <double> wField, double[] Uhub, double kWake, int iMax, int jMax, int nTurb, double dTurb, ILArray <double> Ct, double dy)
        {
            #region "Used variables declaration"
            double[,] vell_i;
            ILArray <double> shadow;
            double           r0;
            double           nk;
            int    k;
            int    J;
            double SS;
            double SS0;
            int    i;
            double RR_i;
            double Dij;
            double Alpha_i;
            double Alpha_k;
            double Area;
            int    ii;
            double rrt;
            double nj;
            int    jjMin;
            int    jjMax;
            #endregion


            //vell_i = wField.C;
            vell_i = new double[wField.Size[0], wField.Size[1]];
            for (var i0 = 0; i0 < vell_i.GetLength(0); i0++)
            {
                for (var i1 = 0; i1 < vell_i.GetLength(1); i1++)
                {
                    vell_i[i0, i1] = wField.GetValue(i0, i1);
                }
            }

            shadow = zeros(1, nTurb);

            r0 = 0.5 * dTurb;
            nk = 2 * ceil(dTurb / dy);

            for (k = 1; k <= nTurb; k++)
            {
                J   = 0;
                SS  = 0;
                SS0 = pi * r0 * r0;

                for (i = 1; i <= k - 1; i++)
                {
                    RR_i = r0 + kWake * (x._(xTurbC._(k)) - x._(xTurbC._(i)));
                    Dij  = abs(yTurb._(i) - yTurb._(k));

                    if ((RR_i >= (r0 + Dij)) || (Dij <= dy))
                    {
                        SS = SS + ((r0 * r0) / (RR_i * RR_i));
                    }
                    else
                    {
                        if (RR_i >= (r0 + Dij) && Dij > dy)
                        {
                            J       = J + 1;
                            Alpha_i = acos((RR_i * RR_i) + (Dij * Dij) - (r0 * r0) / (2 * RR_i * Dij));
                            Alpha_k = acos(((r0 * r0) + (Dij * Dij) - (RR_i * RR_i)) / (2 * r0 * Dij));
                            AArea(out Area, RR_i, r0, Dij);
                            shadow._(J, '=', (Alpha_i * (RR_i * RR_i) + Alpha_k * (r0 * r0)) - 2 * Area);
                            SS = SS + ((shadow._(J)) / SS0) * ((r0 * r0) / (RR_i * RR_i));
                        }
                    }
                }

                for (ii = xTurbC._(k); ii <= iMax; ii++)
                {
                    rrt = r0 + kWake * (x._(ii) - x._(xTurbC._(k)));
                    nj  = ceil(rrt / dy);

                    jjMin = floor_(max(1, yTurbC._(k) - nj));
                    jjMax = ceil_(min(jMax, yTurbC._(k) + nj));

                    for (var j = jjMin; j <= jjMax; j++)
                    {
                        if (((-vell_i[ii - 1, j - 1] + Uhub[k - 1]) > 0) && (ii > xTurbC._(k) + nk))
                        {
                            vell_i[ii - 1, j - 1] = min(vell_i[ii - 2, j - 1], Uhub[k - 1] + Uhub[k - 1] * (sqrt(1 - Ct._(k)) - 1) * ((r0 * r0) / (rrt * rrt)) * (1 - (1 - sqrt(1 - Ct._(k))) * SS));
                            vell_i[ii - 1, j - 1] = max(0, vell_i[ii - 1, j - 1]);
                        }
                        else
                        {
                            vell_i[ii - 1, j - 1] = (Uhub[k - 1] + Uhub[k - 1] * (sqrt(1 - Ct._(k)) - 1) * (r0 / rrt) * (r0 / rrt)) * (1 - (1 - sqrt(1 - Ct._(k))) * SS);
                            vell_i[ii - 1, j - 1] = max(0, vell_i[ii - 1, j - 1]);
                        }
                    }
                }
            }

            vel_output = vell_i;
        }
Beispiel #13
0
        internal static void NowCastWFPFunc(out string outMethod, out ILArray<double> outTime, out ILArray<double> outX, out ILArray<double> outXhmsAll, out int outXhmsAllTimeOffset, out int outXhmsLLength, out int outXhmsUOffset, ILArray<double> Data, double TPredict = TPredictDef, string Method = MethodDef, int r = rDef, double Ts = TsDef)
        {
            #region "Original function comments"
            //Nowcasting with  model based on total wind farm power
            //
            // NowCastWFPFunc(Data,TPredict,Method,r,Ts)
            //
            // Data : Total wind farm power
            // TPredict : Time for starting multi step prediction.  If TPredict<1 it
            //            is assumed  a fraction of the end time (default 0.5)
            // Method : 'AR(1)' or 'Persistence' only first letter count (default 'a')
            // r : Decimation with a moving average of order r (default 1)
            // Ts : Sampling time (default 0.1)
            // 
            // External input: None

            // Time-stamp: <2014-10-17 14:09:40 tk>
            // Version 1: Initial version
            // Torben Knudsen
            // Aalborg University, Dept. of Electronic Systems, Section of Automation
            // and Control
            // E-mail: [email protected]
            #endregion

            #region "Used variables declaration"
            int IMT;
            double q0;
            double TauLambdaLRel;
            double Lambda0;
            double TauLambdaInf;
            double TimeScaling;
            //string TitleStr;
            int NS;
            ILArray<double> T;
            ILArray<double> TimePlot;
            double NWT;
            double NomWFP;
            ILArray<double> PWF;
            double MinWFP;
            double TauLambdaL;
            double LambdaL;
            double LambdaInf;
            int TPS;
            ILArray<double> Theta;
            ILArray<double> Sigma;
            ILArray<double> Xh;
            ILArray<double> Lambda;
            ILArray<int> Time;
            ILArray<double> Res;
            int TPSEst;
            double A;
            double B;
            ILArray<double> xhms;
            ILArray<double> covxhms;
            double aux;
            int i;
            ILArray<double> q;
            double xh;
            double xt;
            double dt;
            ILArray<double> sigmaxhms;
            ILArray<double> ConIntAWFP;
            int NS10Min;
            int NSOneHour;
            #endregion

            //% setting up inputs
            //TsDef = 0.1;
            //rDef = 1;
            //MethodDef = "a";
            //TPredictDef = 0.5;
            //if nargin < 5; Ts= []; end;
            //if nargin < 4; r= []; end;
            //if nargin < 3; Method= []; end;
            //if nargin < 2; TPredict= []; end;
            //if nargin < 1; error('Error TK: To few input arguments'); end;
            //if isempty(r); r= rDef; end;
            //if isempty(TPredict); TPredict= TPredictDef; end;
            //if isempty(Ts); Ts= TsDef; end;
            //if isempty(Method); Method= MethodDef; end;

            //% Parameters

            IMT = 1;                                    // Include measurement time;
            q0 = 0;
            TauLambdaLRel = 0.1;                        // TauLambdaL= 10% of the samples
            Lambda0 = 0.5;                              // Initial Lambda
            TauLambdaInf= 600;                          // TauLambdaInf= 10min
            TimeScaling = 1.0 / 3600;                   // From seconds to hours

            //% Initialization

            // Use Offwind simulation data made by Rasmus 2014-10-14
            // The format is:
            // [time sumPower sumRef sumAvai] as a matrix NS x 4.  Power i MW
            // 48 WT are simulated.  Data for individual WT are also found e.g. in
            // Power, P_ref, PA, beta etc
            if (strncmpi(Method, "a", 1))
            {
                Method = "AR(1)";
            }
            else
            {
                Method = "Persistence";
            }
            //TitleStr = "Nowcasting with " + Method + " model based on total wind farm " //...
            //            + "power, Offwind simulation";
            Data = Data[_(':')];
            NS = size(Data, 1);                        // Number of samples
            NS = max_(find(Data > 0));         // Number of samples;
            Data = Data[_(1, ':', NS)];                 // Limit the data
            T = Ts * (_c(1, NS)).T;
            TimePlot = T * TimeScaling;                   // Time in hours
            NWT = 48;
            NomWFP = NWT * 5e6 * 1e-6;               // Power in MW
            PWF = Data;                     // Total Power in MW
            if (r > 1)
            {
                DecimateWMA(out PWF, out _ILArray_double, PWF, r);
                NS = size(PWF, 1);                        // Number of samples
                Ts = Ts * r;
                T = Ts * (_c(1, NS)).T;
                TimePlot = T * TimeScaling;                   // Time in hours
            }
            MinWFP = 0;                            // For real WFs


            //% Definitions etc.

            // Calculate Lamba* from TauLambda* and dt
            TauLambdaL = TauLambdaLRel * (T._(end) - T._(1));// TauLambdaL= 10% of the samples
            LambdaL = exp(-Ts / TauLambdaL);
            LambdaInf = exp(-Ts / TauLambdaInf);

            //% Algorithm

            // Initialization

            // Prediction from time in TPredict
            // if TPredict is a fraction calculate TPredict
            if (TPredict < 1)
            {
                TPredict = round(TPredict * T._(end) / Ts) * Ts;
            }
            if (TPredict < TauLambdaInf)
            {
                warning(__[ "TK: Prediction time is so small that the estimator/predictor ", //...
                            "might not have converged yet" ]);
            }
            TPS = min_(find(T >= TPredict));            // Use time from measurements

            // Multi step prediction
            if (strncmpi(Method, "a", 1))
            {
                // ARX1 version;
                // Recursive parameter estimation
                RLSMARX1(out Theta, out Sigma, out Xh, out Lambda, out Time, out _ILArray_double, out _ILArray_double, out _ILArray_double, PWF, 1, LambdaInf);
                Res = __[ TimePlot[_(Time)], PWF[_(Time)], Xh, Sigma, Lambda ];
                Res = __[ nan(Time._(1) - 1, size(Res, 2)), ';', Res ];

                // Notice that length of Time is shorter than length of T if batch RLS
                // start is used so TPSEst < TPS in that case
                TPSEst = min_(find(_dbl(Time) * Ts >= TPredict));      // Use time from estimates
  
                // Parameter values must be taken for index TPSEst
                A = Theta._(TPSEst, 1);
                if (abs(A) > 1)
                {
                    warning(__[ "TK: Unstable pole, max(abs(eig)): ", num2str(abs(A)) ]);
                }
                B = Theta._(TPSEst, 2);
                xhms = zeros(NS - TPS, 1);
                covxhms = zeros(NS - TPS, 1);
                xhms._(1, '=', Xh._(TPSEst + 1));
                covxhms._(1, '=', Sigma._(TPSEst + 1));
                aux = Sigma._(TPSEst + 1);
                for (i = 2; i <= NS - TPS; i++)
                {
                    xhms._(i, '=', A * xhms._(i - 1) + B);
                    aux = A * aux * A.T();
                    covxhms._(i, '=', covxhms._(i - 1) + aux);
                }

                // Prepend xhms with the present measurement so the plot clearly indicates
                // the time for the measurement
            }
            else
            {
                // Persistence version;
                // Initialization
                Lambda = Lambda0;
                q = q0;
                xh = PWF._(1);
                Res = __[ T._(1), PWF._(1), xh, q, Lambda0 ];

                // Recursive estimation of incremental covariance
                for (i = 2; i <= NS; i++)
                {
                    xt = PWF._(i) - xh;
                    dt = T._(i) - T._(i - 1);
                    q = _m(Lambda, '*', q) + (1 - Lambda) * _p(xt, 2) / dt;
                    Res = __[ Res, ';', __[ T._(i), PWF._(i), xh, q, Lambda ] ];
                    Lambda = LambdaL * Lambda + (1 - LambdaL) * LambdaInf;
                    xh = PWF._(i);
                }
                Res[_(':'), _(1)] = Res[_(':'), _(1)] * TimeScaling;

                // Persistence version;
                xhms = Res._(TPS + 1, 3) * ones(NS - TPS, 1);
                covxhms = Res._(TPS + 1, 4) * Ts * ((_c(1, NS - TPS)).T);
            }

            if (IMT != 0)
            {
                xhms = __[ PWF._(TPS), ';', xhms ];
                covxhms = __[ 0, ';', covxhms ];
            }
            sigmaxhms = sqrt(covxhms);
            ConIntAWFP = _m(xhms, '*', __[ 1, 1, 1 ]) + _m(sigmaxhms, '*', __[ -2, 0, 2 ]);
            ConIntAWFP = min(max(ConIntAWFP, MinWFP), NomWFP); // Limit confidence limits

            // Plot results
            // Plot actual as black solid and lower, prediction and upper confidence
            // limits as red, green and blue solid for 10 min, dashed for one hour and
            // dotted for the rest.
            //figure;
            NS10Min = min(NS - TPS - 1, round_(600.0 / Ts));
            NSOneHour = min(NS - TPS - 1, round_(3600.0 / Ts));
            //set(gcf, "defaultaxescolororder", ILMath.eye(3, 3));
            outMethod = Method;
            outTime = TimePlot;
            outX = Res[_(':'), _(2)];
            outXhmsAll = ConIntAWFP;
            outXhmsAllTimeOffset = (TPS - IMT);
            outXhmsLLength = (NS10Min + IMT);
            outXhmsUOffset = (NSOneHour + IMT);
            //plot(
            //    TimePlot, Res[ILMath.full, 2 - 1], 'k',///...
            //    TimePlot[ILMath.r(TPS + 1 - IMT - 1, TPS + NS10Min - 1)], ConIntAWFP[ILMath.r(1 - 1, NS10Min + IMT - 1), ILMath.full],//...
            //    TimePlot[ILMath.r(TPS + NS10Min + 1 - 1, TPS + NSOneHour - 1)], ConIntAWFP[_a(NS10Min + 1, 1, NSOneHour) + IMT - 1, ILMath.full], "--",//...
            //    TimePlot[ILMath.r(TPS + NSOneHour + 1 - 1, ILMath.end)], ConIntAWFP[ILMath.r(NSOneHour + 1 + IMT - 1, ILMath.end), ILMath.full], ':');
            //title(TitleStr);
            //Legend= {'x' 'xhmsL' 'xhms' 'xhmsU'};
            //legend(Legend);
            //grid('on');
        }
Beispiel #14
0
        private static void RLSMARX1(out ILArray<double> Theta, out ILArray<double> Sigma, out ILArray<double> Xh, out ILArray<double> Lambda, out ILArray<int> Time, out ILArray<double> AByTime, out ILArray<double> BByTime, out ILArray<double> SigmaByTime, ILArray<double> X, ILArray<double> U = null, ILArray<double> lambda = null, ILArray<double> theta0 = null, ILArray<double> sigma0 = null, int Plot = PlotDef)
        {
            #region "Original function comments"
            //RLS calculates recursive least squares parameter estimates corresponding
            // to the output input data X U and the model x(n+1)= A*x(n)+B*u(n)+e(n)
            // <=> x(n+1)'= [x(n)' u(n)']*[A'; B']+e(n)
            // Duble exponential forgetting can be used where lamba increases
            // exponentielly from lamba0 to lambda.
            //
            // [Theta,Sigma,Xh,Lambda,Time]= RLSMARX1(X,U,lambda,theta0,sigma0)
            //
            // X: Output Matrix with size number of samples * number of channels
            // U: Input Matrix with size number of samples * number of channels
            //    zero scalar/matrix corresponds to no input, ones corresponds to estimating
            //    a mean value parameter. (default ones)
            // lambda : Forgetting factor (default 0.99) if lambda= [lambda lambda0]
            //          the forgetting factor increases exponentially from lambda0 
            //          to lambda.
            // theta0 : Initial parameter estimate. Notice that theta0= [A0';B0'];
            // sigma0 : Initial covvariance estimate.  
            //          If no initial parameters are specifyed a offline/batch
            //          estimate is used for the start.
            // Plot   : If 1/true plot informative plots (default: false)
            //
            // External input: 

            // Time-stamp: <2014-10-17 11:44:27 tk>
            // Version 1: 2014-10-01 app.
            // Version 2: 2014-10-02 12:53:07 tk Included LS/offline/batch startup
            // Version 3: 2014-10-07 13:57:54 tk Included additional output and
            //            plotting
            // Torben Knudsen
            // Aalborg University, Dept. of Electronic Systems, Section of Automation
            // and Control
            // E-mail: [email protected]
            #endregion

            #region "Used variables declaration"
            double TauLambdaLRel;
            double lambdaInf;
            double lambda0;
            double IniNumSampFrac;
            int N;
            int n;
            int m;
            double TauLambdaL;
            double lambdaL;
            ILArray<double> sigma;
            ILArray<double> theta;
            int NIni;
            ILArray<double> XX;
            ILArray<double> YY;
            ILArray<double> R;
            ILArray<double> Epsilon;
            ILArray<double> xh;
            ILArray<double> Res;
            int i;
            ILArray<double> phi;
            ILArray<double> epsilon;
            #endregion

            //% setting up inputs
            //UDef = 1;
            //lambdaDef = 0.99;
            //theta0Def = 0;
            //sigma0Def = 0;
            //PlotDef = 0;
            //if (nargin < 6) { Plot = []; }
            if (sigma0 == null) { sigma0 = __[' ']; }
            if (theta0 == null) { theta0 = __[' ']; }
            if (lambda == null) { lambda = __[' ']; }
            if (U == null) { U = __[' ']; }
            //if (nargin < 1) { error('Error TK: To few input arguments'); }
            if (isempty(U)) { U = UDef; }
            //if (isempty(Plot)) { Plot = PlotDef; }
            if (isempty(lambda)) { lambda = lambdaDef; }
            if (isempty(theta0)) { theta0 = theta0Def; }
            if (isempty(sigma0)) { sigma0 = sigma0Def; }

            //% Parameters

            TauLambdaLRel = 0.1;                     // TauLambdaL= 10% of the samples
            lambdaInf = lambda._(1);
            if (length(lambda) > 1)                    // Initial lambda;
            {
                lambda0 = lambda._(2);
            }
            else
            {
                lambda0 = lambdaInf;                           
            }
            IniNumSampFrac = 0.1;                    // Number of samples to use for init

            //% Definitions etc.

            N = size(X, 1);
            n = size(X, 2);
            m = size(U, 2);
            // Calculate Lamba* from TauLambda* assuming Ts= 1
            TauLambdaL = TauLambdaLRel * N;
            lambdaL = exp(-1.0 / TauLambdaL);
            if (all(U == 1))
            {
                U = ones(N, 1);
            }

            //% Algorithm

            // Initialisation
            if (all(all(sigma0 == 0)))                 // No sigma0 specifyed
            {
                sigma = 0 * eye(n);
            }
            else
            {
                sigma = sigma0;
            }
            if (all(all(theta0 == 0)))                 // No sigma0 specifyed
            {
                theta = zeros(n + m, n);
            }
            else
            {
                theta = theta0;
            }

            // Start with a offline estimate if initial parameters are not specifyed
            if (all(__[ theta0, ';', sigma0 ] == 0))
            {
                NIni = max(n + 1, ceil_(N * IniNumSampFrac));
                XX = __[ X[_(1, ':', NIni - 1), _(':')], U[_(1, ':', NIni - 1), _(':')] ];
                YY = X[_(_c_(1, NIni - 1) + 1), _(':')];
                R = _m(XX.T, '*', XX);
                theta = _m(_m(inv(R), '*', (XX.T)), '*', YY);
                Epsilon = YY - _m(XX, '*', theta);
                sigma = _m(Epsilon.T, '*', Epsilon) / NIni;
                xh = _m(XX[_(end), _(':')], '*', theta);
            }
            else
            {
                NIni = 1;
                xh = X[_(1), _(':')];
                R = 1e6 * eye(n);
            }

            lambda = lambda0;
            Res = __[ NIni, (theta[_(':')]).T, (sigma[_(':')]).T, xh, lambda ];

            AByTime = zeros(n, n, N - NIni + 1);
            AByTime[_(':'), _(':'), _(1)] = (theta[_(1, ':', n), _(1, ':', n)]).T;
            BByTime = zeros(n, m, N - NIni + 1);
            BByTime[_(':'), _(':'), _(1)] = (theta[_(n + 1, ':', n + m), _(1, ':', n)]).T;
            SigmaByTime = zeros(n, n, N - NIni + 1);
            SigmaByTime[_(':'), _(':'), _(1)] = sigma;

            // Recursion
            // Model x(n+1)= A*x(n)+B*u(n)+e(n) <=>
            // x(n+1)'= [x(n)' u(n)']*[A'; B']+e(n)
            for (i = NIni + 1; i <= N; i++)
            {
                phi = (__[ X[_(i - 1), _(':')], U[_(i - 1), _(':')] ]).T;           // phi(i)
                R = (lambda._Scalar()) * R + _m(phi, '*', (phi.T));                 // R(i)
                xh = _m((phi.T), '*', theta);                       // xh(i)
                epsilon = X[_(i), _(':')] - xh;                   // epsilon(i)
                theta = theta + _m(_s(R, '\\', phi), '*', epsilon);           // theta(i)
                sigma = _m(lambda, '*', sigma) + _m(_m((1 - lambda), '*', (epsilon.T)), '*', epsilon);
                Res = __[ Res, ';', __[ i, theta[_(':')].T, sigma[_(':')].T, xh, lambda ] ];
                lambda = lambdaL * lambda + (1 - lambdaL) * lambdaInf;
                AByTime[_(':'), _(':'), _(i - NIni + 1)] = (theta[_(1, ':', n), _(1, ':', n)]).T; // Index start at 2
                BByTime[_(':'), _(':'), _(i - NIni + 1)] = (theta[_(n + 1, ':', n + m), _(1, ':', n)]).T;
                SigmaByTime[_(':'), _(':'), _(i - NIni + 1)] = sigma;
            }
            // Res is organised like 
            // i theta(:)' sigma(:)' xh lambda with the dimensions
            // 1 (n+m)*n   n^2       n   1
            Time = _int(Res[_(':'), _(1)]);
            Theta = Res[_(':'), _(1 + 1, ':', 1 + (n + m) * n)];
            Sigma = Res[_(':'), _(1 + 1 + (n + m) * n, ':', 1 + (n + m) * n + _p_(n, 2))];
            Xh = Res[_(':'), _(1 + 1 + (n + m) * n + _p_(n, 2), ':', 1 + (n + m) * n + _p_(n, 2) + n)];
            Lambda = Res[_(':'), _(1 + 1 + (n + m) * n + _p_(n, 2) + n, ':', end)];

            // Do informative plotting and output
            //if (Plot)
            //{
            //    figure;
            //    plot([U X]);
            //    title('Input and measurements');
            //    figure;
            //    plot(Time,reshape(AByTime,n*n,N-NIni+1)');
            //    title('A parameters');
            //    figure;
            //    plot(Time,reshape(BByTime,n*m,N-NIni+1)');
            //    title('B parameters');
            //    figure;
            //    plot(Time,reshape(SigmaByTime,n*n,N-NIni+1)');
            //    title('Sigma parameters');
            //    figure;
            //    plot(Time,Lambda);
            //    title('Lambda');
            //    Epsilon= X(Time,:)-Xh;
            //    Epsilon= Epsilon(100:end,:);
            //    figure;
            //    XCorrtkAll(Epsilon);
            //    figure;
            //    normplot(Epsilon);
            //    gridtk('on',figures);
            //    Lab= ['Final parameters A n*n B n*m Sigma n*n'];
            //    RowLab= {''};
            //    ColLab= {''};
            //    Res= [AByTime(:,:,end) BByTime(:,:,end) SigmaByTime(:,:,end)];
            //    printmattk(Res,Lab);
            //}
        }
Beispiel #15
0
        internal static void NowCastWFPFunc(out string outMethod, out ILArray <double> outTime, out ILArray <double> outX, out ILArray <double> outXhmsAll, out int outXhmsAllTimeOffset, out int outXhmsLLength, out int outXhmsUOffset, ILArray <double> Data, double TPredict = TPredictDef, string Method = MethodDef, int r = rDef, double Ts = TsDef)
        {
            #region "Original function comments"
            //Nowcasting with  model based on total wind farm power
            //
            // NowCastWFPFunc(Data,TPredict,Method,r,Ts)
            //
            // Data : Total wind farm power
            // TPredict : Time for starting multi step prediction.  If TPredict<1 it
            //            is assumed  a fraction of the end time (default 0.5)
            // Method : 'AR(1)' or 'Persistence' only first letter count (default 'a')
            // r : Decimation with a moving average of order r (default 1)
            // Ts : Sampling time (default 0.1)
            //
            // External input: None

            // Time-stamp: <2014-10-17 14:09:40 tk>
            // Version 1: Initial version
            // Torben Knudsen
            // Aalborg University, Dept. of Electronic Systems, Section of Automation
            // and Control
            // E-mail: [email protected]
            #endregion

            #region "Used variables declaration"
            int    IMT;
            double q0;
            double TauLambdaLRel;
            double Lambda0;
            double TauLambdaInf;
            double TimeScaling;
            //string TitleStr;
            int NS;
            ILArray <double> T;
            ILArray <double> TimePlot;
            double           NWT;
            double           NomWFP;
            ILArray <double> PWF;
            double           MinWFP;
            double           TauLambdaL;
            double           LambdaL;
            double           LambdaInf;
            int TPS;
            ILArray <double> Theta;
            ILArray <double> Sigma;
            ILArray <double> Xh;
            ILArray <double> Lambda;
            ILArray <int>    Time;
            ILArray <double> Res;
            int              TPSEst;
            double           A;
            double           B;
            ILArray <double> xhms;
            ILArray <double> covxhms;
            double           aux;
            int              i;
            ILArray <double> q;
            double           xh;
            double           xt;
            double           dt;
            ILArray <double> sigmaxhms;
            ILArray <double> ConIntAWFP;
            int              NS10Min;
            int              NSOneHour;
            #endregion

            //% setting up inputs
            //TsDef = 0.1;
            //rDef = 1;
            //MethodDef = "a";
            //TPredictDef = 0.5;
            //if nargin < 5; Ts= []; end;
            //if nargin < 4; r= []; end;
            //if nargin < 3; Method= []; end;
            //if nargin < 2; TPredict= []; end;
            //if nargin < 1; error('Error TK: To few input arguments'); end;
            //if isempty(r); r= rDef; end;
            //if isempty(TPredict); TPredict= TPredictDef; end;
            //if isempty(Ts); Ts= TsDef; end;
            //if isempty(Method); Method= MethodDef; end;

            //% Parameters

            IMT           = 1;                          // Include measurement time;
            q0            = 0;
            TauLambdaLRel = 0.1;                        // TauLambdaL= 10% of the samples
            Lambda0       = 0.5;                        // Initial Lambda
            TauLambdaInf  = 600;                        // TauLambdaInf= 10min
            TimeScaling   = 1.0 / 3600;                 // From seconds to hours

            //% Initialization

            // Use Offwind simulation data made by Rasmus 2014-10-14
            // The format is:
            // [time sumPower sumRef sumAvai] as a matrix NS x 4.  Power i MW
            // 48 WT are simulated.  Data for individual WT are also found e.g. in
            // Power, P_ref, PA, beta etc
            if (strncmpi(Method, "a", 1))
            {
                Method = "AR(1)";
            }
            else
            {
                Method = "Persistence";
            }
            //TitleStr = "Nowcasting with " + Method + " model based on total wind farm " //...
            //            + "power, Offwind simulation";
            Data     = Data[_(':')];
            NS       = size(Data, 1);        // Number of samples
            NS       = max_(find(Data > 0)); // Number of samples;
            Data     = Data[_(1, ':', NS)];  // Limit the data
            T        = Ts * (_c(1, NS)).T;
            TimePlot = T * TimeScaling;      // Time in hours
            NWT      = 48;
            NomWFP   = NWT * 5e6 * 1e-6;     // Power in MW
            PWF      = Data;                 // Total Power in MW
            if (r > 1)
            {
                DecimateWMA(out PWF, out _ILArray_double, PWF, r);
                NS       = size(PWF, 1);                  // Number of samples
                Ts       = Ts * r;
                T        = Ts * (_c(1, NS)).T;
                TimePlot = T * TimeScaling;        // Time in hours
            }
            MinWFP = 0;                            // For real WFs


            //% Definitions etc.

            // Calculate Lamba* from TauLambda* and dt
            TauLambdaL = TauLambdaLRel * (T._(end) - T._(1));// TauLambdaL= 10% of the samples
            LambdaL    = exp(-Ts / TauLambdaL);
            LambdaInf  = exp(-Ts / TauLambdaInf);

            //% Algorithm

            // Initialization

            // Prediction from time in TPredict
            // if TPredict is a fraction calculate TPredict
            if (TPredict < 1)
            {
                TPredict = round(TPredict * T._(end) / Ts) * Ts;
            }
            if (TPredict < TauLambdaInf)
            {
                warning(__["TK: Prediction time is so small that the estimator/predictor ",  //...
                           "might not have converged yet"]);
            }
            TPS = min_(find(T >= TPredict));            // Use time from measurements

            // Multi step prediction
            if (strncmpi(Method, "a", 1))
            {
                // ARX1 version;
                // Recursive parameter estimation
                RLSMARX1(out Theta, out Sigma, out Xh, out Lambda, out Time, out _ILArray_double, out _ILArray_double, out _ILArray_double, PWF, 1, LambdaInf);
                Res = __[TimePlot[_(Time)], PWF[_(Time)], Xh, Sigma, Lambda];
                Res = __[nan(Time._(1) - 1, size(Res, 2)), ';', Res];

                // Notice that length of Time is shorter than length of T if batch RLS
                // start is used so TPSEst < TPS in that case
                TPSEst = min_(find(_dbl(Time) * Ts >= TPredict));      // Use time from estimates

                // Parameter values must be taken for index TPSEst
                A = Theta._(TPSEst, 1);
                if (abs(A) > 1)
                {
                    warning(__["TK: Unstable pole, max(abs(eig)): ", num2str(abs(A))]);
                }
                B       = Theta._(TPSEst, 2);
                xhms    = zeros(NS - TPS, 1);
                covxhms = zeros(NS - TPS, 1);
                xhms._(1, '=', Xh._(TPSEst + 1));
                covxhms._(1, '=', Sigma._(TPSEst + 1));
                aux = Sigma._(TPSEst + 1);
                for (i = 2; i <= NS - TPS; i++)
                {
                    xhms._(i, '=', A * xhms._(i - 1) + B);
                    aux = A * aux * A.T();
                    covxhms._(i, '=', covxhms._(i - 1) + aux);
                }

                // Prepend xhms with the present measurement so the plot clearly indicates
                // the time for the measurement
            }
            else
            {
                // Persistence version;
                // Initialization
                Lambda = Lambda0;
                q      = q0;
                xh     = PWF._(1);
                Res    = __[T._(1), PWF._(1), xh, q, Lambda0];

                // Recursive estimation of incremental covariance
                for (i = 2; i <= NS; i++)
                {
                    xt     = PWF._(i) - xh;
                    dt     = T._(i) - T._(i - 1);
                    q      = _m(Lambda, '*', q) + (1 - Lambda) * _p(xt, 2) / dt;
                    Res    = __[Res, ';', __[T._(i), PWF._(i), xh, q, Lambda]];
                    Lambda = LambdaL * Lambda + (1 - LambdaL) * LambdaInf;
                    xh     = PWF._(i);
                }
                Res[_(':'), _(1)] = Res[_(':'), _(1)] * TimeScaling;

                // Persistence version;
                xhms    = Res._(TPS + 1, 3) * ones(NS - TPS, 1);
                covxhms = Res._(TPS + 1, 4) * Ts * ((_c(1, NS - TPS)).T);
            }

            if (IMT != 0)
            {
                xhms    = __[PWF._(TPS), ';', xhms];
                covxhms = __[0, ';', covxhms];
            }
            sigmaxhms  = sqrt(covxhms);
            ConIntAWFP = _m(xhms, '*', __[1, 1, 1]) + _m(sigmaxhms, '*', __[-2, 0, 2]);
            ConIntAWFP = min(max(ConIntAWFP, MinWFP), NomWFP); // Limit confidence limits

            // Plot results
            // Plot actual as black solid and lower, prediction and upper confidence
            // limits as red, green and blue solid for 10 min, dashed for one hour and
            // dotted for the rest.
            //figure;
            NS10Min   = min(NS - TPS - 1, round_(600.0 / Ts));
            NSOneHour = min(NS - TPS - 1, round_(3600.0 / Ts));
            //set(gcf, "defaultaxescolororder", ILMath.eye(3, 3));
            outMethod            = Method;
            outTime              = TimePlot;
            outX                 = Res[_(':'), _(2)];
            outXhmsAll           = ConIntAWFP;
            outXhmsAllTimeOffset = (TPS - IMT);
            outXhmsLLength       = (NS10Min + IMT);
            outXhmsUOffset       = (NSOneHour + IMT);
            //plot(
            //    TimePlot, Res[ILMath.full, 2 - 1], 'k',///...
            //    TimePlot[ILMath.r(TPS + 1 - IMT - 1, TPS + NS10Min - 1)], ConIntAWFP[ILMath.r(1 - 1, NS10Min + IMT - 1), ILMath.full],//...
            //    TimePlot[ILMath.r(TPS + NS10Min + 1 - 1, TPS + NSOneHour - 1)], ConIntAWFP[_a(NS10Min + 1, 1, NSOneHour) + IMT - 1, ILMath.full], "--",//...
            //    TimePlot[ILMath.r(TPS + NSOneHour + 1 - 1, ILMath.end)], ConIntAWFP[ILMath.r(NSOneHour + 1 + IMT - 1, ILMath.end), ILMath.full], ':');
            //title(TitleStr);
            //Legend= {'x' 'xhmsL' 'xhms' 'xhmsU'};
            //legend(Legend);
            //grid('on');
        }
Beispiel #16
0
        //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        // DESCRIPTION:
        // RLC - 8/9/2014, interpolation, for getting an accurate CP/CT value. The
        // reason for a standalone script, is that the built in MATLAB script
        // (interp) includes a lot of redundancy checks that are not necessary, and
        // not feasible for embedded solutions. 
        // Based on the NREL5MW Turbine.
        // Uses Linear Polynomial Extrapolation, to get a value for CP, given a Beta
        // (Revolutional speed) and Lambda (Tip-Speed-Ratio) of the Turbine. 
        // The interpolation is computed as:
        // y = y0 + (y1 - y0)*(x-x0)/(x1-x0)
        //
        // Beta is the revolutional entry.
        // Lambda is the TSR entry ratio. 
        // turbineTable defines the table to lookup in. 
        // negYes defines wether the CP value should be allowed to be negative.
        //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        #endregion
        internal static void interpTable(out double interpValue, double Beta, double Lambda, ILArray<double> table, ILArray<double> turbineTableBeta, ILArray<double> turbineTableLambda, bool negYes)
        {
            #region "Used variables declaration"
            ILArray<double> turbineTable;
            int sizeBt;
            int sizeLa;
            int Bt0;
            int Bt1;
            int La0;
            int La1;
            ILArray<double> tableLookup;
            ILArray<double> lambdaIntervals;
            double betaIntervals;
            #endregion

            //% Setup, loads the table, and stores it.
            //persistent turbineTable tableLoad

            //if isempty(tableLoad)
                turbineTable        = table.C;
            //    tableLoad           = 1;
            //end

            size(out sizeBt, out sizeLa, turbineTable);

            //% Index Interpolation
            // Finds the beta-point of the interpolation.
            min(out Bt0, abs(turbineTableBeta - Beta));  // Determines the index of the closest point.

            if (Beta > turbineTableBeta._(Bt0))
            {
                if (Bt0 == sizeBt) //length(turbineTableBeta)
                {
                    Bt1 = Bt0;
                    Bt0 = Bt0 - 1;
                }
                else
                {
                    Bt1 = Bt0 + 1;
                }
            }
            else
            {
                if (Bt0 == 1)
                {
                    Bt1 = Bt0 + 1;
                }
                else
                {
                    Bt1 = Bt0;
                    Bt0 = Bt1 - 1;
                }
            }

            // Finds the Lambda-point of the interpolation.
            min(out La0, abs(turbineTableLambda - Lambda)); // Determines the index of the closest point.

            if (Lambda > turbineTableLambda._(La0))
                if (La0 == sizeLa) //length(turbineTableLambda)
                {
                    La1 = La0;
                    La0 = La1 - 1;
                }
                else
                {
                    La1 = La0 + 1;
                }
            else
            {
                if (La0 == 1)
                {
                    La1 = La0 + 1;
                }
                else
                {
                    La1 = La0;
                    La0 = La1 - 1;
                }
            }

            //% Table Interpolation
            // Table lookup using indexes obtained previously:
            tableLookup     = __[ turbineTable._(Bt0, La0), turbineTable._(Bt0, La1), ';',
                                  turbineTable._(Bt1, La0), turbineTable._(Bt1, La1) ];

            // Interpolating, using the Lambda values first, then the Betas.
            lambdaIntervals = __[ ( (tableLookup._(1, 2) - tableLookup._(1, 1)) / (turbineTableLambda._(La1) - turbineTableLambda._(La0)) ) * (Lambda - turbineTableLambda._(La0)) + tableLookup._(1, 1), ';',
                                  ( (tableLookup._(2, 2) - tableLookup._(2, 1)) / (turbineTableLambda._(La1) - turbineTableLambda._(La0)) ) * (Lambda - turbineTableLambda._(La0)) + tableLookup._(1, 2) ];

            // Interpolation, using the Beta values (using the intervales computed above).
            betaIntervals   = ( (lambdaIntervals._(2) - lambdaIntervals._(1)) / (turbineTableBeta._(Bt1) - turbineTableBeta._(Bt0)) ) * (Beta - turbineTableBeta._(Bt0)) + lambdaIntervals._(1);

            //% Negativity Handling
            // If the negYes value is set as true in the system, the functino will only
            // give an absolute value of Ct and Cp - have to be modified so it does this
            // correctly.

            if (negYes)
            {
                interpValue = 0;
            }
            else
            {
                interpValue = betaIntervals;
            }
        }
Beispiel #17
0
        private static void RLSMARX1(out ILArray <double> Theta, out ILArray <double> Sigma, out ILArray <double> Xh, out ILArray <double> Lambda, out ILArray <int> Time, out ILArray <double> AByTime, out ILArray <double> BByTime, out ILArray <double> SigmaByTime, ILArray <double> X, ILArray <double> U = null, ILArray <double> lambda = null, ILArray <double> theta0 = null, ILArray <double> sigma0 = null, int Plot = PlotDef)
        {
            #region "Original function comments"
            //RLS calculates recursive least squares parameter estimates corresponding
            // to the output input data X U and the model x(n+1)= A*x(n)+B*u(n)+e(n)
            // <=> x(n+1)'= [x(n)' u(n)']*[A'; B']+e(n)
            // Duble exponential forgetting can be used where lamba increases
            // exponentielly from lamba0 to lambda.
            //
            // [Theta,Sigma,Xh,Lambda,Time]= RLSMARX1(X,U,lambda,theta0,sigma0)
            //
            // X: Output Matrix with size number of samples * number of channels
            // U: Input Matrix with size number of samples * number of channels
            //    zero scalar/matrix corresponds to no input, ones corresponds to estimating
            //    a mean value parameter. (default ones)
            // lambda : Forgetting factor (default 0.99) if lambda= [lambda lambda0]
            //          the forgetting factor increases exponentially from lambda0
            //          to lambda.
            // theta0 : Initial parameter estimate. Notice that theta0= [A0';B0'];
            // sigma0 : Initial covvariance estimate.
            //          If no initial parameters are specifyed a offline/batch
            //          estimate is used for the start.
            // Plot   : If 1/true plot informative plots (default: false)
            //
            // External input:

            // Time-stamp: <2014-10-17 11:44:27 tk>
            // Version 1: 2014-10-01 app.
            // Version 2: 2014-10-02 12:53:07 tk Included LS/offline/batch startup
            // Version 3: 2014-10-07 13:57:54 tk Included additional output and
            //            plotting
            // Torben Knudsen
            // Aalborg University, Dept. of Electronic Systems, Section of Automation
            // and Control
            // E-mail: [email protected]
            #endregion

            #region "Used variables declaration"
            double           TauLambdaLRel;
            double           lambdaInf;
            double           lambda0;
            double           IniNumSampFrac;
            int              N;
            int              n;
            int              m;
            double           TauLambdaL;
            double           lambdaL;
            ILArray <double> sigma;
            ILArray <double> theta;
            int              NIni;
            ILArray <double> XX;
            ILArray <double> YY;
            ILArray <double> R;
            ILArray <double> Epsilon;
            ILArray <double> xh;
            ILArray <double> Res;
            int              i;
            ILArray <double> phi;
            ILArray <double> epsilon;
            #endregion

            //% setting up inputs
            //UDef = 1;
            //lambdaDef = 0.99;
            //theta0Def = 0;
            //sigma0Def = 0;
            //PlotDef = 0;
            //if (nargin < 6) { Plot = []; }
            if (sigma0 == null)
            {
                sigma0 = __[' '];
            }
            if (theta0 == null)
            {
                theta0 = __[' '];
            }
            if (lambda == null)
            {
                lambda = __[' '];
            }
            if (U == null)
            {
                U = __[' '];
            }
            //if (nargin < 1) { error('Error TK: To few input arguments'); }
            if (isempty(U))
            {
                U = UDef;
            }
            //if (isempty(Plot)) { Plot = PlotDef; }
            if (isempty(lambda))
            {
                lambda = lambdaDef;
            }
            if (isempty(theta0))
            {
                theta0 = theta0Def;
            }
            if (isempty(sigma0))
            {
                sigma0 = sigma0Def;
            }

            //% Parameters

            TauLambdaLRel = 0.1;                     // TauLambdaL= 10% of the samples
            lambdaInf     = lambda._(1);
            if (length(lambda) > 1)                  // Initial lambda;
            {
                lambda0 = lambda._(2);
            }
            else
            {
                lambda0 = lambdaInf;
            }
            IniNumSampFrac = 0.1;                    // Number of samples to use for init

            //% Definitions etc.

            N = size(X, 1);
            n = size(X, 2);
            m = size(U, 2);
            // Calculate Lamba* from TauLambda* assuming Ts= 1
            TauLambdaL = TauLambdaLRel * N;
            lambdaL    = exp(-1.0 / TauLambdaL);
            if (all(U == 1))
            {
                U = ones(N, 1);
            }

            //% Algorithm

            // Initialisation
            if (all(all(sigma0 == 0)))                 // No sigma0 specifyed
            {
                sigma = 0 * eye(n);
            }
            else
            {
                sigma = sigma0;
            }
            if (all(all(theta0 == 0)))                 // No sigma0 specifyed
            {
                theta = zeros(n + m, n);
            }
            else
            {
                theta = theta0;
            }

            // Start with a offline estimate if initial parameters are not specifyed
            if (all(__[theta0, ';', sigma0] == 0))
            {
                NIni    = max(n + 1, ceil_(N * IniNumSampFrac));
                XX      = __[X[_(1, ':', NIni - 1), _(':')], U[_(1, ':', NIni - 1), _(':')]];
                YY      = X[_(_c_(1, NIni - 1) + 1), _(':')];
                R       = _m(XX.T, '*', XX);
                theta   = _m(_m(inv(R), '*', (XX.T)), '*', YY);
                Epsilon = YY - _m(XX, '*', theta);
                sigma   = _m(Epsilon.T, '*', Epsilon) / NIni;
                xh      = _m(XX[_(end), _(':')], '*', theta);
            }
            else
            {
                NIni = 1;
                xh   = X[_(1), _(':')];
                R    = 1e6 * eye(n);
            }

            lambda = lambda0;
            Res    = __[NIni, (theta[_(':')]).T, (sigma[_(':')]).T, xh, lambda];

            AByTime = zeros(n, n, N - NIni + 1);
            AByTime[_(':'), _(':'), _(1)] = (theta[_(1, ':', n), _(1, ':', n)]).T;
            BByTime = zeros(n, m, N - NIni + 1);
            BByTime[_(':'), _(':'), _(1)] = (theta[_(n + 1, ':', n + m), _(1, ':', n)]).T;
            SigmaByTime = zeros(n, n, N - NIni + 1);
            SigmaByTime[_(':'), _(':'), _(1)] = sigma;

            // Recursion
            // Model x(n+1)= A*x(n)+B*u(n)+e(n) <=>
            // x(n+1)'= [x(n)' u(n)']*[A'; B']+e(n)
            for (i = NIni + 1; i <= N; i++)
            {
                phi     = (__[X[_(i - 1), _(':')], U[_(i - 1), _(':')]]).T; // phi(i)
                R       = (lambda._Scalar()) * R + _m(phi, '*', (phi.T));   // R(i)
                xh      = _m((phi.T), '*', theta);                          // xh(i)
                epsilon = X[_(i), _(':')] - xh;                             // epsilon(i)
                theta   = theta + _m(_s(R, '\\', phi), '*', epsilon);       // theta(i)
                sigma   = _m(lambda, '*', sigma) + _m(_m((1 - lambda), '*', (epsilon.T)), '*', epsilon);
                Res     = __[Res, ';', __[i, theta[_(':')].T, sigma[_(':')].T, xh, lambda]];
                lambda  = lambdaL * lambda + (1 - lambdaL) * lambdaInf;
                AByTime[_(':'), _(':'), _(i - NIni + 1)]     = (theta[_(1, ':', n), _(1, ':', n)]).T; // Index start at 2
                BByTime[_(':'), _(':'), _(i - NIni + 1)]     = (theta[_(n + 1, ':', n + m), _(1, ':', n)]).T;
                SigmaByTime[_(':'), _(':'), _(i - NIni + 1)] = sigma;
            }
            // Res is organised like
            // i theta(:)' sigma(:)' xh lambda with the dimensions
            // 1 (n+m)*n   n^2       n   1
            Time   = _int(Res[_(':'), _(1)]);
            Theta  = Res[_(':'), _(1 + 1, ':', 1 + (n + m) * n)];
            Sigma  = Res[_(':'), _(1 + 1 + (n + m) * n, ':', 1 + (n + m) * n + _p_(n, 2))];
            Xh     = Res[_(':'), _(1 + 1 + (n + m) * n + _p_(n, 2), ':', 1 + (n + m) * n + _p_(n, 2) + n)];
            Lambda = Res[_(':'), _(1 + 1 + (n + m) * n + _p_(n, 2) + n, ':', end)];

            // Do informative plotting and output
            //if (Plot)
            //{
            //    figure;
            //    plot([U X]);
            //    title('Input and measurements');
            //    figure;
            //    plot(Time,reshape(AByTime,n*n,N-NIni+1)');
            //    title('A parameters');
            //    figure;
            //    plot(Time,reshape(BByTime,n*m,N-NIni+1)');
            //    title('B parameters');
            //    figure;
            //    plot(Time,reshape(SigmaByTime,n*n,N-NIni+1)');
            //    title('Sigma parameters');
            //    figure;
            //    plot(Time,Lambda);
            //    title('Lambda');
            //    Epsilon= X(Time,:)-Xh;
            //    Epsilon= Epsilon(100:end,:);
            //    figure;
            //    XCorrtkAll(Epsilon);
            //    figure;
            //    normplot(Epsilon);
            //    gridtk('on',figures);
            //    Lab= ['Final parameters A n*n B n*m Sigma n*n'];
            //    RowLab= {''};
            //    ColLab= {''};
            //    Res= [AByTime(:,:,end) BByTime(:,:,end) SigmaByTime(:,:,end)];
            //    printmattk(Res,Lab);
            //}
        }
Beispiel #18
0
 /// <summary>
 /// (i1,i2) =
 /// </summary>
 /// <param name="equalitySign">'='</param>
 public static void _(this ILArray <double> ilArray, int index1, int index2, char equalitySign, double value)
 {
     ilArray._ <double>(index1, index2, equalitySign, value);
 }
Beispiel #19
0
        // Wake Simulation
        // (C) Rasmus Christensen
        // Control and Automation, Aalborg University 2014

        // Compute the velocity in front of each wind-turbine, with respect to the wind input.
        #endregion
        internal static void Compute_Vell(out double[,] vel_output, ILArray<double> yTurb, ILArray<int> xTurbC, ILArray<int> yTurbC, ILArray<double> x, ILArray<double> wField, double[] Uhub, double kWake, int iMax, int jMax, int nTurb, double dTurb, ILArray<double> Ct, double dy)
        {
            #region "Used variables declaration"
            double[,] vell_i;
            ILArray<double> shadow;
            double r0;
            double nk;
            int k;
            int J;
            double SS;
            double SS0;
            int i;
            double RR_i;
            double Dij;
            double Alpha_i;
            double Alpha_k;
            double Area;
            int ii;
            double rrt;
            double nj;
            int jjMin;
            int jjMax;
            #endregion


            //vell_i = wField.C;
            vell_i = new double[wField.Size[0], wField.Size[1]];
            for (var i0 = 0; i0 < vell_i.GetLength(0); i0++)
            {
                for (var i1 = 0; i1 < vell_i.GetLength(1); i1++)
                {
                    vell_i[i0, i1] = wField.GetValue(i0, i1);
                }
            }

            shadow = zeros(1, nTurb);

            r0 = 0.5 * dTurb;
            nk = 2 * ceil(dTurb / dy);

            for (k = 1; k <= nTurb; k++)
            {
                J = 0;
                SS = 0;
                SS0 = pi * r0 * r0;

                for (i = 1; i <= k - 1; i++)
                {
                    RR_i = r0 + kWake * (x._(xTurbC._(k)) - x._(xTurbC._(i)));
                    Dij = abs(yTurb._(i) - yTurb._(k));

                    if ((RR_i >= (r0 + Dij)) || (Dij <= dy))
                    {
                        SS = SS + ((r0 * r0) / (RR_i * RR_i));
                    }
                    else
                    {
                        if (RR_i >= (r0 + Dij) && Dij > dy)
                        {
                            J               = J + 1;
                            Alpha_i         = acos((RR_i * RR_i) + (Dij * Dij) - (r0 * r0) / (2 * RR_i * Dij));
                            Alpha_k         = acos(((r0 * r0) + (Dij * Dij) - (RR_i * RR_i)) / (2 * r0 * Dij));
                            AArea(out Area, RR_i, r0, Dij);
                            shadow._(J,     '=', (Alpha_i * (RR_i * RR_i) + Alpha_k * (r0 * r0)) - 2 * Area);
                            SS              = SS + ((shadow._(J)) / SS0) * ((r0 * r0) / (RR_i * RR_i));
                        }
                    }
                }

                for (ii = xTurbC._(k); ii <= iMax; ii++)
                {
                    rrt     = r0 + kWake * (x._(ii) - x._(xTurbC._(k)));
                    nj      = ceil(rrt / dy);

                    jjMin   = floor_(max(1, yTurbC._(k) - nj));
                    jjMax   = ceil_(min(jMax, yTurbC._(k) + nj));

                    for (var j = jjMin; j <= jjMax; j++)
                    {
                        if (((-vell_i[ii - 1, j - 1] + Uhub[k - 1]) > 0) && (ii > xTurbC._(k) + nk))
                        {
                            vell_i[ii - 1, j - 1] = min(vell_i[ii - 2, j - 1], Uhub[k - 1] + Uhub[k - 1] * (sqrt(1 - Ct._(k)) - 1) * ((r0 * r0) / (rrt * rrt)) * (1 - (1 - sqrt(1 - Ct._(k))) * SS));
                            vell_i[ii - 1, j - 1] = max(0, vell_i[ii - 1, j - 1]);
                        }
                        else
                        {
                            vell_i[ii - 1, j - 1] = (Uhub[k - 1] + Uhub[k - 1] * (sqrt(1 - Ct._(k)) - 1) * (r0 / rrt) * (r0 / rrt)) * (1 - (1 - sqrt(1 - Ct._(k))) * SS);
                            vell_i[ii - 1, j - 1] = max(0, vell_i[ii - 1, j - 1]);
                        }
                    }
                }
            }

            vel_output = vell_i;
        }
Beispiel #20
0
 /// <summary>
 /// = (i)
 /// </summary>
 public static int _(this ILArray <int> ilArray, int index)
 {
     return(ilArray._ <int>(index));
 }
Beispiel #21
0
 /// <summary>
 /// (i) =
 /// </summary>
 /// <param name="equalitySign">'='</param>
 public static void _(this ILArray <int> ilArray, int index, char equalitySign, int value)
 {
     ilArray._ <int>(index, equalitySign, value);
 }
Beispiel #22
0
 /// <summary>
 /// = (i)
 /// </summary>
 public static double _(this ILArray <double> ilArray, int index)
 {
     return(ilArray._ <double>(index));
 }