public static void OUTPUT(int NI, int NJ, int NK, bool intermediate) { // force a garbage collection on the Large Object heap to clean up the envrionment //GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(); //Check for quasi-steady-state requirement (VDI 3783-7) -> the lateral region where topography is smoothed is not considered if (Program.REALTIME > 0.8 * Program.DTI) { StreamWriter writesteadystate = null; // create streamwriter-container if (Program.WriteSteadyState) // write data for steady state criterion to a file { string filename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + "_steady_state.txt"); try { writesteadystate = new StreamWriter(filename); writesteadystate.WriteLine("ncols " + Convert.ToString(NI - 2 * Program.nr_cell_smooth)); writesteadystate.WriteLine("nrows " + Convert.ToString(NJ - 2 * Program.nr_cell_smooth)); writesteadystate.WriteLine("xllcorner " + Convert.ToString(Program.IKOOA + Program.nr_cell_smooth * Program.DDX[1])); // TODO: Fix for horizontal mesh grading writesteadystate.WriteLine("yllcorner " + Convert.ToString(Program.JKOOA + Program.nr_cell_smooth * Program.DDX[1])); // TODO: Fix for horizontal mesh grading writesteadystate.WriteLine("cellsize " + Convert.ToString(Program.DDX[1])); writesteadystate.WriteLine("NODATA_value " + "-9999"); } catch { } } double UTREFFER = 0; double VTREFFER = 0; double WTREFFER = 0; for (int j = NJ - Program.nr_cell_smooth; j >= 1 + Program.nr_cell_smooth; j--) { string steadystateline = ""; for (int i = 1 + Program.nr_cell_smooth; i <= NI - Program.nr_cell_smooth; i++) { Byte steadystatevalue = 0; if ((Math.Abs(Program.U_TEMP[i][j] - Program.U[i][j][1]) <= 0.35) || (Math.Abs((Program.U_TEMP[i][j] - Program.U[i][j][1]) / (Math.Max(Math.Abs(Program.U[i][j][1]), 0.001))) <= 0.1)) { UTREFFER++; steadystatevalue = 1; } if ((Math.Abs(Program.V_TEMP[i][j] - Program.V[i][j][1]) <= 0.35) || (Math.Abs((Program.V_TEMP[i][j] - Program.V[i][j][1]) / (Math.Max(Math.Abs(Program.V[i][j][1]), 0.001))) <= 0.1)) { VTREFFER++; steadystatevalue += 2; } if ((Math.Abs(Program.W_TEMP[i][j] - Program.W[i][j][1]) <= 0.35) || (Math.Abs((Program.W_TEMP[i][j] - Program.W[i][j][1]) / (Math.Max(Math.Abs(Program.W[i][j][1]), 0.001))) <= 0.1)) { WTREFFER++; steadystatevalue += 4; } if (writesteadystate != null) // write file! { if (j == 1 + Program.nr_cell_smooth && i == 1 + Program.nr_cell_smooth) // Avoid blank raster data set for GUI { steadystateline += Convert.ToString((double)steadystatevalue + 0.01).Replace(Program.decsep, ".") + " "; } else { steadystateline += Convert.ToString(steadystatevalue) + " "; } } } if (writesteadystate != null) { writesteadystate.WriteLine(steadystateline); } } if (writesteadystate != null) { try { writesteadystate.Close(); writesteadystate.Dispose(); } catch { } } UTREFFER /= ((NI - 2 * Program.nr_cell_smooth) * (NJ - 2 * Program.nr_cell_smooth)); VTREFFER /= ((NI - 2 * Program.nr_cell_smooth) * (NJ - 2 * Program.nr_cell_smooth)); WTREFFER /= ((NI - 2 * Program.nr_cell_smooth) * (NJ - 2 * Program.nr_cell_smooth)); } //Check for possible numerical instabilities if (Program.MASSOURCE_FIRST < Program.SUMG) { //compute maximum wind speeds float UMAX = 0; float VMAX = 0; float WMAX = 0; for (int i = 2; i <= NI - 1; i++) { for (int j = 2; j <= NJ - 1; j++) { for (int k = 1; k <= NK - 1; k++) { UMAX = (float)Math.Max(Math.Abs(Program.U[i][j][k]), UMAX); VMAX = (float)Math.Max(Math.Abs(Program.V[i][j][k]), VMAX); WMAX = (float)Math.Max(Math.Abs(Program.W[i][j][k]), WMAX); } } } try { if ((UMAX > 50) || (VMAX > 50) || (WMAX > 20)) { try { string err = "Final mass divergence is larger than initial mass divergence." + " Possible numerical instabilities detected for flow field: " + Program.IWETTER.ToString(); ProgramWriters.LogfileProblemreportWrite(err); err = "Maximum wind speeds in east/west/vertical direction: " + UMAX.ToString("0000.0") + ";" + VMAX.ToString("0000.0") + ";" + WMAX.ToString("0000.0"); ProgramWriters.LogfileProblemreportWrite(err); } catch { } } } catch { } } //differentiating between intermediate output and final output in case of meteopgt.all input string wndfilename; string wndExtrafilename; if (intermediate == false) { wndfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".wnd"); wndExtrafilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".ewnd"); } else { wndfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".wnd"); wndExtrafilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".ewnd"); //intermediate output in case of meteopgt.all if (((METEO == "Y") || (METEO == "y")) && (Program.ISTAT == 0)) { //compute fictious weather number int FILENUMBER = 0; double time_real = Program.REALTIME; if (time_real < Program.IOUTPUT) // 1st situation should be stored after 1800 s { time_real = Program.IOUTPUT + 2; } Meteopgtall.meteopgtall_calculate(Program.meteopgt_nr, Program.IWETTER, Program.DTI, time_real, Program.IOUTPUT, Program.TLIMIT2, ref FILENUMBER); wndfilename = (Convert.ToString(FILENUMBER).PadLeft(5, '0') + ".wnd"); wndExtrafilename = (Convert.ToString(FILENUMBER).PadLeft(5, '0') + ".ewnd"); } } Console.Write(wndfilename + " "); // write windfile name to the console bool writeExtra = true; BinaryWriter writer = new BinaryWriter(File.Open(wndfilename, FileMode.Create)); int header = -1; Int16 dummy; Int32 dummy2; float GRAMMhorgridsize = (float)Program.DDX[1]; // TODO: Not possible with horizontal mesh grading if (writeExtra) { Console.Write(wndExtrafilename + " "); // write windfile name to the console BinaryWriter ewriter = new BinaryWriter(File.Open(wndExtrafilename, FileMode.Create)); ewriter.Write(header); ewriter.Write(NI); ewriter.Write(NJ); ewriter.Write(NK); ewriter.Write(GRAMMhorgridsize); for (int i = 1; i <= NI; i++) { for (int j = 1; j <= NJ; j++) { for (int k = 1; k <= NK; k++) { try { dummy = Convert.ToInt16(Program.TE[i][j][k] * 10000.0); } catch { dummy = Int16.MaxValue; } ewriter.Write(dummy); try { dummy = Convert.ToInt16(Program.DISS[i][j][k] * 1000000.0); } catch { dummy = Int16.MaxValue; } ewriter.Write(dummy); try { dummy = Convert.ToInt16(Program.DP[i][j][k] * 100.0); } catch { dummy = Int16.MaxValue; } ewriter.Write(dummy); try { dummy = Convert.ToInt16((Program.TABS[i][j][k] - 273.15) * 100.0); } catch { dummy = Int16.MaxValue; } ewriter.Write(dummy); } } } ewriter.Close(); ewriter.Dispose(); } //there are two different formats: IOUTPUT = 0 (standard output for GRAL-GUI users) and IOUTPUT = 3 for SOUNDPLAN USERS if (Program.IOUT == 0) { writer.Write(header); writer.Write(NI); writer.Write(NJ); writer.Write(NK); writer.Write(GRAMMhorgridsize); for (int i = 1; i <= NI; i++) { for (int j = 1; j <= NJ; j++) { for (int k = 1; k <= NK; k++) { try { dummy = Convert.ToInt16(Program.U[i][j][k] * 100); } catch { //Console.WriteLine("U " + e.Message.ToString() + Program.U[i][j][k].ToString()); dummy = Int16.MaxValue; } writer.Write(dummy); try { dummy = Convert.ToInt16(Program.V[i][j][k] * 100); } catch { //Console.WriteLine("V " + e.Message.ToString() + Program.V[i][j][k].ToString()); dummy = Int16.MaxValue; } writer.Write(dummy); try { dummy = Convert.ToInt16(Program.W[i][j][k] * 100); } catch { //Console.WriteLine("W " + e.Message.ToString() + Program.W[i][j][k].ToString()); dummy = Int16.MaxValue; } writer.Write(dummy); } } } } if (Program.IOUT == 3) { for (int i = 1; i <= NI; i++) { for (int j = 1; j <= NJ; j++) { for (int k = 1; k <= NK; k++) { writer.Write((float)Program.U[i][j][k]); writer.Write((float)Program.V[i][j][k]); writer.Write((float)Program.W[i][j][k]); } } } } writer.Close(); writer.Dispose(); //output for friction velocity and Obukhov length // write a Zip file string stabclassfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".scl"); if (intermediate == false) { stabclassfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".scl"); } else { stabclassfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".scl"); //intermediate output in case of meteopgt.all if (((METEO == "Y") || (METEO == "y")) && (Program.ISTAT == 0)) { //compute fictious weather number int FILENUMBER = 0; double time_real = Program.REALTIME; if (time_real < Program.IOUTPUT) // 1st situation should be stored after 1800 s { time_real = Program.IOUTPUT + 2; } Meteopgtall.meteopgtall_calculate(Program.meteopgt_nr, Program.IWETTER, Program.DTI, time_real, Program.IOUTPUT, Program.TLIMIT2, ref FILENUMBER); stabclassfilename = (Convert.ToString(FILENUMBER).PadLeft(5, '0') + ".scl"); } } try { Console.Write(stabclassfilename + " "); // write windfile name to the console using (FileStream zipToOpen = new FileStream(stabclassfilename, FileMode.Create)) { using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update)) { string ustarfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".ust"); ZipArchiveEntry write_entry1 = archive.CreateEntry(ustarfilename); using (writer = new BinaryWriter(write_entry1.Open())) { writer.Write(header); writer.Write(NI); writer.Write(NJ); writer.Write(NK); writer.Write(GRAMMhorgridsize); for (int i = 1; i <= NI; i++) { for (int j = 1; j <= NJ; j++) { dummy = Convert.ToInt16(Program.UST[i][j] * 1000); writer.Write(dummy); } } } string obukhovfilename = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".obl"); ZipArchiveEntry write_entry2 = archive.CreateEntry(obukhovfilename); using (writer = new BinaryWriter(write_entry2.Open())) { writer.Write(header); writer.Write(NI); writer.Write(NJ); writer.Write(NK); writer.Write(GRAMMhorgridsize); for (int i = 1; i <= NI; i++) { for (int j = 1; j <= NJ; j++) { dummy = Convert.ToInt16(Program.OL[i][j] * 10); writer.Write(dummy); } } } //computation and ouput of stability classes string stabilityfile = (Convert.ToString(Program.IWETTER).PadLeft(5, '0') + ".scl"); ZipArchiveEntry write_entry3 = archive.CreateEntry(stabilityfile); using (writer = new BinaryWriter(write_entry3.Open())) { writer.Write(header); writer.Write(NI); writer.Write(NJ); writer.Write(NK); writer.Write(GRAMMhorgridsize); for (int i = 1; i <= NI; i++) { for (int j = 1; j <= NJ; j++) { writer.Write(Program.stabilityclass[i][j]); } } } } // archive } // Zip File } // catch catch { } Program.Max_Proc_File_Read(); // read number of max. Processors if (recexist == true && IWetter_Console_First == 0) // write receptor wind fields; not if multi-instances are used { try { using (StreamWriter wr = new StreamWriter("GRAMM.dat", true)) { for (int ianz = 0; ianz < Urec.Count(); ianz++) { double angle = winkel(Urec[ianz], Vrec[ianz]); wr.Write(Math.Sqrt(Math.Pow(Urec[ianz], 2) + Math.Pow(Vrec[ianz], 2)).ToString("0.00").Replace(decsep, ".") + "," + angle.ToString("0").Replace(decsep, ".") + "," + Trec[ianz].ToString("0.0").Replace(decsep, ".") + "," + Globradrec[ianz].ToString("0").Replace(decsep, ".") + "," + Longradrec[ianz].ToString("0").Replace(decsep, ".") + "," + Soilheatfluxrec[ianz].ToString("0").Replace(decsep, ".") + "," + Sensheatfluxrec[ianz].ToString("0").Replace(decsep, ".") + "," + Latheatfluxrec[ianz].ToString("0").Replace(decsep, ".") + ","); Urec[ianz] = 0; Vrec[ianz] = 0; Trec[ianz] = 0; Globradrec[ianz] = 0; Longradrec[ianz] = 0; Soilheatfluxrec[ianz] = 0; Sensheatfluxrec[ianz] = 0; Latheatfluxrec[ianz] = 0; } wr.WriteLine(); } } catch { } } }
/*INPUT FILES : * BASIC DOMAIN INFORMATION GRAMM.geb * MAIN CONTROL PARAM FILEs iin.dat or IIN.dat * GEOMETRY DATA ggeom.asc * LANDUSE DATA landuse.asc * METEOROLOGICAL DATA meteopgt.all * MAX. NUMBER OF CPUs Max_Proc.txt */ static void Main(string[] args) { // Arguments: "First Situation" "Final Situation" "Max. Time Step" "RelaxV" "RelaxT" // if "First Situation" = "?" -> print Info & Stop int p = (int)Environment.OSVersion.Platform; if ((p == 4) || (p == 6) || (p == 128)) { //Console.WriteLine ("Running on Unix"); unix = true; } else { //Console.WriteLine ("NOT running on Unix"); } //WRITE GRAMM VERSION INFORMATION TO SCREEN Console.WriteLine(""); Console.WriteLine("+------------------------------------------------------+"); Console.WriteLine("| |"); string Info = "+ > > G R A M M VERSION: 20.09 < < +"; Console.WriteLine(Info); if (unix) { Console.WriteLine("| L I N U X |"); } #if NETCOREAPP2_1 || NETCOREAPP2_0 || NETCOREAPP3_0 Console.WriteLine("| .Net Core Version |"); #endif Console.WriteLine("+------------------------------------------------------+"); Console.WriteLine(" "); //show licence terms ShowCopyright(args); // 11.04.17 Ku use arguments Console_Arguments(args); //User defined decimal seperator decsep = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; //read number of grid cells stored in the file "GRAMM.geb" Read_Gramm_Geb(); //check if chemistry is envoked if (File.Exists("chemistry.txt")) { Read_Chemistry(); //@Johannes: at this place call the chemical mechanism, that feeds back the number of spezies to be computed } // Write to "Logfile_GRAMMCore" try { ProgramWriters.LogfileGrammCoreWrite(new String('-', 80)); ProgramWriters.LogfileGrammCoreWrite(Info); ProgramWriters.LogfileGrammCoreWrite("Computation started at: " + DateTime.Now.ToString()); ProgramWriters.LogfileGrammCoreWrite("Computation folder: " + Directory.GetCurrentDirectory()); Info = "Application hash code: " + GetAppHashCode(); ProgramWriters.LogfileGrammCoreWrite(Info); } catch { } //Allocate Memory -> Define Arrays Define_Arrays(); List <int>[] Month_List = new List <int> [3]; // 3 types of month lists Month_List[0] = new List <int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; Month_List[1] = new List <int>() { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2 }; Month_List[2] = new List <int>() { 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5 }; if (NX * NY < 50 * 50) { TerminalThreshold = 12; } else if (NX * NY < 200 * 200) { TerminalThreshold = 6; } else { TerminalThreshold = 1; } Console.WriteLine("."); //END OF VARIABLE DECLARATION BLOCK //SET NUMBER OF FLOW FIELD SITUATION TO ZERO IWETTER = 0; //OPEN THE MAIN CONTROL FILE "IIN.dat" Read_IIN_Dat(); //read k-epsilon constant Read_TURB_Dat(); //When using ERA5 data GRAMM automatically starts with a number for the weather situation based on the existing *wnd files if (ISTAT >= 2) { string wdir = Directory.GetCurrentDirectory(); DirectoryInfo d = new DirectoryInfo(wdir); FileInfo[] Files = d.GetFiles("*.wnd"); IWETTER = Files.Length; } //Total simulation time DTI = TLIMIT2; DTMAX = DT; max_time_step_original = DTMAX; if (MaxTimeStep_Console > 0.99) { max_time_step_original = MaxTimeStep_Console; } if (Relaxv_Console > 0.0099) { RELAXV = Relaxv_Console; } if (Relaxt_Console > 0.0099) { RELAXT = Relaxt_Console; } // Read number of max. used processors IPROC = 1; Max_Proc_File_Read(); //Convert relative humidity in % QUINIT *= 0.01; //Get year, month, day, hour, and minute of the simulation start if (NDATUM.ToString().Length == 8) { IJAHR4digits = Convert.ToInt32(Math.Floor(NDATUM / 10000d)); IJAHR = IJAHR4digits - Convert.ToInt32(Math.Floor(IJAHR4digits / 100d)) * 100; IMON = Convert.ToInt32(Math.Floor(NDATUM / 100d)) - IJAHR4digits * 100; ITAG = NDATUM - IJAHR4digits * 10000 - IMON * 100; } else { IJAHR = Convert.ToInt32(Math.Floor(NDATUM / 10000d)); IJAHR4digits = IJAHR; IMON = Convert.ToInt32(Math.Floor(NDATUM / 100d)) - IJAHR * 100; ITAG = NDATUM - IJAHR * 10000 - IMON * 100; } ISTU = Convert.ToInt32(Math.Floor(ISTUNDE / 100d)); IMIN = ISTUNDE - 100 * ISTU; //Set flags for various compuation options ICU = false; ICV = false; ICW = false; ICPN = false; ICT = false; ICPH = false; IFOU = false; ICQU = false; ICPSI = false; ICTE = false; ICSTR = false; ICPR = false; ICBR = false; ICTB = false; ICGW = false; Int32 INUMM = 0; if (IFLAGS1 / 1000000 == 1) { ICU = true; } if (ICU) { INUMM += 1000000; } if ((IFLAGS1 - INUMM + 1) / 100000 == 1) { ICV = true; } if (ICV) { INUMM += 100000; } if ((IFLAGS1 - INUMM + 1) / 10000 == 1) { ICW = true; } if (ICW) { INUMM += 10000; } if ((IFLAGS1 - INUMM + 1) / 1000 == 1) { ICPN = true; } if (ICPN) { INUMM += 1000; } if ((IFLAGS1 - INUMM + 1) / 100 == 1) { ICT = true; } if (ICT) { INUMM += 100; } if ((IFLAGS1 - INUMM + 1) / 10 == 1) { ICGW = true; } if (ICGW) { INUMM += 10; } if ((IFLAGS1 - INUMM) == 1) { IFOU = true; } INUMM = 0; if (IFLAGS2 / 1000000 == 1) { ICBR = true; } if (ICBR) { INUMM += 1000000; } if ((IFLAGS2 - INUMM + 1) / 100000 == 1) { ICPR = true; } if (ICPR) { INUMM += 100000; } if ((IFLAGS2 - INUMM + 1) / 10000 == 1) { ICQU = true; } if (ICQU) { INUMM += 10000; } if ((IFLAGS2 - INUMM + 1) / 1000 == 1) { ICPSI = true; } if (ICPSI) { INUMM += 1000; } if ((IFLAGS2 - INUMM + 1) / 100 == 1) { ICTE = true; } if (ICTE) { INUMM += 100; } if ((IFLAGS2 - INUMM + 1) / 10 == 1) { ICTB = true; } if (ICTB) { INUMM += 10; } if ((IFLAGS2 - INUMM) == 1) { ICSTR = true; } //COMPUTE MODEL GRID Console.WriteLine(" *** GENERATING MODEL GRID *** "); GEOM(); //INQUIRE IF RECEPTOR POINTS ARE SET Read_Receptor_Dat(); //INQUIRE IF PROBE POINTS ARE SET Read_Probes_Dat(); //Analyze_Topography(); // find U valleys and bassins Relaxv_ori = RELAXV; Relaxt_ori = RELAXT; Relax_Border_factor[0][0] = -4; // flag, that factor must be computed ProgramWriters.LogfileGrammCoreInfo(); // init radiation model RadiationModel = new RadiationCalculation(); //Loop_______________________________________________________________________________________________ NEXTWEATHERSITUATION: clear_arrays(); //INITIALIZE FIELDS Console.WriteLine(); Console.WriteLine(); Console.WriteLine(" *** INITIALIZATION *** "); INITA(NX, NY, NZ); Int32 ISTUD = Convert.ToInt32(Math.Floor(TLIMIT / 3600d)); double AMIND = (TLIMIT / 3600 - (float)ISTUD) * 60; Int32 IMIND = Convert.ToInt32(Math.Floor(AMIND)); double ASECD = (AMIND - (float)IMIND) * 60; Int32 ISECD = Convert.ToInt32(Math.Floor(ASECD)); if (ISTAT == 0) { Intermed_Threshold = IOUTPUT / 2; // 1st intermediate output after IOUTPUT / 2 (default 1800 s) for SC 5, 6 and SC 7 if (AKLA < 5) { Intermed_Threshold = IOUTPUT; // 1st intermediate output after IOUTPUT s } } else { Intermed_Threshold = IOUTPUT; } int Radiation_Threshold = 1800; // compute new radiation each 1800 s //set further initial values if (ISTAT < 2) { INITB.INIT(NX, NY, NZ); } Relax_Border(); // set reduction factors for the border cells //initialize the radiation model if (((METEO != "Y") && (METEO != "y")) || (Program.ISTAT != 0)) { TLIMIT = TLIMIT2; } Boolean LGEOM = false; Boolean LGEOMW = false; Boolean LGEOMR = false; INIT_Radiation(ref LGEOM, ref LGEOMW, ref LGEOMR, ref ISTUD, ref AMIND, ref IMIND, ref ASECD, ref ISECD, Month_List); Console.WriteLine(ITAG.ToString() + "." + IMON.ToString() + " - " + ISTU.ToString() + ":" + IMIND.ToString("D2")); REALTIME = 0; ITIME = 0; INUMS = 0; DIVSUM = 0; IDIV = 0; DT = 1.5; for (int i = 0; i < 11; i++) { MASSOURCE[i] = 0; } // Create File ${IWETTER}.probes.dat initProbes(); //START OF THE INTEGRATION LOOP while (REALTIME < TLIMIT) { //number of iteration ITIME++; if (ITIME % 20 == 0) { Max_Proc_File_Read(); // read MaxProc at 20th time step } //total simulation expressed in seconds TJETZT = (float)ISTU * 3600 + (float)IMIN * 60 + REALTIME; //write normalised actual time used in the GUI for visualisation of the modelling progress if ((ITIME % 10) == 0 && (IWetter_Console_First <= 1)) // 11.4.17 Ku use arguments { try { using (StreamWriter w = new StreamWriter("PercentGramm.txt")) { double tnorm = REALTIME * TLIMIT2 / TLIMIT; w.WriteLine(tnorm.ToString()); } } catch { } } //Online output of fields for GUI if (GRAMM_Online_flag || (ITIME % 10d) == 0) { GRAMM_Online_flag = false; // reset flag GrammOnline(NX, NY, NZ); // flag is at GRAMMOnline set to true, if only output is necessary } //Implicit solution algorith for conservation equations (SIMPLE - Patankar, 1980) if (REALTIME <= DTI) { if (SOLUTION(NX, NY, NZ) == false && ISTAT == 0) // numerical problems using overall massdivergence { computation_retry++; if (computation_retry < 3) // try 3 times -> otherwise let the app crash { IWETTER--; //try same situation TLIMIT += TLIMIT2; DTI += TLIMIT2; clear_arrays(); GEOM(); goto NEXTWEATHERSITUATION; } } } //new radiation data if (ITIME == 1) { LGEOM = true; LGEOMW = true; LGEOMR = false; } else { LGEOM = false; LGEOMW = false; LGEOMR = false; } if (ICSTR == true) { if ((ITIME == 1) || ((ITIME % IRAD) == 0)) { double TJETZT1 = TJETZT; int IMIN_RAD = IMIN; int ITAG_RAD = ITAG; int IMON_RAD = IMON; if (ISTAT == 0) { ISTUD = Convert.ToInt32(Math.Floor((TJETZT + 10) / 3600d)); } else if (ISTAT == 1) { ISTUD = ISTU; TJETZT1 = (float)ISTU * 3600 + (float)IMIN * 60; } else if (ISTAT >= 2) { //ISTUD = Convert.ToInt32(Math.Floor((TJETZT + 10) / 3600d)); //GRAMM uses sun time -> UTC has to be transferred DateTime dateref = new DateTime(Program.IJAHR4digits, Program.IMON, Program.ITAG, Program.ISTU, Program.IMIN, 0); dateref = dateref.AddSeconds(REALTIME); IMON_RAD = dateref.Month; ITAG_RAD = dateref.Day; ISTUD = dateref.Hour; IMIND = dateref.Minute; TJETZT1 = ISTUD * 3600; } AMIND = (TJETZT / 3600 - (float)ISTUD) * 60; IMIND = Convert.ToInt32(Math.Floor(AMIND)); ASECD = (AMIND - (float)IMIND) * 60; ISECD = Convert.ToInt32(Math.Floor(ASECD)); for (int II = 1; II <= 1000; II++) { if (TJETZT1 >= 86400) { TJETZT1 -= 86400; } } RadiationModel.RADIATRAD(LGEOM, LGEOMW, LGEOMR, ITAG_RAD, IMON_RAD, IJAHR, TJETZT1, NX, NY, NZ); Console.WriteLine(ITAG_RAD.ToString() + "." + IMON_RAD.ToString() + " - " + ISTUD.ToString() + ":" + IMIND.ToString("D2")); } //dynamic sun (global radiation) every 1800 seconds if (((METEO == "Y") || (METEO == "y")) && (Program.ISTAT == 0)) { if (Program.AKLA < 4) { if (REALTIME > Radiation_Threshold) { Radiation_Threshold += 1800; // compute new radiation each 1800 s double TJETZT1 = TJETZT; ISTUD = Convert.ToInt32(Math.Floor((TJETZT + 10) / 3600d)); AMIND = (TJETZT / 3600 - (float)ISTUD) * 60; IMIND = Convert.ToInt32(Math.Floor(AMIND)); ASECD = (AMIND - (float)IMIND) * 60; ISECD = Convert.ToInt32(Math.Floor(ASECD)); for (int II = 1; II <= 1000; II++) { if (TJETZT1 >= 86400) { TJETZT1 -= 86400; } } RadiationModel.RADIATRAD(LGEOM, LGEOMW, LGEOMR, ITAG, IMON, IJAHR, TJETZT1, NX, NY, NZ); Console.WriteLine(ITAG.ToString() + "." + IMON.ToString() + " - " + ISTUD.ToString() + ":" + IMIND.ToString("D2")); } } } } //store last time step STOREcalculate(NX, NY, NZ); //intermediate output if (((METEO == "Y") || (METEO == "y")) && (Program.ISTAT == 0)) { //only in case of steady-state simulations using meteopgt.all no intermediate output is provided if (Program.meteopgt_nr == 0) { IOUTPUT = 100000000; Intermed_Threshold = 100000000; } } Int16 IHOUR = Convert.ToInt16(Math.Floor(TJETZT / IOUTPUT)); if (REALTIME > Intermed_Threshold && DTI > 3602) // if threshold is exceeded && simulation time > 1 h -> create intermed. outputs { Console.Write(" INTERMEDIATE OUTPUT "); // set new Threshold value if (Intermed_Threshold < IOUTPUT) { Intermed_Threshold = IOUTPUT * 2; // 2nd intermediate output after 2 hours } else { Intermed_Threshold += IOUTPUT; } OUTPUT(NX, NY, NZ, true); // intermediate output //generating meteopgt.all and mettimeseries.dat for ERA5/GUI postprocessing if (Program.ISTAT == 2 || Program.ISTAT == 4) { Meteopgtall.GRALGenerateMeteoFilesForERA5(); } Console.WriteLine(); Console.WriteLine(); if (((METEO != "Y") && (METEO != "y")) || (Program.ISTAT != 0)) { IWETTER++; } } //increase simulation time REALTIME += DT; IHOURO = IHOUR; //save intermediate surface flow fields after 75% of the total simulatin time (VDI 3783-7) if ((REALTIME >= DTI * 0.75) && (REALTIME <= (DTI * 0.75 + DT * 2))) { Parallel.For(1, NX + 1, Program.pOptions, i => { for (int j = 1; j <= NY; j++) { U_TEMP[i][j] = (float)(U[i][j][1]); V_TEMP[i][j] = (float)(V[i][j][1]); W_TEMP[i][j] = (float)(W[i][j][1]); } }); } } computation_retry = 0; // reset compuation retry counter //Ultimate output at the end of each situation Console.WriteLine(""); Console.Write(" MMAIN : OUT "); if ((METEO != "Y") && (METEO != "y")) { OUTPUT(NX, NY, NZ, false); // final output Console.WriteLine(); } else { OUTPUT(NX, NY, NZ, false); // final output Console.WriteLine(); goto NEXTWEATHERSITUATION; } }