diff --git a/README.md b/README.md index 4837a8f63327332dc31a7093ff6ca770ad94e569..e8088e3361cccc4f4b8aa6d783cb64509f4145ba 100644 --- a/README.md +++ b/README.md @@ -51,37 +51,17 @@ which are very useful also for us. -## Installation (from source) - -### Prerequisites - -CORSIKA 8 is tested regularly via gitlab-CI using recent gcc and clang -versions. Additional software prerequisites: cmake, g++, git. -Furthermore, eigen3, boost, catch2, spdlog are shipped in the -ThirdParty directory, so an installation on the system is optional. -Also Pythia 8, CONEX and PROPOSAL are distributed in the ThirdParty -folder. You may also install those packages on your system and use -those; we test with Pythia version 8.235. +CORSIKA 8 is tested regularly at least on gcc7.3.0 and clang-8.0.0. +Additional software prerequisites you need to install are: eigen3, zlib, libbz2, cmake, g++, git. On a bare Ubuntu 18.04, just add: ``` -sudo apt install binutils gfortran make python3 cmake gcc g++ git libz-dev libspdlog-dev libeigen3-dev libboost-iostreams-dev +sudo apt install libeigen3-dev zlib1g-dev libbz2-dev cmake g++ git ``` -Furthermore these packages are also reqommended: -add ```gcc ssh-client less rsync libboost-dev``` - -If you work with FreeBSD, run: -``` -pkg install git cmake python3 flang eigen +Follow these steps to download and install CORSIKA 8 ``` -or add ```boost-libs``` if you want to use the system versions. - -### Compiling - -Follow these steps to download and install CORSIKA 8, master development version -``` -git clone --recursive https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika.git +git clone --recursive git@gitlab.ikp.kit.edu:AirShowerPhysics/corsika.git cd corsika mkdir ../corsika-build cd ../corsika-build @@ -116,12 +96,9 @@ make install Type `make test` to run the unit test suite. -## Running, Examples - -There are various examples in the folder `Documentation/Examples`. +### Running examples -If you want to see how the first simple hadron cascade develops, -see `Documentation/Examples/cascade_example.cc` for a starting point. +and if you want to see how the first simple hadron cascade develops, see `Documentation/Examples/cascade_example.cc` for a starting point. Run the cascade_example with: ``` diff --git a/corsika/detail/framework/logging/Logging.inl b/corsika/detail/framework/logging/Logging.inl new file mode 100644 index 0000000000000000000000000000000000000000..e99e788b8de6a6eaf2e3965fb10c51049e720058 --- /dev/null +++ b/corsika/detail/framework/logging/Logging.inl @@ -0,0 +1,72 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +#pragma once + +#include <spdlog/fmt/ostr.h> // will output whenerver a streaming operator is found +#include <spdlog/sinks/stdout_color_sinks.h> +#include <spdlog/spdlog.h> + +namespace corsika { + + // many of these free functions are special to the logging + // infrastructure so we hide them in the corsika::logging namespace. + namespace logging { + + /* + * The default pattern for CORSIKA8 loggers. + */ + std::string const default_pattern{"[%n:%^%-8l%$] %v"}; + + inline auto set_default_level(level::level_enum const minlevel) -> void { + spdlog::set_level(minlevel); + } + + template <typename TLogger> + inline auto add_source_info(TLogger& logger) -> void { + logger->set_pattern("[%n:%^%-8l%$(%s:%!:%#)] %v"); + } + + template <typename TLogger> + inline auto reset_pattern(TLogger& logger) -> void { + logger->set_pattern(default_pattern); + } + + } // namespace logging + + inline std::shared_ptr<spdlog::logger> create_logger(std::string const& name, + bool const defaultlog) { + + // create the logger + // this is currently a colorized multi-threading safe logger + auto logger = spdlog::stdout_color_mt(name); + + // set the default C8 format + logger->set_pattern(logging::default_pattern); + + // if defaultlog is True, we set this as the default spdlog logger. + if (defaultlog) { spdlog::set_default_logger(logger); } + + return logger; + } + + inline std::shared_ptr<spdlog::logger> get_logger(std::string const& name, + bool const defaultlog) { + + // attempt to get the logger from the registry + auto logger = spdlog::get(name); + + // weg found the logger, so just return it + if (logger) { + return logger; + } else { // logger was not found so create it + return create_logger(name, defaultlog); + } + } + +} // namespace corsika diff --git a/corsika/framework/logging/BufferedSink.h b/corsika/framework/logging/BufferedSink.h deleted file mode 100644 index 5b2b3a62ae40ce505c682cc704e9428a7f5821fe..0000000000000000000000000000000000000000 --- a/corsika/framework/logging/BufferedSink.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * See file AUTHORS for a list of contributors. - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#ifndef _include_BufferedSink_h_ -#define _include_BufferedSink_h_ - -namespace corsika::logging { - - namespace sink { - - /** - Output buffer template. NoBuffer does nothingk. - */ - /* - struct NoBuffer { - inline bool Test(const std::string&) const { return false; } - inline std::string GetString() const { return std::string(""); } - inline void Clear() {} - inline void Add(const std::string&) {} - }; - */ - /** - Output buffer template. StdBuffer records fSize characters in - local memeory before passing it on to further output stages. - */ - - struct StdBuffer { - StdBuffer(const int size) - : fSize(size) {} - inline bool Test(const std::string& s) { - return int(fBuffer.tellp()) + s.length() < fSize; - } - inline std::string GetString() const { return fBuffer.str(); } - inline void Clear() { fBuffer.str(""); } - inline void Add(const std::string& s) { fBuffer << s; } - - private: - unsigned int fSize; - std::ostringstream fBuffer; - }; - - /** - Definition of Sink for log output. - */ - template <typename TStream, typename TBuffer = StdBuffer> - class BufferedSink { - public: - BufferedSink(TStream& out, TBuffer buffer = {}) - : fOutput(out) - , fBuffer(std::move(buffer)) {} - void operator<<(const std::string& msg) { - if (!fBuffer.Test(msg)) { - fOutput << fBuffer.GetString(); - fBuffer.Clear(); - } - if (!fBuffer.Test(msg)) - fOutput << msg; - else - fBuffer.Add(msg); - } - void Close() { fOutput << fBuffer.GetString(); } - - private: - TStream& fOutput; - TBuffer fBuffer; - }; - - typedef BufferedSink<std::ostream, StdBuffer> BufferedSinkStream; - - } // namespace sink -} // namespace corsika::logging - -#endif diff --git a/corsika/framework/logging/Logger.h b/corsika/framework/logging/Logger.h deleted file mode 100644 index 15ebe3c54f521f0112d0a61bf80d14521903808c..0000000000000000000000000000000000000000 --- a/corsika/framework/logging/Logger.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * See file AUTHORS for a list of contributors. - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -/** - @File Logger.h - - Everything around logfile generation and text output. - */ - -#ifndef _include_logger_h_ -#define _include_logger_h_ - -#include <iosfwd> -#include <sstream> -#include <string> -#include <typeinfo> - -#include <boost/format.hpp> - -#include <corsika/logging/BufferedSink.h> -#include <corsika/logging/MessageOff.h> -#include <corsika/logging/MessageOn.h> -#include <corsika/logging/NoSink.h> -#include <corsika/logging/Sink.h> - -namespace corsika::logging { - - /** - @class Logger - - Defines one stream to accept messages, and to wrote those into - TSink. The helper class MessageOn will convert input at - compile-time into message strings. The helper class MessageOff, - will just do nothing and will be optimized away at compile time. - */ - template <typename MSG = MessageOn, typename TSink = sink::NoSink> - class Logger : private MSG { - - using MSG::Message; - - public: - // Logger() : fName("") {} - Logger(const std::string color, const std::string name, TSink& sink) - : fSink(sink) - , fName(color + "[" + name + "]\033[39m ") {} - ~Logger() { fSink.Close(); } - // Logger(const Logger&) = delete; - - /** - Function to add string-concatenation of all inputs to output - sink. - */ - template <typename... Strings> - void Log(const Strings&... inputs) { - fSink << MSG::Message(inputs...); - } - - const std::string& GetName() const { return fName; } - - private: - TSink& fSink; - std::string fName; - }; - -} // namespace corsika::logging - -/** - * @def LOG(...) - * - * This is the main interface to the logging facilities. If Logger - * object are defined (e.g. log1) use as - * @example LOG(log1, "var1=", variable1int, "var2=", variabl2double) - * for arbitrary long sequence - * of arguments. This may also include boost::format objects the - * output is concatenated, if log1 is switched off at compile time, - * the whole LOG command is optimized away by the compiler. - */ - -#define LOG(__LOGGER, ...) \ - __LOGGER.Log(__LOGGER.GetName(), __FILE__, ":", __LINE__, " (", __func__, ") -> ", \ - __VA_ARGS__); - -#endif diff --git a/corsika/framework/logging/Logging.hpp b/corsika/framework/logging/Logging.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6bc3ebcaa2f7706a784e91fa2a94e4b48063d70d --- /dev/null +++ b/corsika/framework/logging/Logging.hpp @@ -0,0 +1,143 @@ +/* + * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +/** + * @File Logging.hpp + * + * CORSIKA8 logging utilities. + * + * See testLogging.cpp for a complete set of examples for + * how the logging functions should be used. + */ + +#pragma once + +// Configure some behaviour of sdlog. +// This must be done before spdlog is included. + +// use the coarse system clock. This is *much* faster +// but introduces a timestamp error of O(10 ms) which is fine for us. +#define SPDLOG_CLOCK_COARSE + +// do not create a default logger (we provide our own "corsika" logger) +#define SPDLOG_DISABLE_DEFAULT_LOGGER + +// use __PRETTY_FUNCTION__ instead of __FUNCTION__ where +// printing function names in trace statements. This is much +// nicer than __FUNCTION__ under GCC/clang. +#define SPDLOG_FUNCTION __PRETTY_FUNCTION__ + +// if this is a Debug build, include debug messages in objects +#ifdef DEBUG +// trace is the highest level of logging (ALL messages will be printed) +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE +#else // otherwise, remove everything but "critical" messages +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_CRITICAL +#endif + +#include <spdlog/fmt/ostr.h> // will output whenerver a streaming operator is found +#include <spdlog/sinks/stdout_color_sinks.h> +#include <spdlog/spdlog.h> + +namespace corsika { + + /** + * Create a new C8-style logger. + * + * Use this if you are explicitly (and can guarantee) that you + * are creating a logger for the first time. It is recommended + * that for regular usage, the `get_logger` function is used instead + * as that will also create the logger if it has not yet been created. + * + * Calling `create_logger` twice to create the same logger will + * result in an spdlog duplicate exception. + * + * @param name The unique name of the logger. + * @param defaultlog If True, set this as the default logger. + * @returns The constructed and formatted logger. + */ + std::shared_ptr<spdlog::logger> create_logger(std::string const& name, + bool const defaultlog = false); + + /** + * Get a smart pointer to an existing logger. + * + * This should be the default method for code to obtain a + * logger. If the logger *does not* exist, it is *created* and + * returned to the caller. + * + * This should be preferred over `create_logger`. + * + * @param name The name of the logger to get. + * @param defaultlog If True, make this the default logger. + * @returns The constructed and formatted logger. + */ + std::shared_ptr<spdlog::logger> get_logger(std::string const& name, + bool const defaultlog = false); + + /** + * The default "corsika" logger. + */ + inline std::shared_ptr<spdlog::logger> corsika_logger = get_logger("corsika", true); + + // many of these free functions are special to the logging + // infrastructure so we hide them in the corsika::logging namespace. + namespace logging { + + // bring spdlog into the corsika::logging namespace + using namespace spdlog; + + /** + * Set the default log level for all *newly* created loggers. + * + * @param name The minimum log level required to print. + * + */ + auto set_default_level(level::level_enum const minlevel) -> void; + + /** + * Add the source (filename, line no) info to the logger. + * + * @param logger The logger to set the level of. + * + */ + template <typename TLogger> + auto add_source_info(TLogger& logger) -> void; + + /** + * Reset the logging pattern to the default. + * + * @param logger The logger to set the level of. + * + */ + template <typename TLogger> + auto reset_pattern(TLogger& logger) -> void; + + } // namespace logging + +// define our macro-style loggers +// these use the default "corsika" logger +#define CORSIKA_LOG_TRACE SPDLOG_TRACE +#define CORSIKA_LOG_DEBUG SPDLOG_DEBUG +#define CORSIKA_LOG_INFO SPDLOG_INFO +#define CORSIKA_LOG_WARN SPDLOG_WARN +#define CORSIKA_LOG_ERROR SPDLOG_ERROR +#define CORSIKA_LOG_CRITICAL SPDLOG_CRITICAL + +// and the specific logger versions +// these take a logger instance as their first argument +#define CORSIKA_LOGGER_TRACE SPDLOG_LOGGER_TRACE +#define CORSIKA_LOGGER_DEBUG SPDLOG_LOGGER_DEBUG +#define CORSIKA_LOGGER_INFO SPDLOG_LOGGER_INFO +#define CORSIKA_LOGGER_WARN SPDLOG_LOGGER_WARN +#define CORSIKA_LOGGER_ERROR SPDLOG_LOGGER_ERROR +#define CORSIKA_LOGGER_CRITICAL SPDLOG_LOGGER_CRITICAL + +} // namespace corsika + +#include <corsika/detail/framework/logging/Logging.inl> diff --git a/corsika/framework/logging/MessageOff.h b/corsika/framework/logging/MessageOff.h deleted file mode 100644 index 691824be0100c9a9123ae4c538241830553073ae..0000000000000000000000000000000000000000 --- a/corsika/framework/logging/MessageOff.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * See file AUTHORS for a list of contributors. - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#ifndef _include_MessageOff_h_ -#define _include_MessageOff_h_ - -namespace corsika::logging { - - /** - Helper class to ignore all arguments to MessagesOn::Message and - always return empty string "". - */ - class MessageOff { - protected: - template <typename First, typename... Strings> - std::string Message(const First&, const Strings&...) { - return ""; - } - }; - -} // namespace corsika::logging - -#endif diff --git a/corsika/framework/logging/MessageOn.h b/corsika/framework/logging/MessageOn.h deleted file mode 100644 index 0b013a6350b95afdd1bb6ef5a43ab34ef47b7a92..0000000000000000000000000000000000000000 --- a/corsika/framework/logging/MessageOn.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * See file AUTHORS for a list of contributors. - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#ifndef _include_MessageOn_h_ -#define _include_MessageOn_h_ - -namespace corsika::logging { - - /** - Helper class to convert all input arguments of MessageOn::Message - into string-concatenated version and return this as string. - */ - class MessageOn { - protected: - std::string Message() { return "\n"; } - - template <typename First, typename... Strings> - std::string Message(const First& arg, const Strings&... rest) { - std::ostringstream ss; - ss << arg << Message(rest...); - return ss.str(); - } - - template <typename... Strings> - std::string Message(const int& arg, const Strings&... rest) { - return std::to_string(arg) + Message(rest...); - } - - template <typename... Strings> - std::string Message(const double& arg, const Strings&... rest) { - return std::to_string(arg) + Message(rest...); - } - - template <typename... Strings> - std::string Message(char const* arg, const Strings&... rest) { - return std::string(arg) + Message(rest...); - } - - template <typename... Strings> - std::string Message(const std::string& arg, const Strings&... rest) { - return arg + Message(rest...); - } - - // ---------------------- - // boost format - template <typename... Strings> - std::string Message(const boost::format& fmt, const Strings&... rest) { - boost::format FMT(fmt); - return bformat(FMT, rest...); - } - - template <typename Arg, typename... Strings> - std::string bformat(boost::format& fmt, const Arg& arg, const Strings&... rest) { - fmt % arg; - return bformat(fmt, rest...); - } - - std::string bformat(boost::format& fmt) { return fmt.str() + "\n"; } - }; - -} // namespace corsika::logging - -#endif diff --git a/corsika/framework/logging/NoSink.h b/corsika/framework/logging/NoSink.h deleted file mode 100644 index 866d35601d8805da00884df2fac551acb4cf7bdd..0000000000000000000000000000000000000000 --- a/corsika/framework/logging/NoSink.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * See file AUTHORS for a list of contributors. - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#ifndef _include_NoSink_h_ -#define _include_NoSink_h_ - -namespace corsika::logging { - - namespace sink { - - struct NoSink { - inline void operator<<(const std::string&) {} - inline void Close() {} - }; - - } // namespace sink -} // namespace corsika::logging - -#endif diff --git a/corsika/framework/logging/Sink.h b/corsika/framework/logging/Sink.h deleted file mode 100644 index 28c768d6f425a25515dfeeff0065df9b9e628643..0000000000000000000000000000000000000000 --- a/corsika/framework/logging/Sink.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu - * - * See file AUTHORS for a list of contributors. - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#ifndef _include_Sink_h_ -#define _include_Sink_h_ - -namespace corsika::logging { - - /** - a sink for the logger must implement the two functions - operator<<(const std::string&) - and - Close() - - See example: NoSink - */ - - namespace sink { - - /** - Definition of Sink for log output. - */ - template <typename TStream> - class Sink { - public: - Sink(TStream& out) - : fOutput(out) {} - void operator<<(const std::string& msg) { fOutput << msg; } - void Close() {} - - private: - TStream& fOutput; - }; - - typedef Sink<std::ostream> SinkStream; - - } // namespace sink -} // namespace corsika::logging - -#endif diff --git a/tests/framework/CMakeLists.txt b/tests/framework/CMakeLists.txt index 55458f17694702f7034f92ea1c96abed6fdc92f1..b39f912afab26ff26fbdc6e3155d7a7a979d13e7 100644 --- a/tests/framework/CMakeLists.txt +++ b/tests/framework/CMakeLists.txt @@ -6,7 +6,7 @@ set (test_framework_sources #testCorsikaFenv.cpp # does not work because of use of exceptions in catch2 testFourVector.cpp testGeometry.cpp - #testLogging.cpp # irrelevant -> not used back in March + testLogging.cpp TestMain.cpp testParticles.cpp testProcessSequence.cpp diff --git a/tests/framework/testLogging.cpp b/tests/framework/testLogging.cpp index 505c96c240b07f2c76f4f0b563e8bbae1c96b2fa..0d55c425979e8256cc6f160300734cfbb3b759e7 100644 --- a/tests/framework/testLogging.cpp +++ b/tests/framework/testLogging.cpp @@ -6,14 +6,14 @@ * the license. */ -#include <corsika/framework/logging/Logger.h> +#include <corsika/framework/logging/Logging.hpp> #include <catch2/catch.hpp> using namespace corsika; TEST_CASE("Logging", "[Logging]") { - SECTION("top level functions using corsika logger") { + SECTION("top level functions using default corsika logger") { logging::info("This is an info message!"); logging::warn("This is a warning message!"); logging::debug("This is a debug message!"); @@ -24,7 +24,7 @@ TEST_CASE("Logging", "[Logging]") { SECTION("create a specific logger") { // create a logger manually - auto logger = logging::CreateLogger("loggerA"); + auto logger = create_logger("loggerA"); // set a custom pattern for this logger logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); @@ -37,7 +37,7 @@ TEST_CASE("Logging", "[Logging]") { logger->critical("This is a critical error message!"); // get a reference to the logger using Get - auto other = logging::GetLogger("loggerA"); + auto other = get_logger("loggerA"); // and make sure we can use this other reference to log other->info("This is an info message!"); @@ -50,7 +50,7 @@ TEST_CASE("Logging", "[Logging]") { SECTION("get a new logger") { // get a reference to an unknown logger - auto logger = logging::GetLogger("loggerB"); + auto logger = get_logger("loggerB"); // and make sure we can log with this created object logger->info("This is an info message!"); @@ -63,7 +63,7 @@ TEST_CASE("Logging", "[Logging]") { SECTION("test log level") { // set the default log level - logging::SetDefaultLevel(logging::level::critical); + logging::set_default_level(logging::level::critical); // and make sure we can log with this created object logging::info("This should NOT be printed!"); @@ -73,10 +73,10 @@ TEST_CASE("Logging", "[Logging]") { logging::critical("This SHOULD BE printed!!"); // get a reference to an unknown logger - auto logger = logging::GetLogger("loggerD"); + auto logger = get_logger("loggerD"); // now set the default log level for this logger - logging::SetLevel(logger, logging::level::critical); + logger->set_level(logging::level::critical); // now try the various logging functions logger->info("This should NOT be printed!"); @@ -86,32 +86,32 @@ TEST_CASE("Logging", "[Logging]") { logger->critical("This SHOULD BE printed!!"); // and reset it for the next tests - logging::SetDefaultLevel(logging::level::debug); - logging::SetLevel(logging::level::debug); + logging::set_default_level(logging::level::debug); + logger->set_level(logging::level::critical); } SECTION("test macro style logging") { // these print with the "corsika" logger - C8LOG_INFO("test macro style logging"); - C8LOG_DEBUG("test macro style logging"); - C8LOG_ERROR("test macro style logging"); - C8LOG_CRITICAL("test macro style logging"); + CORSIKA_LOG_INFO("test macro style logging"); + CORSIKA_LOG_DEBUG("test macro style logging"); + CORSIKA_LOG_ERROR("test macro style logging"); + CORSIKA_LOG_CRITICAL("test macro style logging"); // get a reference to an unknown logger - auto logger = logging::GetLogger("loggerE"); + auto logger = get_logger("loggerE"); // add the filename, source information to this logger - logging::AddSourceInfo(logger); + logging::add_source_info(logger); // these print with the "loggerE" logger - C8LOG_LOGGER_INFO(logger, "test macro style logging"); - C8LOG_LOGGER_WARN(logger, "test macro style logging"); + CORSIKA_LOGGER_INFO(logger, "test macro style logging"); + CORSIKA_LOGGER_WARN(logger, "test macro style logging"); // reset the logging pattern - logging::ResetPattern(logger); + logging::reset_pattern(logger); // these trace macros should not print file, function, and line - C8LOG_LOGGER_TRACE(logger, "test macro style logging:"); + CORSIKA_LOGGER_TRACE(logger, "test macro style logging:"); } }