Ejemplo n.º 1
0
        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 { }
            }
        }
Ejemplo n.º 2
0
        public static bool SOLUTION(int NI, int NJ, int NK)
        {
            //Check for numerical problems using overall massdivergence
            if (Program.MASSOURCE[Program.IDIV] > 1000) // 13.4.2017 Ku Check if Divergence increased to a very high value
            {
                Program.Divergence_Min = Math.Min(Program.Divergence_Min, Program.MASSOURCE[Program.IDIV]);
            }

            if ((Program.MASSOURCE[Program.IDIV] * 0.001 >= 500000) || (Program.MASSOURCE[Program.IDIV] > Program.Divergence_Min * 50))
            {
                if (Program.computation_retry >= 3) // try 4 times
                {
                    try
                    {
                        string err = "Numerical instabilities detected for flow field: " + Program.IWETTER.ToString();
                        ProgramWriters.LogfileProblemreportWrite(err);
                    }
                    catch { }

                    Program.REALTIME = Program.TLIMIT; // exit this situation
                }
                for (int i = 0; i < 11; i++)
                {
                    Program.MASSOURCE[i] = 0;
                }
                return(false); // error
            }

            //Calculation of several terms for the implicit scheme according to Patankar, 1980
            //Note that the wind speeds and the non-hydrostatic pressure are calculated using half-cells,
            //while pot. temperature, humidity, turbulent-kinetic energy and dissipation are modelled based on the full-cell
            if (Program.REALTIME < Program.DTI)
            {
                TERMIVterms(NI, NJ, NK);

                TERMIPSterms(NI, NJ, NK);

                TERMIPterms(NI, NJ, NK);

                //Prandtl-layer quantities
                if (Program.ICPR)
                {
                    Prandtl_calculate(NI, NJ, NK);
                }

                //Soil temperature (as the last 5 cells near the borders are not calculated, the routine just makes sense if model domains have more than 10 grid cells in the horizontal directions
                if ((NI > 10) && (NJ > 10) && (Program.ICTB))
                {
                    Calctb_calculate(NI, NJ, NK);
                }

                //Solve momentum equations
                if (Program.pOptions.MaxDegreeOfParallelism > 3) // more cores - divide the work -> try to avoid false sharing
                {
                    //                  int cores = Program.pOptions.MaxDegreeOfParallelism;
                    //                  Program.pOptions.MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling(cores / 3.0f));

                    Parallel.Invoke(Program.pOptions,
                                    () => UIMPcalculate(NI, NJ, NK),
                                    () => VIMPcalculate(NI, NJ, NK),
                                    () => WVELcalculate(NI, NJ, NK));

                    //                  Program.pOptions.MaxDegreeOfParallelism = cores; // reset core-count
                }
                else
                {
                    UIMPcalculate(NI, NJ, NK);
                    VIMPcalculate(NI, NJ, NK);
                    WVELcalculate(NI, NJ, NK);
                }

                //Boundary conditions
                Bords_calculate(NI, NJ, NK);

                //Solve the non-hydrostatic pressure equation
                if (Program.ICPN == true)
                {
                    CALCPR_calculate(NI, NJ, NK);
                }

                //save initial mass-divergence to check for numerical instabilities at the end of the simulation
                if (Program.REALTIME <= (1.5 * Program.DT))
                {
                    Program.MASSOURCE_FIRST = Program.SUMG;
                }


                if (Program.ICT == true && Program.ICQU == true)
                {
                    Parallel.Invoke(Program.pOptions,
                                    () => Timp_calculate(NI, NJ, NK),
                                    () => Fimp_calculate(NI, NJ, NK));
                    //computation of water vapour content
                    if (Program.ICQU == true && Program.ISTAT != 0)
                    {
                        WatVap_calculate(NI, NJ, NK);
                    }
                }
                else
                {
                    //computation of pot. temperature
                    if (Program.ICT == true)
                    {
                        Timp_calculate(NI, NJ, NK);
                    }
                    //computation of humidity
                    if (Program.ICQU == true)
                    {
                        Fimp_calculate(NI, NJ, NK);
                    }
                    //computation of water vapour content
                    if (Program.ICQU == true && Program.ISTAT != 0)
                    {
                        WatVap_calculate(NI, NJ, NK);
                    }
                }

                //computation of thermal pressure
                //if (Program.ICPSI == true) THERMPRESScalculate(NI, NJ, NK);

                //computation of turbulent kinetic energy and dissipation rate
                if (Program.ICTE == true)
                {
                    Parallel.Invoke(Program.pOptions,
                                    () => Tkeimp_calculate(NI, NJ, NK),
                                    () => Epsimp_calculate(NI, NJ, NK));
                }

                //time-step adjustion
                if (Program.ISTAT == 0)
                {
                    Program.IDIV_LockDown2--;
                    if (Program.IDIV_LockDown > 0) // 5.4.2017 Ku avoid increase of time step after a decrease
                    {
                        Program.IDIV_LockDown--;
                    }
                    else
                    {
                        Program.STEIGUNG = Math.Round(Program.STEIGUNG, 2);
                        if ((Program.IDIV == 10) && (Program.STEIGUNG <= 0))
                        {
                            if (REALTIME <= DTI * 0.75)                                             // do not adjust time step if steady state criterion is measured
                            {
                                Program.DT             = Math.Min(Program.DT + 0.5, Program.DTMAX); //3.4.2017 Ku
                                Program.IDIV_LockUp    = 0;
                                Program.IDIV_LockDown2 = 40;
                            }
                        }
                    }

                    //5.4.2017 Ku
                    if (((Program.MASSOURCE_Old * 1.01 < Program.MASSOURCE_Act) || ((Program.MASSOURCE_Old + 500) < Program.MASSOURCE_Act)) && IDIV_LockUp <= 3 && IDIV_LockDown == 0 && IDIV_LockDown2 < 0)
                    {
                        Program.DT             = Math.Max(Program.DT * 0.80, 1.5); //5.4.2017 Ku
                        RELAXV                 = Math.Max(RELAXV * 0.80, 0.05);
                        RELAXT                 = Math.Max(RELAXT * 0.80, 0.05);
                        Program.IDIV_LockDown  = 11;
                        Program.IDIV_LockDown2 = 20;
                        Program.IDIV_LockUp++;
                        Program.IDIV_PingPong++;

                        if (Program.IDIV_PingPong > 6 * Math.Pow(Program.Relaxv_ori / Program.RELAXV, 2) && Program.IDIV_LockRelax < 6)
                        {                                                  // Set relax factors down and increase lockDown value if downsteps occur periodically
                            Program.DT = Math.Max(Program.DT * 0.80, 1.5); //5.4.2017 Ku
                            RELAXV     = Math.Max(RELAXV * 0.80, 0.05);
                            RELAXT     = Math.Max(RELAXT * 0.80, 0.05);
                            Program.IDIV_LockRelax++;
                            Program.IDIV_PingPong = 0;
                            Program.IDIV_LockDown = 20;
                        }
                        else if (IDIV_LockUp > 2 && IDIV_LockRelax < 6)
                        {
                            RELAXV = Math.Max(RELAXV * 0.80, 0.05);
                            RELAXT = Math.Max(RELAXT * 0.80, 0.05);
                            Program.IDIV_LockRelax++;
                        }
                    }
                }
                //5.4.2017 Ku


                //2.9.2019 Öt
                //dynamic time step and relaxation factor adjustments for GRAMM full transient simulations
                if (Program.ISTAT != 0)
                {
                    //Console.WriteLine(Program.IDIV.ToString() + "," + Program.MASSOURCE[Program.IDIV].ToString() + "," + Program.MASSOURCE[1].ToString() + "," + Program.MASSOURCE_FIRST.ToString());

                    /*
                     * if ((Program.IDIV == 5) && (Program.MASSOURCE[Program.IDIV] > Program.MASSOURCE[1]) && (Program.MASSOURCE_FIRST < Program.MASSOURCE[Program.IDIV]))
                     * {
                     *  Program.DT = Math.Max(Program.DT * 0.70, 1.5); //5.4.2017 Ku
                     *  RELAXV = Math.Max(RELAXV * 0.70, 0.05);
                     *  RELAXT = Math.Max(RELAXT * 0.70, 0.05);
                     *  Program.IDIV = 0;
                     * }
                     * else if ((Program.IDIV == 5) && (Program.MASSOURCE[Program.IDIV] <= Program.MASSOURCE[1]))
                     * {
                     *
                     *  Program.DT = Math.Min(Program.DT + 0.5, Program.DTMAX);
                     *  RELAXV = Math.Min(RELAXV * 1.01, 0.15);
                     *  RELAXT = Math.Min(RELAXT * 1.01, 0.15);
                     *  Program.IDIV = 0;
                     * }
                     */
                    Program.DT = Program.DTMAX;
                }
                //2.9.2019 Öt



                Program.TerminalOut++;
                if (Program.TerminalOut >= TerminalThreshold) // if Counter is even
                {
                    writeProbes();

                    //output to screen
                    string LOGT = "-";
                    string LOGH = "-";
                    string LOGU = "-";
                    string LOGV = "-";
                    string LOGW = "-";
                    if (Program.ICT)
                    {
                        LOGT = "+";
                    }
                    if (Program.ICQU)
                    {
                        LOGH = "+";
                    }
                    if (Program.ICU)
                    {
                        LOGU = "+";
                    }
                    if (Program.ICV)
                    {
                        LOGV = "+";
                    }
                    if (Program.ICW)
                    {
                        LOGW = "+";
                    }
                    Console.WriteLine("-------------------------------------------------------------------------------------");
                    Console.WriteLine("WEATHER-SIT. TIME[s]  TIMESTEP[s]  ENDTIME[s]  PRESS-ITERATIONS  DIVERGENCE U V W T H");
                    Console.WriteLine(Program.IWETTER.ToString().PadLeft(10) + "/" + (1 + computation_retry).ToString().PadLeft(1) + " " + Program.REALTIME.ToString("0.0").PadLeft(7) + "  " +
                                      Program.DT.ToString("0.0").PadLeft(11) + "  " + Program.DTI.ToString("0").PadLeft(10) + "               " +
                                      (Program.INUMS - 1).ToString("0").PadLeft(3) + "  " + (Program.SUMG * 0.001).ToString("0.000").PadLeft(10) + " " +
                                      LOGU + " " + LOGV + " " + LOGW + " " + LOGT + " " + LOGH);
                }
            }

            return(true); // computation OK
        }
Ejemplo n.º 3
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;
            }
        }