Esempio n. 1
0
        /*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;
            }
        }