From e5dc2996e2c1f928d7b28f8a2f7f964d2f7e930d Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Wed, 1 Feb 2023 08:40:41 +0100 Subject: [PATCH] changed: move banner printing to separate compile unit --- CMakeLists_files.cmake | 2 + opm/simulators/flow/Banners.cpp | 125 +++++++++++++++++++++++++++ opm/simulators/flow/Banners.hpp | 43 +++++++++ opm/simulators/flow/FlowMainEbos.hpp | 104 +--------------------- opm/simulators/flow/Main.cpp | 6 +- opm/simulators/flow/Main.hpp | 37 +++++++- 6 files changed, 209 insertions(+), 108 deletions(-) create mode 100644 opm/simulators/flow/Banners.cpp create mode 100644 opm/simulators/flow/Banners.hpp diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 447cc9dac..272572545 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -40,6 +40,7 @@ list (APPEND MAIN_SOURCE_FILES opm/core/props/phaseUsageFromDeck.cpp opm/core/props/satfunc/RelpermDiagnostics.cpp opm/simulators/timestepping/SimulatorReport.cpp + opm/simulators/flow/Banners.cpp opm/simulators/flow/countGlobalCells.cpp opm/simulators/flow/ConvergenceOutputConfiguration.cpp opm/simulators/flow/ExtraConvergenceOutputThread.cpp @@ -280,6 +281,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/simulators/flow/countGlobalCells.hpp opm/simulators/flow/BlackoilModelEbos.hpp opm/simulators/flow/BlackoilModelParametersEbos.hpp + opm/simulators/flow/Banners.hpp opm/simulators/flow/ConvergenceOutputConfiguration.hpp opm/simulators/flow/ExtraConvergenceOutputThread.hpp opm/simulators/flow/FlowMainEbos.hpp diff --git a/opm/simulators/flow/Banners.cpp b/opm/simulators/flow/Banners.cpp new file mode 100644 index 000000000..50844aa94 --- /dev/null +++ b/opm/simulators/flow/Banners.cpp @@ -0,0 +1,125 @@ +/* + Copyright 2013, 2014, 2015 SINTEF ICT, Applied Mathematics. + Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services + Copyright 2015 IRIS AS + Copyright 2014 STATOIL ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +unsigned long long getTotalSystemMemory() +{ + long pages = sysconf(_SC_PHYS_PAGES); + long page_size = sysconf(_SC_PAGE_SIZE); + return pages * page_size; +} + +} + +namespace Opm { + +void printPRTHeader(const std::string& parameters) +{ + const std::string version = moduleVersion(); + const double megabyte = 1024 * 1024; + unsigned num_cpu = std::thread::hardware_concurrency(); + struct utsname arch; + const char* user = getlogin(); + std::time_t now = std::time(0); + struct std::tm tstruct; + char tmstr[80]; + tstruct = *std::localtime(&now); + std::strftime(tmstr, sizeof(tmstr), "%d-%m-%Y at %X", &tstruct); + const double mem_size = getTotalSystemMemory() / megabyte; + std::ostringstream ss; + ss << "\n\n\n"; + ss << " ######## # ###### # #\n"; + ss << " # # # # # # \n"; + ss << " ##### # # # # # # \n"; + ss << " # # # # # # # # \n"; + ss << " # ####### ###### # # \n\n"; + ss << "Flow is a simulator for fully implicit three-phase black-oil flow,"; + ss << " and is part of OPM.\nFor more information visit: https://opm-project.org \n\n"; + ss << "Flow Version = " + version + "\n"; + if (uname(&arch) == 0) { + ss << "Machine name = " << arch.nodename << " (Number of logical cores: " << num_cpu; + ss << ", Memory size: " << std::fixed << std::setprecision (2) << mem_size << " MB) \n"; + ss << "Operating system = " << arch.sysname << " " << arch.machine << " (Kernel: " << arch.release; + ss << ", " << arch.version << " )\n"; + ss << "Build time = " << compileTimestamp() << "\n"; + } + if (user) { + ss << "User = " << user << std::endl; + } + ss << "Simulation started on " << tmstr << " hrs\n"; + + ss << "Parameters used by Flow:\n" << parameters; + + OpmLog::note(ss.str()); +} + +void printFlowBanner(int nprocs, int nthreads) +{ + const int lineLen = 70; + const std::string version = moduleVersionName(); + const std::string banner = "This is flow "+version; + const int bannerPreLen = (lineLen - 2 - banner.size())/2; + const int bannerPostLen = bannerPreLen + (lineLen - 2 - banner.size())%2; + std::cout << "**********************************************************************\n"; + std::cout << "* *\n"; + std::cout << "*" << std::string(bannerPreLen, ' ') << banner << std::string(bannerPostLen, ' ') << "*\n"; + std::cout << "* *\n"; + std::cout << "* Flow is a simulator for fully implicit three-phase black-oil flow, *\n"; + std::cout << "* including solvent and polymer capabilities. *\n"; + std::cout << "* For more information, see https://opm-project.org *\n"; + std::cout << "* *\n"; + std::cout << "**********************************************************************\n\n"; + + std::cout << "Using "<< nprocs << " MPI processes with "<< nthreads <<" OMP threads on each \n\n"; +} + +void printFlowTrailer(int nprocs, int nthreads, + const SimulatorReport& report) +{ + std::ostringstream ss; + ss << "\n\n================ End of simulation ===============\n\n"; + ss << fmt::format("Number of MPI processes: {:9}\n", nprocs); + ss << fmt::format("Threads per MPI process: {:9}\n", nthreads); + report.reportFullyImplicit(ss); + OpmLog::info(ss.str()); +} + +} // namespace Opm diff --git a/opm/simulators/flow/Banners.hpp b/opm/simulators/flow/Banners.hpp new file mode 100644 index 000000000..29aaa6215 --- /dev/null +++ b/opm/simulators/flow/Banners.hpp @@ -0,0 +1,43 @@ +/* + Copyright 2013, 2014, 2015 SINTEF ICT, Applied Mathematics. + Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services + Copyright 2015 IRIS AS + Copyright 2014 STATOIL ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ +#ifndef OPM_FLOW_BANNERS_HEADER_INCLUDED +#define OPM_FLOW_BANNERS_HEADER_INCLUDED + +#include + +namespace Opm { + +class SimulatorReport; + +// Print an ASCII-art header to the PRT and DEBUG files. +void printPRTHeader(const std::string& parameters); + +// Print flow application banner. +void printFlowBanner(int nprocs, int threads); + +// Print flow application trailer. +void printFlowTrailer(int nprocs, int nthreads, + const SimulatorReport& report); + +} // namespace Opm + +#endif // OPM_FLOW_BANNERS_EBOS_HEADER_INCLUDED diff --git a/opm/simulators/flow/FlowMainEbos.hpp b/opm/simulators/flow/FlowMainEbos.hpp index fbf02f65c..b6982c01a 100644 --- a/opm/simulators/flow/FlowMainEbos.hpp +++ b/opm/simulators/flow/FlowMainEbos.hpp @@ -22,10 +22,8 @@ #ifndef OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED #define OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED - -#include - #include +#include #include #include #include @@ -37,7 +35,6 @@ #include #include -#include #include #if HAVE_DUNE_FEM @@ -274,45 +271,6 @@ namespace Opm return status; } - static void printBanner(Parallel::Communication comm) - { - const int lineLen = 70; - const std::string version = moduleVersionName(); - const std::string banner = "This is flow "+version; - const int bannerPreLen = (lineLen - 2 - banner.size())/2; - const int bannerPostLen = bannerPreLen + (lineLen - 2 - banner.size())%2; - std::cout << "**********************************************************************\n"; - std::cout << "* *\n"; - std::cout << "*" << std::string(bannerPreLen, ' ') << banner << std::string(bannerPostLen, ' ') << "*\n"; - std::cout << "* *\n"; - std::cout << "* Flow is a simulator for fully implicit three-phase black-oil flow, *\n"; - std::cout << "* including solvent and polymer capabilities. *\n"; - std::cout << "* For more information, see https://opm-project.org *\n"; - std::cout << "* *\n"; - std::cout << "**********************************************************************\n\n"; - - int threads = 1; - -#ifdef _OPENMP - // This function is called before the parallel OpenMP stuff gets initialized. - // That initialization happends after the deck is read and we want this message. - // Hence we duplicate the code of setupParallelism to get the number of threads. - if (getenv("OMP_NUM_THREADS")) - threads = omp_get_max_threads(); - else - threads = std::min(2, omp_get_max_threads()); - - const int input_threads = EWOMS_GET_PARAM(TypeTag, int, ThreadsPerProcess); - - if (input_threads > 0) - threads = std::min(input_threads, omp_get_max_threads()); -#endif - - int mpiSize = comm.size(); - - std::cout << "Using "<< mpiSize << " MPI processes with "<< threads <<" OMP threads on each \n\n"; - } - /// This is the main function of Flow. It runs a complete simulation with the /// given grid and simulator classes, based on the user-specified command-line /// input. @@ -342,50 +300,6 @@ namespace Opm return report.success.exit_status; } - // Print an ASCII-art header to the PRT and DEBUG files. - static void printPRTHeader(bool output_cout) - { - if (output_cout) { - const std::string version = moduleVersion(); - const double megabyte = 1024 * 1024; - unsigned num_cpu = std::thread::hardware_concurrency(); - struct utsname arch; - const char* user = getlogin(); - time_t now = std::time(0); - struct tm tstruct; - char tmstr[80]; - tstruct = *localtime(&now); - strftime(tmstr, sizeof(tmstr), "%d-%m-%Y at %X", &tstruct); - const double mem_size = getTotalSystemMemory() / megabyte; - std::ostringstream ss; - ss << "\n\n\n"; - ss << " ######## # ###### # #\n"; - ss << " # # # # # # \n"; - ss << " ##### # # # # # # \n"; - ss << " # # # # # # # # \n"; - ss << " # ####### ###### # # \n\n"; - ss << "Flow is a simulator for fully implicit three-phase black-oil flow,"; - ss << " and is part of OPM.\nFor more information visit: https://opm-project.org \n\n"; - ss << "Flow Version = " + version + "\n"; - if (uname(&arch) == 0) { - ss << "Machine name = " << arch.nodename << " (Number of logical cores: " << num_cpu; - ss << ", Memory size: " << std::fixed << std::setprecision (2) << mem_size << " MB) \n"; - ss << "Operating system = " << arch.sysname << " " << arch.machine << " (Kernel: " << arch.release; - ss << ", " << arch.version << " )\n"; - ss << "Build time = " << compileTimestamp() << "\n"; - } - if (user) { - ss << "User = " << user << std::endl; - } - ss << "Simulation started on " << tmstr << " hrs\n"; - - ss << "Parameters used by Flow:\n"; - Parameters::printValues(ss); - - OpmLog::note(ss.str()); - } - } - EbosSimulator *getSimulatorPtr() { return ebosSimulator_.get(); } @@ -584,12 +498,7 @@ namespace Opm = omp_get_max_threads(); #endif - std::ostringstream ss; - ss << "\n\n================ End of simulation ===============\n\n"; - ss << fmt::format("Number of MPI processes: {:9}\n", mpi_size_ ); - ss << fmt::format("Threads per MPI process: {:9}\n", threads); - report.reportFullyImplicit(ss); - OpmLog::info(ss.str()); + printFlowTrailer(mpi_size_, threads, report); const auto extraConvOutput = ConvergenceOutputConfiguration { EWOMS_GET_PARAM(TypeTag, std::string, OutputExtraConvergenceInfo), @@ -660,14 +569,6 @@ namespace Opm simulator_.reset(new Simulator(*ebosSimulator_)); } - static unsigned long long getTotalSystemMemory() - { - long pages = sysconf(_SC_PHYS_PAGES); - long page_size = sysconf(_SC_PAGE_SIZE); - return pages * page_size; - } - - Grid& grid() { return ebosSimulator_->vanguard().grid(); } @@ -683,6 +584,7 @@ namespace Opm bool output_cout_; bool output_files_; }; + } // namespace Opm #endif // OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED diff --git a/opm/simulators/flow/Main.cpp b/opm/simulators/flow/Main.cpp index b018c0c79..ac5312234 100644 --- a/opm/simulators/flow/Main.cpp +++ b/opm/simulators/flow/Main.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #if HAVE_DAMARIS @@ -172,7 +173,7 @@ void Main::readDeck(const std::string& deckFilename, const bool strictParsing, const int mpiRank, const int output_param, - std::function outputPrt) + const std::string& parameters) { auto omode = setupLogging(mpiRank, deckFilename, @@ -180,9 +181,8 @@ void Main::readDeck(const std::string& deckFilename, outputMode, outputCout_, "STDOUT_LOGGER", allRanksDbgPrtLog); - outputPrt(outputCout_); - if (outputCout_) { + printPRTHeader(parameters); OpmLog::info("Reading deck file '" + deckFilename + "'"); } diff --git a/opm/simulators/flow/Main.hpp b/opm/simulators/flow/Main.hpp index c9ab80237..237c783cd 100644 --- a/opm/simulators/flow/Main.hpp +++ b/opm/simulators/flow/Main.hpp @@ -54,6 +54,7 @@ #include #include +#include #include #if HAVE_DUNE_FEM @@ -68,7 +69,6 @@ #include #include -#include #include #include #include @@ -354,8 +354,13 @@ private: exitCode = EXIT_FAILURE; return false; } + + std::string cmdline_params; if (outputCout_) { - FlowMainEbos::printBanner(EclGenericVanguard::comm()); + printFlowBanner(EclGenericVanguard::comm().size(), getNumThreads()); + std::ostringstream str; + Parameters::printValues(str); + cmdline_params = str.str(); } // Create Deck and EclipseState. @@ -368,7 +373,7 @@ private: EWOMS_GET_PARAM(PreTypeTag, bool, EclStrictParsing), mpiRank, EWOMS_GET_PARAM(PreTypeTag, int, EclOutputInterval), - FlowMainEbos::printPRTHeader); + cmdline_params); setupTime_ = externalSetupTimer.elapsed(); } catch (const std::invalid_argument& e) @@ -612,10 +617,34 @@ private: const bool strictParsing, const int mpiRank, const int output_param, - std::function outputPrt); + const std::string& parameters); void setupVanguard(); + template + static int getNumThreads() + { + + int threads = 1; + +#ifdef _OPENMP + // This function is called before the parallel OpenMP stuff gets initialized. + // That initialization happends after the deck is read and we want this message. + // Hence we duplicate the code of setupParallelism to get the number of threads. + if (std::getenv("OMP_NUM_THREADS")) + threads = omp_get_max_threads(); + else + threads = std::min(2, omp_get_max_threads()); + + const int input_threads = EWOMS_GET_PARAM(TypeTag, int, ThreadsPerProcess); + + if (input_threads > 0) + threads = std::min(input_threads, omp_get_max_threads()); +#endif + + return threads; + } + #if HAVE_DAMARIS void setupDamaris(const std::string& outputDir, const bool enableDamarisOutputCollective);