public static float getSunlightAngle(PlanetSimulator pSim, int AltLayer, Cell cell) { Vector3 sunPos = pSim.sunDir; Vector3 cellPos = cell.Position; return(Vector3.Angle(cellPos, sunPos)); }
internal static float calculateHeatTransferCoefficient(PlanetSimulator pSim, int AltLayer, Cell cellA, Cell cellB) { //h = (Nu)(k)/D //Nu = Nusselt number, k = thermal conductivity, D = characteristic length parameter, such as diameter for flow through a pipe. float tg = calculateTemperatureGradient(pSim, AltLayer, AltLayer, cellA, cellB); float cellHeight = pSim.LiveMap[AltLayer][cellA].Height; float pointWidth = 2500f; //the width of the intersecting area between two cells float D = Mathf.Sqrt((pointWidth * cellHeight)); float Nu; float h; float k = (float)Heating.atmoThermalConductivity; if (tg > 0) //is cooling { Nu = calculateNusseltNumber(pSim, AltLayer, cellA, cellB, true); h = (Nu * k) / D; } else { Nu = calculateNusseltNumber(pSim, AltLayer, cellA, cellB, false); h = (Nu * k) / D; } return(h); }
internal static float calculateTemperatureGradient(PlanetSimulator pSim, int AltLayerA, int AltLayerB, Cell cellA, Cell cellB) { float Tgrad = pSim.LiveMap[AltLayerA][cellA].Temperature - pSim.LiveMap[AltLayerB][cellB].Temperature; return(Tgrad); }
internal static float calculateFinalTempDelta(PlanetSimulator pSim, int AltLayer, Cell cell) { //deltaT = ((h * A * Tgrad)/m)/c float deltaT; float HF = calculateNetHeatFlow(pSim, AltLayer, cell); float m = 100f; float c = (float)atmoHeatCapacity; deltaT = (HF / m) / c; return(deltaT); }
internal static float calculatePrandtlNumber(PlanetSimulator pSim, int AltLayer, Cell cell) { //PN = v*Cp/k //v is viscosity, Cp is specific heat capacity, k is thermal conductivity float v = calculateViscosity(pSim, AltLayer, cell); float Cp = (float)Heating.atmoHeatCapacity; float k = (float)Heating.atmoThermalConductivity; float PN = (v * Cp) / k; return(PN); }
public static bool isSunlight(PlanetSimulator pSim, int AltLayer, Cell cell) { if (Heating.getSunlightAngle(pSim, AltLayer, cell) > 90) { return(false); } else { return(true); } }
public static void CalculateShortwaves(PlanetSimulator pSim, Cell cell, WeatherCell[] wCellColumn) { for (int AltLayer = wCellColumn.Length - 1; AltLayer >= 0; AltLayer--) { WeatherCell temp = wCellColumn[AltLayer]; if (AltLayer == pSim.BufferMap.Count - 1) //Is it top layer? { float SunriseFactor = (float)(Mathf.Cos(WeatherFunctions.getLatitude(cell) * Mathf.Deg2Rad) + Mathf.Cos(getSunlightAngle(pSim, AltLayer, cell) * Mathf.Deg2Rad)) / 2f; //Debug.Log("Sunrise Factor: " + SunriseFactor); //checks out //Do check to see if top layer is in sunlight if (WeatherFunctions.isSunlight(pSim, AltLayer, cell)) { float bodyKSun = pSim.bodyKSun * SunriseFactor; //Debug.Log("bodyKSun: " + bodyKSun); temp.SWReflected = bodyKSun * temp.Albedo; temp.SWTransmitted = bodyKSun * temp.Transmissivity; //Debug.Log(temp.SWTransmitted); //top layer gives real values temp.SWAbsorbed = bodyKSun * (1 - temp.Albedo - temp.Transmissivity); } //Else, it's danky dark and this is where the sun don't shine else { temp.SWAbsorbed = 0; temp.SWReflected = 0; temp.SWTransmitted = 0; } } else if (AltLayer == 0) //Is it bottom layer? No transmit { temp.SWReflected = wCellColumn[AltLayer + 1].SWTransmitted * temp.Albedo; temp.SWTransmitted = 0f; temp.SWAbsorbed = wCellColumn[AltLayer + 1].SWTransmitted * (1 - temp.Albedo); //Debug.Log(pSim.BufferMap[AltLayer +1][cell].SWTransmitted); //Gives 0 } else //it's middle layers { temp.SWReflected = wCellColumn[AltLayer + 1].SWTransmitted * temp.Albedo; temp.SWTransmitted = wCellColumn[AltLayer + 1].SWTransmitted * temp.Transmissivity; temp.SWAbsorbed = wCellColumn[AltLayer + 1].SWTransmitted * (1 - temp.Albedo - temp.Transmissivity); //Debug.Log("Layer: "+ AltLayer + ", " + pSim.BufferMap[pSim.LiveMap.Count-1][cell].SWTransmitted); //gives 0 } wCellColumn[AltLayer] = temp; } }
public static float calculateEmissivity(PlanetSimulator pSim, int AltLayer, Cell cell) { if (pSim.LiveMap[0][cell].isOcean) { return(0.96f); } else if (WeatherFunctions.getLatitude(cell) > 60 || WeatherFunctions.getLatitude(cell) < -60 && pSim.LiveMap[0][cell].isOcean == false) { return(0.97f); } else { return(0.92f); } }
internal static float calculateViscosity(PlanetSimulator pSim, int AltLayer, Cell cell) { //u/u0 = (T/T0)^0.7 //u = u0 * ((T/273.15)^0.7) float T = pSim.LiveMap[AltLayer][cell].Temperature; float u = (float)Heating.atmoViscAtRef0C * (Mathf.Pow((T / 273.15f), 0.7f)); if (cell.Index == 10) { //Debug.Log("viscosity is: " + u); } return(u); }
internal static float calculateNetHeatFlow(PlanetSimulator pSim, int AltLayer, Cell cell) { //HF = h * A * Tgrad float HF = 0; foreach (Cell neighbor in cell.GetNeighbors(pSim.level)) { float Tgrad = calculateTemperatureGradient(pSim, AltLayer, AltLayer, cell, neighbor); float h = calculateHeatTransferCoefficient(pSim, AltLayer, cell, neighbor); float A = pSim.LiveMap[AltLayer][cell].Height * 2500; HF += h * A * Tgrad; } return(HF); //returns W/s }
internal static float calculateAtmosphericPathLength(PlanetSimulator pSim, int AltLayer, Cell cell) { float zenithAngle = getSunlightAngle(pSim, AltLayer, cell) * Mathf.Deg2Rad; float ymax = pSim.LiveMap[pSim.LiveMap.Count - 1][cell].Altitude + 2500f; float stuff = (float)Math.Sqrt( (((pSim.bodyRadius + pSim.LiveMap[AltLayer][cell].Altitude) / ymax) * ((pSim.bodyRadius + pSim.LiveMap[AltLayer][cell].Altitude) / ymax)) * (Mathf.Cos(zenithAngle) * Mathf.Cos(zenithAngle)) + ((2 * pSim.bodyRadius) / (ymax * ymax)) * (ymax - pSim.LiveMap[AltLayer][cell].Altitude) - ((ymax / ymax) * (ymax / ymax)) + 1 - ((pSim.bodyRadius + pSim.LiveMap[AltLayer][cell].Altitude) / ymax) * (Mathf.Cos(zenithAngle)) ); return(stuff); }
internal static float calculateTransmissivity(PlanetSimulator pSim, int AltLayer, Cell cell) { //Beers-lambert law covers transmissivity //basically: transmitting rad = starting rad * e^(-m*optical depth) //rearranged: transmissivity = e^(-m * optical depth) //-m is the optical airmass //which is a scaling parameter based on the amount of air that the ray will travel through //optical depth is the "opacity" of the air and is dependant on composition //optical airmass is dependant on the thickness of the layers, and pressure float opticalDepth = calculateOpticalDepth(pSim, cell); float opticalAirMass = calculateAtmosphericPathLength(pSim, AltLayer, cell); float T = Mathf.Pow((float)Math.E, (-opticalAirMass * opticalDepth)); return(T * (1 - pSim.LiveMap[AltLayer][cell].Albedo)); }
internal static void CalculateLongwaves(PlanetSimulator pSim, Cell cell, WeatherCell[] wCellColumn) { //calc emissions //calc transmissions //calc incoming //calc temp for (int AltLayer = 0; AltLayer < wCellColumn.Length; AltLayer++) { wCellColumn[AltLayer] = CalculateEmissions(pSim, AltLayer, cell, wCellColumn[AltLayer]); CalculateTransmissions(pSim, AltLayer, cell, wCellColumn); } for (int i = 0; i < wCellColumn.Length; i++) { CalculateIncoming(pSim, i, cell, wCellColumn); } }
internal static float calculateNusseltNumber(PlanetSimulator pSim, int AltLayer, Cell cellA, Cell cellB, bool isCooling) { float Re = calculateReynoldsNumber(pSim, AltLayer, cellA, cellB); float Pr = calculatePrandtlNumber(pSim, AltLayer, cellA); float Nu; if (isCooling) { Nu = 0.023f * Mathf.Pow(Re, 0.8f) * Mathf.Pow(Pr, 0.3f); } else { Nu = 0.023f * Mathf.Pow(Re, 0.8f) * Mathf.Pow(Pr, 0.4f); } return(Nu); }
void Awake() { sunMove = new SunMove(); pSim = new PlanetSimulator(5, 10, SunFunction, sunAngle, angularVelocity); simDisplay = new SimulatorDisplay(pSim, DisplayMapType.PRESSURE_MAP); aRenderer = new AxisRenderer(); debug = new DebugGUI(pSim); //cloudSystem = new CloudSystem(pSim); pSim.bufferFlip += simDisplay.OnBufferChange; if (mainCamera == null) { mainCamera = GameObject.Find("Main Camera"); SetCamera(); } }
internal static double atmoThermalConductivity = 0.024; //W/m-K public static void InitShortwaves(PlanetSimulator pSim, Cell cell) { //Debug.Log("Init shortwaves"); for (int index = pSim.LiveMap.Count - 1; index > 0; index--) { WeatherCell temp = pSim.BufferMap[index][cell]; if (index == pSim.LiveMap.Count - 1) //Is it top layer? { float SunriseFactor = (float)(Mathf.Cos(WeatherFunctions.getLatitude(cell) * Mathf.Deg2Rad) + Mathf.Cos(getSunlightAngle(pSim, index, cell) * Mathf.Deg2Rad)) / 2f; //check for sunlight if (WeatherFunctions.isSunlight(pSim, index, cell)) { float bodyKSun = pSim.bodyKSun * SunriseFactor; temp.SWReflected = bodyKSun * temp.Albedo; temp.SWTransmitted = bodyKSun * temp.Transmissivity; temp.SWAbsorbed = bodyKSun * (1 - temp.Albedo - temp.Transmissivity); } else { temp.SWAbsorbed = 0f; temp.SWReflected = 0f; temp.SWTransmitted = 0f; } } else if (index == 0) //is it bottom layer? No transmit { temp.SWReflected = pSim.BufferMap[index + 1][cell].SWTransmitted * temp.Albedo; temp.SWTransmitted = 0f; temp.SWAbsorbed = pSim.BufferMap[index + 1][cell].SWTransmitted * (1 - temp.Albedo - temp.Transmissivity); } else { temp.SWReflected = pSim.BufferMap[index + 1][cell].SWTransmitted * temp.Albedo; temp.SWTransmitted = pSim.BufferMap[index + 1][cell].SWTransmitted * temp.Transmissivity; temp.SWAbsorbed = pSim.BufferMap[index + 1][cell].SWTransmitted * (1 - temp.Albedo - temp.Transmissivity); } pSim.BufferMap[index][cell] = temp; } }
public static float newCalculatePressure(PlanetSimulator pSim, int AltLayer, Cell cell) { //p1 * t2 = p2 * t1; //p2 = (p1 * t2)/t1; float temp1 = pSim.LiveMap[AltLayer][cell].Temperature; float temp2 = pSim.BufferMap[AltLayer][cell].Temperature; float press1 = pSim.LiveMap[AltLayer][cell].Pressure; if (temp1 == 0) { temp1 = 1f; //Debug.Log("Temp is zero!"); } if (temp2 == 0) { temp2 = 1f; } float pressure = (press1 * temp1) / temp2; return(pressure); }
internal static float calculateReynoldsNumber(PlanetSimulator pSim, int AltLayer, Cell cellA, Cell cellB) { //Re = DVp/u //D = Distance parameter thing, V = velocity, p = density, u = viscosity float D = Mathf.Sqrt(pSim.LiveMap[AltLayer][cellA].Height * 2500); Vector3 cellVector = cellA.Position - cellB.Position; float v = pSim.LiveMap[AltLayer][cellB].WindDirection.magnitude; float V = v * Mathf.Cos((Vector3.Dot(cellVector, pSim.LiveMap[AltLayer][cellB].WindDirection))); if (float.IsNaN(V) && cellA.Index == 10) { Debug.Log("Velocity is NaN"); } float p = pSim.LiveMap[AltLayer][cellA].Density; float u = calculateViscosity(pSim, AltLayer, cellA); float Re = (D * V * p) / u; return(Re); }
internal static void CalculateIncoming(PlanetSimulator pSim, int AltLayer, Cell cell, WeatherCell[] wCellColumn) { WeatherCell temp = wCellColumn[AltLayer]; if (AltLayer == 0) //ground layer { temp.LWIn = temp.Emissivity * (wCellColumn[AltLayer + 1].LWOut + wCellColumn[AltLayer + 1].LWIn); } else if (AltLayer == pSim.LiveMap.Count - 2) //middle layers { temp.LWIn = temp.Emissivity * ((wCellColumn[AltLayer - 1].LWOut + wCellColumn[AltLayer - 1].LWTransmit) + (wCellColumn[AltLayer + 1].LWOut + wCellColumn[AltLayer + 1].LWTransmit)); } else //top layer { temp.LWIn = temp.Emissivity * (wCellColumn[AltLayer - 1].LWOut + wCellColumn[AltLayer - 1].LWTransmit); } wCellColumn[AltLayer] = temp; }
internal static float CalculateTemperature(PlanetSimulator pSim, int AltLayer, Cell cell) { //Kin + Lin = Lout; //Lout = e,layer * SBC * T,layer^4 //t^4 = Lout/ e,layer * SBC //t = 4throot(Lout/e,layer * SBC) //CalculateShortwaves(pSim, AltLayer, cell); //CalculateLongwaves(pSim, AltLayer, cell); //Debug.Log("SWAbs: " + pSim.BufferMap[AltLayer][cell].SWAbsorbed); //return Mathf.Pow((float)(((pSim.BufferMap[AltLayer][cell].LWOut) / //(pSim.LiveMap[AltLayer][cell].Emissivity * SBC))), 0.25f); if (pSim.timesLeft > 0) { return(Mathf.Pow((float)(((pSim.BufferMap[AltLayer][cell].SWAbsorbed + pSim.BufferMap[AltLayer][cell].LWIn) / 2.0f) / (pSim.LiveMap[AltLayer][cell].Emissivity * SBC)), 0.25f)); } else { return(Mathf.Pow((float)(((pSim.BufferMap[AltLayer][cell].SWAbsorbed + pSim.BufferMap[AltLayer][cell].LWIn) / 2.0f) / (pSim.LiveMap[AltLayer][cell].Emissivity * SBC)), 0.25f)); //+calculateFinalTempDelta(pSim, AltLayer, cell); } }
internal static void CalculateTransmissions(PlanetSimulator pSim, int AltLayer, Cell cell, WeatherCell[] wCellColumn) { WeatherCell wCell = wCellColumn[AltLayer]; if (AltLayer == 0) //ground layer, no transmit { wCell.LWTransmit = 0; } else if (AltLayer == 1) //layer above ground { wCell.LWTransmit = wCellColumn[AltLayer - 1].LWOut * (1 - wCell.Emissivity); } else if (AltLayer <= pSim.LiveMap.Count - 2) //middle layers { wCell.LWOut = (1 - wCell.Emissivity) * (wCellColumn[AltLayer - 1].LWOut + wCellColumn[AltLayer - 1].LWTransmit); } else //Top layer { wCell.LWOut = (1 - wCell.Emissivity) * (wCellColumn[AltLayer - 1].LWOut + wCellColumn[AltLayer - 1].LWTransmit); } wCellColumn[AltLayer] = wCell; }
internal static void InitLongwaves(PlanetSimulator pSim, Cell cell) { for (int index = 0; index <= pSim.LiveMap.Count - 1; index++) { WeatherCell temp = pSim.BufferMap[index][cell]; if (index == 0) //is surface layer { temp.LWOut = temp.Emissivity * SBC * ToTheFourth(temp.Temperature); temp.LWIn = 0; temp.LWTransmit = 0; } else if (index == 1) //layer above surface { temp.LWIn = pSim.BufferMap[index - 1][cell].LWOut * temp.Emissivity; temp.LWTransmit = pSim.BufferMap[index - 1][cell].LWOut * (1 - temp.Emissivity); temp.LWOut = temp.Emissivity * SBC * ToTheFourth(temp.Temperature); } else if (index < pSim.LiveMap.Count - 2) //middle layers { temp.LWIn = temp.Emissivity * (pSim.BufferMap[index - 1][cell].LWOut + pSim.BufferMap[index - 1][cell].LWTransmit); temp.LWTransmit = (1 - temp.Emissivity) * (pSim.BufferMap[index - 1][cell].LWOut + pSim.BufferMap[index - 1][cell].LWTransmit); temp.LWOut = temp.Emissivity * SBC * ToTheFourth(temp.Temperature); } else//top layer { temp.LWIn = temp.Emissivity * (pSim.BufferMap[index - 1][cell].LWOut + pSim.BufferMap[index - 1][cell].LWTransmit); temp.LWTransmit = (1 - temp.Emissivity) * (pSim.BufferMap[index - 1][cell].LWOut + pSim.BufferMap[index - 1][cell].LWTransmit); temp.LWOut = temp.Emissivity * SBC * ToTheFourth(temp.Temperature); } pSim.BufferMap[index][cell] = temp; } }
public static Vector3 CalculateWindVector(PlanetSimulator pSim, int AltLayer, Cell cell) { //Debug.Log("Calcing wind vector"); Vector3 resultant = Vector3.zero; foreach (Cell neighbour in cell.GetNeighbors(pSim.level)) { float deltaPressure = pSim.LiveMap[AltLayer][cell].Pressure - pSim.LiveMap[AltLayer][neighbour].Pressure; Vector3 cellVector = cell.Position - neighbour.Position; float neighbourDistance = cellVector.magnitude; cellVector.Normalize(); if (deltaPressure == 0f) { continue; } float acc = (-1 / pSim.LiveMap[AltLayer][cell].Density) * (deltaPressure / neighbourDistance); //v = a * sqrt(2d/a) float windSpeed = acc * Mathf.Sqrt((2 * neighbourDistance) / Mathf.Abs(acc)); //divide by 2 because opposite shit. Trust me, it is. Vector3 windVector = new Vector3(cellVector.x * windSpeed / 2f, cellVector.y * windSpeed / 2f, cellVector.z * windSpeed / 2f); //Apply Coriolis to windVector Vector3 corAcc = 2 * Vector3.Cross(windVector, pSim.angularVelocity + new Vector3(0f, Mathf.Cos(WeatherFunctions.getLatitude(cell)), Mathf.Sin(WeatherFunctions.getLatitude(cell)))); windVector = windVector + corAcc; resultant += windVector; } //Start work on upper cell and lower cell if (AltLayer + 1 <= pSim.LiveMap.Count - 1) { float deltaPressure1 = pSim.LiveMap[AltLayer][cell].Pressure - pSim.LiveMap[AltLayer + 1][cell].Pressure; Vector3 cellVector = cell.Position - (cell.Position * 1.25f); float neighbourDistance = cellVector.magnitude; cellVector.Normalize(); if (deltaPressure1 == 0f) { } else { float acc = (-1 / pSim.LiveMap[AltLayer][cell].Density) * (deltaPressure1 / neighbourDistance); //v = a * sqrt(2d/a) float windSpeed = acc * Mathf.Sqrt((2 * neighbourDistance) / Mathf.Abs(acc)); //divide by 2 because opposite shit. Trust me, it is. Vector3 windVector = new Vector3(cellVector.x * windSpeed / 2f, cellVector.y * windSpeed / 2f, cellVector.z * windSpeed / 2f); //Apply Coriolis to windVector Vector3 corAcc = 2 * Vector3.Cross(windVector, pSim.angularVelocity + new Vector3(0f, Mathf.Cos(WeatherFunctions.getLatitude(cell)), Mathf.Sin(WeatherFunctions.getLatitude(cell)))); windVector = windVector + corAcc; resultant += windVector; } } if (AltLayer - 1 >= 0) { float deltaPressure1 = pSim.LiveMap[AltLayer][cell].Pressure - pSim.LiveMap[AltLayer - 1][cell].Pressure; Vector3 cellVector = cell.Position - (cell.Position * -0.75f); float neighbourDistance = cellVector.magnitude; cellVector.Normalize(); if (deltaPressure1 == 0f) { } else { float acc = (-1 / pSim.LiveMap[AltLayer][cell].Density) * (deltaPressure1 / neighbourDistance); //v = a * sqrt(2d/a) float windSpeed = acc * Mathf.Sqrt((2 * neighbourDistance) / Mathf.Abs(acc)); //divide by 2 because opposite shit. Trust me, it is. Vector3 windVector = new Vector3(cellVector.x * windSpeed / 2f, cellVector.y * windSpeed / 2f, cellVector.z * windSpeed / 2f); //Apply Coriolis to windVector Vector3 corAcc = 2 * Vector3.Cross(windVector, pSim.angularVelocity + new Vector3(0f, Mathf.Cos(WeatherFunctions.getLatitude(cell)), Mathf.Sin(WeatherFunctions.getLatitude(cell)))); windVector = windVector + corAcc; resultant += windVector; } } return(resultant); }
public static float getAltitude(PlanetSimulator pSim, int AltLayer, Cell cell) { return(pSim.LiveMap[AltLayer][cell].Altitude); }
public static float getCellAlbedo(PlanetSimulator pSim, int AltLayer, Cell cell) { return(0f); }
public float getWindSpeed(PlanetSimulator pSim, int AltLayer, Cell cell) { return(pSim.LiveMap[AltLayer][cell].WindDirection.magnitude); }
public static float getTemperature(PlanetSimulator pSim, int AltLayer, Cell cell) { return(pSim.LiveMap[AltLayer][cell].Temperature); }
public static float calculateAlbedo(PlanetSimulator pSim, int AltLayer, Cell cell) { return(0.30f * Mathf.Pow(0.85f, AltLayer)); }
internal static WeatherCell CalculateEmissions(PlanetSimulator pSim, int AltLayer, Cell cell, WeatherCell wCell) { wCell.LWOut = wCell.Emissivity * SBC * ToTheFourth(wCell.Temperature); //temp = wCell; return(wCell); }
internal static float calculateOpticalDepth(PlanetSimulator pSim, Cell cell) { float opticalDepth = 0.02f; //Original: 0.2f return(opticalDepth); }