public JsonResult Run() { var randomDir = Guid.NewGuid().ToString(); Session["WakeSimDir"] = randomDir; var modelGeneral = GetModelGeneral(); var modelTurbines = GetModelTurbines(); string dir = WebConfigurationManager.AppSettings["WakeSimulationDir"]; dir = Path.Combine(dir, randomDir); // root temp dir Directory.CreateDirectory(dir); var resultDir = Path.Combine(dir, "output"); Directory.CreateDirectory(resultDir); var calcData = new CalcData(); var generalData = new GeneralData(); var dataWriter = new DataWriter(); var calc = new WakeCalc(); generalData.GridPointsX = modelGeneral.GridPointsX; generalData.GridPointsY = modelGeneral.GridPointsY; generalData.TurbinesAmount = modelTurbines.Turbines.Count; generalData.RotationAngle = (double)modelGeneral.RotationAngle; generalData.x_turb = new double[modelTurbines.Turbines.Count]; generalData.y_turb = new double[modelTurbines.Turbines.Count]; for (var i = 0; i < modelTurbines.Turbines.Count; i++) { var t = modelTurbines.Turbines[i]; generalData.x_turb[i] = (double) t.X; generalData.y_turb[i] = (double) t.Y; } generalData.TurbineDiameter = (double)modelGeneral.TurbineDiameter; generalData.TurbineHeight = (double)modelGeneral.TurbineHeight; generalData.TurbineThrust = (double)modelGeneral.TurbineThrust; generalData.WakeDecay = (double)modelGeneral.WakeDecay; generalData.VelocityAtHub = (double)modelGeneral.VelocityAtHub; generalData.AirDensity = (double)modelGeneral.AirDensity; generalData.PowerDistance = (double)modelGeneral.PowerDistance; calc.Initialize(generalData, calcData); calc.Run(generalData, calcData); dataWriter.Write(generalData, calcData, resultDir); dataWriter.WritePower(generalData, calcData, resultDir); SharpZipUtils.CompressFolder(resultDir, Path.Combine(dir, "output.zip"), null); System.Drawing.Image resultImage = null; try { resultImage = ResultDrawer.ProcessResult(generalData, calcData, Math.Min(480, generalData.GridPointsX), Math.Min(320, generalData.GridPointsY)); } catch { } Session["WakeSimImage"] = resultImage; return Json("OK", JsonRequestBehavior.AllowGet); }
/// <summary> /// SUBROUTINE _DATA /// </summary> /// <param name="generalData"></param> /// <param name="generalData"></param> /// <param name="calcData"> </param> /// <param name="dir"> </param> public void Write(GeneralData generalData, CalcData calcData, string dir) { using (var fileStream = File.Open(Path.Combine(dir, "FLOW.xyz"), FileMode.OpenOrCreate, FileAccess.Write)) using (var streamWriter = new StreamWriter(fileStream)) { WRITE(streamWriter, generalData.GridPointsX, generalData.GridPointsY); for (var j = 1; j <= generalData.GridPointsY; j++) { for (var i = 0; i <= generalData.GridPointsX - 1; i++) { WRITE(streamWriter, calcData.x[i]); } } WRITE(streamWriter); for (var j = 0; j <= generalData.GridPointsY - 1; j++) { for (var i = 1; i <= generalData.GridPointsX; i++) { WRITE(streamWriter, calcData.y[j]); } } } using (var fileStream = File.Open(Path.Combine(dir, "FLOW.q"), FileMode.OpenOrCreate, FileAccess.Write)) using (var streamWriter = new StreamWriter(fileStream)) { WRITE(streamWriter, generalData.GridPointsX, generalData.GridPointsY); WRITE(streamWriter, "0.1 ", " 10 ", " 10000 ", " 0.1 "); for (var j = 1; j <= generalData.GridPointsY; j++) { for (var i = 1; i <= generalData.GridPointsX; i++) { WRITE(streamWriter, generalData.AirDensity); } } for (var j = 0; j <= generalData.GridPointsY - 1; j++) { for (var i = 0; i <= generalData.GridPointsX - 1; i++) { WRITE(streamWriter, generalData.AirDensity * calcData.vell_i[i, j]); } } for (var j = 1; j <= generalData.GridPointsY; j++) { for (var i = 1; i <= generalData.GridPointsX; i++) { WRITE(streamWriter, 0); } } for (var j = 1; j <= generalData.GridPointsY; j++) { for (var i = 1; i <= generalData.GridPointsX; i++) { WRITE(streamWriter, 0); } } } }
public void Initialize(GeneralData generalData, CalcData calcData) { calcData.x = new double[generalData.GridPointsX]; calcData.y = new double[generalData.GridPointsY]; calcData.vell_i = new double[generalData.GridPointsX, generalData.GridPointsY]; calcData.R_TURB = new double[generalData.TurbinesAmount]; calcData.WPOWER = new double[generalData.TurbinesAmount]; calcData.xc_turb = new Int32[generalData.TurbinesAmount]; calcData.yc_turb = new Int32[generalData.TurbinesAmount]; }
/// <summary> /// SUBROUTINE _DATA Power /// </summary> /// <param name="generalData"></param> /// <param name="calcData"> </param> /// <param name="dir"> </param> public void WritePower(GeneralData generalData, CalcData calcData, string dir) { using (var fileStream = File.Open(Path.Combine(dir, "Power_Output.dat"), FileMode.OpenOrCreate, FileAccess.Write)) using (var streamWriter = new StreamWriter(fileStream)) { WRITE(streamWriter, " Turbine Number(m) ", "Turbine Location-X(m) ", "Turbine Location-Y(m) ", "POWER(W)"); for (var i = 1; i <= generalData.TurbinesAmount; i++) { WRITE(streamWriter, i, generalData.x_turb[i - 1], generalData.y_turb[i - 1], calcData.WPOWER[i - 1]); } } }
private static void Main(string[] args) { var dir = ""; if (args.Length > 0) { dir = args[0]; } var generalData = new GeneralData(); var calcData = new CalcData(); var dataReader = new DataReader(); var dataWriter = new DataWriter(); var calc = new WakeCalc(); dataReader.Read(generalData, dir); calc.Initialize(generalData, calcData); calc.Run(generalData, calcData); dataWriter.Write(generalData, calcData, dir); dataWriter.WritePower(generalData, calcData, dir); }
public void Run(GeneralData generalData, CalcData calcData) { //************************************************************************ //ROTATE THE DOMAIN, AND THE X,Y COORDINATE OF THE TURBINE so that the wind to be in x direction //------------------------------------------------------------------ ROTATE_coord(generalData); if (generalData.TurbineThrust > 1) { Console.WriteLine(" The value of the TurbineThrust should be less 1, hence TurbineThrust=0.3)"); generalData.TurbineThrust = 0.3; } calcData.Cp = 0.5 * (1 + Math.Sqrt(1 - generalData.TurbineThrust)) * generalData.TurbineThrust; ORDER(generalData); DOMAIN_PT(ref calcData.x, ref generalData.GridPointsX, ref calcData.dx, ref generalData.TurbineDiameter, ref generalData.x_turb, ref generalData.TurbinesAmount, ref calcData.xmax, ref calcData.xmin, 5.0); DOMAIN_PT(ref calcData.y, ref generalData.GridPointsY, ref calcData.dy, ref generalData.TurbineDiameter, ref generalData.y_turb, ref generalData.TurbinesAmount, ref calcData.ymax, ref calcData.ymin, 2.0); Turb_centr_coord(ref generalData.TurbinesAmount, ref generalData.GridPointsX, ref calcData.x, ref generalData.x_turb, ref calcData.xc_turb); Turb_centr_coord(ref generalData.TurbinesAmount, ref generalData.GridPointsY, ref calcData.y, ref generalData.y_turb, ref calcData.yc_turb); COMPUTE_VELL(generalData, calcData); COMPUTE_WPower(generalData, calcData); }
public static Image ProcessResult(GeneralData generalData, CalcData calcData, int imageWidth, int imageHeight) { return DrawContourPlot(generalData.GridPointsX, generalData.GridPointsY, calcData.x, calcData.y, new double[1, 1], generalData.AirDensity, calcData.vell_i, imageWidth, imageHeight); }
/// <summary> /// SUBROUTINE _SHADOW AREA /// </summary> /// <param name="generalData"></param> /// <param name="generalData"></param> private void COMPUTE_VELL(GeneralData generalData, CalcData calcData) { var SHADOW = new double[generalData.TurbinesAmount]; double rr_max = 0; double area = 0; for (var i = 0; i <= generalData.GridPointsX - 1; i++) for (var j = 0; j <= generalData.GridPointsY - 1; j++) { calcData.vell_i[i, j] = generalData.VelocityAtHub; } double r0 = 0.5 * generalData.TurbineDiameter; int nk = 2 * (INT(generalData.TurbineDiameter / calcData.dy)); for (var k = 1; k <= generalData.TurbinesAmount; k++) { int J = 0; double SS = 0.0; double ss0 = (pi * r0 * r0); for (var i = 1; i <= k - 1; i = i + 1) // calculate the influence of the turbine i over the turbine k { double RR_I = r0 + generalData.WakeDecay * (calcData.x[calcData.xc_turb[k - 1] - 1] - calcData.x[calcData.xc_turb[i - 1] - 1]); double DIJ = Math.Abs(generalData.y_turb[i - 1] - generalData.y_turb[k - 1]); if (RR_I >= (r0 + DIJ) || DIJ <= calcData.dy) { SS = SS + ((r0 * r0) / (RR_I * RR_I)); } else { if ((DIJ) < (RR_I + r0) && (DIJ) > calcData.dy) { J = J + 1; double ALPHA_I = (RR_I * RR_I) + (DIJ * DIJ) - (r0 * r0); ALPHA_I = ALPHA_I / (2 * RR_I * DIJ); ALPHA_I = Math.Acos(ALPHA_I); double ALPHA_K = (r0 * r0) + (DIJ * DIJ) - (RR_I * RR_I); ALPHA_K = ALPHA_K / (2 * r0 * DIJ); ALPHA_K = Math.Acos(ALPHA_K); AAREA(ref RR_I, ref r0, ref DIJ, ref area); SHADOW[J - 1] = (ALPHA_I * (Math.Pow(RR_I, 2)) + ALPHA_K * (Math.Pow(r0, 2))); SHADOW[J - 1] = SHADOW[J - 1] - 2 * area; SS = SS + ((SHADOW[J - 1]) / ss0) * ((r0 * r0) / (RR_I * RR_I)); } else { SS = SS; } } } for (var ii = calcData.xc_turb[k - 1]; ii <= generalData.GridPointsX; ii++) { double rrt = r0 + generalData.WakeDecay * (calcData.x[ii - 1] - calcData.x[calcData.xc_turb[k - 1] - 1]); rr_max = Math.Max(rrt, rr_max); int nj = (INT(rrt / calcData.dy)); int jj_min = Math.Max(1, calcData.yc_turb[k - 1] - nj); int jj_max = Math.Min(generalData.GridPointsY, calcData.yc_turb[k - 1] + nj); for (J = jj_min; J <= jj_max; J++) { if (((-calcData.vell_i[ii - 1, J - 1] + generalData.VelocityAtHub) > 0) && (ii > calcData.xc_turb[k - 1] + nk)) { double vv = calcData.vell_i[ii - 1, J - 1]; calcData.vell_i[ii - 1, J - 1] = generalData.VelocityAtHub + generalData.VelocityAtHub * (Math.Sqrt(1 - generalData.TurbineThrust) - 1) * ((r0 * r0) / (rrt * rrt)); calcData.vell_i[ii - 1, J - 1] = calcData.vell_i[ii - 1, J - 1] * (1 - (1 - Math.Sqrt(1 - generalData.TurbineThrust)) * SS); //vell_i(ii,j)=(vell_i(ii,j)+0.15*vv)/1.15; calcData.vell_i[ii - 1, J - 1] = Math.Min(vv, calcData.vell_i[ii - 1, J - 1]); } else { calcData.vell_i[ii - 1, J - 1] = generalData.VelocityAtHub + generalData.VelocityAtHub * (Math.Sqrt(1 - generalData.TurbineThrust) - 1) * (r0 / rrt) * (r0 / rrt); calcData.vell_i[ii - 1, J - 1] = calcData.vell_i[ii - 1, J - 1] * (1 - (1 - Math.Sqrt(1 - generalData.TurbineThrust)) * SS); } } } } }
public static Image ProcessResult(GeneralData generalData, CalcData calcData, int imageWidth, int imageHeight) { return(DrawContourPlot(generalData.GridPointsX, generalData.GridPointsY, calcData.x, calcData.y, new double[1, 1], generalData.AirDensity, calcData.vell_i, imageWidth, imageHeight)); }
/// <summary> /// SUBROUTINE compute the power at the distance PowerDistance behind the WT /// </summary> /// <param name="generalData"></param> /// <param name="generalData"></param> /// <param name="calcData"> </param> private void COMPUTE_WPower(GeneralData generalData, CalcData calcData) { var SHADOW = new double[generalData.TurbinesAmount]; var v_power = new double[generalData.TurbinesAmount]; double area = 0; double r0 = 0.5 * generalData.TurbineDiameter; double ss0 = (pi * r0 * r0); var I = (int)Math.Truncate(generalData.PowerDistance / calcData.dx); int nd = Math.Max(1, I); for (var k = 1; k <= generalData.TurbinesAmount; k++) { int J = 0; double SS = 0.0; int nk = Math.Max(1, calcData.xc_turb[k - 1] - nd); double vv1 = calcData.vell_i[nk - 1, calcData.yc_turb[k - 1] - 1]; calcData.WPOWER[k - 1] = 0.0; double vv2 = 0.0; for (var i = k - 1; i >= 1; i = i - 1) // calculate the influence of the turbine i over the turbine k { double RR_I = r0 + generalData.WakeDecay * (calcData.x[nk - 1] - calcData.x[calcData.xc_turb[i - 1] - 1]); double DIJ = Math.Abs(generalData.y_turb[i - 1] - generalData.y_turb[k - 1]); if (((DIJ) < (RR_I + r0)) && (RR_I <= (r0 + DIJ))) { J = J + 1; double ALPHA_I = (RR_I * RR_I) + (DIJ * DIJ) - (r0 * r0); ALPHA_I = ALPHA_I / (2 * RR_I * DIJ); ALPHA_I = Math.Acos(ALPHA_I); double ALPHA_K = (r0 * r0) + (DIJ * DIJ) - (RR_I * RR_I); ALPHA_K = ALPHA_K / (2 * r0 * DIJ); ALPHA_K = Math.Acos(ALPHA_K); AAREA(ref RR_I, ref r0, ref DIJ, ref area); SHADOW[J - 1] = (ALPHA_I * (Math.Pow(RR_I, 2)) + ALPHA_K * (Math.Pow(r0, 2))); SHADOW[J - 1] = SHADOW[J - 1] - 2 * area; SS = SS + SHADOW[J - 1]; if (SS < ss0) { int jj_max; int jj_min; int mm; if (generalData.y_turb[k - 1] > generalData.y_turb[i - 1]) { mm = (INT(RR_I / calcData.dy)); jj_max = Math.Min(generalData.GridPointsY, calcData.yc_turb[i - 1] + mm + 1); jj_min = Math.Max(1, calcData.yc_turb[i - 1] + mm - 2); vv1 = calcData.vell_i[nk - 1, jj_max - 1]; v_power[J - 1] = calcData.vell_i[nk - 1, jj_min - 1]; } else { mm = (INT(RR_I / calcData.dy)); jj_max = Math.Min(generalData.GridPointsY, calcData.yc_turb[i - 1] + mm + 1); jj_min = Math.Max(1, calcData.yc_turb[i - 1] + mm - 2); vv1 = calcData.vell_i[nk - 1, jj_min - 1]; v_power[J - 1] = calcData.vell_i[nk - 1, jj_max - 1]; } } else { J = J - 1; } } } if (J > 0) { for (var i = 1; i <= J; i++) { vv2 = v_power[J - 1] * SHADOW[J - 1] + vv2; } } vv2 = (vv2 + vv1 * (ss0 - SS)) / ss0; calcData.WPOWER[k - 1] = 0.5 * generalData.AirDensity * (Math.Pow(vv2, 3)) * ss0 * calcData.Cp; } }
/// <summary> /// SUBROUTINE _SHADOW AREA /// </summary> /// <param name="generalData"></param> /// <param name="generalData"></param> private void COMPUTE_VELL(GeneralData generalData, CalcData calcData) { var SHADOW = new double[generalData.TurbinesAmount]; double rr_max = 0; double area = 0; for (var i = 0; i <= generalData.GridPointsX - 1; i++) { for (var j = 0; j <= generalData.GridPointsY - 1; j++) { calcData.vell_i[i, j] = generalData.VelocityAtHub; } } double r0 = 0.5 * generalData.TurbineDiameter; int nk = 2 * (INT(generalData.TurbineDiameter / calcData.dy)); for (var k = 1; k <= generalData.TurbinesAmount; k++) { int J = 0; double SS = 0.0; double ss0 = (pi * r0 * r0); for (var i = 1; i <= k - 1; i = i + 1) // calculate the influence of the turbine i over the turbine k { double RR_I = r0 + generalData.WakeDecay * (calcData.x[calcData.xc_turb[k - 1] - 1] - calcData.x[calcData.xc_turb[i - 1] - 1]); double DIJ = Math.Abs(generalData.y_turb[i - 1] - generalData.y_turb[k - 1]); if (RR_I >= (r0 + DIJ) || DIJ <= calcData.dy) { SS = SS + ((r0 * r0) / (RR_I * RR_I)); } else { if ((DIJ) < (RR_I + r0) && (DIJ) > calcData.dy) { J = J + 1; double ALPHA_I = (RR_I * RR_I) + (DIJ * DIJ) - (r0 * r0); ALPHA_I = ALPHA_I / (2 * RR_I * DIJ); ALPHA_I = Math.Acos(ALPHA_I); double ALPHA_K = (r0 * r0) + (DIJ * DIJ) - (RR_I * RR_I); ALPHA_K = ALPHA_K / (2 * r0 * DIJ); ALPHA_K = Math.Acos(ALPHA_K); AAREA(ref RR_I, ref r0, ref DIJ, ref area); SHADOW[J - 1] = (ALPHA_I * (Math.Pow(RR_I, 2)) + ALPHA_K * (Math.Pow(r0, 2))); SHADOW[J - 1] = SHADOW[J - 1] - 2 * area; SS = SS + ((SHADOW[J - 1]) / ss0) * ((r0 * r0) / (RR_I * RR_I)); } else { SS = SS; } } } for (var ii = calcData.xc_turb[k - 1]; ii <= generalData.GridPointsX; ii++) { double rrt = r0 + generalData.WakeDecay * (calcData.x[ii - 1] - calcData.x[calcData.xc_turb[k - 1] - 1]); rr_max = Math.Max(rrt, rr_max); int nj = (INT(rrt / calcData.dy)); int jj_min = Math.Max(1, calcData.yc_turb[k - 1] - nj); int jj_max = Math.Min(generalData.GridPointsY, calcData.yc_turb[k - 1] + nj); for (J = jj_min; J <= jj_max; J++) { if (((-calcData.vell_i[ii - 1, J - 1] + generalData.VelocityAtHub) > 0) && (ii > calcData.xc_turb[k - 1] + nk)) { double vv = calcData.vell_i[ii - 1, J - 1]; calcData.vell_i[ii - 1, J - 1] = generalData.VelocityAtHub + generalData.VelocityAtHub * (Math.Sqrt(1 - generalData.TurbineThrust) - 1) * ((r0 * r0) / (rrt * rrt)); calcData.vell_i[ii - 1, J - 1] = calcData.vell_i[ii - 1, J - 1] * (1 - (1 - Math.Sqrt(1 - generalData.TurbineThrust)) * SS); //vell_i(ii,j)=(vell_i(ii,j)+0.15*vv)/1.15; calcData.vell_i[ii - 1, J - 1] = Math.Min(vv, calcData.vell_i[ii - 1, J - 1]); } else { calcData.vell_i[ii - 1, J - 1] = generalData.VelocityAtHub + generalData.VelocityAtHub * (Math.Sqrt(1 - generalData.TurbineThrust) - 1) * (r0 / rrt) * (r0 / rrt); calcData.vell_i[ii - 1, J - 1] = calcData.vell_i[ii - 1, J - 1] * (1 - (1 - Math.Sqrt(1 - generalData.TurbineThrust)) * SS); } } } } }