public static void absorbCO2(TClima clima, TWorld w, TSolarSurface s, long i, long j) { double absorption, rain_times; if (clima.isIce[i, j] || clima.co2_tons[i, j] == 0 || !statechanges.isInSunlight(i, j, s)) { return; } if (w.isOcean[i, j]) { // absorption scaled over 12 h per day and over 3 quarters of earth surface absorption = TSimConst.co2_absorption_ocean / (365 / 12 / 15 * TSimConst.degree_step) / (360 * 180 * 3 / 4); } else { // absorption scaled over 12 h per day and over 1 quarter of earth surface absorption = TSimConst.co2_absorption_vegetation / (365 / 12 / 15 * TSimConst.degree_step) / (360 * 180 * 1 / 4); // jungle absorbs more than desert rain_times = clima.rain_times[i, j]; if (rain_times > 5) { rain_times = 5; } absorption = absorption * rain_times; } clima.co2_tons[i, j] = clima.co2_tons[i, j] - absorption; if (clima.co2_tons[i, j] < 0) { clima.co2_tons[i, j] = 0; } }
public static void moveSteamDown(TClima clima, TWorld w, TSolarSurface s, int l, long i, long j) { double transferSteam, maxSteam, transferEnergy; // recalculate temperature clima.T_atmosphere[l, i, j] = statechanges.thermicGradient(w, clima, l * TMdlConst.distance_atm_layers, clima.T_atmosphere[0, i, j], i, j); if (clima.steam[l, i, j] == 0) { return; } // how much steam could stay in the upper layer l maxSteam = statechanges.maxWaterInSteam(clima, w, l, i, j); // how much steam has to be transferred down transferSteam = (clima.steam[l, i, j] - maxSteam) * (1 / TSimConst.steam_hours); if (transferSteam < 0) { return; } // energy which is given back to atmosphere transferEnergy = transferSteam * TPhysConst.grav_acc * TMdlConst.distance_atm_layers; // let's move it dowm clima.energy_atmosphere[i, j] = clima.energy_atmosphere[i, j] + transferEnergy; clima.steam[l, i, j] = clima.steam[l, i, j] - transferSteam; clima.steam[l - 1, i, j] = clima.steam[l - 1, i, j] + transferSteam; }
public static void moveSteamUp(TClima clima, TWorld w, TSolarSurface s, int l, long i, long j) { double availableSteam, maxSteam, transferEnergy, evaporationPct; // let's compute first the temperature on the upper layer based on the thermic gradient clima.T_atmosphere[l, i, j] = statechanges.thermicGradient(w, clima, l * TMdlConst.distance_atm_layers, clima.T_atmosphere[0, i, j], i, j); // we do not add altitude here, as altitude is already in clima.T_atmosphere[0, i, j] // if there is ice on ground or no steam to push up we exit if (clima.isIce[i, j] || clima.steam[l - 1, i, j] == 0) { return; } evaporationPct = statechanges.evaporatePercentage(clima, clima.T_atmosphere[l - 1, i, j], i, j); if (evaporationPct == 0) { return; } // how much steam could stay in the upper layer l? maxSteam = statechanges.maxWaterInSteam(clima, w, l, i, j); // how much steam is available for transfer availableSteam = Math.Min(clima.steam[l - 1, i, j], maxSteam) * (1 / TSimConst.steam_hours) * evaporationPct; // is there enough energy to perform the transfer to the upper layer? transferEnergy = availableSteam * TPhysConst.grav_acc * TMdlConst.distance_atm_layers; if (clima.energy_atmosphere[i, j] > transferEnergy) { // let's move it up clima.energy_atmosphere[i, j] = clima.energy_atmosphere[i, j] - transferEnergy; clima.steam[l - 1, i, j] = clima.steam[l - 1, i, j] - availableSteam; clima.steam[l, i, j] = clima.steam[l, i, j] + availableSteam; } }
public static void computeSolarSurface(TSolarSurface s, TTime t, double earthDeclination) { int j, shift; double daylengthhour; for (j = 0; j < 180; j++) { daylengthhour = computeDayLenghtDuration(earthDeclination, j, t); // for fix daylength 12; if (daylengthhour == Constants.FULL_NIGHT) { s.degstart[j] = Constants.FULL_NIGHT; s.degend[j] = Constants.FULL_NIGHT; } else { shift = (int)Math.Round(daylengthhour * 15 / 2); // each hour are 15 degrees (360/24) s.degstart[j] = 179 - shift; s.degend[j] = 179 + shift; s.degstart[j] = s.degstart[j] + TMdlConst.initDegreeSunlight; s.degend[j] = s.degend[j] + TMdlConst.initDegreeSunlight; // 12 hours which are 15 degrees a part if (s.degstart[j] >= 360) { s.degstart[j] = s.degstart[j] - 360; } if (s.degend[j] >= 360) { s.degend[j] = s.degend[j] - 360; } } // else FULL_NIGHT } // for }
public static void updateOutgoingEnergyOnCellGrid(TClima clima, TWorld w, TSolarSurface sSurface, double earthInclination, int i, int j) { updateTemperature(clima, w, i, j); exchangeEnergyBetweenAtmAndTerrain(clima, w, i, j); updateTemperature(clima, w, i, j); radiateEnergyIntoSpace(clima, w, i, j); updateTemperature(clima, w, i, j); }
static void TestTwoDays() { double[,] tmpGrid = new double[360, 180]; short[,] wind = new short[360, 180]; double[,] T_atmosphere = new double[360, 180]; TWorld world = new TWorld(); Debug.WriteLine("Init World"); initmodel.initWorld(world); TClima clima = new TClima(); Debug.WriteLine("Init Clima"); initmodel.initClima(world, clima, 16, 16); TTime t = new TTime(); TSolarSurface s = new TSolarSurface(); Debug.WriteLine("Init time and solar surface"); initmodel.initTime(t, s); Debug.WriteLine("Initial conditions created"); Debug.WriteLine("Simulating 3 days of weather including energy cycle, winds,"); Debug.WriteLine("marine currents, steam generation and rain"); for (int day = 170; day < 173; day++) { Debug.Write("Simulating day = " + day + " "); for (int hour = 0; hour < 24; hour++) { Debug.Write("."); riverandlakes.clearRain(clima); double earthInclination = energyfunctions.computeEarthDeclination(day); for (int j = 0; j < 180; j++) { for (int i = 0; i < 360; i++) { energyfunctions.updateIncomingEnergyOnCellGrid(clima, world, s, earthInclination, i, j); watercycle.formSteam(clima, world, s, i, j, t.day); } } flux.moveEnergy(clima, clima.energy_atmosphere, tmpGrid, T_atmosphere, wind, flux.WIND, world, true); #if TODO flux.moveEnergy(clima, clima.energy_ocean_terr, tmpGrid, clima.T_ocean_terr, clima.surfaceTransfer, flux.SURFACE_AND_MARINE_CURRENT, world, true); //printPlanet(2000, day, hour, clima, world, true, false); watercycle.moveSteam(clima.wind, clima.steam, tmpGrid); #endif } } }
public static void mainSimDayLoop(TWorld world, TClima clima, TSolarSurface s, TTime t, double[,] tmpGrid, double earthDeclination) { #if TODO computeSolarSurface(s, t, earthDeclination); increasePopulation(clima, 1); printEarthStatus(t.year, t.day, Round(t.hour), clima, world); printPlanet(t.year, t.day, Round(t.hour), clima, world, false, true); if (t.day % TSimConst.decrease_rain_times == 0) { decreaseRainTimes(clima); } #endif throw new NotImplementedException(); }
public static void updateIncomingEnergyOnCellGrid(TClima clima, TWorld w, TSolarSurface sSurface, double earthInclination, int i, int j) { double energyIn; if (statechanges.isInSunlight(i, j, sSurface)) { energyIn = computeEnergyFromSunOnSquare(i, j, earthInclination, clima, w); spreadEnergyOnAtmosphereAndTerrain(clima, energyIn, i, j); updateTemperature(clima, w, i, j); } radiateTerrestrialEnergy(clima, w, i, j); updateTemperature(clima, w, i, j); }
public static bool isInSunlight(long i, long j, TSolarSurface sSurface) { if (sSurface.degstart[j] == Constants.FULL_NIGHT) { return(false); } if (sSurface.degend[j] > sSurface.degstart[j]) { return((i >= sSurface.degstart[j]) && (i <= sSurface.degend[j])); } else { return((i <= sSurface.degend[j]) || (i >= sSurface.degstart[j])); } }
public static void stepTime(TTime t, TSolarSurface sSurface) { long j; t.hour = t.hour + TSimConst.degree_step / 15; if (t.hour >= 24) { t.hour = 0; t.day = t.day + 1; if (t.day > 365) { t.day = 1; t.year = t.year + 1; } } if (TMdlConst.rotation) { for (j = 90; j < 180; j++) { if (sSurface.degstart[j] == Constants.FULL_NIGHT) { continue; } sSurface.degstart[j] = sSurface.degstart[j] - TSimConst.degree_step * TMdlConst.inverse_rotation; if (sSurface.degstart[j] < 0) { sSurface.degstart[j] = sSurface.degstart[j] + 360; } if (sSurface.degstart[j] >= 360) { sSurface.degstart[j] = sSurface.degstart[j] - 360; } sSurface.degend[j] = sSurface.degend[j] - TSimConst.degree_step * TMdlConst.inverse_rotation; if (sSurface.degend[j] < 0) { sSurface.degend[j] = sSurface.degend[j] + 360; } if (sSurface.degend[j] >= 360) { sSurface.degend[j] = sSurface.degend[j] - 360; } } } }
public static void initTimeHDY(long hour, long day, long year, TTime t, TSolarSurface sSurface) { if ((hour < 0) || (hour > 23)) { throw new Exception("Hour has to lie between 0 and 23"); } if ((day < 1) || (day > 365)) { throw new Exception("Day has to lie between 1 and 365"); } if ((year < 0) || (year > 10000)) { throw new Exception("Year has to lie between 0 and 10000"); } t.hour = hour; t.day = day; t.year = year; }
public static void formSteam(TClima clima, TWorld w, TSolarSurface s, long i, long j, long day) { double energyToBoil, evaporationPct, evaporationQty; if (clima.isIce[i, j] || statechanges.isInSunlight(i, j, s)) { return; } evaporationPct = statechanges.evaporatePercentage(clima, clima.T_ocean_terr[i, j], i, j); if (evaporationPct == 0) { return; } // steam over ocean if (w.isOcean[i, j]) { // check how much steam we could form evaporationQty = (statechanges.maxWaterInSteam(clima, w, 0, i, j) - clima.steam[0, i, j]) * (1 / TSimConst.steam_hours) * evaporationPct; } else // steam produced by river and lakes { if (clima.water_surface[i, j] == 0) { return; } // vegetation (where it rains more than one time, slows down evaporation) if (clima.rain_times[i, j] > 0) { evaporationQty = clima.water_surface[i, j] / clima.rain_times[i, j] * evaporationPct * (1 / TSimConst.steam_hours); } else { evaporationQty = clima.water_surface[i, j] * evaporationPct * (1 / TSimConst.steam_hours); } if (day % TSimConst.decrease_rain_times == 0) { clima.rain_times[i, j]--; if (clima.rain_times[i, j] < 0) { clima.rain_times[i, j] = 0; } } } if (evaporationQty > 0) // here we will rain in a later public static void call { // energy to boil the steam if (TPhysConst.kT_boil - clima.T_atmosphere[0, i, j] > 0) { energyToBoil = TPhysConst.cp_steam * evaporationQty * (TPhysConst.kT_boil - clima.T_atmosphere[0, i, j]); } else { energyToBoil = 0; } if (clima.energy_ocean_terr[i, j] >= energyToBoil) // the atmosphere has enough energy to carry the steam { clima.steam[0, i, j] = clima.steam[0, i, j] + evaporationQty; clima.energy_ocean_terr[i, j] = clima.energy_ocean_terr[i, j] - energyToBoil; if (!w.isOcean[i, j]) { clima.water_surface[i, j] = clima.water_surface[i, j] - evaporationQty; } } } }
public static void mainSimTimestepLoop(TWorld world, TClima clima, TSolarSurface s, TTime t, double[,] tmpGrid, double arthDeclination) { long l, i, j; #if TODO clearRain(clima); for (j = 0; j < 180; j++) { for (i = 0; i < 360; i++) { updateIncomingEnergyOnCellGrid(clima, world, s, earthDeclination, i, j); formSteam(clima, world, s, i, j, t.day); // add steam to layer 0 for (l = 1; l < TMdlConst.atmospheric_layers; l++) // move steam from layer l-1 to layer l { moveSteamUp(clima, world, s, l, i, j); } formCO2(clima, world, i, j); } } moveEnergy(clima, clima.energy_ocean_terr, tmpGrid, clima.T_ocean_terr, clima.surfaceTransfer, SURFACE_AND_MARINE_CURRENT, world, true); moveEnergy(clima, clima.energy_atmosphere, tmpGrid, clima.T_atmosphere[0, 0, 0], clima.wind[0, 0, 0], WIND, world, true); flux.applyCoriolis(clima.wind[0], clima.wind[0], TMdlConst.rotation); for (l = 1; l < TMdlConst.atmospheric_layers; l++) { flux.applyCoriolis(clima.wind[l - 1], clima.wind[l], TMdlConst.rotation); } followSurface(world, clima.wind[0]); for (l = 0; l < TMdlConst.atmospheric_layers; l++) { moveSteam(clima.wind[l], clima.steam[l], tmpGrid); } moveCO2(clima.wind[0], clima.co2_tons[0], tmpGrid); vulcanoEruption(world, clima); singleNuclearBomb(world, clima); nuclearWar(world, clima); moveAshes(clima.wind[0, 0, 0], clima.ashes_pct[0, 0], tmpGrid); ashesFallDown(world, clima); for (j = 0; j < 180; j++) { for (i = 0; i < 360; i++) { for (l = TMdlConst.atmospheric_layers - 1; l > 0; l--) // move steam from layer l to layer l-1 { moveSteamDown(clima, world, s, l, i, j); } rainSteam(clima, world, i, j); waterOrIce(clima, world, i, j); absorbCO2(clima, world, s, i, j); updateOutgoingEnergyOnCellGrid(clima, world, s, earthDeclination, i, j); } } moveWaterDownToOcean(world, clima, clima.water_surface, tmpGrid); stepTime(t, s); #endif throw new NotImplementedException(); }
public static void initTime(TTime t, TSolarSurface sSurface) { initTimeHDY(0, 1, 2000, t, sSurface); }