Ejemplo n.º 1
0
        //% The main file for running the wind farm controll and wake simulation.
        // It is not completely done yet. Further updates will come
        // Currently there are only 4 turbines, for test purposes. But is should be
        // easily updated to a larger number of turbines.
        // Similarly there is a lot of room for speed optimizations, even though it
        // now runs slowly with only 4 turbines
        // 19/07-13 MS

        public static double[][] Simulation(WakeFarmControlConfig config)
        {
            var parm = new WindTurbineParameters();

            ILMatFile env;
            ILMatFile wt;

            ILArray <int>    idx;
            ILArray <double> ee;

            double           Ki;
            double           Kp;
            int              PC_MaxPit;
            int              PC_MinPit;
            double           VS_CtInSp;
            double           VS_RtGnSp;
            double           VS_Rgn2K;
            double           omega0;
            double           beta0;
            double           power0;
            ILArray <double> x;
            ILArray <double> u0;
            ILArray <double> u;
            ILArray <double> Mg_old;
            ILArray <double> P_ref;
            ILArray <double> Pa;
            ILArray <double> Power;
            ILArray <double> Ct;
            ILArray <double> P_ref_new;
            ILArray <double> v_nac;
            double           alpha;
            double           Mg_max_rate;
            ILArray <double> e;
            ILArray <double> Mg;
            ILArray <double> beta;
            ILArray <double> Cp;
            ILArray <double> Omega;
            ILArray <double> out_;

            if (config.NTurbines == 0)
            {
                return(null);
            }

            // Wind farm properties
            //turbine properties
            env             = wt = new ILMatFile(config.NREL5MW_MatFile);                                             //Load parameters from the NREL 5MW turbine
            parm.N          = config.NTurbines;                                                                       // number of turbines in farm
            parm.rho        = (double)env.GetArray <double>("env_rho");                                               //air density
            parm.radius     = ((double)(wt.GetArray <double>("wt_rotor_radius"))) * ILMath.ones(1, config.NTurbines); // rotor radius (NREL5MW)
            parm.rated      = 5e6 * ILMath.ones(1, config.NTurbines);                                                 //rated power (NREL5MW)
            parm.ratedSpeed = (double)wt.GetArray <double>("wt_rotor_ratedspeed");                                    //rated rotor speed

            idx = ILMath.empty <int>();
            ILMath.max(wt.GetArray <double>("wt_cp_table")[ILMath.full], idx);                                        //Find index for max Cp;
            parm.Cp = ILMath.ones(1, config.NTurbines) * wt.GetArray <double>("wt_cp_table").GetValue(idx.ToArray()); //Set power coefficent to maximum value in the cp table
            parm.Ct = ILMath.ones(1, config.NTurbines) * wt.GetArray <double>("wt_ct_table").GetValue(idx.ToArray()); //Set power coefficent to maximum value in the ct table

            // NOTE: controller parameters should be imported from the wt....struct in
            //Pitch control

            ee = 0;                                 //blade pitch integrator
            Ki = 0.008068634 * 360 / 2 / ILMath.pi; // integral gain (NREL5MW)
            Kp = 0.01882681 * 360 / 2 / ILMath.pi;  // proportional gain (NREL5MW)

            PC_MaxPit = 90;
            PC_MinPit = 0;

            //region control NREL
            VS_CtInSp = 70.16224;
            VS_RtGnSp = 121.6805;
            VS_Rgn2K  = 2.332287;


            // load initial wind data
            var wind = new ILMatFile(config.Wind_MatFile);

            //% Set initial conditions
            omega0 = 1.267; //Rotation speed
            beta0  = 0;     //Pitch

            var timeLine = (int)config.TimeLine();

            power0 = parm.rated.GetValue(0); //Power production
            x      = (omega0 * ILMath.ones(parm.N, 1)).Concat((wind.GetArray <double>("wind").GetValue(0, 1) * ILMath.ones(parm.N, 1)), 1);
            u0     = (beta0 * ILMath.ones(parm.N, 1)).Concat((power0 * ILMath.ones(parm.N, 1)), 1);
            u      = u0.C;
            Mg_old = u[ILMath.full, 1];
            P_ref  = ILMath.zeros(parm.N, (int)config.TimeLine()); //Initialize matrix to save the power production history for each turbine
            Pa     = P_ref.C;                                      //Initialize available power matrix
            Power  = P_ref.C;
            Ct     = parm.Ct.C;                                    //Initialize Ct - is this correct?
            Ct[timeLine - 1, ILMath.full] = Ct[0, ILMath.full];
            P_ref_new = power0 * ILMath.ones(config.NTurbines, 1);

            v_nac = ILMath.zeros(Ct.Size[1], timeLine);
            Mg    = ILMath.zeros(u.Size[0], timeLine);
            beta  = ILMath.zeros(u.Size[0], timeLine);
            Omega = ILMath.zeros(Ct.Size[1], timeLine);
            Cp    = ILMath.zeros(timeLine, parm.Cp.Size[1]);

            var turbineModel = new TurbineDrivetrainModel();

            //% Simulate wind farm operation
            //var timeLine = (int) config.TimeLine();
            for (var i = 2; i <= timeLine; i++) //At each sample time(DT) from Tstart to Tend
            {
                //Calculate the wake using the current Ct values
                {
                    ILArray <double> out_v_nac;
                    WakeCalculation.Calculate((Ct[i - 1 - 1, ILMath.full]), i, wind, out out_v_nac);
                    v_nac[ILMath.full, i - 1] = out_v_nac;
                }
                x[ILMath.full, 1] = v_nac[ILMath.full, i - 1];


                //Farm control
                //Calculate the power distribution references for each turbine
                if (config.EnablePowerDistribution)
                {
                    ILArray <double> out_Pa;
                    PowerDistributionControl.DistributePower(v_nac[ILMath.full, i - 1], config.Pdemand, Power[ILMath.full, i - 1 - 1], parm, out P_ref_new, out out_Pa);
                    Pa[ILMath.full, i - 1] = out_Pa;
                }

                //Hold  the demand for some seconds
                if (ILMath.mod(i, ILMath.round(config.PRefSampleTime / config.DT)) == 2) //???
                {
                    P_ref[ILMath.full, i - 1] = P_ref_new;
                }
                else
                {
                    if (config.PowerRefInterpolation)
                    {
                        alpha = 0.01;
                        P_ref[ILMath.full, i - 1] = (1 - alpha) * P_ref[ILMath.full, i - 1 - 1] + (alpha) * P_ref_new;
                    }
                    else
                    {
                        P_ref[ILMath.full, i - 1] = P_ref_new;
                    }
                }


                //Calculate control for each individual turbine - should be moved to the
                //turbine (drivetrain) model.

                //Torque controller
                for (var j = 1; j <= parm.N; j++)
                {
                    if ((x.GetValue(j - 1, 0) * 97 >= VS_RtGnSp) || (u.GetValue(j - 1, 0) >= 1))   // We are in region 3 - power is constant
                    {
                        u.SetValue(P_ref.GetValue(j - 1, i - 1) / x.GetValue(j - 1, 0), j - 1, 1);
                    }
                    else if (x.GetValue(j - 1, 0) * 97 <= VS_CtInSp)                            //! We are in region 1 - torque is zero
                    {
                        u.SetValue(0.0, j - 1, 1);
                    }
                    else                                                         //! We are in region 2 - optimal torque is proportional to the square of the generator speed
                    {
                        u.SetValue(97 * VS_Rgn2K * x.GetValue(j - 1, 0) * x.GetValue(j - 1, 0) * Math.Pow(97, 2), j - 1, 1);
                    }
                }

                //Rate limit torque change
                //  u(:,2) - Mg_old;
                Mg_max_rate       = 1e6 * config.DT;
                u[ILMath.full, 1] = ILMath.sign(u[ILMath.full, 1] - Mg_old) * ILMath.min(ILMath.abs(u[ILMath.full, 1] - Mg_old), Mg_max_rate) + Mg_old;

                //Pitch controller
                e  = 97 * (omega0 * ILMath.ones(parm.N, 1) - x[ILMath.full, 0]);
                ee = ee - config.DT * e;
                ee = ILMath.min(ILMath.max(ee, PC_MinPit / Ki), PC_MaxPit / Ki);

                u[ILMath.full, 0] = -Kp * config.DT * e + Ki * ee;
                for (var j = 1; j <= parm.N; j++)
                {
                    u.SetValue(Math.Min(Math.Max(u.GetValue(j - 1, 0), PC_MinPit), PC_MaxPit), j - 1, 0);
                }

                if (!config.EnableTurbineDynamics)
                {
                    u = u0;
                }

                Mg[ILMath.full, i - 1] = u[ILMath.full, 1];
                Mg_old = Mg[ILMath.full, i - 1];
                beta[ILMath.full, i - 1] = u[ILMath.full, 0]; //Set pitch


                //Turbine dynamics - can be simplified
                if (config.EnableTurbineDynamics)
                {
                    for (var j = 1; j <= parm.N; j++)
                    {
                        double out_x;
                        double out_Ct;
                        double out_Cp;
                        turbineModel.Model(x[j - 1, ILMath.full], u[j - 1, ILMath.full], wt, env, config.DT, out out_x, out out_Ct, out out_Cp);
                        x.SetValue(out_x, j - 1, 0);
                        Ct.SetValue(out_Ct, i - 1, j - 1);
                        Cp.SetValue(out_Cp, i - 1, j - 1);
                    }
                }
                else
                {
                    Ct[i - 1, ILMath.full] = parm.Ct;
                    Cp[i - 1, ILMath.full] = parm.Cp;
                    x[ILMath.full, 0]      = parm.ratedSpeed;//Rotational speed
                }

                Omega[ILMath.full, i - 1] = x[ILMath.full, 0];
                Power[ILMath.full, i - 1] = Omega[ILMath.full, i - 1] * Mg[ILMath.full, i - 1];
            }

            //% Save output data
            out_ = (config.DT * (ILMath.counter(0, 1, config.TimeLine())));
            out_ = out_.Concat(v_nac.T, 1);
            out_ = out_.Concat(Omega.T, 1);
            out_ = out_.Concat(beta.T, 1);
            out_ = out_.Concat(P_ref.T, 1);
            out_ = out_.Concat(Ct, 1);
            out_ = out_.Concat(Cp, 1);
            out_ = out_.Concat(Pa.T, 1);
            out_ = out_.Concat(Mg.T, 1);
            out_ = out_.Concat(Power.T, 1);

            //Ttotal power demand
            var l = config.NTurbines * 3 + 1;
            var r = l + config.NTurbines - 1;

            out_ = out_.Concat(ILMath.sum(out_[ILMath.full, ILMath.r(l, r)], 1) / 1e6, 1);    // P_ref sum

            l = config.NTurbines * 6 + 1;
            r = l + config.NTurbines - 1;

            out_ = out_.Concat(ILMath.sum(out_[ILMath.full, ILMath.r(l, r)], 1) / 1e6, 1);    // Pa sum. 'Power Demand'
            out_ = out_.Concat(ILMath.sum(Power).T / 1e6, 1);                                 // 'Actual Production'

            //Ttotal power demand
            out_ = out_.Concat(ILMath.sum(P_ref.T, 1), 1);              // 'Demand'
            out_ = out_.Concat(ILMath.sum(Pa.T, 1), 1);                 // 'Available'
            out_ = out_.Concat(ILMath.sum(Mg * Omega).T, 1);            // 'Actual'

            //Total power produced
            out_ = out_.Concat((Mg * Omega).T, 1);

            var out_doubleArray = new double[out_.Size[0]][];

            for (int i = 0; i <= out_doubleArray.GetLength(0) - 1; i++)
            {
                out_doubleArray[i] = new double[out_.Size[1]];
                for (int j = 0; j <= out_doubleArray[i].GetLength(0) - 1; j++)
                {
                    out_doubleArray[i][j] = out_.GetValue(i, j);
                }
            }
            return(out_doubleArray);
        }
