diff --git a/.clang-format b/.clang-format index 6cb0c6e..494ecb6 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2020 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + Language: Cpp AccessModifierOffset: -4 AlignAfterOpenBracket: Align @@ -121,4 +125,3 @@ StatementMacros: - QT_REQUIRE_VERSION TabWidth: 8 UseTab: Never - diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 1a0de52..5efd9ea 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2020 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + # Apply LLVM stlye for the first time b864952a14025d953acc5fad1198e5ba119e25d3 # Apply mneme style diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index cefdad9..be078f9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2022 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + name: CMake on: [push] @@ -8,6 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: build_type: ["Release", "Debug"] @@ -18,27 +23,23 @@ jobs: run: | sudo apt-get update sudo apt-get install -qq g++ openmpi-bin openmpi-common libopenmpi-dev hdf5-tools libhdf5-openmpi-dev libnetcdf-dev - + - name: Configure PUMGen working-directory: ${{ github.workspace }} run: | git submodule update --init --recursive mkdir build_${{ matrix.build_type}} && cd build_${{ matrix.build_type}} cmake .. -DCMAKE_PREFIX_PATH=${{ runner.workspace }}/opt -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - + - name: Build working-directory: ${{ github.workspace }}/build_${{ matrix.build_type }} run: cmake --build . - - clang-format: + + pre-commit-check: runs-on: ubuntu-latest - steps: + steps: - uses: actions/checkout@v5 + with: + submodules: recursive - - name: clang-format - run: | - sudo apt-get update - sudo apt-get install -qq python3 python3-pip - pip3 install clang-format==19.1.0 - git submodule update --init - ./submodules/run-clang-format/run-clang-format.py --clang-format-executable clang-format --exclude src/third_party -r src + - uses: pre-commit/action@v3.0.1 diff --git a/.gitignore b/.gitignore index a7ef3c3..02155bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2017 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + # KDevelop4 *.kdev4 *.kdev4/ diff --git a/.gitmodules b/.gitmodules index 3526bca..22291b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,10 @@ +# SPDX-FileCopyrightText: 2017 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + [submodule "submodules/utils"] path = submodules/utils url = ../../TUM-I5/utils.git [submodule "submodules/tinyxml2"] path = submodules/tinyxml2 url = ../../leethomason/tinyxml2.git -[submodule "submodules/run-clang-format"] - path = submodules/run-clang-format - url = ../../Sarcasm/run-clang-format.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d38090d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: 2025 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause +# SPDX-LicenseComments: Full text under /LICENSE and /LICENSES/ +# +# SPDX-FileContributor: Author lists in /AUTHORS and /CITATION.cff + +--- + +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-merge-conflict + name: '[GENERIC] merge conflict check' + - id: check-symlinks + name: '[GENERIC] symlink check' + - id: destroyed-symlinks + name: '[GENERIC] detect broken symlinks' + - id: detect-private-key + name: '[GENERIC] detect private keys uploaded by accident' + - id: check-case-conflict + name: '[GENERIC] detect OS file naming case conflicts' + - id: check-executables-have-shebangs + name: '[GENERIC] check for shebangs in executable files' + - id: check-illegal-windows-names + name: '[GENERIC] detect illegal Windows file names' + - id: check-json + name: '[JSON] check' + #- id: check-xml + # name: '[XML] check' + +- repo: https://github.com/DavidAnson/markdownlint-cli2 + rev: v0.18.1 + hooks: + - id: markdownlint-cli2 + name: '[MARKDOWN] lint' + +- repo: https://github.com/fsfe/reuse-tool + rev: v5.1.1 + hooks: + - id: reuse + name: '[GENERIC] REUSE compatibiltiy' + +- repo: https://github.com/sphinx-contrib/sphinx-lint + rev: 'v1.0.0' + hooks: + - id: sphinx-lint + name: '[SPHINX/RST] sphinx lint' + +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: 'v21.1.0' + hooks: + - id: clang-format + name: '[C++] clang-format' + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: end-of-file-fixer + name: '[GENERIC] newline eof' + - id: trailing-whitespace + name: '[GENERIC] remove trailing whitespace' diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fd34d8..58e4d5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2020 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + cmake_minimum_required(VERSION 3.9) cmake_policy(SET CMP0074 NEW) @@ -38,8 +42,8 @@ add_executable(pumgen ${CMAKE_CURRENT_SOURCE_DIR}/src/third_party/GMSHLexer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/third_party/GMSHParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/third_party/GMSH2Parser.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/aux/InsphereCalculator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/aux/MPIConvenience.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/helper/InsphereCalculator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/helper/MPIConvenience.cpp ) target_include_directories(pumgen PUBLIC src @@ -93,7 +97,7 @@ if (SIMMETRIX) find_package(easi 1.0.0 REQUIRED) target_link_libraries(pumgen PUBLIC easi::easi) - target_sources(pumgen PUBLIC + target_sources(pumgen PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/input/AnalysisAttributes.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/input/EasiMeshSize.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/input/MeshAttributes.cpp diff --git a/LICENSES/BSD-3-Clause.txt b/LICENSES/BSD-3-Clause.txt new file mode 100644 index 0000000..086d399 --- /dev/null +++ b/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,11 @@ +Copyright (c) . + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index ec34e81..1e2678e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ + + # PUMGen + A mesh converter to the PUML format, as used in SeisSol. ## Installing -See our wiki for detailed install instructions: https://github.com/SeisSol/PUMGen/wiki + +See our [wiki](https://github.com/SeisSol/PUMGen/wiki) for detailed install instructions. diff --git a/XmlExample/meshAttributes.xml b/XmlExample/meshAttributes.xml index 9f53a41..80c2118 100644 --- a/XmlExample/meshAttributes.xml +++ b/XmlExample/meshAttributes.xml @@ -1,8 +1,14 @@ + + 1 2 3,4 -7 +7 7 8,9 @@ -27,8 +33,8 @@ 1,2 1,4 - @@ -36,6 +42,6 @@ in the easi query using the (optional) argument bypassFindRegionAndUseGroup --> diff --git a/cmake/FindAPF.cmake b/cmake/FindAPF.cmake index 4cda4dd..65e4703 100644 --- a/cmake/FindAPF.cmake +++ b/cmake/FindAPF.cmake @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2021 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + include(FindPackageHandleStandardArgs) # simmetrixLibs = [('gmi_sim', 'gmi_sim.h'), ('apf_sim', 'apfSIM.h')] diff --git a/cmake/FindNetCDF.cmake b/cmake/FindNetCDF.cmake index 8d4d202..1e09ffa 100644 --- a/cmake/FindNetCDF.cmake +++ b/cmake/FindNetCDF.cmake @@ -11,6 +11,7 @@ Provides the following variables: # Stolen from VTK with some small modifications # https://github.com/Kitware/VTK/blob/master/CMake/FindNetCDF.cmake # (BSD 3-Clause License) +# SPDX-License-Identifier: BSD-3-Clause #[[========================================================================= diff --git a/cmake/FindSIMMETRIX.cmake b/cmake/FindSIMMETRIX.cmake index ba86b7e..24f0835 100644 --- a/cmake/FindSIMMETRIX.cmake +++ b/cmake/FindSIMMETRIX.cmake @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2021 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + include(FindPackageHandleStandardArgs) if (SCOREC) @@ -36,7 +40,7 @@ find_library(SIM_PARTITIONED_MESH_LIB SimPartitionedMesh ${SIM_LIB_HINT}) find_library(SIM_PARTITIONED_MESH_MPI_LIB SimPartitionedMesh-mpi ${SIM_LIB_HINT}) find_library(SIM_PARTITIONED_WRAPPER_LIB SimPartitionWrapper-${SIM_MPI} ${SIM_LIB_HINT}) find_library(SIM_PS_KRNL_LIB pskernel ${SIM_LIB_HINT}/psKrnl) - + get_filename_component(SIM_PS_KRNL_LIB_DIR ${SIM_PS_KRNL_LIB} DIRECTORY) list(APPEND SIMMETRIX_LIBRARIES diff --git a/header.py b/header.py new file mode 100755 index 0000000..4bc5715 --- /dev/null +++ b/header.py @@ -0,0 +1,324 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2025 SeisSol Group +# +# SPDX-License-Identifier: BSD-3-Clause + +import argparse +import datetime +import os +import pathlib +import re +import stat +import subprocess +import sys +from typing import List + + +class Settings: + MAIN_DEVELOPER = "SeisSol Group" + PROJECT_NAME = "PUMgen" + PROJECT_WEBPAGE = "www.seissol.org" + LICENSE = "BSD-3-Clause" + + CPP_HEADER_ENDINGS = [".h", ".hpp", ".cuh", ".hh"] + CPP_SOURCE_ENDINGS = [".cpp", ".cu", ".cc"] + PY_SOURCE_ENDINGS = [".py"] + SHELL_SOURCE_ENDINGS = [".sh"] + CMAKE_SOURCE_ENDINGS = [".cmake"] + CMAKE_FILE_NAMES = ["CMakeLists.txt"] + + +class Span: + def __init__(self, start, end=None): + self.start = start + if end is None: + self.end = start + else: + self.end = end + + def unite(self, other): + return Span(min(self.start, other.start), max(self.end, other.end)) + + def extend(self, year): + return Span(min(self.start, year), max(self.end, year)) + + def __str__(self): + if self.start == self.end: + return f"{self.start}" + else: + return f"{self.start}-{self.end}" + + +def rootpath(): + path = subprocess.getoutput("git rev-parse --show-toplevel") + return pathlib.Path(path) + + +def textCopyrights(copyrights, authorspans): + crregex = re.compile( + r"(?:(?:[Cc][Oo][Pp][Yy][Rr][Ii][Gg][Hh][Tt]\s+)|(?:SPDX\-FileCopyrightText\:\s*)|[\(\[]\s*[Cc]\s*[\)\]])+\s*(?:(\d+)(?:\s*-\s*(\d+))?)?[\s,;]*([\w\d\s\-_]*)" + ) + for cr in copyrights: + result = crregex.search(cr) + holder = result.group(3).strip() + year = result.group(1) + year2 = result.group(2) + if year2 is None: + timespan = Span(int(year)) + else: + timespan = Span(int(year), int(year2)) + + if holder not in authorspans: + authorspans[holder] = timespan + else: + authorspans[holder] = authorspans[holder].unite(timespan) + + +def textAuthors(authors): + aregex = re.compile( + r"(?:(?:[Aa][Uu][Tt][Hh][Oo][Rr]\s+)|(?:SPDX\-FileContributor\:\s*))(.*)" + ) + alines = [] + for author in authors: + result = aregex.search(author) + holder = result.group(1).strip() + if holder != "Author lists in /AUTHORS and /CITATION.cff": + alines += [holder] + return alines + + +def licenseHeader(authorspans, authors, commentstyle="//"): + # the main developer always comes first + if Settings.MAIN_DEVELOPER is not None: + authorlist = [Settings.MAIN_DEVELOPER] + [ + author for author in authorspans if author != Settings.MAIN_DEVELOPER + ] + else: + authorlist = [author for author in authorspans] + + # no titleline for now + # titleline = f'{commentstyle} This file is part of {Settings.PROJECT_NAME} ( {Settings.PROJECT_WEBPAGE} ).' + + crlines = [] + for author in authorlist: + # TODO: unite year spans + timespan = authorspans[author] + crlines += [f"{commentstyle} SPDX-FileCopyrightText: {timespan} {author}"] + alines = [] + for author in authors: + alines += [f"{commentstyle} SPDX-FileContributor: {author}"] + + # NOTE: the escaped SPDX is needed to make the REUSE linter happy + return ( + crlines + + [ + f"{commentstyle}", + f"{commentstyle} {'SPDX'}-License-Identifier: {Settings.LICENSE}", + ] + + alines + ) + + +def makeLicense(path, copyrights, authors, commentstyle="//"): + authorspans = {} + textCopyrights(copyrights, authorspans) + authors = textAuthors(authors) + + # let the main developer always hold the copyright for the current year + if Settings.MAIN_DEVELOPER is not None: + currentYear = datetime.date.today().year + if Settings.MAIN_DEVELOPER not in authorspans: + authorspans[Settings.MAIN_DEVELOPER] = Span(currentYear) + else: + authorspans[Settings.MAIN_DEVELOPER] = authorspans[ + Settings.MAIN_DEVELOPER + ].extend(currentYear) + + # ...or just set it to the first year + if Settings.MAIN_DEVELOPER is not None: + authorspans[Settings.MAIN_DEVELOPER] = Span( + authorspans[Settings.MAIN_DEVELOPER].start + ) + + return licenseHeader(authorspans, authors, commentstyle) + + +def licenseCleaner(path, lines, commentstyle="//"): + inComment = False + copyrights = [] + authors = [] + + rest = [] + + for i, line in enumerate(lines): + if (line.strip().startswith("#") and commentstyle != "#") or ( + not inComment + and not line.strip().startswith(commentstyle) + and not line.strip().startswith("/*") + ): + rest = lines[i:] + break + + commentStart = line.find("/*") + if commentStart != -1: + inComment = True + + commentEnd = line.find("*/") + if inComment or line.strip().startswith(commentstyle): + copyrightpos = line.lower().find("copyright") + if ( + copyrightpos != -1 + and (commentEnd == -1 or copyrightpos < commentEnd) + and (commentStart == -1 or copyrightpos > commentStart) + ): + copyrights += [line] + authorpos = line.lower().find("author") + if authorpos == -1: + authorpos = line.lower().find("contributor") + if ( + authorpos != -1 + and (commentEnd == -1 or authorpos < commentEnd) + and (commentStart == -1 or authorpos > commentStart) + ): + authors += [line] + + if commentEnd != -1: + inComment = False + + return makeLicense(path, copyrights, authors, commentstyle) + rest + + +def cppCanonicalHeaders(path: pathlib.Path, lines: List[str]): + # remove pragma once + for i, line in enumerate(lines): + if line.strip() == "#pragma once": + preheader = lines[:i] + innerlines = lines[i + 1 :] + break + + # TODO: check if there's an include guard at all + # remove default include guard + ifndefline = None + innerlinesPre = None + for i, line in enumerate(lines): + if line.strip().startswith("#ifndef"): + ifndefline = i + elif line.strip().startswith("#define") and ifndefline is not None: + preheader = lines[:ifndefline] + innerlinesPre = lines[i + 1 :] + break + elif not (line.strip().startswith("//") or line.strip() == ""): + preheader = lines[:i] + innerlinesPre = lines[i + 1 :] + break + innerlines = None + for i, line in reversed(list(enumerate(innerlinesPre))): + if line.strip().startswith("#endif"): + innerlines = innerlinesPre[:i] + break + elif not (line.strip().startswith("//") or line.strip() == ""): + innerlines = innerlinesPre[: (i + 1)] + break + + # re-insert new include guard + strpath = str(path.relative_to(rootpath())) + sanitizedpath = strpath.replace("/", "_").replace(".", "_").upper() + projectprefix = Settings.PROJECT_NAME.upper() + guard = f"{projectprefix}_{sanitizedpath}_" + + return ( + preheader + + [f"#ifndef {guard}", f"#define {guard}"] + + innerlines + + [f"#endif // {guard}"] + ) + + +def addShebang(path, lines, program): + # only add shebang for files that are executable + + stats = path.stat().st_mode + if ( + (stats & stat.S_IXUSR) != 0 + or (stats & stat.S_IXGRP) != 0 + or (stats & stat.S_IXOTH) != 0 + ): + shebang = f"#!/usr/bin/env {program}" + if lines[0].strip().startswith("#!"): + return [shebang, ""] + lines[1:] + else: + return [shebang, ""] + lines + else: + return lines + + +def sanitizeLineEndings(lines): + return [line if line.endswith("\n") else line + "\n" for line in lines] + + +def processFile(path, dryrun): + pathobj = pathlib.Path(path).resolve() + with open(path) as file: + lines = file.readlines() + + if pathobj.suffix in Settings.PY_SOURCE_ENDINGS: + lines = licenseCleaner(pathobj, lines, "#") + lines = addShebang(pathobj, lines, "python3") + if pathobj.suffix in Settings.SHELL_SOURCE_ENDINGS: + lines = licenseCleaner(pathobj, lines, "#") + lines = addShebang(pathobj, lines, "sh") + if ( + pathobj.suffix in Settings.CMAKE_SOURCE_ENDINGS + or pathobj.name in Settings.CMAKE_FILE_NAMES + ): + lines = licenseCleaner(pathobj, lines, "#") + if pathobj.suffix in Settings.CPP_HEADER_ENDINGS + Settings.CPP_SOURCE_ENDINGS: + lines = licenseCleaner(pathobj, lines, "//") + if pathobj.suffix in Settings.CPP_HEADER_ENDINGS and not pathobj.name.endswith( + ".t.h" + ): + lines = cppCanonicalHeaders(pathobj, lines) + lines = sanitizeLineEndings(lines) + + with open(path) as file: + linescomp = file.readlines() + if not dryrun: + with open(path, "w") as file: + file.writelines(lines) + return lines != linescomp + + +def main(): + print("SeisSol File Sanitizer") + + argParser = argparse.ArgumentParser() + argParser.add_argument("--fix", action="store_true") + argParser.add_argument("path", nargs="*") + argParser.set_defaults(fix=False) + args = argParser.parse_args() + + found = False + + for path in args.path: + for root, dirs, files in pathlib.Path(path).walk(top_down=False): + for prefile in files: + file = root / prefile + if ( + not os.path.islink(file) + and file.suffix + in Settings.CPP_HEADER_ENDINGS + Settings.CPP_SOURCE_ENDINGS + ): + result = processFile(file, not args.fix) + if result: + print(f"Reformatted: {file}") + found |= result + + if found: + print("Unsanitized files found.") + sys.exit(1) + else: + print("All files conformant.") + + +if __name__ == "__main__": + main() diff --git a/src/aux/Distributor.h b/src/helper/Distributor.h similarity index 67% rename from src/aux/Distributor.h rename to src/helper/Distributor.h index 6666a4e..02897f2 100644 --- a/src/aux/Distributor.h +++ b/src/helper/Distributor.h @@ -1,5 +1,8 @@ -#ifndef PUMGEN_AUX_DISTRIBUTOR_H_ -#define PUMGEN_AUX_DISTRIBUTOR_H_ +// SPDX-FileCopyrightText: 2025 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_HELPER_DISTRIBUTOR_H_ +#define PUMGEN_SRC_HELPER_DISTRIBUTOR_H_ #include #include @@ -17,4 +20,4 @@ constexpr std::size_t getChunksum(std::size_t total, int until, int size) { return base + addon; } -#endif // PUMGEN_AUX_DISTRIBUTOR_H_ +#endif // PUMGEN_SRC_HELPER_DISTRIBUTOR_H_ diff --git a/src/aux/InsphereCalculator.cpp b/src/helper/InsphereCalculator.cpp similarity index 98% rename from src/aux/InsphereCalculator.cpp rename to src/helper/InsphereCalculator.cpp index 9f0735b..309e35e 100644 --- a/src/aux/InsphereCalculator.cpp +++ b/src/helper/InsphereCalculator.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2025 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include "InsphereCalculator.h" #include "third_party/MPITraits.h" #include diff --git a/src/aux/InsphereCalculator.h b/src/helper/InsphereCalculator.h similarity index 56% rename from src/aux/InsphereCalculator.h rename to src/helper/InsphereCalculator.h index acd4b04..9a8e548 100644 --- a/src/aux/InsphereCalculator.h +++ b/src/helper/InsphereCalculator.h @@ -1,5 +1,8 @@ -#ifndef PUMGEN_AUX_INSPHERE_CALCULATOR_H_ -#define PUMGEN_AUX_INSPHERE_CALCULATOR_H_ +// SPDX-FileCopyrightText: 2025 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_HELPER_INSPHERECALCULATOR_H_ +#define PUMGEN_SRC_HELPER_INSPHERECALCULATOR_H_ #include #include @@ -10,4 +13,4 @@ std::vector calculateInsphere(const std::vector& connectivity, const std::vector& geometry, MPI_Comm comm); -#endif // PUMGEN_AUX_INSPHERE_CALCULATOR_H_ +#endif // PUMGEN_SRC_HELPER_INSPHERECALCULATOR_H_ diff --git a/src/aux/MPIConvenience.cpp b/src/helper/MPIConvenience.cpp similarity index 98% rename from src/aux/MPIConvenience.cpp rename to src/helper/MPIConvenience.cpp index f1d32a7..0907ac3 100644 --- a/src/aux/MPIConvenience.cpp +++ b/src/helper/MPIConvenience.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2025 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include "MPIConvenience.h" #include #include diff --git a/src/aux/MPIConvenience.h b/src/helper/MPIConvenience.h similarity index 82% rename from src/aux/MPIConvenience.h rename to src/helper/MPIConvenience.h index b757e24..d04b000 100644 --- a/src/aux/MPIConvenience.h +++ b/src/helper/MPIConvenience.h @@ -1,5 +1,8 @@ -#ifndef PUMGEN_AUX_MPI_CONVENIENCE_H_ -#define PUMGEN_AUX_MPI_CONVENIENCE_H_ +// SPDX-FileCopyrightText: 2025 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_HELPER_MPICONVENIENCE_H_ +#define PUMGEN_SRC_HELPER_MPICONVENIENCE_H_ #include #include @@ -20,4 +23,4 @@ void largeScatterv(const void* sendbuf, const std::size_t* sendsize, const std:: MPI_Datatype sendtype, void* recvbuf, std::size_t recvsize, MPI_Datatype recvtype, int root, MPI_Comm comm); -#endif // PUMGEN_AUX_MPI_CONVENIENCE_H_ +#endif // PUMGEN_SRC_HELPER_MPICONVENIENCE_H_ diff --git a/src/input/AnalysisAttributes.cpp b/src/input/AnalysisAttributes.cpp index b889957..352804e 100644 --- a/src/input/AnalysisAttributes.cpp +++ b/src/input/AnalysisAttributes.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include "AnalysisAttributes.h" AnalysisAttributes::AnalysisAttributes(const char* xmlFilename, int numFaces) { diff --git a/src/input/AnalysisAttributes.h b/src/input/AnalysisAttributes.h index ed91eee..5981e88 100644 --- a/src/input/AnalysisAttributes.h +++ b/src/input/AnalysisAttributes.h @@ -1,5 +1,8 @@ -#ifndef ANALYSISATTRIBUTES_H -#define ANALYSISATTRIBUTES_H +// SPDX-FileCopyrightText: 2020 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_INPUT_ANALYSISATTRIBUTES_H_ +#define PUMGEN_SRC_INPUT_ANALYSISATTRIBUTES_H_ #include "split.h" #include "tinyxml2/tinyxml2.h" @@ -28,4 +31,4 @@ class AnalysisAttributes { void set_BoundaryConditions(); }; -#endif +#endif // PUMGEN_SRC_INPUT_ANALYSISATTRIBUTES_H_ diff --git a/src/input/ApfNative.h b/src/input/ApfNative.h index a9794bf..107a906 100644 --- a/src/input/ApfNative.h +++ b/src/input/ApfNative.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef APF_NATIVE_H -#define APF_NATIVE_H +#ifndef PUMGEN_SRC_INPUT_APFNATIVE_H_ +#define PUMGEN_SRC_INPUT_APFNATIVE_H_ #include #include @@ -35,4 +29,4 @@ class ApfNative : public ApfMeshInput { } }; -#endif // APF_NATIVE_H +#endif // PUMGEN_SRC_INPUT_APFNATIVE_H_ diff --git a/src/input/EasiMeshSize.cpp b/src/input/EasiMeshSize.cpp index 8417c93..6c82a96 100644 --- a/src/input/EasiMeshSize.cpp +++ b/src/input/EasiMeshSize.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2021 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include "EasiMeshSize.h" #include #include diff --git a/src/input/EasiMeshSize.h b/src/input/EasiMeshSize.h index e4aa96a..a9fa62e 100644 --- a/src/input/EasiMeshSize.h +++ b/src/input/EasiMeshSize.h @@ -1,5 +1,8 @@ -#ifndef PUMGEN_EASIMESHSIZE_H -#define PUMGEN_EASIMESHSIZE_H +// SPDX-FileCopyrightText: 2021 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_INPUT_EASIMESHSIZE_H_ +#define PUMGEN_SRC_INPUT_EASIMESHSIZE_H_ #include "MeshAttributes.h" #include @@ -37,4 +40,4 @@ class EasiMeshSize { double getMeshSize(const std::array& point); }; -#endif // PUMGEN_EASIMESHSIZE_H +#endif // PUMGEN_SRC_INPUT_EASIMESHSIZE_H_ diff --git a/src/input/MeshAttributes.cpp b/src/input/MeshAttributes.cpp index de77884..4559e6f 100644 --- a/src/input/MeshAttributes.cpp +++ b/src/input/MeshAttributes.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include "MeshAttributes.h" VelocityAwareRefinementSettings::VelocityAwareRefinementSettings(double elementsPerWaveLength, @@ -82,10 +85,10 @@ void MeshAttributes::set_SurfaceMeshingAttributes() { } else { logError() << "Unrecognised surfaceSmoothingType (Laplacian or Gradient)" << sSmoothingType; } - logInfo(PMU_rank()) << "surface smoothing option: surfaceSmoothingLevel " - "surfaceSmoothingType surfaceFaceRotationLimit Snap" - << surfaceSmoothingLevel << " " << static_cast(surfaceSmoothingType) - << " " << surfaceFaceRotationLimit << " " << surfaceSnap; + logInfo() << "surface smoothing option: surfaceSmoothingLevel " + "surfaceSmoothingType surfaceFaceRotationLimit Snap" + << surfaceSmoothingLevel << " " << static_cast(surfaceSmoothingType) << " " + << surfaceFaceRotationLimit << " " << surfaceSnap; } } @@ -101,8 +104,8 @@ void MeshAttributes::set_VolumeMeshingAttributes() { } else { logError() << "Unrecognised volumeSmoothingType (Laplacian or Gradient)" << sSmoothingType; } - logInfo(PMU_rank()) << "volume smoothing option: volumeSmoothingLevel volumeSmoothingType" - << volumeSmoothingLevel << " " << static_cast(volumeSmoothingType); + logInfo() << "volume smoothing option: volumeSmoothingLevel volumeSmoothingType" + << volumeSmoothingLevel << " " << static_cast(volumeSmoothingType); } } @@ -175,8 +178,8 @@ void MeshAttributes::set_velocity_aware_meshing() { velocityAwareRefinementSettings = VelocityAwareRefinementSettings(elementsPerWaveLength, easiFileName); constexpr auto cuboidName = "VelocityRefinementCuboid"; - logInfo(PMU_rank()) << "Activating velocity aware meshing, using" << elementsPerWaveLength - << "elements per wavelength and easi file" << easiFileName; + logInfo() << "Activating velocity aware meshing, using" << elementsPerWaveLength + << "elements per wavelength and easi file" << easiFileName; for (auto child = velocityAwareMeshingElement->FirstChildElement(cuboidName); child; child = child->NextSiblingElement(cuboidName)) { @@ -207,23 +210,21 @@ void MeshAttributes::set_velocity_aware_meshing() { velocityAwareRefinementSettings.addRefinementRegion(cuboid, targetedFrequency, bypassFindRegionAndUseGroup); - logInfo(PMU_rank()) << "Adding velocity aware refinement region targeting" - << targetedFrequency << "Hz, centered at x =" << cuboid.center[0] - << "y=" << cuboid.center[1] << "z=" << cuboid.center[2] - << "with half sizes" - << "x =" << cuboid.halfSize[0] << "y =" << cuboid.halfSize[1] - << "z =" << cuboid.halfSize[2]; + logInfo() << "Adding velocity aware refinement region targeting" << targetedFrequency + << "Hz, centered at x =" << cuboid.center[0] << "y=" << cuboid.center[1] + << "z=" << cuboid.center[2] << "with half sizes" + << "x =" << cuboid.halfSize[0] << "y =" << cuboid.halfSize[1] + << "z =" << cuboid.halfSize[2]; if (std::abs(cuboid.rotationZ) > 0.0) { - logInfo(PMU_rank()) << "rotated around z axis by " << cuboid.rotationZ - << "degree(s) counterclockwise from x axis."; + logInfo() << "rotated around z axis by " << cuboid.rotationZ + << "degree(s) counterclockwise from x axis."; } if (bypassFindRegionAndUseGroup) { - logInfo(PMU_rank()) << "bypass findRegion and use group =" << bypassFindRegionAndUseGroup; + logInfo() << "bypass findRegion and use group =" << bypassFindRegionAndUseGroup; } } if (!velocityAwareRefinementSettings.isVelocityAwareRefinementOn()) { - logWarning(PMU_rank()) - << "Activated velocity aware meshing but did not specify any refinement region!"; + logWarning() << "Activated velocity aware meshing but did not specify any refinement region!"; } ++numChilds; } diff --git a/src/input/MeshAttributes.h b/src/input/MeshAttributes.h index 86fe757..cac7e40 100644 --- a/src/input/MeshAttributes.h +++ b/src/input/MeshAttributes.h @@ -1,5 +1,8 @@ -#ifndef MESHATTRIBUTES_H -#define MESHATTRIBUTES_H +// SPDX-FileCopyrightText: 2020 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_INPUT_MESHATTRIBUTES_H_ +#define PUMGEN_SRC_INPUT_MESHATTRIBUTES_H_ #include #include @@ -119,4 +122,4 @@ class MeshAttributes { std::list fill_list_using_parsed_string(std::string line); }; -#endif +#endif // PUMGEN_SRC_INPUT_MESHATTRIBUTES_H_ diff --git a/src/input/MeshData.h b/src/input/MeshData.h index 286c764..5622703 100644 --- a/src/input/MeshData.h +++ b/src/input/MeshData.h @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause -#ifndef MESH_DATA_H -#define MESH_DATA_H +#ifndef PUMGEN_SRC_INPUT_MESHDATA_H_ +#define PUMGEN_SRC_INPUT_MESHDATA_H_ #include #include @@ -22,10 +25,12 @@ class MeshData { virtual std::size_t cellCount() const = 0; virtual std::size_t vertexCount() const = 0; - virtual const std::vector& connectivity() = 0; - virtual const std::vector& geometry() = 0; - virtual const std::vector& group() = 0; - virtual const std::vector& boundary() = 0; + virtual const std::vector& connectivity() const = 0; + virtual const std::vector& geometry() const = 0; + virtual const std::vector& group() const = 0; + virtual const std::vector& boundary() const = 0; + virtual const std::vector& identify() const = 0; + virtual bool hasIdentify() const = 0; // TODO: generalize? virtual std::size_t vertexSize() const { return 3; } @@ -34,15 +39,18 @@ class MeshData { class FullStorageMeshData : public MeshData { public: - virtual ~FullStorageMeshData() = default; + ~FullStorageMeshData() override = default; - virtual std::size_t cellCount() const { return cellCountValue; } - virtual std::size_t vertexCount() const { return vertexCountValue; } + std::size_t cellCount() const override { return cellCountValue; } + std::size_t vertexCount() const override { return vertexCountValue; } - virtual const std::vector& connectivity() { return connectivityData; } - virtual const std::vector& geometry() { return geometryData; } - virtual const std::vector& group() { return groupData; } - virtual const std::vector& boundary() { return boundaryData; } + const std::vector& connectivity() const override { return connectivityData; } + const std::vector& geometry() const override { return geometryData; } + const std::vector& group() const override { return groupData; } + const std::vector& boundary() const override { return boundaryData; } + const std::vector& identify() const override { return identifyData; } + + bool hasIdentify() const override { return !identifyData.empty(); } protected: FullStorageMeshData(int boundarySize) : bndShift(boundarySize) {} @@ -54,15 +62,16 @@ class FullStorageMeshData : public MeshData { std::vector geometryData; std::vector groupData; std::vector boundaryData; + std::vector identifyData; int bndShift = 8; - void setBoundary(std::size_t cell, int face, int value) { + void setBoundary(std::size_t cell, int face, int64_t value) { if (bndShift < 0) { boundaryData[cell * (vertexSize() + 1) + face] = value; } else { - constexpr auto i32limit = std::numeric_limits::max(); - constexpr auto i64limit = std::numeric_limits::max(); + constexpr int64_t i32limit = std::numeric_limits::max(); + constexpr int64_t i64limit = std::numeric_limits::max(); if (value < 0 || (value > i32limit && bndShift == 8) || (value > i64limit && bndShift == 16)) { logError() << "Cannot handle boundary condition" << value; @@ -72,7 +81,7 @@ class FullStorageMeshData : public MeshData { } } - void setup(std::size_t cellCount, std::size_t vertexCount) { + void setup(std::size_t cellCount, std::size_t vertexCount, bool identify = false) { cellCountValue = cellCount; vertexCountValue = vertexCount; @@ -86,7 +95,11 @@ class FullStorageMeshData : public MeshData { } // TODO: reconsider the times 4 or 3 + + if (identify) { + identifyData.resize(vertexCount); + } } }; -#endif // MESH_INPUT_H +#endif // PUMGEN_SRC_INPUT_MESHDATA_H_ diff --git a/src/input/MeshInput.h b/src/input/MeshInput.h index fae39a2..957325f 100644 --- a/src/input/MeshInput.h +++ b/src/input/MeshInput.h @@ -1,16 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ - -#include "MeshData.h" +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger + +#ifndef PUMGEN_SRC_INPUT_MESHINPUT_H_ +#define PUMGEN_SRC_INPUT_MESHINPUT_H_ #include "utils/logger.h" #include #include @@ -116,4 +111,4 @@ class ApfMeshInput : public FullStorageMeshData { } }; -#endif // MESH_INPUT_H +#endif // PUMGEN_SRC_INPUT_MESHINPUT_H_ diff --git a/src/input/NetCDFMesh.h b/src/input/NetCDFMesh.h index fac05f7..e298a22 100644 --- a/src/input/NetCDFMesh.h +++ b/src/input/NetCDFMesh.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef NETCDF_MESH_H -#define NETCDF_MESH_H +#ifndef PUMGEN_SRC_INPUT_NETCDFMESH_H_ +#define PUMGEN_SRC_INPUT_NETCDFMESH_H_ #include @@ -88,7 +82,7 @@ class NetCDFMesh : public FullStorageMeshData { bool useGroups = true; if (nc_inq_varid(ncFile, "element_group", &ncVarElemGroup) != NC_NOERR) { useGroups = false; - logWarning(rank) << "No group found, using group 0 for all elements"; + logWarning() << "No group found, using group 0 for all elements"; } else { collectiveAccess(ncFile, ncVarElemGroup); } @@ -102,7 +96,7 @@ class NetCDFMesh : public FullStorageMeshData { collectiveAccess(ncFile, ncVarVrtxCoords); // Read elements - logInfo(rank) << "Reading netCDF file"; + logInfo() << "Reading netCDF file"; for (std::size_t i = 0; i < nMaxLocalPart; i++) { std::size_t j = i % nLocalPart; @@ -158,7 +152,7 @@ class NetCDFMesh : public FullStorageMeshData { vertexOffset += partitions[i].nVertices(); } - logInfo(rank) << "Running vertex filter"; + logInfo() << "Running vertex filter"; ParallelVertexFilter filter(commIO); filter.filter(nVertices, verticesLocal); @@ -196,7 +190,7 @@ class NetCDFMesh : public FullStorageMeshData { vertexOffset += partitions[i].nVertices(); } - logInfo(rank) << "Converting local to global vertex identifier"; + logInfo() << "Converting local to global vertex identifier"; #ifdef _OPENMP #pragma omp parallel for #endif @@ -220,4 +214,4 @@ class NetCDFMesh : public FullStorageMeshData { } }; -#endif // NETCDF_MESH_H +#endif // PUMGEN_SRC_INPUT_NETCDFMESH_H_ diff --git a/src/input/NetCDFPartition.cpp b/src/input/NetCDFPartition.cpp index d1c257e..7c314a6 100644 --- a/src/input/NetCDFPartition.cpp +++ b/src/input/NetCDFPartition.cpp @@ -1,14 +1,8 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger #include "NetCDFPartition.h" diff --git a/src/input/NetCDFPartition.h b/src/input/NetCDFPartition.h index 71953d1..4478ab5 100644 --- a/src/input/NetCDFPartition.h +++ b/src/input/NetCDFPartition.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef PARTITION_H -#define PARTITION_H +#ifndef PUMGEN_SRC_INPUT_NETCDFPARTITION_H_ +#define PUMGEN_SRC_INPUT_NETCDFPARTITION_H_ #include @@ -88,4 +82,4 @@ class Partition { const static int INTERNAL2EX_ORDER[4]; }; -#endif // PARTITION_H +#endif // PUMGEN_SRC_INPUT_NETCDFPARTITION_H_ diff --git a/src/input/ParallelVertexFilter.cpp b/src/input/ParallelVertexFilter.cpp index 65b61e4..5726efd 100644 --- a/src/input/ParallelVertexFilter.cpp +++ b/src/input/ParallelVertexFilter.cpp @@ -1,14 +1,8 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger #include diff --git a/src/input/ParallelVertexFilter.h b/src/input/ParallelVertexFilter.h index 144058e..5810fd3 100644 --- a/src/input/ParallelVertexFilter.h +++ b/src/input/ParallelVertexFilter.h @@ -1,20 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - * - * @remark This class is taken from XdmfWriter - * (https://github.com/TUM-I5/XdmfWriter) - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef PARALLEL_VERTEX_FILTER_H -#define PARALLEL_VERTEX_FILTER_H +#ifndef PUMGEN_SRC_INPUT_PARALLELVERTEXFILTER_H_ +#define PUMGEN_SRC_INPUT_PARALLELVERTEXFILTER_H_ #include @@ -30,7 +21,7 @@ #include "third_party/MPITraits.h" -#include "aux/MPIConvenience.h" +#include "helper/MPIConvenience.h" /** * Filters duplicate vertices in parallel @@ -363,4 +354,4 @@ class ParallelVertexFilter { constexpr static int BUCKETS_PER_RANK = 8; }; -#endif // PARALLEL_VERTEX_FILTER_H +#endif // PUMGEN_SRC_INPUT_PARALLELVERTEXFILTER_H_ diff --git a/src/input/SerialMeshFile.h b/src/input/SerialMeshFile.h index bab36a9..d3c38a6 100644 --- a/src/input/SerialMeshFile.h +++ b/src/input/SerialMeshFile.h @@ -1,23 +1,17 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef SERIAL_MESH_FILE_H -#define SERIAL_MESH_FILE_H +#ifndef PUMGEN_SRC_INPUT_SERIALMESHFILE_H_ +#define PUMGEN_SRC_INPUT_SERIALMESHFILE_H_ #ifdef PARALLEL #include #endif // PARALLEL -#include "aux/Distributor.h" +#include "helper/Distributor.h" #include #include @@ -80,18 +74,23 @@ template class SerialMeshFile : public FullStorageMeshData { const std::size_t nLocalVertices = getChunksize(nVertices, m_rank, m_nProcs); const std::size_t nLocalElements = getChunksize(nElements, m_rank, m_nProcs); - setup(nLocalElements, nLocalVertices); + bool identify = false; + if constexpr (T::SupportsIdentify) { + identify = m_meshReader.hasIdentify(); + } + + setup(nLocalElements, nLocalVertices, identify); - logInfo(m_rank) << "Read vertex coordinates"; + logInfo() << "Read vertex coordinates"; m_meshReader.readVertices(geometryData.data()); - logInfo(m_rank) << "Read cell vertices"; + logInfo() << "Read cell vertices"; m_meshReader.readElements(connectivityData.data()); - logInfo(m_rank) << "Read cell groups"; + logInfo() << "Read cell groups"; m_meshReader.readGroups(groupData.data()); - logInfo(m_rank) << "Read boundary conditions"; + logInfo() << "Read boundary conditions"; std::vector preBoundaryData(nLocalElements * (vertexSize() + 1)); m_meshReader.readBoundaries(preBoundaryData.data()); for (std::size_t i = 0; i < nLocalElements; ++i) { @@ -99,7 +98,13 @@ template class SerialMeshFile : public FullStorageMeshData { setBoundary(i, j, preBoundaryData[(vertexSize() + 1) * i + j]); } } + + if constexpr (T::SupportsIdentify) { + if (identify) { + m_meshReader.readIdentify(identifyData.data()); + } + } } }; -#endif // SERIAL_MESH_FILE_H +#endif // PUMGEN_SRC_INPUT_SERIALMESHFILE_H_ diff --git a/src/input/SimModSuite.h b/src/input/SimModSuite.h index aa5501f..7d82088 100644 --- a/src/input/SimModSuite.h +++ b/src/input/SimModSuite.h @@ -1,18 +1,12 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017,2023 Technical University of Munich - * @author Sebastian Rettenberger - * @author David Schneller - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger +// SPDX-FileContributor: David Schneller -#ifndef SIM_MOD_SUITE_H -#define SIM_MOD_SUITE_H +#ifndef PUMGEN_SRC_INPUT_SIMMODSUITE_H_ +#define PUMGEN_SRC_INPUT_SIMMODSUITE_H_ #include @@ -101,7 +95,7 @@ class SimModSuite : public FullStorageMeshData { Sim_setMessageHandler(messageHandler); // Load CAD - logInfo(PMU_rank()) << "Loading model"; + logInfo() << "Loading model"; std::string smodFile = modFile; if (cadFile != nullptr) { @@ -120,7 +114,7 @@ class SimModSuite : public FullStorageMeshData { } // Extract cases - logInfo(PMU_rank()) << "Extracting cases"; + logInfo() << "Extracting cases"; pACase meshCase, analysisCase; MeshAttributes MeshAtt; @@ -141,7 +135,7 @@ class SimModSuite : public FullStorageMeshData { Progress_setCallback(prog, progressHandler); // create the mesh - logInfo(PMU_rank()) << "Starting the surface mesher"; + logInfo() << "Starting the surface mesher"; pSurfaceMesher surfaceMesher = SurfaceMesher_new(meshCase, m_simMesh); if (xmlFile != nullptr) { SurfaceMesher_setSmoothing(surfaceMesher, MeshAtt.surfaceSmoothingLevel); @@ -154,7 +148,7 @@ class SimModSuite : public FullStorageMeshData { PM_setTotalNumParts(m_simMesh, PMU_size()); - logInfo(PMU_rank()) << "Starting the volume mesher"; + logInfo() << "Starting the volume mesher"; pVolumeMesher volumeMesher = VolumeMesher_new(meshCase, m_simMesh); if (xmlFile != nullptr) { #ifdef BEFORE_SIM_2024 @@ -180,7 +174,7 @@ class SimModSuite : public FullStorageMeshData { AttCase_unassociate(meshCase); } - logInfo(PMU_rank()) << "Iterating over mesh to get data..."; + logInfo() << "Iterating over mesh to get data..."; int parts = PM_numParts(m_simMesh); std::size_t vertexCount = 0; std::size_t vertexIDCount = 0; @@ -190,7 +184,7 @@ class SimModSuite : public FullStorageMeshData { std::vector vertexIDStart(parts + 1); std::vector cellStart(parts + 1); for (int i = 0; i < parts; i++) { - logInfo(PMU_rank()) << "Counting part" << i << "/" << parts; + logInfo() << "Counting part" << i << "/" << parts; vertexStart[i] = vertexCount; vertexIDStart[i] = vertexIDCount; cellStart[i] = cellCount; @@ -229,9 +223,9 @@ class SimModSuite : public FullStorageMeshData { cellStart.back() = cellCount; vertexIDStart.back() = vertexIDCount; - logInfo(PMU_rank()) << "Local cells:" << cellCount; - logInfo(PMU_rank()) << "Local vertices:" << vertexCount; - logInfo(PMU_rank()) << "Local vertices (with duplicates):" << vertexIDCount; + logInfo() << "Local cells:" << cellCount; + logInfo() << "Local vertices:" << vertexCount; + logInfo() << "Local vertices (with duplicates):" << vertexIDCount; AttCase_associate(analysisCase, nullptr); @@ -240,8 +234,8 @@ class SimModSuite : public FullStorageMeshData { { std::vector vertexData(vertexIDCount * 3); for (int i = 0; i < parts; i++) { - logInfo(PMU_rank()) << "Processing part" << i << "/" << parts; - logInfo(PMU_rank()) << "Vertices:" << vertexStart[i] << "to" << vertexStart[i + 1]; + logInfo() << "Processing part" << i << "/" << parts; + logInfo() << "Vertices:" << vertexStart[i] << "to" << vertexStart[i + 1]; { std::size_t indexID = vertexIDStart[i]; VIter reg_it = M_vertexIter(PM_mesh(m_simMesh, i)); @@ -261,14 +255,14 @@ class SimModSuite : public FullStorageMeshData { } vertexCount = vertexFilter.numLocalVertices(); - logInfo(PMU_rank()) << "Local vertices (after filtering):" << vertexCount; + logInfo() << "Local vertices (after filtering):" << vertexCount; setup(cellCount, vertexCount); std::copy(vertexFilter.localVertices().begin(), vertexFilter.localVertices().end(), geometryData.begin()); for (int i = 0; i < parts; i++) { - logInfo(PMU_rank()) << "Processing part" << i << "/" << parts; - logInfo(PMU_rank()) << "Connectivity:" << cellStart[i] << "to" << cellStart[i + 1]; + logInfo() << "Processing part" << i << "/" << parts; + logInfo() << "Connectivity:" << cellStart[i] << "to" << cellStart[i + 1]; { std::size_t index = cellStart[i]; RIter reg_it = M_regionIter(PM_mesh(m_simMesh, i)); @@ -291,7 +285,7 @@ class SimModSuite : public FullStorageMeshData { RIter_delete(reg_it); } - logInfo(PMU_rank()) << "Groups"; + logInfo() << "Groups"; { int groupIdx = 0; GRIter modelRegionIter = GM_regionIter(m_model); @@ -309,7 +303,7 @@ class SimModSuite : public FullStorageMeshData { GRIter_delete(modelRegionIter); } - logInfo(PMU_rank()) << "Boundaries"; + logInfo() << "Boundaries"; { GFIter modelFaceIter = GM_faceIter(m_model); while (pGFace mface = GFIter_next(modelFaceIter)) { @@ -410,13 +404,13 @@ class SimModSuite : public FullStorageMeshData { switch (type) { case Sim_InfoMsg: // Show sim info messages as debug messages - logDebug(PMU_rank()) << "SimModeler:" << msg; + logDebug() << "SimModeler:" << msg; break; case Sim_DebugMsg: // Ignore sim debug messages break; case Sim_WarningMsg: - logWarning(PMU_rank()) << "SimModeler:" << msg; + logWarning() << "SimModeler:" << msg; break; case Sim_ErrorMsg: // Use warning because error will abort the program @@ -433,20 +427,20 @@ class SimModSuite : public FullStorageMeshData { switch (currentVal) { case -2: // task is started, do nothing - logInfo(PMU_rank()) << "Progress:" << what << ", 0" - << "/" << endVal; + logInfo() << "Progress:" << what << ", 0" + << "/" << endVal; break; case -1: // end of the task - logInfo(PMU_rank()) << "Progress:" << what << ", done"; + logInfo() << "Progress:" << what << ", done"; break; default: - logInfo(PMU_rank()) << "Progress:" << what << "," << currentVal << "/" << endVal; + logInfo() << "Progress:" << what << "," << currentVal << "/" << endVal; break; } } else { if (currentVal == -2) - logInfo(PMU_rank()) << "Progress:" << what; + logInfo() << "Progress:" << what; } logDebug() << what << level << startVal << endVal << currentVal; } @@ -454,7 +448,7 @@ class SimModSuite : public FullStorageMeshData { private: void extractCases(pGModel m_model, pACase& meshCase, const char* meshCaseName, pACase& analysisCase, const char* analysisCaseName) { - logInfo(PMU_rank()) << "Extracting cases"; + logInfo() << "Extracting cases"; #ifdef BEFORE_SIM_2024 pAManager attMngr = GM_attManager(m_model); #else @@ -496,8 +490,8 @@ class SimModSuite : public FullStorageMeshData { << "not found in model."; } else { MS_setMeshSize(meshCase, entity, 1, MSize, nullptr); - logInfo(PMU_rank()) << element_name[element_type_id] << "id:" << element_id - << ", MSize =" << MSize; + logInfo() << element_name[element_type_id] << "id:" << element_id + << ", MSize =" << MSize; } } } @@ -507,7 +501,7 @@ class SimModSuite : public FullStorageMeshData { void setCases(pGModel model, pACase& meshCase, pACase& analysisCase, MeshAttributes& MeshAtt, AnalysisAttributes& AnalysisAtt, std::unordered_map groupMap) { - logInfo(PMU_rank()) << "Setting cases"; + logInfo() << "Setting cases"; // ------------------------------ Set boundary conditions // ------------------------------ @@ -562,7 +556,7 @@ class SimModSuite : public FullStorageMeshData { // the creation of the AttributeVoid on the face as soon as the // association process is started if (fb.bcType != 0) { - logInfo(PMU_rank()) << "faceBound[" << fb.faceID + 1 << "] =" << fb.bcType; + logInfo() << "faceBound[" << fb.faceID + 1 << "] =" << fb.bcType; AMA_addGEntity(aBC[fb.bcType], face); } } @@ -576,7 +570,7 @@ class SimModSuite : public FullStorageMeshData { // Set global mesh size pModelItem modelDomain = GM_domain(model); if (MeshAtt.globalMSize > 0) { - logInfo(PMU_rank()) << "globalMSize =" << MeshAtt.globalMSize; + logInfo() << "globalMSize =" << MeshAtt.globalMSize; // ( , , <1=absolute, 2=relative>, , ) MS_setMeshSize(meshCase, modelDomain, 1, MeshAtt.globalMSize, nullptr); @@ -586,7 +580,7 @@ class SimModSuite : public FullStorageMeshData { setMeshSize(model, meshCase, MeshAtt); if (MeshAtt.velocityAwareRefinementSettings.isVelocityAwareRefinementOn()) { - logInfo(PMU_rank()) << "Enabling velocity aware meshing"; + logInfo() << "Enabling velocity aware meshing"; easiMeshSize = std::make_shared(MeshAtt.velocityAwareRefinementSettings, model, groupMap); auto easiMeshSizeFunc = [](pSizeAttData sadata, void* userdata) { @@ -607,18 +601,18 @@ class SimModSuite : public FullStorageMeshData { if (MeshAtt.gradation > 0) { // Set gradation relative - logInfo(PMU_rank()) << "Gradation rate =" << MeshAtt.gradation; + logInfo() << "Gradation rate =" << MeshAtt.gradation; MS_setGlobalSizeGradationRate(meshCase, MeshAtt.gradation); } if (MeshAtt.vol_AspectRatio > 0) { // Set target equivolume AspectRatio - logInfo(PMU_rank()) << "Target equivolume AspectRatio =" << MeshAtt.vol_AspectRatio; + logInfo() << "Target equivolume AspectRatio =" << MeshAtt.vol_AspectRatio; MS_setVolumeShapeMetric(meshCase, modelDomain, ShapeMetricType_AspectRatio, MeshAtt.vol_AspectRatio); } if (MeshAtt.area_AspectRatio > 0) { // Set target equiarea AspectRatio - logInfo(PMU_rank()) << "Target equiarea AspectRatio =" << MeshAtt.area_AspectRatio; + logInfo() << "Target equiarea AspectRatio =" << MeshAtt.area_AspectRatio; #ifdef BEFORE_SIM_11 MS_setSurfaceShapeMetric(meshCase, modelDomain, ShapeMetricType_AspectRatio, MeshAtt.area_AspectRatio); @@ -628,15 +622,15 @@ class SimModSuite : public FullStorageMeshData { #endif } for (auto& mycube : MeshAtt.lCube) { - logInfo(PMU_rank()) << "Cube mesh refinement: " << mycube.CubeMSize; - logInfo(PMU_rank()) << "Center" << mycube.CubeCenter[0] << " " << mycube.CubeCenter[1] << " " - << mycube.CubeCenter[2]; - logInfo(PMU_rank()) << "Width" << mycube.CubeWidth[0] << " " << mycube.CubeWidth[1] << " " - << mycube.CubeWidth[2]; - logInfo(PMU_rank()) << "Height" << mycube.CubeHeight[0] << " " << mycube.CubeHeight[1] << " " - << mycube.CubeHeight[2]; - logInfo(PMU_rank()) << "Depth" << mycube.CubeDepth[0] << " " << mycube.CubeDepth[1] << " " - << mycube.CubeDepth[2]; + logInfo() << "Cube mesh refinement: " << mycube.CubeMSize; + logInfo() << "Center" << mycube.CubeCenter[0] << " " << mycube.CubeCenter[1] << " " + << mycube.CubeCenter[2]; + logInfo() << "Width" << mycube.CubeWidth[0] << " " << mycube.CubeWidth[1] << " " + << mycube.CubeWidth[2]; + logInfo() << "Height" << mycube.CubeHeight[0] << " " << mycube.CubeHeight[1] << " " + << mycube.CubeHeight[2]; + logInfo() << "Depth" << mycube.CubeDepth[0] << " " << mycube.CubeDepth[1] << " " + << mycube.CubeDepth[2]; MS_addCubeRefinement(meshCase, mycube.CubeMSize, &mycube.CubeCenter[0], &mycube.CubeWidth[0], &mycube.CubeHeight[0], &mycube.CubeDepth[0]); } @@ -647,9 +641,9 @@ class SimModSuite : public FullStorageMeshData { if (face == nullptr) { logError() << "MeshSizeProp faceid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "MeshSizeProp faceid:" << iElem - << ", distance =" << MeshAtt.MeshSizePropagationDistance - << ", scaling factor =" << MeshAtt.MeshSizePropagationScalingFactor; + logInfo() << "MeshSizeProp faceid:" << iElem + << ", distance =" << MeshAtt.MeshSizePropagationDistance + << ", scaling factor =" << MeshAtt.MeshSizePropagationScalingFactor; #ifdef BEFORE_SIM_15 MS_setMeshSizePropagation(meshCase, face, 1, MeshAtt.MeshSizePropagationDistance, MeshAtt.MeshSizePropagationScalingFactor); @@ -665,8 +659,8 @@ class SimModSuite : public FullStorageMeshData { if (face == nullptr) { logError() << "UseDiscreteMesh; faceid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "UseDiscreteMesh; faceid, noModification:" << iElem - << MeshAtt.UseDiscreteMesh_noModification; + logInfo() << "UseDiscreteMesh; faceid, noModification:" << iElem + << MeshAtt.UseDiscreteMesh_noModification; MS_useDiscreteGeometryMesh(meshCase, face, MeshAtt.UseDiscreteMesh_noModification); // MS_limitSurfaceMeshModification(meshCase,face,UseDiscreteMesh_noModification); } @@ -676,7 +670,7 @@ class SimModSuite : public FullStorageMeshData { if (face == nullptr) { logError() << "No Mesh; faceid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "No Mesh; faceid:" << iElem; + logInfo() << "No Mesh; faceid:" << iElem; MS_setNoMesh(meshCase, face, 1); } } @@ -685,7 +679,7 @@ class SimModSuite : public FullStorageMeshData { if (region == nullptr) { logError() << "No Mesh; regionid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "No Mesh; regionid:" << iElem; + logInfo() << "No Mesh; regionid:" << iElem; MS_setNoMesh(meshCase, region, 1); } } @@ -718,8 +712,8 @@ class SimModSuite : public FullStorageMeshData { if (!GM_isValid(m_model, 1, modelErrors)) { void* iter = nullptr; while (pSimError err = static_cast(PList_next(modelErrors, &iter))) { - logInfo(PMU_rank()) << " Error code: " << SimError_code(err) << std::endl; - logInfo(PMU_rank()) << " Error string: " << SimError_toString(err) << std::endl; + logInfo() << " Error code: " << SimError_code(err) << std::endl; + logInfo() << " Error string: " << SimError_toString(err) << std::endl; } logError() << "Input model is not valid"; } @@ -730,8 +724,8 @@ class SimModSuite : public FullStorageMeshData { if (!GM_isValid(m_model, 1, modelInfos)) { void* iter = nullptr; while (pSimInfo info = static_cast(PList_next(modelInfos, &iter))) { - logInfo(PMU_rank()) << " Info code: " << SimInfo_code(info) << std::endl; - logInfo(PMU_rank()) << " Info string: " << SimInfo_toString(info) << std::endl; + logInfo() << " Info code: " << SimInfo_code(info) << std::endl; + logInfo() << " Info string: " << SimInfo_toString(info) << std::endl; } logError() << "Input model is not valid"; } @@ -750,15 +744,14 @@ class SimModSuite : public FullStorageMeshData { for (int i = 0; i < PList_size(entities); i += 2) { pEntity firstEnt = (pEntity)PList_item(entities, i); pEntity secondEnt = (pEntity)PList_item(entities, i + 1); - logInfo(PMU_rank()) << "Self-intersection between" << element_name[EN_whatInType(firstEnt)] - << GEN_tag(EN_whatIn(firstEnt)) << "and" - << element_name[EN_whatInType(secondEnt)] - << GEN_tag(EN_whatIn(secondEnt)); + logInfo() << "Self-intersection between" << element_name[EN_whatInType(firstEnt)] + << GEN_tag(EN_whatIn(firstEnt)) << "and" << element_name[EN_whatInType(secondEnt)] + << GEN_tag(EN_whatIn(secondEnt)); double centroid[3], centroid2[3]; EN_centroid(firstEnt, ¢roid[0]); EN_centroid(secondEnt, ¢roid2[0]); - logInfo(PMU_rank()) << "centroids" << centroid[0] << centroid[1] << centroid[2] << "and " - << centroid2[0] << centroid2[1] << centroid2[2] << std::flush; + logInfo() << "centroids" << centroid[0] << centroid[1] << centroid[2] << "and " + << centroid2[0] << centroid2[1] << centroid2[2] << std::flush; } logError() << PList_size(entities) / 2 << "Self-intersection(s) detected in CAD mesh"; } @@ -799,20 +792,20 @@ class SimModSuite : public FullStorageMeshData { RIter_delete(reg_it); // Print the statistics - logInfo(PMU_rank()) << "AR statistics:"; + logInfo() << "AR statistics:"; MPI_Allreduce(&maxAR, &AR_global, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); - logInfo(PMU_rank()) << "AR max:" << AR_global; - logInfo(PMU_rank()) << "AR (target: < ~10):"; + logInfo() << "AR max:" << AR_global; + logInfo() << "AR (target: < ~10):"; long int bin_global; for (int i = 0; i < num_bins - 1; i++) { MPI_Allreduce(&AR_vol_bins[i], &bin_global, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD); - logInfo(PMU_rank()) << std::fixed << std::setprecision(2) << "[" << AR[i] << "," << AR[i + 1] - << "):" << bin_global; + logInfo() << std::fixed << std::setprecision(2) << "[" << AR[i] << "," << AR[i + 1] + << "):" << bin_global; } MPI_Allreduce(&AR_vol_bins[num_bins - 1], &bin_global, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD); - logInfo(PMU_rank()) << std::fixed << std::setprecision(2) << "[" << AR[num_bins - 1] - << ",inf):" << bin_global; + logInfo() << std::fixed << std::setprecision(2) << "[" << AR[num_bins - 1] + << ",inf):" << bin_global; } }; -#endif // SIM_MOD_SUITE_H +#endif // PUMGEN_SRC_INPUT_SIMMODSUITE_H_ diff --git a/src/input/SimModSuiteApf.h b/src/input/SimModSuiteApf.h index 7dbb723..4f40ba8 100644 --- a/src/input/SimModSuiteApf.h +++ b/src/input/SimModSuiteApf.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2023 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef SIM_MOD_SUITE_APF_H -#define SIM_MOD_SUITE_APF_H +#ifndef PUMGEN_SRC_INPUT_SIMMODSUITEAPF_H_ +#define PUMGEN_SRC_INPUT_SIMMODSUITEAPF_H_ #include @@ -103,7 +97,7 @@ class SimModSuiteApf : public ApfMeshInput { Sim_setMessageHandler(messageHandler); // Load CAD - logInfo(PMU_rank()) << "Loading model"; + logInfo() << "Loading model"; std::string smodFile = modFile; if (cadFile != nullptr) { @@ -122,7 +116,7 @@ class SimModSuiteApf : public ApfMeshInput { } // Extract cases - logInfo(PMU_rank()) << "Extracting cases"; + logInfo() << "Extracting cases"; pACase meshCase, analysisCase; MeshAttributes MeshAtt; @@ -143,7 +137,7 @@ class SimModSuiteApf : public ApfMeshInput { Progress_setCallback(prog, progressHandler); // create the mesh - logInfo(PMU_rank()) << "Starting the surface mesher"; + logInfo() << "Starting the surface mesher"; pSurfaceMesher surfaceMesher = SurfaceMesher_new(meshCase, m_simMesh); if (xmlFile != nullptr) { SurfaceMesher_setSmoothing(surfaceMesher, MeshAtt.surfaceSmoothingLevel); @@ -156,7 +150,7 @@ class SimModSuiteApf : public ApfMeshInput { PM_setTotalNumParts(m_simMesh, PMU_size()); - logInfo(PMU_rank()) << "Starting the volume mesher"; + logInfo() << "Starting the volume mesher"; pVolumeMesher volumeMesher = VolumeMesher_new(meshCase, m_simMesh); if (xmlFile != nullptr) { VolumeMesher_setSmoothing(volumeMesher, MeshAtt.volumeSmoothingLevel); @@ -183,7 +177,7 @@ class SimModSuiteApf : public ApfMeshInput { gmi_register_sim(); gmi_model* model = gmi_import_sim(m_model); - logInfo(PMU_rank()) << "Converting mesh to APF"; + logInfo() << "Converting mesh to APF"; m_mesh = apf::createMdsMesh(model, tmpMesh); apf::destroyMesh(tmpMesh); @@ -288,13 +282,13 @@ class SimModSuiteApf : public ApfMeshInput { switch (type) { case Sim_InfoMsg: // Show sim info messages as debug messages - logDebug(PMU_rank()) << "SimModeler:" << msg; + logDebug() << "SimModeler:" << msg; break; case Sim_DebugMsg: // Ignore sim debug messages break; case Sim_WarningMsg: - logWarning(PMU_rank()) << "SimModeler:" << msg; + logWarning() << "SimModeler:" << msg; break; case Sim_ErrorMsg: // Use warning because error will abort the program @@ -311,20 +305,20 @@ class SimModSuiteApf : public ApfMeshInput { switch (currentVal) { case -2: // task is started, do nothing - logInfo(PMU_rank()) << "Progress:" << what << ", 0" - << "/" << endVal; + logInfo() << "Progress:" << what << ", 0" + << "/" << endVal; break; case -1: // end of the task - logInfo(PMU_rank()) << "Progress:" << what << ", done"; + logInfo() << "Progress:" << what << ", done"; break; default: - logInfo(PMU_rank()) << "Progress:" << what << "," << currentVal << "/" << endVal; + logInfo() << "Progress:" << what << "," << currentVal << "/" << endVal; break; } } else { if (currentVal == -2) - logInfo(PMU_rank()) << "Progress:" << what; + logInfo() << "Progress:" << what; } logDebug() << what << level << startVal << endVal << currentVal; } @@ -332,7 +326,7 @@ class SimModSuiteApf : public ApfMeshInput { private: void extractCases(pGModel m_model, pACase& meshCase, const char* meshCaseName, pACase& analysisCase, const char* analysisCaseName) { - logInfo(PMU_rank()) << "Extracting cases"; + logInfo() << "Extracting cases"; #ifdef BEFORE_SIM_2024 pAManager attMngr = GM_attManager(m_model); @@ -376,8 +370,8 @@ class SimModSuiteApf : public ApfMeshInput { << "not found in model."; } else { MS_setMeshSize(meshCase, entity, 1, MSize, nullptr); - logInfo(PMU_rank()) << element_name[element_type_id] << "id:" << element_id - << ", MSize =" << MSize; + logInfo() << element_name[element_type_id] << "id:" << element_id + << ", MSize =" << MSize; } } } @@ -387,7 +381,7 @@ class SimModSuiteApf : public ApfMeshInput { void setCases(pGModel model, pACase& meshCase, pACase& analysisCase, MeshAttributes& MeshAtt, AnalysisAttributes& AnalysisAtt, std::unordered_map groupMap) { - logInfo(PMU_rank()) << "Setting cases"; + logInfo() << "Setting cases"; // ------------------------------ Set boundary conditions // ------------------------------ @@ -442,7 +436,7 @@ class SimModSuiteApf : public ApfMeshInput { // the creation of the AttributeVoid on the face as soon as the // association process is started if (fb.bcType != 0) { - logInfo(PMU_rank()) << "faceBound[" << fb.faceID + 1 << "] =" << fb.bcType; + logInfo() << "faceBound[" << fb.faceID + 1 << "] =" << fb.bcType; AMA_addGEntity(aBC[fb.bcType], face); } } @@ -456,7 +450,7 @@ class SimModSuiteApf : public ApfMeshInput { // Set global mesh size pModelItem modelDomain = GM_domain(model); if (MeshAtt.globalMSize > 0) { - logInfo(PMU_rank()) << "globalMSize =" << MeshAtt.globalMSize; + logInfo() << "globalMSize =" << MeshAtt.globalMSize; // ( , , <1=absolute, 2=relative>, , ) MS_setMeshSize(meshCase, modelDomain, 1, MeshAtt.globalMSize, nullptr); @@ -466,7 +460,7 @@ class SimModSuiteApf : public ApfMeshInput { setMeshSize(model, meshCase, MeshAtt); if (MeshAtt.velocityAwareRefinementSettings.isVelocityAwareRefinementOn()) { - logInfo(PMU_rank()) << "Enabling velocity aware meshing"; + logInfo() << "Enabling velocity aware meshing"; easiMeshSize = EasiMeshSize(MeshAtt.velocityAwareRefinementSettings, model, groupMap); auto easiMeshSizeFunc = [](pSizeAttData sadata, void* userdata) { auto* easiMeshSize = static_cast(userdata); @@ -486,18 +480,18 @@ class SimModSuiteApf : public ApfMeshInput { if (MeshAtt.gradation > 0) { // Set gradation relative - logInfo(PMU_rank()) << "Gradation rate =" << MeshAtt.gradation; + logInfo() << "Gradation rate =" << MeshAtt.gradation; MS_setGlobalSizeGradationRate(meshCase, MeshAtt.gradation); } if (MeshAtt.vol_AspectRatio > 0) { // Set target equivolume AspectRatio - logInfo(PMU_rank()) << "Target equivolume AspectRatio =" << MeshAtt.vol_AspectRatio; + logInfo() << "Target equivolume AspectRatio =" << MeshAtt.vol_AspectRatio; MS_setVolumeShapeMetric(meshCase, modelDomain, ShapeMetricType_AspectRatio, MeshAtt.vol_AspectRatio); } if (MeshAtt.area_AspectRatio > 0) { // Set target equiarea AspectRatio - logInfo(PMU_rank()) << "Target equiarea AspectRatio =" << MeshAtt.area_AspectRatio; + logInfo() << "Target equiarea AspectRatio =" << MeshAtt.area_AspectRatio; #ifdef BEFORE_SIM_11 MS_setSurfaceShapeMetric(meshCase, modelDomain, ShapeMetricType_AspectRatio, MeshAtt.area_AspectRatio); @@ -507,15 +501,15 @@ class SimModSuiteApf : public ApfMeshInput { #endif } for (auto& mycube : MeshAtt.lCube) { - logInfo(PMU_rank()) << "Cube mesh refinement: " << mycube.CubeMSize; - logInfo(PMU_rank()) << "Center" << mycube.CubeCenter[0] << " " << mycube.CubeCenter[1] << " " - << mycube.CubeCenter[2]; - logInfo(PMU_rank()) << "Width" << mycube.CubeWidth[0] << " " << mycube.CubeWidth[1] << " " - << mycube.CubeWidth[2]; - logInfo(PMU_rank()) << "Height" << mycube.CubeHeight[0] << " " << mycube.CubeHeight[1] << " " - << mycube.CubeHeight[2]; - logInfo(PMU_rank()) << "Depth" << mycube.CubeDepth[0] << " " << mycube.CubeDepth[1] << " " - << mycube.CubeDepth[2]; + logInfo() << "Cube mesh refinement: " << mycube.CubeMSize; + logInfo() << "Center" << mycube.CubeCenter[0] << " " << mycube.CubeCenter[1] << " " + << mycube.CubeCenter[2]; + logInfo() << "Width" << mycube.CubeWidth[0] << " " << mycube.CubeWidth[1] << " " + << mycube.CubeWidth[2]; + logInfo() << "Height" << mycube.CubeHeight[0] << " " << mycube.CubeHeight[1] << " " + << mycube.CubeHeight[2]; + logInfo() << "Depth" << mycube.CubeDepth[0] << " " << mycube.CubeDepth[1] << " " + << mycube.CubeDepth[2]; MS_addCubeRefinement(meshCase, mycube.CubeMSize, &mycube.CubeCenter[0], &mycube.CubeWidth[0], &mycube.CubeHeight[0], &mycube.CubeDepth[0]); } @@ -526,9 +520,9 @@ class SimModSuiteApf : public ApfMeshInput { if (face == nullptr) { logError() << "MeshSizeProp faceid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "MeshSizeProp faceid:" << iElem - << ", distance =" << MeshAtt.MeshSizePropagationDistance - << ", scaling factor =" << MeshAtt.MeshSizePropagationScalingFactor; + logInfo() << "MeshSizeProp faceid:" << iElem + << ", distance =" << MeshAtt.MeshSizePropagationDistance + << ", scaling factor =" << MeshAtt.MeshSizePropagationScalingFactor; #ifdef BEFORE_SIM_15 MS_setMeshSizePropagation(meshCase, face, 1, MeshAtt.MeshSizePropagationDistance, MeshAtt.MeshSizePropagationScalingFactor); @@ -544,8 +538,8 @@ class SimModSuiteApf : public ApfMeshInput { if (face == nullptr) { logError() << "UseDiscreteMesh; faceid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "UseDiscreteMesh; faceid, noModification:" << iElem - << MeshAtt.UseDiscreteMesh_noModification; + logInfo() << "UseDiscreteMesh; faceid, noModification:" << iElem + << MeshAtt.UseDiscreteMesh_noModification; MS_useDiscreteGeometryMesh(meshCase, face, MeshAtt.UseDiscreteMesh_noModification); // MS_limitSurfaceMeshModification(meshCase,face,UseDiscreteMesh_noModification); } @@ -555,7 +549,7 @@ class SimModSuiteApf : public ApfMeshInput { if (face == nullptr) { logError() << "No Mesh; faceid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "No Mesh; faceid:" << iElem; + logInfo() << "No Mesh; faceid:" << iElem; MS_setNoMesh(meshCase, face, 1); } } @@ -564,7 +558,7 @@ class SimModSuiteApf : public ApfMeshInput { if (region == nullptr) { logError() << "No Mesh; regionid:" << iElem << "not found in model."; } else { - logInfo(PMU_rank()) << "No Mesh; regionid:" << iElem; + logInfo() << "No Mesh; regionid:" << iElem; MS_setNoMesh(meshCase, region, 1); } } @@ -597,8 +591,8 @@ class SimModSuiteApf : public ApfMeshInput { if (!GM_isValid(m_model, 1, modelErrors)) { void* iter = nullptr; while (pSimError err = static_cast(PList_next(modelErrors, &iter))) { - logInfo(PMU_rank()) << " Error code: " << SimError_code(err) << std::endl; - logInfo(PMU_rank()) << " Error string: " << SimError_toString(err) << std::endl; + logInfo() << " Error code: " << SimError_code(err) << std::endl; + logInfo() << " Error string: " << SimError_toString(err) << std::endl; } logError() << "Input model is not valid"; } @@ -609,8 +603,8 @@ class SimModSuiteApf : public ApfMeshInput { if (!GM_isValid(m_model, 1, modelInfos)) { void* iter = nullptr; while (pSimInfo info = static_cast(PList_next(modelInfos, &iter))) { - logInfo(PMU_rank()) << " Info code: " << SimInfo_code(info) << std::endl; - logInfo(PMU_rank()) << " Info string: " << SimInfo_toString(info) << std::endl; + logInfo() << " Info code: " << SimInfo_code(info) << std::endl; + logInfo() << " Info string: " << SimInfo_toString(info) << std::endl; } logError() << "Input model is not valid"; } @@ -629,15 +623,14 @@ class SimModSuiteApf : public ApfMeshInput { for (int i = 0; i < PList_size(entities); i += 2) { pEntity firstEnt = (pEntity)PList_item(entities, i); pEntity secondEnt = (pEntity)PList_item(entities, i + 1); - logInfo(PMU_rank()) << "Self-intersection between" << element_name[EN_whatInType(firstEnt)] - << GEN_tag(EN_whatIn(firstEnt)) << "and" - << element_name[EN_whatInType(secondEnt)] - << GEN_tag(EN_whatIn(secondEnt)); + logInfo() << "Self-intersection between" << element_name[EN_whatInType(firstEnt)] + << GEN_tag(EN_whatIn(firstEnt)) << "and" << element_name[EN_whatInType(secondEnt)] + << GEN_tag(EN_whatIn(secondEnt)); double centroid[3], centroid2[3]; EN_centroid(firstEnt, ¢roid[0]); EN_centroid(secondEnt, ¢roid2[0]); - logInfo(PMU_rank()) << "centroids" << centroid[0] << centroid[1] << centroid[2] << "and " - << centroid2[0] << centroid2[1] << centroid2[2] << std::flush; + logInfo() << "centroids" << centroid[0] << centroid[1] << centroid[2] << "and " + << centroid2[0] << centroid2[1] << centroid2[2] << std::flush; } logError() << PList_size(entities) / 2 << "Self-intersection(s) detected in CAD mesh"; } @@ -678,20 +671,20 @@ class SimModSuiteApf : public ApfMeshInput { RIter_delete(reg_it); // Print the statistics - logInfo(PMU_rank()) << "AR statistics:"; + logInfo() << "AR statistics:"; MPI_Allreduce(&maxAR, &AR_global, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); - logInfo(PMU_rank()) << "AR max:" << AR_global; - logInfo(PMU_rank()) << "AR (target: < ~10):"; + logInfo() << "AR max:" << AR_global; + logInfo() << "AR (target: < ~10):"; long int bin_global; for (int i = 0; i < num_bins - 1; i++) { MPI_Allreduce(&AR_vol_bins[i], &bin_global, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD); - logInfo(PMU_rank()) << std::fixed << std::setprecision(2) << "[" << AR[i] << "," << AR[i + 1] - << "):" << bin_global; + logInfo() << std::fixed << std::setprecision(2) << "[" << AR[i] << "," << AR[i + 1] + << "):" << bin_global; } MPI_Allreduce(&AR_vol_bins[num_bins - 1], &bin_global, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD); - logInfo(PMU_rank()) << std::fixed << std::setprecision(2) << "[" << AR[num_bins - 1] - << ",inf):" << bin_global; + logInfo() << std::fixed << std::setprecision(2) << "[" << AR[num_bins - 1] + << ",inf):" << bin_global; } }; -#endif // SIM_MOD_SUITE_APF_H +#endif // PUMGEN_SRC_INPUT_SIMMODSUITEAPF_H_ diff --git a/src/input/split.cpp b/src/input/split.cpp index 8b03f5c..387159b 100644 --- a/src/input/split.cpp +++ b/src/input/split.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2020 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include #include diff --git a/src/input/split.h b/src/input/split.h index c935c62..585e62a 100644 --- a/src/input/split.h +++ b/src/input/split.h @@ -1,5 +1,8 @@ -#ifndef INPUT_SPLIT_H -#define INPUT_SPLIT_H +// SPDX-FileCopyrightText: 2020 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_INPUT_SPLIT_H_ +#define PUMGEN_SRC_INPUT_SPLIT_H_ #include #include @@ -12,4 +15,4 @@ std::vector& split(std::vector& elems, const std::string& s, char delim); -#endif +#endif // PUMGEN_SRC_INPUT_SPLIT_H_ diff --git a/src/meshreader/GMSH4Parser.cpp b/src/meshreader/GMSH4Parser.cpp index 806694d..ab36671 100644 --- a/src/meshreader/GMSH4Parser.cpp +++ b/src/meshreader/GMSH4Parser.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2022 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause #include "GMSH4Parser.h" #include @@ -10,7 +13,7 @@ bool GMSH4Parser::parse_() { errorMsg.clear(); getNextToken(); - double version = parseMeshFormat(); + const double version = parseMeshFormat(); if (version < 4.0 || version >= 5.0) { char buf[128]; sprintf(buf, "Unsupported MSH version %.1lf", version); @@ -20,6 +23,7 @@ bool GMSH4Parser::parse_() { bool hasEntities = false; bool hasNodes = false; bool hasElements = false; + bool hasPeriodic = false; while (curTok != tndm::GMSHToken::eof) { switch (curTok) { @@ -32,6 +36,9 @@ bool GMSH4Parser::parse_() { case tndm::GMSHToken::elements: hasElements = parseElements(); break; + case tndm::GMSHToken::periodic: + hasPeriodic = parsePeriodic(version >= 4.1); + break; default: getNextToken(); break; @@ -156,7 +163,9 @@ bool GMSH4Parser::parseEntities() { getNextToken(); tags.push_back(expectNonNegativeInt()); } - physicalVolumeIds.insert_or_assign(id, tags.at(0)); + if (!tags.empty()) { + physicalVolumeIds.insert_or_assign(id, tags.at(0)); + } getNextToken(); const std::size_t numBoundaryTags = expectNonNegativeInt(); // ignore boundary @@ -262,4 +271,53 @@ bool GMSH4Parser::parseElements() { return true; } +bool GMSH4Parser::parsePeriodic(bool variableAffine) { + getNextToken(); + const auto numPeriodic = expectNonNegativeInt(); + + // ignore everything but the node identification + + for (std::size_t blockIdx = 0; blockIdx < numPeriodic; blockIdx++) { + getNextToken(); + [[maybe_unused]] const std::size_t entityDim = expectNonNegativeInt(); + getNextToken(); + [[maybe_unused]] const std::size_t entityId = expectNonNegativeInt(); + getNextToken(); + [[maybe_unused]] const std::size_t entityIdentifyId = expectNonNegativeInt(); + + // for MSH4.1 vs MSH4.0 + const auto affineSize = [&]() -> std::size_t { + if (variableAffine) { + getNextToken(); + return expectNonNegativeInt(); + } else { + return 16; + } + }(); + for (std::size_t i = 0; i < affineSize; ++i) { + getNextToken(); + [[maybe_unused]] const double affineValue = expectNumber(); + } + + getNextToken(); + const std::size_t identifySize = expectNonNegativeInt(); + + for (std::size_t i = 0; i < identifySize; ++i) { + getNextToken(); + const std::size_t nodeId = expectNonNegativeInt() - 1; + getNextToken(); + const std::size_t nodeIdentifyId = expectNonNegativeInt() - 1; + builder->addVertexLink(nodeId, nodeIdentifyId); + } + } + + getNextToken(); + if (curTok != tndm::GMSHToken::end_periodic) { + return logErrorAnnotated("Expected $EndPeriodic"); + } + getNextToken(); + + return true; +} + } // namespace puml diff --git a/src/meshreader/GMSH4Parser.h b/src/meshreader/GMSH4Parser.h index d7ac78b..92f7ff4 100644 --- a/src/meshreader/GMSH4Parser.h +++ b/src/meshreader/GMSH4Parser.h @@ -1,5 +1,8 @@ -#ifndef PUMGEN_GMSH4PARSER_H -#define PUMGEN_GMSH4PARSER_H +// SPDX-FileCopyrightText: 2022 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_MESHREADER_GMSH4PARSER_H_ +#define PUMGEN_SRC_MESHREADER_GMSH4PARSER_H_ #include #include @@ -37,9 +40,10 @@ class GMSH4Parser : public tndm::GMSHParser { bool parseEntities(); bool parseNodes(); bool parseElements(); + bool parsePeriodic(bool variableAffine); virtual bool parse_() override; }; } // namespace puml -#endif // PUMGEN_GMSH4PARSER_H +#endif // PUMGEN_SRC_MESHREADER_GMSH4PARSER_H_ diff --git a/src/meshreader/GMSHBuilder.h b/src/meshreader/GMSHBuilder.h index 778edbe..d47cebc 100644 --- a/src/meshreader/GMSHBuilder.h +++ b/src/meshreader/GMSHBuilder.h @@ -1,9 +1,15 @@ -#ifndef GMSHBUILDER_20201014_H -#define GMSHBUILDER_20201014_H +// SPDX-FileCopyrightText: 2020 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_MESHREADER_GMSHBUILDER_H_ +#define PUMGEN_SRC_MESHREADER_GMSHBUILDER_H_ #include #include #include +#include +#include #include #include "utils/logger.h" @@ -144,12 +150,22 @@ template class GMSHBuilder : public tndm::GMS using facet_t = std::array; std::vector vertices; + std::vector identify; std::vector elements; std::vector groups; std::vector facets; std::vector bcs; + void resizeIdentifyIfNeeded(std::size_t newSize) { + const auto oldSize = identify.size(); + if (newSize > oldSize) { + identify.resize(newSize); + std::iota(identify.begin() + oldSize, identify.end(), oldSize); + } + } + void setNumVertices(std::size_t numVertices) { vertices.resize(numVertices); } + void setVertex(long id, std::array const& x) { for (std::size_t i = 0; i < D; ++i) { vertices[id][i] = x[i]; @@ -180,8 +196,42 @@ template class GMSHBuilder : public tndm::GMS bcs.emplace_back(static_cast(tag)); } } + void addVertexLink(std::size_t vertex, std::size_t linkVertex) { + // needed in case we parse periodic before we parse the vertex/node section + resizeIdentifyIfNeeded(vertex + 1); + identify[vertex] = linkVertex; + } + + void postprocess() { + // GMSH does not pick the same node to identify for all + // thus, stratify (i.e. "path compress" in "union find" terms) + + if (!identify.empty()) { + // only resize if we have an identification array + resizeIdentifyIfNeeded(vertices.size()); + for (std::size_t i = 0; i < identify.size(); ++i) { + if (identify[i] != i) { + + // find until we loop + std::size_t curr = i; + std::set equivalent; + equivalent.insert(curr); + while (equivalent.find(identify[curr]) == equivalent.end()) { + curr = identify[curr]; + equivalent.insert(curr); + } + + // then set everything to one value + const auto identifyEquiv = *equivalent.begin(); + for (const auto& index : equivalent) { + identify[index] = identifyEquiv; + } + } + } + } + } }; } // namespace puml -#endif // GMSHBUILDER_20201014_H +#endif // PUMGEN_SRC_MESHREADER_GMSHBUILDER_H_ diff --git a/src/meshreader/GambitReader.cpp b/src/meshreader/GambitReader.cpp index ca70be2..394fdc4 100644 --- a/src/meshreader/GambitReader.cpp +++ b/src/meshreader/GambitReader.cpp @@ -1,14 +1,8 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger #include "GambitReader.h" diff --git a/src/meshreader/GambitReader.h b/src/meshreader/GambitReader.h index ec9a2cd..a00d653 100644 --- a/src/meshreader/GambitReader.h +++ b/src/meshreader/GambitReader.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger -#ifndef GAMBIT_READER_H -#define GAMBIT_READER_H +#ifndef PUMGEN_SRC_MESHREADER_GAMBITREADER_H_ +#define PUMGEN_SRC_MESHREADER_GAMBITREADER_H_ #include #include @@ -50,6 +44,19 @@ struct GambitBoundaryFace { }; class GambitReader : public MeshReader { + private: + /** Number of character required to store a coordinate */ + static constexpr size_t COORDINATE_SIZE = 20ul; + /** Number of elements stored in one group line */ + static constexpr size_t ELEMENTS_PER_LINE_GROUP = 10ul; + + static const char* GAMBIT_FILE_ID; + static const char* ENDSECTION; + static const char* NODAL_COORDINATES; + static const char* ELEMENT_CELLS; + static const char* ELEMENT_GROUP; + static const char* BOUNDARY_CONDITIONS; + private: struct ElementSection : FileSection { /** Start of vertices in an element */ @@ -534,21 +541,8 @@ class GambitReader : public MeshReader { boundaries[faces[i].element * 4 + faces[i].face] = faces[i].type; } } - - private: - /** Number of character required to store a coordinate */ - static const size_t COORDINATE_SIZE = 20ul; - /** Number of elements stored in one group line */ - static const size_t ELEMENTS_PER_LINE_GROUP = 10ul; - - static const char* GAMBIT_FILE_ID; - static const char* ENDSECTION; - static const char* NODAL_COORDINATES; - static const char* ELEMENT_CELLS; - static const char* ELEMENT_GROUP; - static const char* BOUNDARY_CONDITIONS; }; } // namespace puml -#endif // GAMBIT_READER_H +#endif // PUMGEN_SRC_MESHREADER_GAMBITREADER_H_ diff --git a/src/meshreader/MeshReader.h b/src/meshreader/MeshReader.h index 6d97832..e928e4d 100644 --- a/src/meshreader/MeshReader.h +++ b/src/meshreader/MeshReader.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ - -#ifndef MESH_READER_H -#define MESH_READER_H +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger + +#ifndef PUMGEN_SRC_MESHREADER_MESHREADER_H_ +#define PUMGEN_SRC_MESHREADER_MESHREADER_H_ #include @@ -93,4 +87,4 @@ class MeshReader { } }; -#endif // MESH_READER_H +#endif // PUMGEN_SRC_MESHREADER_MESHREADER_H_ diff --git a/src/meshreader/ParallelGMSHReader.h b/src/meshreader/ParallelGMSHReader.h index 53f8031..19dcb99 100644 --- a/src/meshreader/ParallelGMSHReader.h +++ b/src/meshreader/ParallelGMSHReader.h @@ -1,5 +1,9 @@ -#ifndef PARALLELGMSHREADER_20201014_H -#define PARALLELGMSHREADER_20201014_H +// SPDX-FileCopyrightText: 2020 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_MESHREADER_PARALLELGMSHREADER_H_ +#define PUMGEN_SRC_MESHREADER_PARALLELGMSHREADER_H_ #include "GMSHBuilder.h" #include "third_party/MPITraits.h" @@ -12,8 +16,8 @@ #include #include -#include "aux/Distributor.h" -#include "aux/MPIConvenience.h" +#include "helper/Distributor.h" +#include "helper/MPIConvenience.h" namespace puml { @@ -38,6 +42,7 @@ template class ParallelGMSHReader { if (!ok) { logError() << meshFile << std::endl << parser.getErrorMessage(); } + builder_.postprocess(); convertBoundaryConditions(); nVertices_ = builder_.vertices.size(); @@ -65,6 +70,12 @@ template class ParallelGMSHReader { } void readGroups(int* groups) const { scatter(builder_.groups.data(), groups, nElements(), 1); } + constexpr static bool SupportsIdentify = true; + bool hasIdentify() const { return !builder_.identify.empty(); } + void readIdentify(std::size_t* vertices) const { + scatter(builder_.identify.data(), vertices, nVertices(), 1); + } + private: /** * GMSH stores boundary conditions on a surface mesh whereas SeisSol expects @@ -168,4 +179,4 @@ template class ParallelGMSHReader { } // namespace puml -#endif // PARALLELGMSHREADER_20201014_H +#endif // PUMGEN_SRC_MESHREADER_PARALLELGMSHREADER_H_ diff --git a/src/meshreader/ParallelGambitReader.h b/src/meshreader/ParallelGambitReader.h index 76b5f29..bf63ab6 100644 --- a/src/meshreader/ParallelGambitReader.h +++ b/src/meshreader/ParallelGambitReader.h @@ -1,23 +1,17 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ - -#ifndef PARALLEL_GAMBIT_READER -#define PARALLEL_GAMBIT_READER +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger + +#ifndef PUMGEN_SRC_MESHREADER_PARALLELGAMBITREADER_H_ +#define PUMGEN_SRC_MESHREADER_PARALLELGAMBITREADER_H_ #include #include "GambitReader.h" #include "ParallelMeshReader.h" -#include "aux/Distributor.h" +#include "helper/Distributor.h" #include "third_party/MPITraits.h" @@ -210,4 +204,4 @@ class ParallelGambitReader : public ParallelMeshReader { } // namespace puml -#endif // PARALLEL_GAMBIT_READER +#endif // PUMGEN_SRC_MESHREADER_PARALLELGAMBITREADER_H_ diff --git a/src/meshreader/ParallelMeshReader.h b/src/meshreader/ParallelMeshReader.h index f7b92c1..205bce8 100644 --- a/src/meshreader/ParallelMeshReader.h +++ b/src/meshreader/ParallelMeshReader.h @@ -1,17 +1,11 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ - -#ifndef PARALLEL_MESH_READER_H -#define PARALLEL_MESH_READER_H +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger + +#ifndef PUMGEN_SRC_MESHREADER_PARALLELMESHREADER_H_ +#define PUMGEN_SRC_MESHREADER_PARALLELMESHREADER_H_ #include @@ -38,6 +32,7 @@ template class ParallelMeshReader { public: constexpr static std::size_t Order = 1; constexpr static std::size_t Dim = 3; + constexpr static bool SupportsIdentify = false; ParallelMeshReader(MPI_Comm comm = MPI_COMM_WORLD) : m_nVertices(0), m_nElements(0), m_nBoundaries(0), m_comm(comm) { init(); @@ -208,4 +203,4 @@ template class ParallelMeshReader { } }; -#endif // PARALLEL_MESH_READER_H +#endif // PUMGEN_SRC_MESHREADER_PARALLELMESHREADER_H_ diff --git a/src/pumgen.cpp b/src/pumgen.cpp index 56964ca..39d1f14 100644 --- a/src/pumgen.cpp +++ b/src/pumgen.cpp @@ -1,14 +1,8 @@ -/** - * @file - * This file is part of PUMGen - * - * For conditions of distribution and use, please see the copyright - * notice in the file 'COPYING' at the root directory of this package - * and the copyright notice at https://github.com/SeisSol/PUMGen - * - * @copyright 2017 Technical University of Munich - * @author Sebastian Rettenberger - */ +// SPDX-FileCopyrightText: 2017 SeisSol Group +// SPDX-FileCopyrightText: 2017 Technical University of Munich +// +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileContributor: Sebastian Rettenberger #include "meshreader/GMSHBuilder.h" #include @@ -55,7 +49,7 @@ #include "meshreader/ParallelGambitReader.h" #include "third_party/GMSH2Parser.h" -#include "aux/InsphereCalculator.h" +#include "helper/InsphereCalculator.h" template static TT _checkH5Err(TT&& status, const char* file, int line) { if (status < 0) { @@ -170,6 +164,19 @@ static void writeH5Data(const F& handler, hid_t h5file, const std::string& name, checkH5Err(H5Pclose(h5dxlist)); } +void addAttribute(hid_t h5file, const std::string& name, const std::string& value) { + hid_t attrSpace = checkH5Err(H5Screate(H5S_SCALAR)); + hid_t attrType = checkH5Err(H5Tcopy(H5T_C_S1)); + checkH5Err(H5Tset_size(attrType, H5T_VARIABLE)); + hid_t attrBoundary = + checkH5Err(H5Acreate(h5file, name.data(), attrType, attrSpace, H5P_DEFAULT, H5P_DEFAULT)); + const void* stringData = value.data(); + checkH5Err(H5Awrite(attrBoundary, attrType, &stringData)); + checkH5Err(H5Aclose(attrBoundary)); + checkH5Err(H5Sclose(attrSpace)); + checkH5Err(H5Tclose(attrType)); +} + template using SMF2 = SerialMeshFile>; template @@ -185,19 +192,21 @@ int main(int argc, char* argv[]) { MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &processes); + utils::Logger::setRank(rank); + #ifdef USE_SCOREC PCU_Comm_Init(); #endif // Parse command line arguments - utils::Args args; - const char* source[] = {"gambit", "msh2", "msh4", "netcdf", - "apf", "simmodsuite", "simmodsuite-apf"}; + utils::Args args("A mesh converter to the PUML format, as used in SeisSol."); + const auto source = std::vector{"gambit", "msh2", "msh4", "netcdf", + "apf", "simmodsuite", "simmodsuite-apf"}; args.addEnumOption("source", source, 's', "Mesh source (default: gambit)", false); - const char* filters[] = {"none", "scaleoffset", "deflate1", "deflate2", - "deflate3", "deflate4", "deflate5", "deflate6", - "deflate7", "deflate8", "deflate9"}; + const auto filters = std::vector{"none", "scaleoffset", "deflate1", "deflate2", + "deflate3", "deflate4", "deflate5", "deflate6", + "deflate7", "deflate8", "deflate9"}; args.addOption("compactify-datatypes", 0, "Compress index and group data types to minimum byte size (no HDF5 filters)", utils::Args::Required, false); @@ -207,7 +216,7 @@ int main(int argc, char* argv[]) { utils::Args::Required, false); args.addOption("chunksize", 0, "Chunksize for writing (default=1 GiB).", utils::Args::Required, false); - const char* boundarytypes[] = {"int32", "int64", "i32", "i64", "i32x4"}; + const auto boundarytypes = std::vector{"int32", "int64", "i32", "i64", "i32x4"}; args.addEnumOption("boundarytype", boundarytypes, 0, "Type for writing out boundary data (default: i32).", false); @@ -227,7 +236,7 @@ int main(int argc, char* argv[]) { "used by SimModSuite)", utils::Args::Required, false); args.addOption("analyseAR", 0, "produce an histogram of AR", utils::Args::No, false); - const char* forces[] = {"0", "1", "2"}; + const auto forces = std::vector{"0", "1", "2"}; args.addEnumOption("enforce-size", forces, 0, "Enforce mesh size (only used by SimModSuite, default: 0)", false); args.addOption("sim_log", 0, "Create SimModSuite log", utils::Args::Required, false); @@ -259,18 +268,18 @@ int main(int argc, char* argv[]) { int filterEnable = args.getArgument("filter-enable", 0); hsize_t filterChunksize = args.getArgument("filter-chunksize", 4096); if (reduceInts) { - logInfo(rank) << "Using compact integer types."; + logInfo() << "Using compact integer types."; } if (filterEnable == 0) { - logInfo(rank) << "No filtering enabled (contiguous storage)"; + logInfo() << "No filtering enabled (contiguous storage)"; } else { - logInfo(rank) << "Using filtering. Chunksize:" << filterChunksize; + logInfo() << "Using filtering. Chunksize:" << filterChunksize; if (filterEnable == 1) { - logInfo(rank) << "Compression: scale-offset compression for integers (disabled for floats)"; + logInfo() << "Compression: scale-offset compression for integers (disabled for floats)"; } else if (filterEnable < 11) { - logInfo(rank) << "Compression: deflate, strength" << filterEnable - 1 - << "(note: this requires HDF5 to be compiled with GZIP support; this applies " - "to SeisSol as well)"; + logInfo() << "Compression: deflate, strength" << filterEnable - 1 + << "(note: this requires HDF5 to be compiled with GZIP support; this applies " + "to SeisSol as well)"; } } @@ -287,14 +296,14 @@ int main(int argc, char* argv[]) { secondShape = NoSecondDim; boundaryFormatAttr = "i32"; boundaryPrecision = 4; - logInfo(rank) << "Using 32-bit integer boundary type conditions, or 8 bit per face (i32)."; + logInfo() << "Using 32-bit integer boundary type conditions, or 8 bit per face (i32)."; } else if (boundaryType == 1 || boundaryType == 3) { boundaryDatatype = H5T_STD_I64LE; faceOffset = 16; secondShape = NoSecondDim; boundaryFormatAttr = "i64"; boundaryPrecision = 8; - logInfo(rank) << "Using 64-bit integer boundary type conditions, or 16 bit per face (i64)."; + logInfo() << "Using 64-bit integer boundary type conditions, or 16 bit per face (i64)."; } else if (boundaryType == 4) { boundaryDatatype = H5T_STD_I32LE; secondShape = 4; @@ -302,7 +311,7 @@ int main(int argc, char* argv[]) { boundaryFormatAttr = "i32x4"; boundaryPrecision = 4; secondDimBoundary = " 4"; - logInfo(rank) << "Using 32-bit integer per boundary face (i32x4)."; + logInfo() << "Using 32-bit integer per boundary face (i32x4)."; } std::string xdmfFile = outputFile; @@ -321,27 +330,27 @@ int main(int argc, char* argv[]) { MeshData* meshInput = nullptr; switch (args.getArgument("source", 0)) { case 0: - logInfo(rank) << "Using Gambit mesh"; + logInfo() << "Using Gambit mesh"; meshInput = new SerialMeshFile(inputFile, faceOffset); break; case 1: - logInfo(rank) << "Using GMSH mesh format 2 (msh2) mesh"; + logInfo() << "Using GMSH mesh format 2 (msh2) mesh"; meshInput = puml::makePointer(meshOrder, inputFile, faceOffset); break; case 2: - logInfo(rank) << "Using GMSH mesh format 4 (msh4) mesh"; + logInfo() << "Using GMSH mesh format 4 (msh4) mesh"; meshInput = puml::makePointer(meshOrder, inputFile, faceOffset); break; case 3: #ifdef USE_NETCDF - logInfo(rank) << "Using netCDF mesh"; + logInfo() << "Using netCDF mesh"; meshInput = new NetCDFMesh(inputFile, faceOffset); #else // USE_NETCDF logError() << "netCDF is not supported in this version"; #endif // USE_NETCDF break; case 4: - logInfo(rank) << "Using APF native format"; + logInfo() << "Using APF native format"; #ifdef USE_SCOREC meshInput = new ApfNative(inputFile, faceOffset, args.getArgument("input", 0L)); (dynamic_cast(meshInput))->generate(); @@ -352,7 +361,7 @@ int main(int argc, char* argv[]) { break; case 5: #ifdef USE_SIMMOD - logInfo(rank) << "Using SimModSuite"; + logInfo() << "Using SimModSuite"; meshInput = new SimModSuite( inputFile, faceOffset, args.getArgument("cad", 0L), @@ -367,7 +376,7 @@ int main(int argc, char* argv[]) { case 6: #ifdef USE_SIMMOD #ifdef USE_SCOREC - logInfo(rank) << "Using SimModSuite with APF (deprecated)"; + logInfo() << "Using SimModSuite with APF (deprecated)"; meshInput = new SimModSuiteApf( inputFile, faceOffset, args.getArgument("cad", 0L), @@ -388,7 +397,7 @@ int main(int argc, char* argv[]) { logError() << "Unknown source."; } - logInfo(rank) << "Parsed mesh successfully, writing output..."; + logInfo() << "Parsed mesh successfully, writing output..."; void* mesh = nullptr; @@ -398,16 +407,17 @@ int main(int argc, char* argv[]) { MPI_Allreduce(MPI_IN_PLACE, globalSize, 2, tndm::mpi_type_t(), MPI_SUM, MPI_COMM_WORLD); - logInfo(rank) << "Coordinates in vertex:" << meshInput->vertexSize(); - logInfo(rank) << "Vertices in cell:" << meshInput->cellSize(); - logInfo(rank) << "Total cell count:" << globalSize[0]; - logInfo(rank) << "Total vertex count:" << globalSize[1]; + logInfo() << "Coordinates in vertex:" << meshInput->vertexSize(); + logInfo() << "Vertices in cell:" << meshInput->cellSize(); + logInfo() << "Total cell count:" << globalSize[0]; + logInfo() << "Total vertex count:" << globalSize[1]; + logInfo() << "Vertex identification:" << meshInput->hasIdentify(); auto inspheres = calculateInsphere(meshInput->connectivity(), meshInput->geometry(), MPI_COMM_WORLD); double min = *std::min_element(inspheres.begin(), inspheres.end()); MPI_Reduce((rank == 0 ? MPI_IN_PLACE : &min), &min, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); - logInfo(rank) << "Minimum insphere found:" << min; + logInfo() << "Minimum insphere found:" << min; // Get offsets std::size_t offsets[2] = {localSize[0], localSize[1]}; @@ -430,13 +440,13 @@ int main(int argc, char* argv[]) { // Write cells std::size_t connectBytesPerData = 8; - logInfo(rank) << "Writing cells"; + logInfo() << "Writing cells"; writeH5Data(meshInput->connectivity(), h5file, "connect", mesh, 3, H5T_NATIVE_UINT64, H5T_STD_U64LE, chunksize, localSize[0], globalSize[0], reduceInts, filterEnable, filterChunksize, meshInput->cellSize()); // Vertices - logInfo(rank) << "Writing vertices"; + logInfo() << "Writing vertices"; writeH5Data(meshInput->geometry(), h5file, "geometry", mesh, 0, H5T_IEEE_F64LE, H5T_IEEE_F64LE, chunksize, localSize[1], globalSize[1], reduceInts, filterEnable, filterChunksize, meshInput->vertexSize()); @@ -444,13 +454,13 @@ int main(int argc, char* argv[]) { // Group information std::size_t groupBytesPerData = 4; - logInfo(rank) << "Writing group information"; + logInfo() << "Writing group information"; writeH5Data(meshInput->group(), h5file, "group", mesh, 3, H5T_NATIVE_INT32, H5T_STD_I32LE, chunksize, localSize[0], globalSize[0], reduceInts, filterEnable, filterChunksize, NoSecondDim); // Write boundary condition - logInfo(rank) << "Writing boundary condition"; + logInfo() << "Writing boundary condition"; if (secondShape != NoSecondDim) { // TODO: a bit ugly, but it works secondShape = meshInput->vertexSize() + 1; @@ -465,16 +475,17 @@ int main(int argc, char* argv[]) { filterEnable, filterChunksize, secondShape); } - hid_t attrSpace = checkH5Err(H5Screate(H5S_SCALAR)); - hid_t attrType = checkH5Err(H5Tcopy(H5T_C_S1)); - checkH5Err(H5Tset_size(attrType, H5T_VARIABLE)); - hid_t attrBoundary = checkH5Err( - H5Acreate(h5file, "boundary-format", attrType, attrSpace, H5P_DEFAULT, H5P_DEFAULT)); - void* stringData = boundaryFormatAttr.data(); - checkH5Err(H5Awrite(attrBoundary, attrType, &stringData)); - checkH5Err(H5Aclose(attrBoundary)); - checkH5Err(H5Sclose(attrSpace)); - checkH5Err(H5Tclose(attrType)); + addAttribute(h5file, "boundary-format", boundaryFormatAttr); + + if (meshInput->hasIdentify()) { + logInfo() << "Writing vertex topology identification"; + writeH5Data(meshInput->identify(), h5file, "identify", mesh, 0, H5T_NATIVE_UINT64, + H5T_STD_U64LE, chunksize, localSize[1], globalSize[1], reduceInts, + filterEnable, filterChunksize, NoSecondDim); + addAttribute(h5file, "topology-format", "identify-vertex"); + } else { + addAttribute(h5file, "topology-format", "geometric"); + } // Writing XDMF file if (rank == 0) { @@ -519,17 +530,21 @@ int main(int argc, char* argv[]) { << " " << basename << ":/boundary" << std::endl - << " " << std::endl - << " " << std::endl - << " " << std::endl - << "" << std::endl; + << " " << std::endl; + if (meshInput->hasIdentify()) { + xdmf << " " << std::endl + << " " << basename << ":/identify" << std::endl + << " " << std::endl; + } + xdmf << " " << std::endl << " " << std::endl << "" << std::endl; } checkH5Err(H5Fclose(h5file)); delete meshInput; - logInfo(rank) << "Finished successfully"; + logInfo() << "Finished successfully"; #ifdef USE_SCOREC PCU_Comm_Free(); diff --git a/src/third_party/GMSH2Parser.cpp b/src/third_party/GMSH2Parser.cpp index 339589a..ca6393c 100644 --- a/src/third_party/GMSH2Parser.cpp +++ b/src/third_party/GMSH2Parser.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2022 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause #include "GMSH2Parser.h" #include "GMSHLexer.h" @@ -6,136 +10,180 @@ namespace tndm { bool GMSH2Parser::parse_() { - errorMsg.clear(); - getNextToken(); - - double version = parseMeshFormat(); - if (version < 2.0 || version >= 3.0) { - char buf[128]; - sprintf(buf, "Unsupported MSH version %.1lf", version); - return logError(buf); - } - - bool hasNodes = false; - bool hasElements = false; - - while (curTok != GMSHToken::eof) { - switch (curTok) { - case GMSHToken::nodes: - hasNodes = parseNodes(); - break; - case GMSHToken::elements: - hasElements = parseElements(); - break; - default: - getNextToken(); - break; - } + errorMsg.clear(); + getNextToken(); + + double version = parseMeshFormat(); + if (version < 2.0 || version >= 3.0) { + char buf[128]; + sprintf(buf, "Unsupported MSH version %.1lf", version); + return logError(buf); + } + + bool hasNodes = false; + bool hasElements = false; + + while (curTok != GMSHToken::eof) { + switch (curTok) { + case GMSHToken::nodes: + hasNodes = parseNodes(); + break; + case GMSHToken::elements: + hasElements = parseElements(); + break; + case GMSHToken::periodic: + parsePeriodic(); + break; + default: + getNextToken(); + break; } + } - return hasNodes && hasElements; + return hasNodes && hasElements; } bool GMSH2Parser::parseNodes() { + getNextToken(); + if (curTok != GMSHToken::integer || lexer.getInteger() < 0) { + return logErrorAnnotated("Expected non-zero integer"); + } + std::size_t numVertices = lexer.getInteger(); + builder->setNumVertices(numVertices); + + for (std::size_t i = 0; i < numVertices; ++i) { getNextToken(); - if (curTok != GMSHToken::integer || lexer.getInteger() < 0) { - return logErrorAnnotated("Expected non-zero integer"); + if (curTok != GMSHToken::integer || lexer.getInteger() < 1 || + lexer.getInteger() > numVertices) { + char buf[128]; + sprintf(buf, "Expected node-tag with 1 <= node-tag <= %zu", numVertices); + return logErrorAnnotated(buf); } - std::size_t numVertices = lexer.getInteger(); - builder->setNumVertices(numVertices); - - for (std::size_t i = 0; i < numVertices; ++i) { - getNextToken(); - if (curTok != GMSHToken::integer || lexer.getInteger() < 1 || - lexer.getInteger() > numVertices) { - char buf[128]; - sprintf(buf, "Expected node-tag with 1 <= node-tag <= %zu", numVertices); - return logErrorAnnotated(buf); - } - std::size_t id = lexer.getInteger() - 1; - - std::array x; - for (std::size_t i = 0; i < 3; ++i) { - getNextToken(); - auto coord = getNumber(); - if (!coord) { - return logErrorAnnotated("Expected coordinate"); - } - x[i] = *coord; - } - builder->setVertex(id, x); + std::size_t id = lexer.getInteger() - 1; + + std::array x; + for (std::size_t i = 0; i < 3; ++i) { + getNextToken(); + auto coord = getNumber(); + if (!coord) { + return logErrorAnnotated("Expected coordinate"); + } + x[i] = *coord; } + builder->setVertex(id, x); + } + getNextToken(); + if (curTok != GMSHToken::end_nodes) { + return logErrorAnnotated("Expected $EndNodes"); + } + getNextToken(); + return true; +} + +bool GMSH2Parser::parseElements() { + getNextToken(); + if (curTok != GMSHToken::integer || lexer.getInteger() < 0) { + return logErrorAnnotated("Expected non-negative integer"); + } + const auto numElements = lexer.getInteger(); + + constexpr std::size_t MaxNodes = sizeof(NumNodes) / sizeof(std::size_t); + long tag{}; + std::array nodes; + + builder->setNumElements(numElements); + + for (std::size_t elementIdx = 0; elementIdx < numElements; ++elementIdx) { getNextToken(); - if (curTok != GMSHToken::end_nodes) { - return logErrorAnnotated("Expected $EndNodes"); + if (curTok != GMSHToken::integer) { + return logErrorAnnotated("Expected element-tag"); } + getNextToken(); - return true; -} + if (curTok != GMSHToken::integer || lexer.getInteger() < 1 || lexer.getInteger() > MaxNodes) { + char buf[128]; + sprintf(buf, "Expected element-type with 1 <= element-type <= %zu", MaxNodes); + return logErrorAnnotated(buf); + } + long type = lexer.getInteger(); -bool GMSH2Parser::parseElements() { getNextToken(); if (curTok != GMSHToken::integer || lexer.getInteger() < 0) { - return logErrorAnnotated("Expected positive integer"); + return logErrorAnnotated("Expected number of tags"); } - const auto numElements = lexer.getInteger(); - - constexpr std::size_t MaxNodes = sizeof(NumNodes) / sizeof(std::size_t); - long tag{}; - std::array nodes; - - builder->setNumElements(numElements); - - for (std::size_t elementIdx = 0; elementIdx < numElements; ++elementIdx) { - getNextToken(); - if (curTok != GMSHToken::integer) { - return logErrorAnnotated("Expected element-tag"); - } - - getNextToken(); - if (curTok != GMSHToken::integer || lexer.getInteger() < 1 || - lexer.getInteger() > MaxNodes) { - char buf[128]; - sprintf(buf, "Expected element-type with 1 <= element-type <= %zu", MaxNodes); - return logErrorAnnotated(buf); - } - long type = lexer.getInteger(); - - getNextToken(); - if (curTok != GMSHToken::integer || lexer.getInteger() < 0) { - return logErrorAnnotated("Expected number of tags"); - } - long numTags = lexer.getInteger(); - for (long tagIdx = 0; tagIdx < numTags; ++tagIdx) { - getNextToken(); - if (curTok != GMSHToken::integer) { - return logErrorAnnotated("Expected tag (integer)"); - } - if (tagIdx == 0) { - tag = lexer.getInteger(); - } - } - - for (std::size_t nodeIdx = 0; nodeIdx < NumNodes[type - 1]; ++nodeIdx) { - getNextToken(); - if (curTok != GMSHToken::integer || lexer.getInteger() < 1) { - char buf[128]; - sprintf(buf, "Expected node number > 0 (%zu/%zu for type %li)", nodeIdx + 1, - NumNodes[type - 1], type); - return logErrorAnnotated(buf); - } - nodes[nodeIdx] = lexer.getInteger() - 1; - } - - builder->addElement(type, tag, nodes.data(), NumNodes[type - 1]); + long numTags = lexer.getInteger(); + for (long tagIdx = 0; tagIdx < numTags; ++tagIdx) { + getNextToken(); + if (curTok != GMSHToken::integer) { + return logErrorAnnotated("Expected tag (integer)"); + } + if (tagIdx == 0) { + tag = lexer.getInteger(); + } } + + for (std::size_t nodeIdx = 0; nodeIdx < NumNodes[type - 1]; ++nodeIdx) { + getNextToken(); + if (curTok != GMSHToken::integer || lexer.getInteger() < 1) { + char buf[128]; + sprintf(buf, "Expected node number > 0 (%zu/%zu for type %li)", nodeIdx + 1, + NumNodes[type - 1], type); + return logErrorAnnotated(buf); + } + nodes[nodeIdx] = lexer.getInteger() - 1; + } + + builder->addElement(type, tag, nodes.data(), NumNodes[type - 1]); + } + getNextToken(); + if (curTok != GMSHToken::end_elements) { + return logErrorAnnotated("Expected $EndElements"); + } + getNextToken(); + + return true; +} + +bool GMSH2Parser::parsePeriodic() { + getNextToken(); + const auto numPeriodic = expectNonNegativeInt(); + + // ignore everything but the node identification + + for (std::size_t blockIdx = 0; blockIdx < numPeriodic; blockIdx++) { + getNextToken(); + [[maybe_unused]] const std::size_t entityDim = expectNonNegativeInt(); getNextToken(); - if (curTok != GMSHToken::end_elements) { - return logErrorAnnotated("Expected $EndElements"); + [[maybe_unused]] const std::size_t entityId = expectNonNegativeInt(); + getNextToken(); + [[maybe_unused]] const std::size_t entityIdentifyId = expectNonNegativeInt(); + + // fixed to 16; the main difference to MSH4.1 + const std::size_t affineSize = 16; + for (std::size_t i = 0; i < affineSize; ++i) { + getNextToken(); + [[maybe_unused]] const double affineValue = expectNumber(); } + getNextToken(); + const std::size_t identifySize = expectNonNegativeInt(); + + for (std::size_t i = 0; i < identifySize; ++i) { + getNextToken(); + const std::size_t nodeId = expectNonNegativeInt() - 1; + getNextToken(); + const std::size_t nodeIdentifyId = expectNonNegativeInt() - 1; + builder->addVertexLink(nodeId, nodeIdentifyId); + } + } + + getNextToken(); + if (curTok != tndm::GMSHToken::end_periodic) { + return logErrorAnnotated("Expected $EndPeriodic"); + } + getNextToken(); - return true; + return true; } } // namespace tndm diff --git a/src/third_party/GMSH2Parser.h b/src/third_party/GMSH2Parser.h index 99b8012..83e33bb 100644 --- a/src/third_party/GMSH2Parser.h +++ b/src/third_party/GMSH2Parser.h @@ -1,9 +1,13 @@ -#ifndef GMSH2PARSER_20200901_H -#define GMSH2PARSER_20200901_H +// SPDX-FileCopyrightText: 2022 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_THIRD_PARTY_GMSH2PARSER_H_ +#define PUMGEN_SRC_THIRD_PARTY_GMSH2PARSER_H_ -#include "GMSHParser.h" #include "GMSHLexer.h" #include "GMSHMeshBuilder.h" +#include "GMSHParser.h" #include #include @@ -13,15 +17,32 @@ namespace tndm { -class GMSH2Parser: public GMSHParser { -public: - using GMSHParser::GMSHParser; -private: - bool parseNodes(); - bool parseElements(); - virtual bool parse_() override; +class GMSH2Parser : public GMSHParser { + public: + using GMSHParser::GMSHParser; + + private: + unsigned long expectNonNegativeInt() { + if (curTok != tndm::GMSHToken::integer || lexer.getInteger() < 0) { + return logErrorAnnotated("Expected non-negative integer"); + } + return static_cast(lexer.getInteger()); + } + + double expectNumber() { + auto num = getNumber(); + if (!num) { + return logErrorAnnotated("Expected number"); + } + return num.value(); + } + + bool parseNodes(); + bool parseElements(); + bool parsePeriodic(); + virtual bool parse_() override; }; }; // namespace tndm -#endif // GMSH2PARSER_20200901_H +#endif // PUMGEN_SRC_THIRD_PARTY_GMSH2PARSER_H_ diff --git a/src/third_party/GMSHLexer.cpp b/src/third_party/GMSHLexer.cpp index d56fb93..dbd04f9 100644 --- a/src/third_party/GMSHLexer.cpp +++ b/src/third_party/GMSHLexer.cpp @@ -1,109 +1,118 @@ +// SPDX-FileCopyrightText: 2022 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause #include "GMSHLexer.h" #include "Hash.h" namespace tndm { void GMSHLexer::advance() { - in->get(lastChar); + in->get(lastChar); - if (lastChar == '\n' || lastChar == '\r') { - ++loc.line; - loc.col = 1; - } else { - ++loc.col; - } + if (lastChar == '\n' || lastChar == '\r') { + ++loc.line; + loc.col = 1; + } else { + ++loc.col; + } } GMSHToken GMSHLexer::getToken() { - if (in == nullptr) { - return GMSHToken::eof; - } - in->peek(); - if (!in->good()) { - return GMSHToken::eof; - } + if (in == nullptr) { + return GMSHToken::eof; + } + in->peek(); + if (!in->good()) { + return GMSHToken::eof; + } - while (isspace(lastChar) && in->good()) { - advance(); - } - if (!in->good()) { - return GMSHToken::eof; - } + while (isspace(lastChar) && in->good()) { + advance(); + } + if (!in->good()) { + return GMSHToken::eof; + } - if (lastChar == '$') { - advance(); - auto hash = fnv1a0(); - while (isalpha(lastChar)) { - hash = fnv1a_step(hash, lastChar); - advance(); - } - GMSHToken token = GMSHToken::unknown_section; - switch (hash) { - case "MeshFormat"_fnv1a: - token = GMSHToken::mesh_format; - break; - case "EndMeshFormat"_fnv1a: - token = GMSHToken::end_mesh_format; - break; - case "Entities"_fnv1a: - token = GMSHToken::entities; - break; - case "EndEntities"_fnv1a: - token = GMSHToken::end_entities; - break; - case "Nodes"_fnv1a: - token = GMSHToken::nodes; - break; - case "EndNodes"_fnv1a: - token = GMSHToken::end_nodes; - break; - case "Elements"_fnv1a: - token = GMSHToken::elements; - break; - case "EndElements"_fnv1a: - token = GMSHToken::end_elements; - break; - default: - break; - } - return token; + if (lastChar == '$') { + advance(); + auto hash = fnv1a0(); + while (isalpha(lastChar)) { + hash = fnv1a_step(hash, lastChar); + advance(); + } + GMSHToken token = GMSHToken::unknown_section; + switch (hash) { + case "MeshFormat"_fnv1a: + token = GMSHToken::mesh_format; + break; + case "EndMeshFormat"_fnv1a: + token = GMSHToken::end_mesh_format; + break; + case "Entities"_fnv1a: + token = GMSHToken::entities; + break; + case "EndEntities"_fnv1a: + token = GMSHToken::end_entities; + break; + case "Nodes"_fnv1a: + token = GMSHToken::nodes; + break; + case "EndNodes"_fnv1a: + token = GMSHToken::end_nodes; + break; + case "Elements"_fnv1a: + token = GMSHToken::elements; + break; + case "EndElements"_fnv1a: + token = GMSHToken::end_elements; + break; + case "Periodic"_fnv1a: + token = GMSHToken::periodic; + break; + case "EndPeriodic"_fnv1a: + token = GMSHToken::end_periodic; + break; + default: + break; } + return token; + } - auto mustbereal = [](char c) { return c == '.' || c == 'e' || c == 'E'; }; - auto isnumber = [&mustbereal](char c) { - return isdigit(c) || c == '+' || c == '-' || mustbereal(c); - }; + auto mustbereal = [](char c) { return c == '.' || c == 'e' || c == 'E'; }; + auto isnumber = [&mustbereal](char c) { + return isdigit(c) || c == '+' || c == '-' || mustbereal(c); + }; - if (isnumber(lastChar)) { - char buf[MaxNumberLength + 1]; - int pos = 0; - bool isreal = false; - do { - buf[pos++] = lastChar; - isreal = isreal || mustbereal(lastChar); - advance(); - } while (isnumber(lastChar) && pos < MaxNumberLength); - buf[pos] = 0; - if (pos == MaxNumberLength) { - throw std::runtime_error("Too large number encountered in GMSHLexer: " + - std::string(buf)); - } - if (isreal) { - real = std::strtod(buf, 0); - return GMSHToken::real; - } - integer = std::strtol(buf, 0, 10); - return GMSHToken::integer; + if (isnumber(lastChar)) { + char buf[MaxNumberLength + 1]; + int pos = 0; + bool isreal = false; + do { + buf[pos++] = lastChar; + isreal = isreal || mustbereal(lastChar); + advance(); + } while (isnumber(lastChar) && pos < MaxNumberLength); + buf[pos] = 0; + if (pos == MaxNumberLength) { + throw std::runtime_error("Too large number encountered in GMSHLexer: " + std::string(buf)); } - - if (lastChar == '"') { - do { - advance(); - } while (lastChar != '"'); - advance(); - return GMSHToken::string; + if (isreal) { + real = std::strtod(buf, 0); + return GMSHToken::real; } - return GMSHToken::unknown_token; + integer = std::strtol(buf, 0, 10); + return GMSHToken::integer; + } + + if (lastChar == '"') { + do { + advance(); + } while (lastChar != '"'); + advance(); + return GMSHToken::string; + } + return GMSHToken::unknown_token; } } // namespace tndm diff --git a/src/third_party/GMSHLexer.h b/src/third_party/GMSHLexer.h index 7f4e89d..2b9eb67 100644 --- a/src/third_party/GMSHLexer.h +++ b/src/third_party/GMSHLexer.h @@ -1,5 +1,9 @@ -#ifndef GMSHLEXER_20200901_H -#define GMSHLEXER_20200901_H +// SPDX-FileCopyrightText: 2022 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_THIRD_PARTY_GMSHLEXER_H_ +#define PUMGEN_SRC_THIRD_PARTY_GMSHLEXER_H_ #include #include @@ -7,52 +11,55 @@ namespace tndm { enum class GMSHToken { - eof, - integer, - real, - string, - mesh_format, - end_mesh_format, - entities, - end_entities, - nodes, - end_nodes, - elements, - end_elements, - unknown_section, - unknown_token + eof, + integer, + real, + string, + mesh_format, + end_mesh_format, + entities, + end_entities, + nodes, + end_nodes, + elements, + end_elements, + periodic, + end_periodic, + unknown_section, + unknown_token }; struct GMSHSourceLocation { - std::size_t line; - std::size_t col; + std::size_t line; + std::size_t col; }; class GMSHLexer { -private: - uint64_t identifier; - long integer; - double real; - char lastChar = ' '; - std::istream* in = nullptr; - GMSHSourceLocation loc = {1, 1}; -protected: - void advance(); -public: - static constexpr std::size_t MaxNumberLength = 128; - - void setIStream(std::istream* istream) { - in = istream; - loc = {1, 1}; - } - - GMSHToken getToken(); - uint64_t getIdentifier() const { return identifier; } - long getInteger() const { return integer; } - double getReal() const { return real; } - GMSHSourceLocation getSourceLoc() const { return loc; } + private: + uint64_t identifier; + long integer; + double real; + char lastChar = ' '; + std::istream* in = nullptr; + GMSHSourceLocation loc = {1, 1}; + protected: + void advance(); + + public: + static constexpr std::size_t MaxNumberLength = 128; + + void setIStream(std::istream* istream) { + in = istream; + loc = {1, 1}; + } + + GMSHToken getToken(); + uint64_t getIdentifier() const { return identifier; } + long getInteger() const { return integer; } + double getReal() const { return real; } + GMSHSourceLocation getSourceLoc() const { return loc; } }; } // namespace tndm -#endif // GMSHLEXER_20200901_H +#endif // PUMGEN_SRC_THIRD_PARTY_GMSHLEXER_H_ diff --git a/src/third_party/GMSHMeshBuilder.h b/src/third_party/GMSHMeshBuilder.h index 043b305..a66ac2a 100644 --- a/src/third_party/GMSHMeshBuilder.h +++ b/src/third_party/GMSHMeshBuilder.h @@ -1,5 +1,8 @@ -#ifndef GMSHMESHBUILDER_20200901_H -#define GMSHMESHBUILDER_20200901_H +// SPDX-FileCopyrightText: 2022 SeisSol Group +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_THIRD_PARTY_GMSHMESHBUILDER_H_ +#define PUMGEN_SRC_THIRD_PARTY_GMSHMESHBUILDER_H_ #include @@ -12,9 +15,10 @@ class GMSHMeshBuilder { virtual void setVertex(long id, std::array const& x) = 0; virtual void setNumElements(std::size_t numElements) = 0; virtual void addElement(long type, long tag, long* node, std::size_t numNodes) = 0; + virtual void addVertexLink(std::size_t vertex, std::size_t linkVertex) = 0; + virtual void postprocess() = 0; }; } // namespace tndm - -#endif // GMSHMESHBUILDER_20200901_H +#endif // PUMGEN_SRC_THIRD_PARTY_GMSHMESHBUILDER_H_ diff --git a/src/third_party/GMSHParser.cpp b/src/third_party/GMSHParser.cpp index e196d9a..92881ee 100644 --- a/src/third_party/GMSHParser.cpp +++ b/src/third_party/GMSHParser.cpp @@ -1,26 +1,30 @@ +// SPDX-FileCopyrightText: 2022 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause #include "GMSHParser.h" namespace tndm { double GMSHParser::parseMeshFormat() { - if (curTok != GMSHToken::mesh_format) { - return logErrorAnnotated("Expected $MeshFormat"); - } - getNextToken(); - auto version = getNumber(); - if (!version) { - return logErrorAnnotated("Expected version number"); - } - getNextToken(); - if (curTok != GMSHToken::integer || lexer.getInteger() != 0) { - return logErrorAnnotated("Expected 0"); - } - getNextToken(); // skip data-size - getNextToken(); - if (curTok != GMSHToken::end_mesh_format) { - return logErrorAnnotated("Expected $EndMeshFormat"); - } - getNextToken(); - return *version; + if (curTok != GMSHToken::mesh_format) { + return logErrorAnnotated("Expected $MeshFormat"); + } + getNextToken(); + auto version = getNumber(); + if (!version) { + return logErrorAnnotated("Expected version number"); + } + getNextToken(); + if (curTok != GMSHToken::integer || lexer.getInteger() != 0) { + return logErrorAnnotated("Expected 0"); + } + getNextToken(); // skip data-size + getNextToken(); + if (curTok != GMSHToken::end_mesh_format) { + return logErrorAnnotated("Expected $EndMeshFormat"); + } + getNextToken(); + return *version; } -} // namespace tndm \ No newline at end of file +} // namespace tndm diff --git a/src/third_party/GMSHParser.h b/src/third_party/GMSHParser.h index 99f598e..dbb7974 100644 --- a/src/third_party/GMSHParser.h +++ b/src/third_party/GMSHParser.h @@ -1,5 +1,9 @@ -#ifndef GMSHPARSER_20200901_H -#define GMSHPARSER_20200901_H +// SPDX-FileCopyrightText: 2022 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_THIRD_PARTY_GMSHPARSER_H_ +#define PUMGEN_SRC_THIRD_PARTY_GMSHPARSER_H_ #include #include @@ -200,4 +204,4 @@ class GMSHParser { }; } // namespace tndm -#endif // GMSHPARSER_20200901_H +#endif // PUMGEN_SRC_THIRD_PARTY_GMSHPARSER_H_ diff --git a/src/third_party/Hash.h b/src/third_party/Hash.h index dee0051..11c328a 100644 --- a/src/third_party/Hash.h +++ b/src/third_party/Hash.h @@ -1,5 +1,9 @@ -#ifndef HASH_20200627_H -#define HASH_20200627_H +// SPDX-FileCopyrightText: 2025 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_THIRD_PARTY_HASH_H_ +#define PUMGEN_SRC_THIRD_PARTY_HASH_H_ #include #include @@ -10,11 +14,11 @@ namespace tndm { constexpr uint64_t fnv1a0() { return 0xcbf29ce484222325; } constexpr uint64_t fnv1a_step(uint64_t hash, char c) { return (hash ^ c) * 0x00000100000001b3; } constexpr uint64_t fnv1a(char const* s, std::size_t len) { - return len > 0 ? fnv1a_step(fnv1a(s, len - 1), s[len - 1]) : fnv1a0(); + return len > 0 ? fnv1a_step(fnv1a(s, len - 1), s[len - 1]) : fnv1a0(); } uint64_t fnv1a(std::string const& s) { return fnv1a(s.data(), s.size()); } constexpr uint64_t operator""_fnv1a(char const* s, std::size_t len) { return tndm::fnv1a(s, len); } } // namespace tndm -#endif // HASH_20200627_H +#endif // PUMGEN_SRC_THIRD_PARTY_HASH_H_ diff --git a/src/third_party/LICENSE.md b/src/third_party/LICENSE similarity index 100% rename from src/third_party/LICENSE.md rename to src/third_party/LICENSE diff --git a/src/third_party/MPITraits.h b/src/third_party/MPITraits.h index 6a1f579..e5b647f 100644 --- a/src/third_party/MPITraits.h +++ b/src/third_party/MPITraits.h @@ -1,42 +1,60 @@ -#ifndef MPITRAITS_H -#define MPITRAITS_H +// SPDX-FileCopyrightText: 2025 SeisSol Group +// SPDX-FileCopyrightText: 2020 Ludwig-Maximilians-Universität München +// +// SPDX-License-Identifier: BSD-3-Clause +#ifndef PUMGEN_SRC_THIRD_PARTY_MPITRAITS_H_ +#define PUMGEN_SRC_THIRD_PARTY_MPITRAITS_H_ #include namespace tndm { -template struct mpi_type; -template inline MPI_Datatype mpi_type_t() { return mpi_type::type(); } +template struct mpi_type; +template inline MPI_Datatype mpi_type_t() { return mpi_type::type(); } // integer types -template<> struct mpi_type { static MPI_Datatype type() { return MPI_INT; } }; -template<> struct mpi_type { static MPI_Datatype type() { return MPI_LONG; } }; -template<> struct mpi_type { static MPI_Datatype type() { return MPI_LONG_LONG; } }; -template<> struct mpi_type { static MPI_Datatype type() { return MPI_UNSIGNED; } }; -template<> struct mpi_type { static MPI_Datatype type() { return MPI_UNSIGNED_LONG; } }; -template<> struct mpi_type { static MPI_Datatype type() { return MPI_UNSIGNED_LONG_LONG; } }; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_INT; } +}; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_LONG; } +}; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_LONG_LONG; } +}; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_UNSIGNED; } +}; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_UNSIGNED_LONG; } +}; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_UNSIGNED_LONG_LONG; } +}; // floating point types -template<> struct mpi_type { static MPI_Datatype type() { return MPI_FLOAT; } }; -template<> struct mpi_type { static MPI_Datatype type() { return MPI_DOUBLE; } }; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_FLOAT; } +}; +template <> struct mpi_type { + static MPI_Datatype type() { return MPI_DOUBLE; } +}; + +template class mpi_array_type { + public: + mpi_array_type(int count) { + MPI_Type_contiguous(count, mpi_type_t(), &type); + MPI_Type_commit(&type); + } -template -class mpi_array_type { -public: - mpi_array_type(int count) { - MPI_Type_contiguous(count, mpi_type_t(), &type); - MPI_Type_commit(&type); - } + ~mpi_array_type() { MPI_Type_free(&type); } - ~mpi_array_type() { - MPI_Type_free(&type); - } + MPI_Datatype const& get() const { return type; } - MPI_Datatype const& get() const { return type; } -private: - MPI_Datatype type; + private: + MPI_Datatype type; }; } // namespace tndm -#endif // MPITRAITS_H +#endif // PUMGEN_SRC_THIRD_PARTY_MPITRAITS_H_ diff --git a/src/third_party/README.md b/src/third_party/README.md index 3db1044..55b51fd 100644 --- a/src/third_party/README.md +++ b/src/third_party/README.md @@ -1,3 +1,9 @@ + + # Third party sources Taken from ; diff --git a/submodules/run-clang-format b/submodules/run-clang-format deleted file mode 160000 index 39081c9..0000000 --- a/submodules/run-clang-format +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 39081c9c42768ab5e8321127a7494ad1647c6a2f diff --git a/submodules/utils b/submodules/utils index 3f1f476..d83d3bc 160000 --- a/submodules/utils +++ b/submodules/utils @@ -1 +1 @@ -Subproject commit 3f1f476d42621dac848a952b50956b6e48f7c92b +Subproject commit d83d3bc1f8f1c71291af81b1b94623abbeb690ce