diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..fd25f08 --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ +--- +Language: Cpp +BasedOnStyle: Microsoft +ColumnLimit: 120 +PointerAlignment: Left +BreakBeforeBraces: Attach +AlignAfterOpenBracket: true +NamespaceIndentation: All +BreakTemplateDeclarations: Yes +IndentCaseLabels: Yes +OneLineFormatOffRegex: '^// NOLINT' +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..757087a --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,157 @@ + +--- +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +ExcludeHeaderFilterRegex: '^.*/tinyxml2.*$' +FormatStyle: 'file' +UseColor: true +SystemHeaders: false + +Checks: > + *bugprone*, + *performance*, + clang-analyzer-optin.cplusplus.VirtualCall, + clang-analyzer-optin.performance.Padding, + cppcoreguidelines-init-variables, + cppcoreguidelines-prefer-member-initializer, + cppcoreguidelines-pro-type-static-cast-downcast, + cppcoreguidelines-slicing, + google-explicit-constructor, + llvm-namespace-comment, + misc-definitions-in-headers, + misc-misplaced-const, + misc-non-copyable-objects, + misc-static-assert, + misc-throw-by-value-catch-by-reference, + misc-uniqueptr-reset-release, + misc-unused-parameters, + misc-include-cleaner, + modernize-avoid-bind, + modernize-loop-convert, + modernize-make-shared, + modernize-redundant-void-arg, + modernize-replace-auto-ptr, + modernize-replace-disallow-copy-and-assign-macro, + modernize-replace-random-shuffle, + modernize-shrink-to-fit, + modernize-use-auto, + modernize-use-bool-literals, + modernize-use-default-member-init, + modernize-use-emplace, + modernize-use-equals-default, + modernize-use-equals-delete, + modernize-use-noexcept, + modernize-use-nullptr, + modernize-use-override, + modernize-use-using, + readability-avoid-const-params-in-decls, + readability-braces-around-statements, + readability-const-return-type, + readability-container-size-empty, + readability-delete-null-pointer, + readability-duplicate-include, + readability-else-after-return, + readability-implicit-bool-conversion, + readability-inconsistent-declaration-parameter-name, + readability-make-member-function-const, + readability-misplaced-array-index, + readability-non-const-parameter, + readability-qualified-auto, + readability-identifier-naming, + readability-identifier-length, + readability-named-parameter, + readability-redundant-casting, + readability-redundant-function-ptr-dereference, + readability-redundant-inline-specifier, + readability-redundant-member-init, + readability-redundant-smartptr-get, + readability-redundant-string-cstr, + readability-simplify-subscript-expr, + readability-static-accessed-through-instance, + readability-string-compare, + readability-suspicious-call-argument, + readability-uniqueptr-delete-release, + -bugprone-chained-comparison, + -bugprone-easily-swappable-parameters, + -bugprone-exception-escape, + -bugprone-reserved-identifier, + -bugprone-unused-raii, + -performance-enum-size, + -performance-avoid-endl, + -performance-inefficient-string-concatenation, + +CheckOptions: + - key: readability-identifier-naming.NamespaceCase + value: lower_case + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.StructCase + value: CamelCase + - key: readability-identifier-naming.FunctionCase + value: CamelCase + - key: readability-identifier-naming.VariableCase + value: camelBack + - key: readability-identifier-naming.ParameterCase + value: camelBack + - key: readability-identifier-naming.MemberCase + value: camelBack + - key: readability-identifier-naming.PrivateMemberCase + value: camelBack + - key: readability-identifier-naming.ProtectedMemberCase + value: camelBack + - key: readability-identifier-naming.EnumCase + value: CamelCase + - key: readability-identifier-naming.EnumConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.ConstexprVariableCase + value: UPPER_CASE + - key: readability-identifier-naming.ConstexprFunctionCase + value: CamelCase + - key: readability-identifier-naming.GlobalConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.GlobalConstantMemberCase + value: UPPER_CASE + - key: readability-identifier-naming.StaticConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.StaticVariableCase + value: camelBack + - key: readability-identifier-naming.MemberConstantCase + value: camelBack + - key: readability-identifier-naming.MemberConstantStaticCase + value: UPPER_CASE + - key: readability-identifier-naming.ConstantMemberCase + value: camelBack + - key: readability-identifier-naming.PrivateConstantMemberCase + value: camelBack + - key: readability-identifier-naming.ProtectedConstantMemberCase + value: camelBack + - key: readability-identifier-naming.GlobalVariableCase + value: camelBack + - key: readability-identifier-naming.PrivateMemberSuffix + value: '_' + - key: readability-identifier-naming.PrivateConstantMemberSuffix + value: '_' + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: false + - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions + value: false + - key: readability-const-return-type.IgnoreMacros + value: false + - key: readability-identifier-length.MinimumVariableNameLength + value: 2 + - key: readability-identifier-length.IgnoredVariableNames + value: '^(i|j|k|x|y|z|n|a|b)$' + - key: readability-identifier-length.MinimumParameterNameLength + value: 2 + - key: readability-identifier-length.IgnoredParameterNames + value: '^(i|j|k|x|y|z|n|a|b)$' + - key: readability-identifier-length.MinimumLoopCounterNameLength + value: 3 + - key: readability-identifier-length.IgnoredLoopCounterNames + value: '^(i|j|k|n)$' + - key: readability-identifier-length.MinimumExceptionNameLength + value: 3 + - key: readability-identifier-length.IgnoredExceptionVariableNames + value: '^(e|ex)$' + - key: misc-include-cleaner.MissingIncludes + value: false diff --git a/.cmake-format.yaml b/.cmake-format.yaml new file mode 100644 index 0000000..14e7d9f --- /dev/null +++ b/.cmake-format.yaml @@ -0,0 +1,20 @@ +--- +# cmake-format configuration file +# See https://github.com/cheshirekow/cmake_format for documentation + +format: + line_width: 100 + tab_size: 4 + command_case: canonical + separate_ctrl_name_with_space: true + separate_fn_name_with_space: false + dangle_parens: true + dangle_align: prefix + min_prefix_chars: 4 + max_prefix_chars: 10 + require_valid_layout: false + enable_sort: true + autosort: true + +markup: + enable_markup: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5684ec6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,59 @@ +name: CI + +on: + push: + branches: [ main, master ] + pull_request: + types: [opened, synchronize, reopened] + branches: [ main, master ] + pull_request_target: + types: [opened, synchronize, reopened] + branches: [ main, master ] + +jobs: + ci: + name: CI (${{ matrix.os }} - ${{ matrix.compiler }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + compiler: g++ + - os: macos-latest + compiler: clang + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies (Ubuntu) + if: matrix.os == 'ubuntu-latest' + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 21 + sudo apt-get update + sudo apt-get install -y build-essential cmake libgtest-dev g++ clang-format-21 + pip install cmake-format + + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install cmake googletest + + - name: Build and Test + id: build-test + run: | + cmake --workflow release-test + + - name: Clang-tidy + id: clang-tidy + if: matrix.os == 'ubuntu-latest' + run: | + cmake --workflow test + + - name: Check formatting + id: check-format + if: always() && matrix.os == 'ubuntu-latest' + run: | + cmake --workflow check-format diff --git a/.gitignore b/.gitignore index 9db17ad..3a41a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build/ /install/ /docs/compiled/ +/.cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index e8b387b..1160335 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,66 +1,96 @@ -## +# # Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. cmake_minimum_required(VERSION 3.13) -project(COLA VERSION 0.3.2) - -set(CMAKE_CXX_STANDARD 17) +project( + COLA + VERSION 0.3.2 + LANGUAGES CXX +) # Add internal dependency to build add_subdirectory(tinyxml2) add_library(COLA SHARED COLA.cc) -target_include_directories(COLA PUBLIC - $ - $) +target_compile_features(COLA PUBLIC cxx_std_17) -target_link_libraries(COLA PRIVATE tinyxml2) +target_include_directories( + COLA PUBLIC $ $ +) -set_target_properties(COLA PROPERTIES - PUBLIC_HEADER "COLA.hh;LorentzVector.hh" - VERSION "${COLA_VERSION}" - SOVERSION "${COLA_VERSION_MAJOR}") +target_link_libraries(COLA PRIVATE tinyxml2) -install(TARGETS COLA - EXPORT COLAExport - LIBRARY DESTINATION lib - PUBLIC_HEADER DESTINATION include - INCLUDES DESTINATION include) +set(COLA_CMAKE_CXX_CLANG_TIDY + "" + CACHE STRING "variable will be passed to CMAKE_CXX_CLANG_TIDY of COLA target" +) + +set_target_properties( + COLA + PROPERTIES PUBLIC_HEADER "COLA.hh;LorentzVector.hh" + VERSION "${COLA_VERSION}" + SOVERSION "${COLA_VERSION_MAJOR}" + CXX_CLANG_TIDY "${COLA_CMAKE_CXX_CLANG_TIDY}" +) + +include(GNUInstallDirs) + +install( + TARGETS COLA + EXPORT COLAExport + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) include(CMakePackageConfigHelpers) configure_package_config_file( - "${PROJECT_SOURCE_DIR}/data/COLAConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/COLAConfig.cmake" - INSTALL_DESTINATION lib/cmake/COLA) + "${PROJECT_SOURCE_DIR}/data/COLAConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/COLAConfig.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/COLA +) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/COLAConfigVersion.cmake - COMPATIBILITY AnyNewerVersion) + ${CMAKE_CURRENT_BINARY_DIR}/COLAConfigVersion.cmake COMPATIBILITY AnyNewerVersion +) -install(EXPORT COLAExport - DESTINATION lib/cmake/COLA) +install(EXPORT COLAExport DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/COLA) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/COLAConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/COLAConfigVersion.cmake" - DESTINATION lib/cmake/COLA) - -install(FILES "${PROJECT_SOURCE_DIR}/data/config.sh" - DESTINATION ${CMAKE_INSTALL_PREFIX}) + "${CMAKE_CURRENT_BINARY_DIR}/COLAConfigVersion.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/COLA +) + +install(FILES "${PROJECT_SOURCE_DIR}/data/config.sh" DESTINATION ${CMAKE_INSTALL_PREFIX}) + +install( + DIRECTORY cmake/ + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/COLA/cmake + FILES_MATCHING + PATTERN "*.cmake" +) + +enable_testing() +if (BUILD_TESTING) + add_subdirectory(tests) +endif () + +# Setup code quality tools (clang-format, cmake-format) +include(cmake/SetupCodeQuality.cmake) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..d16c4d1 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,235 @@ + +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 13, + "patch": 0 + }, + "configurePresets": [ + { + "name": "base", + "hidden": true, + "binaryDir": "${sourceDir}/build/${presetName}", + "generator": "Unix Makefiles", + "cacheVariables": { + "BUILD_TESTING": "OFF", + "CMAKE_COLOR_DIAGNOSTICS": true + } + }, + { + "name": "default", + "displayName": "Default", + "inherits": "base", + "errors": { + "dev": true, + "deprecated": true + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_EXPORT_COMPILE_COMMANDS": true + } + }, + { + "name": "release", + "displayName": "Release", + "inherits": "base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "release-test", + "displayName": "Release with Tests", + "inherits": "release", + "cacheVariables": { + "BUILD_TESTING": "ON" + } + }, + { + "name": "tidy", + "displayName": "Clang-tidy", + "inherits": "default", + "cacheVariables": { + "BUILD_TESTING": "ON", + "COLA_CMAKE_CXX_CLANG_TIDY": "clang-tidy" + } + }, + { + "name": "tidy-fix", + "displayName": "Clang-tidy fix", + "inherits": "default", + "cacheVariables": { + "BUILD_TESTING": "ON", + "COLA_CMAKE_CXX_CLANG_TIDY": "clang-tidy;--fix" + } + } + ], + "buildPresets": [ + { + "name": "default", + "displayName": "Default Build", + "configurePreset": "default" + }, + { + "name": "release", + "displayName": "Release Build", + "configurePreset": "release" + }, + { + "name": "release-test", + "displayName": "Release Test Build", + "configurePreset": "release-test" + }, + { + "name": "tidy", + "displayName": "Tidy Build", + "configurePreset": "tidy" + }, + { + "name": "tidy-fix", + "displayName": "Tidy fix Build", + "configurePreset": "tidy-fix" + }, + { + "name": "clang-format-check", + "displayName": "Check clang-format", + "configurePreset": "tidy", + "targets": ["clang-format-check"] + }, + { + "name": "clang-format-fix", + "displayName": "Fix clang-format", + "configurePreset": "tidy", + "targets": ["clang-format-fix"] + }, + { + "name": "cmake-format-check", + "displayName": "Check cmake-format", + "configurePreset": "tidy", + "targets": ["cmake-format-check"] + }, + { + "name": "cmake-format-fix", + "displayName": "Fix cmake-format", + "configurePreset": "tidy", + "targets": ["cmake-format-fix"] + }, + { + "name": "check-format", + "displayName": "Check all linters", + "configurePreset": "tidy", + "targets": [ + "clang-format-check", + "cmake-format-check" + ] + }, + { + "name": "fix-format", + "displayName": "Fix all linters", + "configurePreset": "tidy", + "targets": [ + "clang-format-fix", + "cmake-format-fix" + ] + } + ], + "testPresets": [ + { + "name": "default", + "displayName": "Run Debug Tests", + "configurePreset": "tidy", + "output": { + "outputOnFailure": true + } + }, + { + "name": "release", + "displayName": "Run Release Tests", + "configurePreset": "release-test", + "output": { + "outputOnFailure": true + } + } + ], + "workflowPresets": [ + { + "name": "default", + "displayName": "Default Workflow", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + } + ] + }, + { + "name": "test", + "displayName": "Test Workflow (with linter checks)", + "steps": [ + { + "type": "configure", + "name": "tidy" + }, + { + "type": "build", + "name": "tidy" + }, + { + "type": "test", + "name": "default" + } + ] + }, + { + "name": "check-format", + "displayName": "Check All Linters Workflow", + "steps": [ + { + "type": "configure", + "name": "tidy" + }, + { + "type": "build", + "name": "check-format" + } + ] + }, + { + "name": "fix-format", + "displayName": "Fix All Linters Workflow", + "steps": [ + { + "type": "configure", + "name": "tidy" + }, + { + "type": "build", + "name": "fix-format" + } + ] + }, + { + "name": "release-test", + "displayName": "Release Test Workflow", + "steps": [ + { + "type": "configure", + "name": "release-test" + }, + { + "type": "build", + "name": "release-test" + }, + { + "type": "test", + "name": "release" + } + ] + } + ] +} diff --git a/COLA.cc b/COLA.cc index d64de7f..8ab49a7 100644 --- a/COLA.cc +++ b/COLA.cc @@ -1,32 +1,56 @@ /** -* Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ + * Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ #include "COLA.hh" +#include +#include +#include +#include +#include +#include +#include + #include +namespace { + std::map GetNameAndParams(const tinyxml2::XMLElement* element, std::string& name) { + const auto* currentAttribute = element->FindAttribute("name"); + name = currentAttribute->Value(); + std::cout << "filter name: " + name + "\nparams:\n"; + currentAttribute = currentAttribute->Next(); + std::map params; + while (currentAttribute != nullptr) { + params.emplace(currentAttribute->Name(), currentAttribute->Value()); + std::cout << currentAttribute->Name() << ": " << currentAttribute->Value() << '\n'; + currentAttribute = currentAttribute->Next(); + } + return params; + } +} // namespace + namespace cola { // converters - AZ pdgToAZ(int pdgCode) { + AZ PdgToAz(int pdgCode) { switch (pdgCode) { case 2112: return {1, 0}; @@ -58,16 +82,18 @@ namespace cola { return 1000000000 + data.first * 10 + data.second * 10000; } - AZ Particle::getAZ() const { - return pdgToAZ(pdgCode); + AZ Particle::GetAz() const { + return PdgToAz(pdgCode); } // operators - std::unique_ptr operator|(const std::unique_ptr& generator, const std::unique_ptr& converter) { + std::unique_ptr operator|(const std::unique_ptr& generator, + const std::unique_ptr& converter) { return (*converter)((*generator)()); } - std::unique_ptr operator|(std::unique_ptr&& data, const std::unique_ptr& converter) { + std::unique_ptr operator|(std::unique_ptr&& data, + const std::unique_ptr& converter) { return (*converter)(std::move(data)); } void operator|(std::unique_ptr&& data, const std::unique_ptr& writer) { @@ -77,80 +103,70 @@ namespace cola { // Metaprocessor MetaProcessor::MetaProcessor(std::map, FilterType>>& filterMap) { - for (auto& item: filterMap) - reg(std::move(item.second.first), item.first, item.second.second); + for (auto& item : filterMap) { + Reg(std::move(item.second.first), item.first, item.second.second); + } } - void MetaProcessor::reg(std::unique_ptr&& factory, const std::string& name, const FilterType type) { + void MetaProcessor::Reg(std::unique_ptr&& factory, const std::string& name, const FilterType type) { switch (type) { - case FilterType::generator: - regGen(std::move(factory), name); + case FilterType::GENERATOR: + RegGen(std::move(factory), name); break; - case FilterType::converter: - regConv(std::move(factory), name); + case FilterType::CONVERTER: + RegConv(std::move(factory), name); break; - case FilterType::writer: - regWrite(std::move(factory), name); + case FilterType::WRITER: + RegWrite(std::move(factory), name); break; default: throw std::domain_error("ERROR in MetaProcessor: No such type of filter."); } } - std::map _get_name_and_params (const tinyxml2::XMLElement* element, std::string& name) { - auto currentAttribute = element->FindAttribute("name"); - name = currentAttribute->Value(); - std::cout << "filter name: " + name +"\nparams:\n"; - currentAttribute = currentAttribute->Next(); - std::map params; - while (currentAttribute != nullptr){ - params.emplace(currentAttribute->Name(), currentAttribute->Value()); - std::cout << currentAttribute->Name() << ": " << currentAttribute->Value() << '\n'; - currentAttribute = currentAttribute->Next(); - } - return params; - } - - FilterEnsemble MetaProcessor::parse(const std::string &fName) const { + FilterEnsemble MetaProcessor::Parse(const std::string& fName) const { using namespace tinyxml2; std::cout << "Parsing XML file:" << '\n'; XMLDocument file; auto code = file.LoadFile(fName.c_str()); - if (code == XML_SUCCESS) { - FilterEnsemble ensemble; + if (code != XML_SUCCESS) { + throw std::runtime_error("ERROR in MetaProcessor: Couldn't open file `" + fName + + "`.\nError code (tinyxml2): " + std::to_string(code)); + } - auto currentElement = file.RootElement()->FirstChildElement("generator"); - std::string name; - std::map params = _get_name_and_params(currentElement, name); - ensemble.generator = std::unique_ptr(dynamic_cast(generatorMap.at(name)->create(params))); - params.clear(); + FilterEnsemble ensemble; - currentElement = currentElement->NextSiblingElement(); - while (currentElement->Name() != std::string("writer")) { - params = _get_name_and_params(currentElement, name); - ensemble.converters.push_back(std::unique_ptr(dynamic_cast(converterMap.at(name)->create(params)))); - params.clear(); - currentElement = currentElement->NextSiblingElement(); - } + auto* currentElement = file.RootElement()->FirstChildElement("generator"); + std::string name; + auto params = GetNameAndParams(currentElement, name); + ensemble.generator = + std::unique_ptr(dynamic_cast(generatorMap_.at(name)->Create(params))); + params.clear(); - params = _get_name_and_params(currentElement, name); - ensemble.writer = std::unique_ptr(dynamic_cast(writerMap.at(name)->create(params))); - return ensemble; - } else { - throw std::runtime_error("ERROR in MetaProcessor: Couldn't open file `" + fName + "`.\nError code (tinyxml2): " + - std::to_string(code)); + currentElement = currentElement->NextSiblingElement(); + while (currentElement->Name() != std::string("writer")) { + params = GetNameAndParams(currentElement, name); + ensemble.converters.push_back( + std::unique_ptr(dynamic_cast(converterMap_.at(name)->Create(params)))); + params.clear(); + currentElement = currentElement->NextSiblingElement(); } + + params = GetNameAndParams(currentElement, name); + ensemble.writer = std::unique_ptr(dynamic_cast(writerMap_.at(name)->Create(params))); + return ensemble; } // Run manager - void ColaRunManager::run(int n) const { - for(int k = 0; k < n; k++) { - auto event = (*(filterEnsemble.generator))(); - for (const auto& converter : filterEnsemble.converters) + void ColaRunManager::Run(int n) const { + for (int k = 0; k < n; k++) { + auto event = (*(filterEnsemble_.generator))(); + for (const auto& converter : filterEnsemble_.converters) { event = std::move(event) | converter; - std::move(event) | filterEnsemble.writer; + } + std::move(event) | filterEnsemble_.writer; } } -} //cola +} // namespace cola diff --git a/COLA.hh b/COLA.hh index d61b197..1656ab6 100644 --- a/COLA.hh +++ b/COLA.hh @@ -1,31 +1,28 @@ /** -* Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ + * Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ #ifndef COLA_COLA_HH #define COLA_COLA_HH -#include -#include #include #include -#include #include #include "LorentzVector.hh" @@ -42,7 +39,7 @@ namespace cola { * @param pdgCode PDG code of the ion. * @return AZ of the ion. */ - AZ pdgToAZ(int pdgCode); + AZ PdgToAz(int pdgCode); /** AZ to PDG code convverter. * @param data AZ of the ion. @@ -57,28 +54,35 @@ namespace cola { /** Particle class by generator output. * This enum represents various outcomes of a generator event for every particle. */ - enum class ParticleClass: char { - produced, /**< A particle that was not present in the starting nuclei. */ - elasticA, /**< A particle that was present in the projectile nucleus and has experienced only elastic interactions. */ - elasticB, /**< A particle that was present in the target nucleus and has experienced only elastic interactions. */ - nonelasticA, /**< A particle that was present in the projectile nucleus and has experienced at least one non-elastic interaction. */ - nonelasticB, /**< A particle that was present in the target nucleus and has experienced at least one non-elastic interaction. */ - spectatorA, /**< A particle that was present in the projectile nucleus and hasn't experienced any interactions. */ - spectatorB /**< A particle that was present in the projectile nucleus and hasn't experienced any interactions. */ + enum class ParticleClass : char { + PRODUCED, /**< A particle that was not present in the starting nuclei. */ + ELASTIC_A, /**< A particle that was present in the projectile nucleus and has experienced only elastic + * interactions. + */ + ELASTIC_B, /**< A particle that was present in the target nucleus and has experienced only elastic interactions. + */ + NONELASTIC_A, /**< A particle that was present in the projectile nucleus and has experienced at least one + non-elastic interaction. */ + NONELASTIC_B, /**< A particle that was present in the target nucleus and has experienced at least one + non-elastic interaction. */ + SPECTATOR_A, /**< A particle that was present in the projectile nucleus and hasn't experienced any interactions. + */ + SPECTATOR_B /**< A particle that was present in the projectile nucleus and hasn't experienced any interactions. + */ }; /** Particle data. * A structure representing data about a single particle */ struct Particle { - AZ getAZ() const; + AZ GetAz() const; LorentzVector position; /**< Position vector. */ LorentzVector momentum; /**< Momentum vector. */ - int pdgCode; /**< PDG code of the particle. */ - ParticleClass pClass; /**< Data about particle origin. See ParticleClass for more info.*/ + int pdgCode; /**< PDG code of the particle. */ + ParticleClass pClass; /**< Data about particle origin. See ParticleClass for more info.*/ }; /** @@ -90,30 +94,31 @@ namespace cola { * This structure contains data about initial state of any given event. */ struct EventIniState { - int pdgCodeA; /**< PDF code of the projectile. */ - int pdgCodeB; /**< PDF code of the target. */ - - double pZA; /** Axial momentum of the projectile */ - double pZB; /** Axial momentum of the target */ - double energy; /** Incidental energy of the event. Depending on pZB being zero, this is either \f$E/A\f$ of target or \f$\sqrt{s_{NN}}\f$. */ - - float sectNN; /** Nucleon-Nucleon cross section from generator. */ - float b; /** Impact parameter of the event. */ - - int nColl; /** Diagnostic. Total number of collisions. */ - int nCollPP; /** Diagnostic. Number of proton-proton. */ - int nCollPN; /** Diagnostic. Number of proton-neutron collisions. */ - int nCollNN; /** Diagnostic. Number of neutron-neutron collisions. */ - int nPart; /** Diagnostic. Total number of participants. */ - int nPartA; /** Diagnostic. Number of participants from the projectile nucleus. */ - int nPartB; /** Diagnostic. Number of participants from the target nucleus. */ - - float phiRotA; /** Diagnostic. Polar angle \f$\phi\f$ of rotation of the projectile nucleon. */ - float thetaRotA; /** Diagnostic. Polar angle \f&\Theta\f$ of rotation of the projectile nucleon. */ - float phiRotB; /** Diagnostic. Polar angle \f$\phi\f$ of rotation of the target nucleon. */ - float thetaRotB; /** Diagnostic. Polar angle \f$\Theta\f$ of rotation of the target nucleon. */ - - EventParticles iniStateParticles; /** The array of all Particles just before the event. */ + int pdgCodeA; /**< PDF code of the projectile. */ + int pdgCodeB; /**< PDF code of the target. */ + + double pZA; /** Axial momentum of the projectile */ + double pZB; /** Axial momentum of the target */ + double energy; /** Incidental energy of the event. Depending on pZB being zero, this is either \f$E/A\f$ of + target or \f$\sqrt{s_{NN}}\f$. */ + + float sectNN; /** Nucleon-Nucleon cross section from generator. */ + float b; /** Impact parameter of the event. */ + + int nColl; /** Diagnostic. Total number of collisions. */ + int nCollPP; /** Diagnostic. Number of proton-proton. */ + int nCollPN; /** Diagnostic. Number of proton-neutron collisions. */ + int nCollNN; /** Diagnostic. Number of neutron-neutron collisions. */ + int nPart; /** Diagnostic. Total number of participants. */ + int nPartA; /** Diagnostic. Number of participants from the projectile nucleus. */ + int nPartB; /** Diagnostic. Number of participants from the target nucleus. */ + + float phiRotA; /** Diagnostic. Polar angle \f$\phi\f$ of rotation of the projectile nucleon. */ + float thetaRotA; /** Diagnostic. Polar angle \f&\Theta\f$ of rotation of the projectile nucleon. */ + float phiRotB; /** Diagnostic. Polar angle \f$\phi\f$ of rotation of the target nucleon. */ + float thetaRotB; /** Diagnostic. Polar angle \f$\Theta\f$ of rotation of the target nucleon. */ + + EventParticles iniStateParticles; /** The array of all Particles just before the event. */ }; /** A structure combining EventIniState and EventParticles of the event. @@ -132,10 +137,10 @@ namespace cola { * A single model in the COLA-driven pipeline is named a Filter. */ class VFilter { - public: + public: VFilter() = default; - VFilter (const VFilter&) = delete; - VFilter (VFilter&&) = delete; + VFilter(const VFilter&) = delete; + VFilter(VFilter&&) = delete; VFilter& operator=(const VFilter&) = delete; VFilter& operator=(VFilter&&) = delete; virtual ~VFilter() = 0; @@ -148,10 +153,10 @@ namespace cola { * files or encapsulate nucleus-nucleus collision generators. */ class VGenerator : public VFilter { - public: + public: VGenerator() = default; - VGenerator (const VGenerator&) = delete; - VGenerator (VGenerator&&) = delete; + VGenerator(const VGenerator&) = delete; + VGenerator(VGenerator&&) = delete; VGenerator& operator=(const VGenerator&) = delete; VGenerator& operator=(VGenerator&&) = delete; ~VGenerator() override = 0; @@ -166,14 +171,14 @@ namespace cola { inline VGenerator::~VGenerator() = default; /** Converter abstract class. - * This is a converter interface. It is inherited by all filters that are in the middle of MC simulation. - * Converters are intended to transform data from previous steps. - */ + * This is a converter interface. It is inherited by all filters that are in the middle of MC simulation. + * Converters are intended to transform data from previous steps. + */ class VConverter : public VFilter { - public: + public: VConverter() = default; - VConverter (const VConverter&) = delete; - VConverter (VConverter&&) = delete; + VConverter(const VConverter&) = delete; + VConverter(VConverter&&) = delete; VConverter& operator=(const VConverter&) = delete; VConverter& operator=(VConverter&&) = delete; ~VConverter() override = 0; @@ -195,10 +200,10 @@ namespace cola { * detector response to the generated event) you can encapsulate these calculations in a writer class. */ class VWriter : public VFilter { - public: + public: VWriter() = default; - VWriter (const VWriter&) = delete; - VWriter (VWriter&&) = delete; + VWriter(const VWriter&) = delete; + VWriter(VWriter&&) = delete; VWriter& operator=(const VWriter&) = delete; VWriter& operator=(VWriter&&) = delete; ~VWriter() override = 0; @@ -215,14 +220,14 @@ namespace cola { inline VWriter::~VWriter() = default; /** Factory abstract class. - * This is a factory interface. It generates a Filter with its VFactory::create method. DI in COLA works via using the - * factory classes, which are registered in a MetaProcessor instance. + * This is a factory interface. It generates a Filter with its VFactory::create method. DI in COLA works via using + * the factory classes, which are registered in a MetaProcessor instance. */ class VFactory { - public: + public: VFactory() = default; - VFactory (const VFactory&) = delete; - VFactory (VFactory&&) = delete; + VFactory(const VFactory&) = delete; + VFactory(VFactory&&) = delete; VFactory& operator=(const VFactory&) = delete; VFactory& operator=(VFactory&&) = delete; virtual ~VFactory() = default; @@ -232,20 +237,21 @@ namespace cola { * @param metaData A dictionary with key-value pairs needed for configuring a model. * @return A configured class that is a VFilter child. */ - virtual VFilter* create(const std::map& metaData) = 0; + virtual VFilter* Create(const std::map& metaData) = 0; }; - - std::unique_ptr operator|(const std::unique_ptr&, const std::unique_ptr&); - std::unique_ptr operator|(std::unique_ptr&&, const std::unique_ptr&); - void operator|(std::unique_ptr&&, const std::unique_ptr&); + std::unique_ptr operator|(const std::unique_ptr& /*generator*/, + const std::unique_ptr& /*converter*/); + std::unique_ptr operator|(std::unique_ptr&& /*data*/, + const std::unique_ptr& /*converter*/); + void operator|(std::unique_ptr&& /*data*/, const std::unique_ptr& /*writer*/); /** An enum for marking Filter types. */ - enum class FilterType: char { - generator, - converter, - writer + enum class FilterType : char { + GENERATOR, + CONVERTER, + WRITER }; /** @} * \defgroup Metadata Classes for constructing and running a model. @@ -255,9 +261,9 @@ namespace cola { /** A structure representing the model pipeline. */ struct FilterEnsemble { - std::unique_ptr generator; /**< Event generator. */ - std::vector> converters; /**< Vector of converters, applied step-by-step. */ - std::unique_ptr writer; /**< Writer to save the results. */ + std::unique_ptr generator; /**< Event generator. */ + std::vector> converters; /**< Vector of converters, applied step-by-step. */ + std::unique_ptr writer; /**< Writer to save the results. */ }; /** A class for processing meta information. @@ -265,15 +271,15 @@ namespace cola { * pipeline using its MetaProcessor:parse method to read all needed information from an XML-file. */ class MetaProcessor { - public: - + public: /** Default constructor. */ MetaProcessor() = default; /** Constructor with immediate factories registration. * Note that unique pointers in the dictionary are invalidated. - * @param filterMap A dictionary with all relevant information. Note that unique pointers in the dictionary are invalidated. + * @param filterMap A dictionary with all relevant information. Note that unique pointers in the dictionary are + * invalidated. */ explicit MetaProcessor(std::map, FilterType>>& filterMap); @@ -284,48 +290,56 @@ namespace cola { * @param name The name of the Filter. * @param type The type of the Filter. See FilterType. */ - void reg(std::unique_ptr&& factory, const std::string& name, FilterType type); + void Reg(std::unique_ptr&& factory, const std::string& name, FilterType type); /** A method to parse a XML-file to set up a configured FilterEnsemble. * This method opens an XML-file @param fName to get the information to set up the model. * Inside the root element should be one element followed by any number of elements * (none is possible) and, finally, a element. Each element must have "name" attribute followed by - * any number of additional attributes. These attributes are then passed to the corresponding factory's VFactory::create - * method as a dictionary with keys being attribute names and values - attribute values. - * This method throws an error if a relevant factory isn't found or XML-file is malformed. + * any number of additional attributes. These attributes are then passed to the corresponding factory's + * VFactory::create method as a dictionary with keys being attribute names and values - attribute values. This + * method throws an error if a relevant factory isn't found or XML-file is malformed. * @param fName Name with the configuration XML-file. * @return A configured FilterEnsemble. */ - FilterEnsemble parse(const std::string& fName) const; - - private: - std::map> generatorMap; - std::map> converterMap; - std::map> writerMap; - - void regGen(std::unique_ptr&& factory, const std::string& name){ generatorMap.emplace(name, std::move(factory)); } - void regConv(std::unique_ptr&& factory, const std::string& name){ converterMap.emplace(name, std::move(factory)); } - void regWrite(std::unique_ptr&& factory, const std::string& name){ writerMap.emplace(name, std::move(factory)); } + FilterEnsemble Parse(const std::string& fName) const; + + private: + std::map> generatorMap_; + std::map> converterMap_; + std::map> writerMap_; + + void RegGen(std::unique_ptr&& factory, const std::string& name) { + generatorMap_.emplace(name, std::move(factory)); + } + void RegConv(std::unique_ptr&& factory, const std::string& name) { + converterMap_.emplace(name, std::move(factory)); + } + void RegWrite(std::unique_ptr&& factory, const std::string& name) { + writerMap_.emplace(name, std::move(factory)); + } }; /** Manager class. * Currently more of a boilerplate, but potentially useful to incorporate parallel computing. */ class ColaRunManager { - public: + public: ColaRunManager() = delete; /** A constructor that moves the configured FilterEnsemble into the manager. * @param ensemble Configured model. */ - explicit ColaRunManager(FilterEnsemble&& ensemble) : filterEnsemble(std::move(ensemble)) {} + explicit ColaRunManager(FilterEnsemble&& ensemble) : filterEnsemble_(std::move(ensemble)) { + } ~ColaRunManager() = default; /** A method to run the resulting model @param n times. * @param n Number of runs. */ - void run(int n = 1) const; - private: - FilterEnsemble filterEnsemble; + void Run(int n = 1) const; + + private: + FilterEnsemble filterEnsemble_; }; -} // cola +} // namespace cola -#endif //COLA_COLA_HH +#endif // COLA_COLA_HH diff --git a/LorentzVector.hh b/LorentzVector.hh index e912012..1e0aea9 100644 --- a/LorentzVector.hh +++ b/LorentzVector.hh @@ -1,22 +1,22 @@ /** -* Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ + * Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ #ifndef COLA_LORENTZVECTOR_HH #define COLA_LORENTZVECTOR_HH @@ -34,7 +34,7 @@ namespace cola { template class LorentzVectorImpl { - public: + public: union { Type e; Type t; @@ -43,106 +43,122 @@ namespace cola { Type y; Type z; - private: + private: using FieldPtr = Type LorentzVectorImpl::*; - static inline constexpr std::array Fields_ = { - &LorentzVectorImpl::e, - &LorentzVectorImpl::x, - &LorentzVectorImpl::y, - &LorentzVectorImpl::z - }; + static constexpr std::array FIELDS = {&LorentzVectorImpl::e, &LorentzVectorImpl::x, + &LorentzVectorImpl::y, &LorentzVectorImpl::z}; - public: - const Type& operator[](int i) const { return this->*Fields_[i]; } - Type& operator[](int i) { return this->*Fields_[i]; } + public: + const Type& operator[](int i) const { + return this->*FIELDS[i]; + } + Type& operator[](int i) { + return this->*FIELDS[i]; + } LorentzVectorImpl& operator+=(const LorentzVectorImpl& other) { - for (size_t i = 0; i < Fields_.size(); ++i) { - this->*Fields_[i] += other.*Fields_[i]; + for (size_t i = 0; i < FIELDS.size(); ++i) { + this->*FIELDS[i] += other.*FIELDS[i]; } return *this; } LorentzVectorImpl& operator-=(const LorentzVectorImpl& other) { - for (size_t i = 0; i < Fields_.size(); ++i) { - this->*Fields_[i] -= other.*Fields_[i]; + for (size_t i = 0; i < FIELDS.size(); ++i) { + this->*FIELDS[i] -= other.*FIELDS[i]; } return *this; } LorentzVectorImpl& operator*=(Type scalar) { - for (size_t i = 0; i < Fields_.size(); ++i) { - this->*Fields_[i] *= scalar; + for (size_t i = 0; i < FIELDS.size(); ++i) { + this->*FIELDS[i] *= scalar; } return *this; } LorentzVectorImpl& operator/=(Type scalar) { - for (size_t i = 0; i < Fields_.size(); ++i) { - this->*Fields_[i] /= scalar; + for (size_t i = 0; i < FIELDS.size(); ++i) { + this->*FIELDS[i] /= scalar; } return *this; } // bx by and bz are projections of beta - LorentzVectorImpl& boost(Type bx, Type by, Type bz) { - - Type b2 = bx * bx + by * by + bz * bz; - - if (b2 >= 1) - throw std::runtime_error("Boost faster than speed of light."); - if (b2 <= .95 or not isSpaceLike()) { - Type ggamma = 1.0 / std::sqrt(1.0 - b2); - Type bp = bx * x + by * y + bz * z; - Type gamma2 = b2 > 0 ? (ggamma - 1.0) / b2 : 0.0; - - x = x + gamma2 * bp * bx + ggamma * bx * t; - y = y + gamma2 * bp * by + ggamma * by * t; - z = z + gamma2 * bp * bz + ggamma * bz * t; - t = ggamma * (t + bp); - - // for big betas use rapidities instead (B = R^-1B'R, where B' is axis boost (Oz here) and R is Rotation matrix for spatial part) - } else { - // calculate direction vector coordinates - Type b1 = std::sqrt(b2); - Vector3 rVec{bx / b1, by / b1, bz / b1}; - Vector3 rBack = rotateUz({0, 0, 1}, rVec); - - // rotate space vector so that boost direction is {0, 0, 1} in new coordinates - auto newCoord = rotateUz({x, y, z}, rVec); - x = newCoord.x, y = newCoord.y, z = newCoord.z; - - boostAxisRapidity(std::atanh(b1)); // boost along Oz - // rotate back - newCoord = rotateUz({x, y, z}, rBack); - x = newCoord.x, y = newCoord.y, z = newCoord.z; - } + LorentzVectorImpl& Boost(Type bx, Type by, Type bz) { - return *this; - } + auto b2 = bx * bx + by * by + bz * bz; - // axis from 1 to 3 correspond to x-y-z. Note: this gives correct results only if other axes components are zero. TODO: Throw an error otherwise - LorentzVectorImpl& boostAxisRapidity(Type rapidity, uint axis=3u) { - if (axis > 3 or axis < 1) - throw std::runtime_error("Wrong axis in boostAxis. 1 for x, 2 for y, 3 for z."); - if (not isSpaceLike()) { - throw std::runtime_error("Rapidity calculation only viable for space-like 4-vectors. Use boost() instead"); + if (b2 >= 1) { + throw std::runtime_error("Boost faster than speed of light."); + } + if (b2 <= .95 or not IsSpaceLike()) { + Type ggamma = 1.0 / std::sqrt(1.0 - b2); + Type bp = bx * x + by * y + bz * z; + Type gamma2 = b2 > 0 ? (ggamma - 1.0) / b2 : 0.0; + + x = x + gamma2 * bp * bx + ggamma * bx * t; + y = y + gamma2 * bp * by + ggamma * by * t; + z = z + gamma2 * bp * bz + ggamma * bz * t; + t = ggamma * (t + bp); + + // for big betas use rapidities instead (B = R^-1B'R, where B' is axis boost (Oz here) and R is Rotation + // matrix for spatial part) + } else { + // calculate direction vector coordinates + Type b1 = std::sqrt(b2); + Vector3 rVec{bx / b1, by / b1, bz / b1}; + Vector3 rBack = rotateUz({0, 0, 1}, rVec); + + // rotate space vector so that boost direction is {0, 0, 1} in new coordinates + auto newCoord = rotateUz({x, y, z}, rVec); + x = newCoord.x, y = newCoord.y, z = newCoord.z; + + BoostAxisRapidity(std::atanh(b1)); // boost along Oz + // rotate back + newCoord = rotateUz({x, y, z}, rBack); + x = newCoord.x, y = newCoord.y, z = newCoord.z; + } + + return *this; } - Type inv = std::sqrt(e*e - this->*Fields_[axis]*this->*Fields_[axis]); - Type rRapidity = rapidity + .5 * (std::log(e + this->*Fields_[axis]) - std::log(e - this->*Fields_[axis])); - e = inv * std::cosh(rRapidity); - this->*Fields_[axis] = inv * std::sinh(rRapidity); - return *this; + // axis from 1 to 3 correspond to x-y-z. Note: this gives correct results only if other axes components are + // zero. + // TODO: Throw an error otherwise + LorentzVectorImpl& BoostAxisRapidity(Type rapidity, uint32_t axis = 3u) { + if (axis > 3 or axis < 1) { + throw std::runtime_error("Wrong axis in boostAxis. 1 for x, 2 for y, 3 for z."); + } + if (not IsSpaceLike()) { + throw std::runtime_error( + "Rapidity calculation only viable for space-like 4-vectors. Use boost() instead"); + } + Type inv = std::sqrt(e * e - this->*FIELDS[axis] * this->*FIELDS[axis]); + Type rRapidity = rapidity + .5 * (std::log(e + this->*FIELDS[axis]) - std::log(e - this->*FIELDS[axis])); + e = inv * std::cosh(rRapidity); + this->*FIELDS[axis] = inv * std::sinh(rRapidity); + + return *this; } - Type mag2() const { return t*t - (x*x + y*y + z*z); } - Type mag() const { return std::sqrt(mag2()); } + Type Mag2() const { + return t * t - (x * x + y * y + z * z); + } + Type Mag() const { + return std::sqrt(Mag2()); + } - bool isSpaceLike() const { return mag2() > 0; } - bool isLightLike() const { return mag2() == 0; } - bool isTimeLike() const { return mag2() < 0; } + bool IsSpaceLike() const { + return Mag2() > 0; + } + bool IsLightLike() const { + return Mag2() == 0; + } + bool IsTimeLike() const { + return Mag2() < 0; + } }; template @@ -195,11 +211,11 @@ namespace cola { } template - Vector3 rotateUz(const Vector3 stVec, const Vector3 uzVec) { + Vector3 RotateUz(const Vector3 stVec, const Vector3 uzVec) { // NewUzVector must be normalized ! Vector3 resVec; - double up = uzVec.x*uzVec.x + uzVec.y*uzVec.y; + auto up = uzVec.x * uzVec.x + uzVec.y * uzVec.y; if (up > 0) { up = std::sqrt(up); diff --git a/README.md b/README.md index 63a92da..d3ccbde 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Architectural framework for merging nucleus-nucleus collision models. in source directory: ```bash -$ cd ../ -$ mkdir build -$ cd build -$ cmake ../COLA -$ cmake --build . --target install +cd ../ +mkdir build +cd build +cmake ../COLA +cmake --build . --target install ``` You can specify `CMAKE_INSTALL_PREFIX` to change the installation location (default for most Linux systems is `/usr/local`, which requires root) @@ -21,9 +21,10 @@ In the installation directory there is `config.sh` file, which should be sourced ## Documentation COLA comes with Doxygen documentation. To generate it, install doxygen and run from source directory: + ```bash -$ cd docs -$ doxygen +cd docs +doxygen ``` Generated documentation will be located in the ```docs/compiled/``` folder. diff --git a/cmake/SetupCodeQuality.cmake b/cmake/SetupCodeQuality.cmake new file mode 100644 index 0000000..6cc7cb8 --- /dev/null +++ b/cmake/SetupCodeQuality.cmake @@ -0,0 +1,95 @@ +if (NOT SETUP_QUALITY_SOURCE_DIR) + set(SETUP_QUALITY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +endif () + +if (NOT SETUP_QUALITY_BINARY_DIR) + set(SETUP_QUALITY_BINARY_DIR ${CMAKE_BINARY_DIR}) +endif () + +# Default exclude patterns +set(DEFAULT_EXCLUDE_PATTERNS ".*/build/.*" ".*/tinyxml2/.*") + +# Merge default and user-provided exclude patterns +set(EXCLUDE_PATTERNS ${DEFAULT_EXCLUDE_PATTERNS} ${SETUP_QUALITY_EXCLUDE_PATTERNS}) + +# Find clang-format +find_program(CLANG_FORMAT_EXE NAMES clang-format-21 clang-format) + +# Find cmake-format +find_program(CMAKE_FORMAT_EXE NAMES cmake-format) + +# Get all C++ source files +file( + GLOB_RECURSE + ALL_SOURCES + "${SETUP_QUALITY_SOURCE_DIR}/*.cc" + "${SETUP_QUALITY_SOURCE_DIR}/*.cpp" + "${SETUP_QUALITY_SOURCE_DIR}/*.cxx" + "${SETUP_QUALITY_SOURCE_DIR}/*.hh" + "${SETUP_QUALITY_SOURCE_DIR}/*.hpp" + "${SETUP_QUALITY_SOURCE_DIR}/*.hxx" + "${SETUP_QUALITY_SOURCE_DIR}/*.h" +) + +# Apply exclude patterns +foreach (PATTERN ${EXCLUDE_PATTERNS}) + list(FILTER ALL_SOURCES EXCLUDE REGEX "${PATTERN}") +endforeach () + +# Setup clang-format targets +if (CLANG_FORMAT_EXE) + add_custom_target( + clang-format-check + COMMAND ${CLANG_FORMAT_EXE} --dry-run --Werror ${ALL_SOURCES} + WORKING_DIRECTORY ${SETUP_QUALITY_SOURCE_DIR} + COMMENT "Checking code formatting with clang-format" + ) + + add_custom_target( + clang-format-fix + COMMAND ${CLANG_FORMAT_EXE} -i ${ALL_SOURCES} + WORKING_DIRECTORY ${SETUP_QUALITY_SOURCE_DIR} + COMMENT "Fixing code formatting with clang-format" + ) + + message(STATUS "clang-format found: ${CLANG_FORMAT_EXE}") + message(STATUS " - Use 'cmake --build . --target clang-format-check' to check formatting") + message(STATUS " - Use 'cmake --build . --target clang-format-fix' to fix formatting") +else () + message(WARNING "clang-format not found. clang-format targets will not be available.") +endif () + +# Get all CMake files +file(GLOB_RECURSE CMAKE_FILES "${SETUP_QUALITY_SOURCE_DIR}/*.cmake" + "${SETUP_QUALITY_SOURCE_DIR}/CMakeLists.txt" +) + +# Apply exclude patterns +foreach (PATTERN ${EXCLUDE_PATTERNS}) + list(FILTER CMAKE_FILES EXCLUDE REGEX "${PATTERN}") +endforeach () + +# Setup cmake-format targets +if (CMAKE_FORMAT_EXE) + add_custom_target( + cmake-format-check + COMMAND ${CMAKE_FORMAT_EXE} --check ${CMAKE_FILES} + WORKING_DIRECTORY ${SETUP_QUALITY_SOURCE_DIR} + COMMENT "Checking CMake file formatting with cmake-format" + ) + + add_custom_target( + cmake-format-fix + COMMAND ${CMAKE_FORMAT_EXE} -i ${CMAKE_FILES} + WORKING_DIRECTORY ${SETUP_QUALITY_SOURCE_DIR} + COMMENT "Fixing CMake file formatting with cmake-format" + ) + + message(STATUS "cmake-format found: ${CMAKE_FORMAT_EXE}") + message( + STATUS " - Use 'cmake --build . --target cmake-format-check' to check CMake formatting" + ) + message(STATUS " - Use 'cmake --build . --target cmake-format-fix' to fix CMake formatting") +else () + message(WARNING "cmake-format not found. cmake-format targets will not be available.") +endif () diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 18b87d0..1d526d3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,42 +1,36 @@ -## +# # Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -cmake_minimum_required(VERSION 3.22) -project(COLATest) - -set(CMAKE_CXX_STANDARD 20) - -set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic -Werror") - -# COLA lib -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_BINARY_DIR}/COLA) - enable_testing() find_package(GTest REQUIRED) include(GoogleTest) -set(Tests - lorentz.cpp -) +set(TEST_SRCS lorentz.cc) -add_executable(COLATest ${Tests}) +add_executable(COLATest ${TEST_SRCS}) +set_target_properties( + COLATest + PROPERTIES CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO + CXX_CLANG_TIDY "${COLA_CMAKE_CXX_CLANG_TIDY}" +) target_link_libraries(COLATest COLA) target_link_libraries(COLATest GTest::GTest GTest::Main) diff --git a/tests/lorentz.cc b/tests/lorentz.cc new file mode 100644 index 0000000..97325b4 --- /dev/null +++ b/tests/lorentz.cc @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include + +#include + +using namespace cola; + +TEST(LorentzVector, Basic) { + LorentzVector vec{.e = 5, .x = 1, .y = 2, .z = 3}; + + EXPECT_EQ(vec.t, vec.e); + + EXPECT_EQ(vec[0], vec.e); + EXPECT_EQ(vec[1], vec.x); + EXPECT_EQ(vec[2], vec.y); + EXPECT_EQ(vec[3], vec.z); + + EXPECT_EQ(vec.Mag2(), 5 * 5 - (1 * 1 + 2 * 2 + 3 * 3)); + EXPECT_EQ(vec.Mag(), std::sqrt(5 * 5 - (1 * 1 + 2 * 2 + 3 * 3))); + EXPECT_TRUE(vec.IsSpaceLike()); +} + +TEST(LorentzVector, Arithmetic) { + LorentzVector vec1{.e = 0, .x = 1, .y = 2, .z = 3}; + + LorentzVector vec2{.e = 4, .x = 3, .y = 2, .z = 1}; + + { + auto expected = LorentzVector{.e = 4, .x = 4, .y = 4, .z = 4}; + EXPECT_EQ(vec1 + vec2, expected); + } + + { + auto expected = LorentzVector{.e = -4, .x = -2, .y = 0, .z = 2}; + EXPECT_EQ(vec1 - vec2, expected); + } + + { + auto expected = LorentzVector{.e = 0, .x = 3, .y = 6, .z = 9}; + EXPECT_EQ(vec1 * 3, expected); + EXPECT_EQ(3 * vec1, expected); + } + + { + auto expected = LorentzVector{.e = 2, .x = 2, .y = 2, .z = 2}; + EXPECT_EQ((vec1 + vec2) / 2, expected); + } + + std::stringstream ss; + ss << vec1; + EXPECT_EQ(ss.str(), "(0, 1, 2, 3)"); +} diff --git a/tests/lorentz.cpp b/tests/lorentz.cpp deleted file mode 100644 index 66dbd08..0000000 --- a/tests/lorentz.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** -* Copyright (c) 2024-2025 Alexandr Svetlichnyi, Savva Savenkov, Artemii Novikov -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in all -* copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -*/ - -#include - -#include -#include - -using namespace cola; - -TEST(LorentzVector, Basic) { - LorentzVector vec{ - .e=5, - .x=1, - .y=2, - .z=3 - }; - - EXPECT_EQ(vec.t, vec.e); - - EXPECT_EQ(vec[0], vec.e); - EXPECT_EQ(vec[1], vec.x); - EXPECT_EQ(vec[2], vec.y); - EXPECT_EQ(vec[3], vec.z); - - EXPECT_EQ(vec.mag2(), 5*5 - (1*1 + 2*2 + 3*3)); - EXPECT_EQ(vec.mag(), std::sqrt(5*5 - (1*1 + 2*2 + 3*3))); - EXPECT_TRUE(vec.isSpaceLike()); -} - -TEST(LorentzVector, Arithmetic) { - LorentzVector vec1{ - .e=0, - .x=1, - .y=2, - .z=3 - }; - - LorentzVector vec2{ - .e=4, - .x=3, - .y=2, - .z=1 - }; - - { - auto expected = LorentzVector{.e=4, 4, 4, 4}; - EXPECT_EQ(vec1 + vec2, expected); - } - - { - auto expected = LorentzVector{.e=-4, -2, 0, 2}; - EXPECT_EQ(vec1 - vec2, expected); - } - - { - auto expected = LorentzVector{.e=0, 3, 6, 9}; - EXPECT_EQ(vec1 * 3, expected); - EXPECT_EQ(3 * vec1, expected); - } - - { - auto expected = LorentzVector{.e=2, 2, 2, 2}; - EXPECT_EQ((vec1 + vec2) / 2, expected); - } - - std::stringstream ss; - ss << vec1; - EXPECT_EQ(ss.str(), "(0, 1, 2, 3)"); -}