Ejemplo n.º 2
0
        public static double[][] FarmControl(WakeFarmControlConfig config, out double[][] dataOut)
        {
            #region "Used variables declaration"
            bool    saveData;
            bool    enablePowerDistribution;
            bool    enableTurbineDynamics;
            bool    powerRefInterpolation;
            bool    enableVaryingDemand;
            SimParm simParm;

            ILArray <double>        wind;
            WindTurbineParameters   parm;
            EnvMatFileDataStructure env;
            WtMatFileDataStructure  wt;
            ILArray <int>           idx;
            double           Mg_max_rate;
            double           Ki, Kp, Umax, Umin;
            double           VS_CtInSp, VS_RtGnSp, VS_Rgn2K;
            double           omega0, beta0, power0;
            ILArray <double> initMatrix;
            ILArray <double> sumPower;
            ILArray <double> sumRef;
            ILArray <double> sumAvai;
            ILArray <double> P_ref_new;
            ILArray <double> P_demand;
            ILArray <double> v_nac;
            ILArray <double> P_ref;
            ILArray <double> Pa;
            ILArray <double> Power;
            ILArray <double> beta;
            ILArray <double> Omega;
            ILArray <double> initVector;
            ILArray <double> Mg___i_;
            ILArray <double> wField;
            double           dZ;
            ILArray <double> du;
            double[]         x___1_;
            double[]         x___2_;
            double[]         u___1_;
            double[]         u___2_;
            double           alpha;
            int j;
            ILArray <double> dx;
            ILArray <double> time;
            #endregion

            //% Initialization
            //General settings to be changed
            saveData = config.saveData;                               // Save all the simulated data to a .mat file?
            enablePowerDistribution = config.enablePowerDistribution; // Enable wind farm control and not only constant power
            enableTurbineDynamics   = config.enableTurbineDynamics;   // Enable dynamical turbine model. Disabling this will increase the speed significantly, but also lower the fidelity of the results (setting to false does not work properly yet)
            powerRefInterpolation   = config.powerRefInterpolation;   // Power Reference table interpolation.
            enableVaryingDemand     = config.enableVaryingDemand;     // Varying Reference

            // Simulation Properties:
            simParm          = new SimParm();
            simParm.tStart   = config.SimParm.tStart;         // time start
            simParm.timeStep = config.SimParm.timeStep;       // time step, 8Hz - the NREL model is 80Hz (for reasons unknown)
            simParm.tEnd     = config.SimParm.tEnd;           // time end
            int _simParm_tEnd_simParm_tStart__simParm_timeStep = (int)((simParm.tEnd - simParm.tStart) / simParm.timeStep);
            simParm.gridRes     = config.SimParm.gridRes;     // Grid Resolution
            simParm.grid        = config.SimParm.grid;        // Grid Size
            simParm.ctrlUpdate  = config.SimParm.ctrlUpdate;  // Update inverval for farm controller
            simParm.powerUpdate = config.SimParm.powerUpdate; // How often the control algorithm should update!
            load(config.Wind_MatFile, out wind);              // Load Wind Data

            // Wind farm and Turbine Properties properties
            parm       = new WindTurbineParameters();
            parm.wf    = load(config.Turbines); // Loads the Wind Farm Layout.
            parm.N     = length(parm.wf);       // number of turbines in farm
            parm.rotA  = -48.80;                // Angle of Attack
            parm.kWake = 0.06;

            //% Turbine properties - Loaded from the NREL5MW.mat file
            load(config.NREL5MW_MatFile, out env, out wt);                                                            // Load parameters from the NREL 5MW Reference turbine struct.
            parm.rho        = env.rho;                                                                                // air density
            parm.radius     = wt.rotor.radius * ones(1, parm.N);                                                      // rotor radius (NREL5MW)
            parm.rated      = wt.ctrl.p_rated * wt.gen.effeciency * ones(1, parm.N);                                  //rated power (NREL5MW)
            parm.ratedSpeed = wt.rotor.ratedspeed;                                                                    //rated rotor speed
            max(out idx, wt.cp.table[_(':')]);                                                                        // Find index for max Cp
            parm.Ct     = 0.0 * wt.ct.table[_(idx)] * ones(parm.N, (_simParm_tEnd_simParm_tStart__simParm_timeStep)); // Define initial Ct as the optimal Ct.
            parm.Cp     = wt.cp.table[_(idx)] * ones(parm.N, (_simParm_tEnd_simParm_tStart__simParm_timeStep));       // Define initial Cp as the optimal Cp.
            Mg_max_rate = wt.ctrl.torq.ratelim;                                                                       // Rate-limit on Torque Change.

            //Pitch control
            Ki   = wt.ctrl.pitch.Igain; // 0.008068634*360/2/pi; % integral gain (NREL5MW).
            Kp   = wt.ctrl.pitch.Pgain; // 0.01882681*360/2/pi; % proportional gain (NREL5MW).
            Umax = wt.ctrl.pitch.ulim;  // Upper limit of the pitch controller
            Umin = wt.ctrl.pitch.llim;  // Lower limit of the pitch controller.

            // NREL Regional Control - extracted from the NREL report.
            VS_CtInSp = 70.162240;
            VS_RtGnSp = 121.680500;
            VS_Rgn2K  = 2.332287;

            //% Set initial conditions
            omega0 = wt.rotor.ratedspeed; // Desired Rotation speed
            beta0  = 0;                   // wt.ctrl.pitch.llim; % Initial pitch at zero.
            power0 = 0;                   // Power Production

            //% Memory Allocation and Memory Initialization
            initMatrix = zeros(parm.N, _simParm_tEnd_simParm_tStart__simParm_timeStep);
            sumPower   = initMatrix[_(1), _(':')]; // Initialize produced power vector
            sumRef     = initMatrix[_(1), _(':')]; // Initialize reference power vector
            sumAvai    = initMatrix[_(1), _(':')]; // Initialize available power vector
            P_ref_new  = initMatrix[_(1), _(':')]; // Initialize new reference vector
            P_demand   = initMatrix[_(1), _(':')]; // Initialize power demand vector
            v_nac      = initMatrix.C;             // Initialize hub velocity matrix.
            P_ref      = initMatrix.C;             // Initialize matrix to save the power production history for each turbine.
            Pa         = initMatrix.C;             // Initialize available power matrix.
            Power      = initMatrix.C;             // Initialize individual WT power production matrix.
            beta       = initMatrix.C;             // Initialize pitch matrix.
            Omega      = initMatrix.C;             // Initialize revolutional velocity matrix.

            initVector = ones(parm.N, 1);
            Mg___i_    = 0 * initVector;
            wField     = zeros(simParm.grid / simParm.gridRes, simParm.grid / simParm.gridRes); // Wind field matrix

            //% Controller Initizliation
            dZ     = 0;                // Integrator Initialization.
            du     = zeros(parm.N, 1); // Integration variable.
            x___1_ = (omega0 * initVector).GetArrayForRead();
            x___2_ = (0 * initVector).GetArrayForRead();
            u___1_ = (beta0 * initVector).GetArrayForRead();  // u0
            u___2_ = (power0 * initVector).GetArrayForRead(); // u0
            P_demand._(1, '=', config.InitialPowerDemand);    // Power Demand.

            double           turbinesDTurb;
            int              turbinesNTurb;
            double           turbinesKWake;
            ILArray <double> turbinesX;
            int              turbinesGridX;
            int              turbinesGridY;
            ILArray <double> turbinesYOrder;
            double           turbinesDy;
            ILArray <int>    turbinesXTurbC;
            ILArray <int>    turbinesYTurbC;
            turbinesCalculations(out turbinesDTurb, out turbinesNTurb, out turbinesKWake, out turbinesX, out turbinesGridX, out turbinesGridY, out turbinesYOrder, out turbinesDy, out turbinesXTurbC, out turbinesYTurbC, parm, simParm);

            //% Simulate wind farm operation
            for (var i = 2; i <= _simParm_tEnd_simParm_tStart__simParm_timeStep; i++) // At each sample time (DT) from Tstart to Tend
            {
                //clc;
                //fprintf('Iteration Counter: %i out of %i \n', i, config.SimParm.tEnd * (1 / config.SimParm.timeStep));

                //%%%%%%%%%%%%%%% WIND FIELD FIFO MATRIX %%%%%%%%%%%%%%%%%%%
                wField[_(':'), _(2, ':', end)] = wField[_(':'), _(1, ':', (end - 1))];
                wField[_(':'), _(1)]           = wind._(i, 2) * ones(simParm.grid / simParm.gridRes, 1) + randn(simParm.grid / simParm.gridRes, 1) * 0.5;
                //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

                // Calculate the wake using the last Ct values
                ILArray <double> v_nac___i_;
                wakeCalculationsRLC(out v_nac___i_, turbinesDTurb, turbinesNTurb, turbinesKWake, turbinesX, turbinesGridX, turbinesGridY, turbinesYOrder, turbinesDy, turbinesXTurbC, turbinesYTurbC, parm.Ct[_(':'), _(i - 1)], transpose(wField), x___2_, parm, simParm);
                v_nac[_(':'), _(i)] = v_nac___i_;
                x___2_ = (v_nac[_(':'), _(i)]).GetArrayForRead();


                if (enableVaryingDemand) // A random walk to simulate fluctuations in the power demand.
                {
                    P_demand._(i, '=', P_demand._(i - 1) + randn() * 50000);
                }
                else
                {
                    P_demand._(i, '=', P_demand._(i - 1));
                }

                // Farm control
                // Calculate the power distribution references for each turbine
                if (enablePowerDistribution)
                {
                    ILArray <double> Pa___i_;
                    powerDistributionControl(out P_ref_new, out Pa___i_, x___2_, P_demand._(i), parm);
                    Pa[_(':'), _(i)] = Pa___i_;
                }

                //Hold  the demand for some seconds
                if (mod(i, round(simParm.ctrlUpdate / simParm.timeStep)) == simParm.powerUpdate)
                {
                    P_ref[_(':'), _(i)] = P_ref_new;
                }
                else
                {
                    if (powerRefInterpolation)
                    {
                        alpha = 0.01;
                        P_ref[_(':'), _(i)] = (1 - alpha) * P_ref[_(':'), _(i - 1)] + (alpha) * P_ref_new;
                    }
                    else
                    {
                        P_ref[_(':'), _(i)] = P_ref_new;
                    }
                }
                //Torque controller
                for (j = 1; j <= parm.N; j++)
                {
                    if ((x___1_[j - 1] * 97 >= VS_RtGnSp) || (u___1_[j - 1] >= 1))      //! We are in region 3 - power is constant
                    {
                        u___2_[j - 1] = P_ref._(j, i) / x___1_[j - 1];
                    }
                    else if (x___1_[j - 1] * 97 <= VS_CtInSp)                     //! We are in region 1 - torque is zero
                    {
                        u___2_[j - 1] = 0.0;
                    }
                    else                                                //! We are in region 2 - optimal torque is proportional to the square of the generator speed
                    {
                        u___2_[j - 1] = 97 * VS_Rgn2K * x___1_[j - 1] * x___1_[j - 1] * _p(97, 2);
                    }
                }

                dx     = (omega0 - ((ILArray <double>)x___1_)) - (omega0 - Omega[_(':'), _(i - 1)]);
                du     = Kp * dx + Ki * simParm.timeStep * (omega0 - ((ILArray <double>)(x___1_)));
                du     = min(max(du, -wt.ctrl.pitch.ratelim), wt.ctrl.pitch.ratelim);
                u___1_ = (min(max(((ILArray <double>)u___1_) + du * simParm.timeStep, Umin), Umax)).GetArrayForRead();


                Mg___i_            = u___2_; // Torque Input
                beta[_(':'), _(i)] = u___1_; // Pitch Input

                // Turbine dynamics - can be simplified:
                if (enableTurbineDynamics)
                {
                    for (j = 1; j <= parm.N; j++)
                    {
                        double x_j_1_; double parm_Ct_j_i_; double parm_Cp_j_i_;
                        turbineDrivetrainModel(out x_j_1_, out parm_Ct_j_i_, out parm_Cp_j_i_, x___1_[j - 1], x___2_[j - 1], u___1_[j - 1], u___2_[j - 1], wt, env, simParm.timeStep);
                        x___1_[j - 1] = x_j_1_; parm.Ct._(j, i, '=', parm_Ct_j_i_); parm.Cp._(j, i, '=', parm_Cp_j_i_);
                    }
                }
                else
                {
                    x___1_.Fill(parm.ratedSpeed); // Rotational speed
                }

                Omega[_(':'), _(i)] = x___1_;
                Power[_(':'), _(i)] = Omega[_(':'), _(i)] * Mg___i_;

                // Power Summations
                sumPower._(i, '=', sum_(Power[_(':'), _(i)]) * _p(10, -6));
                sumRef._(i, '=', sum_(P_ref[_(':'), _(i)]) * _p(10, -6));
                sumAvai._(i, '=', sum_(Pa[_(':'), _(i)]) * _p(10, -6));

                // NOWCASTING FUNKTION HER
                // powerPrediction(i) = powerPrediction(i,sumPower(i:-1:i-10)) % or something
                // similar.
            }

            //%
            //time = (_c((decimal)simParm.tStart, (decimal)simParm.timeStep, (decimal)simParm.tEnd - (decimal)simParm.timeStep)).T;
            time = (_c(0.0, 1.0, _simParm_tEnd_simParm_tStart__simParm_timeStep - 1) * simParm.timeStep + simParm.tStart).T;


            if (saveData)
            {
                //throw new ApplicationException(string.Format("{0}\t{1}\t{2}\t{3}", time.Dimensions, sumPower.T.Dimensions, sumRef.T.Dimensions, sumAvai.T.Dimensions));
                dataOut = (__[time, sumPower.T, sumRef.T, sumAvai.T]).ToDoubleArray();
                //save dataOut;
            }
            else
            {
                dataOut = new double[][] { new double[] { 0, 0, 0, 0 } };
            }
            //% Plotting
            //Below a number of different plots are made. Most of them for test purposes
            ILArray <double> plotsData;
            plotsData = time.C;
            plotsData = __[plotsData, P_ref.T *(_p(10, -6))];               // f1 = figure(1); xlabel('Time [s]'); ylabel('Power Reference [MW]'); title('Individual Power Reference');
            plotsData = __[plotsData, v_nac.T];                             // f2 = figure(2); xlabel('Time [s]'); ylabel('Wind Speed [m/s]'); title('Wind Speed @ individual turbine');
            plotsData = __[plotsData, beta.T];                              // f4 = figure(4); xlabel('Time [s]'); ylabel('Pitch Angle [deg]'); title('Evolution of Pitch angle over time');
            plotsData = __[plotsData, Omega.T];                             // f5 = figure(5); xlabel('Time [s]'); ylabel('Revolutional Velocity [rpm]'); title('Evolution of Revolutional Velocity over time');
            plotsData = __[plotsData, sumRef.T, sumAvai.T, sumPower.T];     // f3 = figure(3); xlabel('Time [s]'); ylabel('Power [MW]'); title('Power Plot'); legend('Reference','Available','Produced');

            return(plotsData.ToDoubleArray());
        }