diff --git a/.github/workflows/build_variant.yml b/.github/workflows/build_variant.yml index ca7e16224f..c43c349f26 100644 --- a/.github/workflows/build_variant.yml +++ b/.github/workflows/build_variant.yml @@ -28,7 +28,7 @@ jobs: - name: Install System dependencies shell: bash -l {0} - run: sudo apt update && sudo apt install -y libaec-dev zlib1g-dev automake autoconf libcurl4-openssl-dev libjpeg-dev wget curl bzip2 m4 flex bison cmake libzip-dev openmpi-bin libopenmpi-dev + run: sudo apt update && sudo apt install -y libaec-dev zlib1g-dev automake autoconf libcurl4-openssl-dev libjpeg-dev wget curl bzip2 m4 flex bison cmake libzip-dev openmpi-bin libopenmpi-dev libboost-all-dev ### # Installing TPL @@ -70,6 +70,8 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -84,6 +86,8 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -98,6 +102,8 @@ jobs: fortran: "NO", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -112,6 +118,8 @@ jobs: fortran: "NO", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -126,6 +134,8 @@ jobs: fortran: "NO", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -140,6 +150,8 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -154,6 +166,8 @@ jobs: fortran: "NO", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -168,6 +182,8 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "YES", extra: "", @@ -182,6 +198,8 @@ jobs: fortran: "NO", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "APPLICATIONS=NO LEGACY=NO", @@ -196,6 +214,8 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "YES", gtest: "YES", extra: "", @@ -210,6 +230,8 @@ jobs: fortran: "YES", use_kokkos: "YES", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "", @@ -224,6 +246,8 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "NO", extra: "OMIT_DEPRECATED=YES", @@ -238,18 +262,52 @@ jobs: fortran: "YES", use_kokkos: "NO", use_adios2: "NO", + use_faodel: "NO", + use_metis: "NO", use_catalyst2: "NO", gtest: "YES", extra: "MODERN=YES", sanitizer: "NO" # address, integer, thread, memory, undefined } + - { + name: "ADIOS2 enabled", + os: ubuntu-latest, + compiler: "mpi", + debug: "NO", + threadsafe: "NO", + fortran: "YES", + use_kokkos: "NO", + use_adios2: "YES", + use_faodel: "NO", + use_metis: "NO", + use_catalyst2: "NO", + gtest: "YES", + extra: "", + sanitizer: "NO" # address, integer, thread, memory, undefined + } + - { + name: "FAODEL and METIS enabled", + os: ubuntu-latest, + compiler: "mpi", + debug: "NO", + threadsafe: "NO", + fortran: "YES", + use_kokkos: "NO", + use_adios2: "NO", + use_faodel: "YES", + use_metis: "YES", + use_catalyst2: "NO", + gtest: "YES", + extra: "", + sanitizer: "NO" # address, integer, thread, memory, undefined + } steps: - uses: actions/checkout@v3 - name: Install System dependencies shell: bash -l {0} - run: sudo apt update && sudo apt install -y libaec-dev zlib1g-dev automake autoconf libcurl4-openssl-dev libjpeg-dev wget curl bzip2 m4 flex bison cmake libzip-dev openmpi-bin libopenmpi-dev + run: sudo apt update && sudo apt install -y libaec-dev zlib1g-dev automake autoconf libcurl4-openssl-dev libjpeg-dev wget curl bzip2 m4 flex bison cmake libzip-dev openmpi-bin libopenmpi-dev libboost-all-dev - name: Fetch TPL Cache id: cache-TPL @@ -263,10 +321,10 @@ jobs: run: ls ${HOME} && ls ${HOME}/environments && ls ${HOME}/environments/${{ matrix.config.compiler }}-${{ matrix.hdf5 }}-${{ matrix.netcdf }}-${{ matrix.cgns }} && ls ${HOME}/environments/${{ matrix.config.compiler }}-${{ matrix.hdf5 }}-${{ matrix.netcdf }}-${{ matrix.cgns }}/lib - name: install additional TPL - if: ${{ matrix.config.use_kokkos == 'YES' || matrix.config.use_adios2 == 'YES' || matrix.config.gtest == 'YES' || matrix.config.use_catalyst == 'YES' }} + if: ${{ matrix.config.use_kokkos == 'YES' || matrix.config.use_adios2 == 'YES' || matrix.config.gtest == 'YES' || matrix.config.use_faodel == 'YES' || matrix.config.use_catalyst == 'YES' || matrix.config.use_metis == 'YES' }} run: | set -x - COMPILER=${{ matrix.config.compiler }} KOKKOS=${{ matrix.config.use_kokkos }} ADIOS2=${{ matrix.config.use_adios2 }} CATALYST2=${{ matrix.config.use_catalyst2 }} GNU_PARALLEL=OFF GTEST=${{ matrix.config.gtest }} INSTALL_PATH=${HOME}/environments/${{ matrix.config.compiler }}-${{ matrix.hdf5 }}-${{ matrix.netcdf }}-${{ matrix.cgns }} ./install-tpl.sh + COMPILER=${{ matrix.config.compiler }} KOKKOS=${{ matrix.config.use_kokkos }} ADIOS2=${{ matrix.config.use_adios2 }} CATALYST2=${{ matrix.config.use_catalyst2 }} FAODEL=${{ matrix.config.use_faodel }} METIS=${{ matrix.config.use_metis }} GNU_PARALLEL=OFF GTEST=${{ matrix.config.gtest }} INSTALL_PATH=${HOME}/environments/${{ matrix.config.compiler }}-${{ matrix.hdf5 }}-${{ matrix.netcdf }}-${{ matrix.cgns }} ./install-tpl.sh ls ${HOME} && ls ${HOME}/environments && ls ${HOME}/environments/${{ matrix.config.compiler }}-${{ matrix.hdf5 }}-${{ matrix.netcdf }}-${{ matrix.cgns }} && ls ${HOME}/environments/${{ matrix.config.compiler }}-${{ matrix.hdf5 }}-${{ matrix.netcdf }}-${{ matrix.cgns }}/lib ### diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index caa749be21..a0cdd53074 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -3,18 +3,25 @@ on: pull_request_target: types: [opened,closed,synchronize] +# explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings +permissions: + actions: write + contents: write + pull-requests: write + statuses: write + jobs: - CLAssistant: + CLAAssistant: runs-on: ubuntu-latest steps: - name: "CLA Assistant" if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' - # Beta Release - uses: cla-assistant/github-action@v2.1.3-beta + uses: contributor-assistant/github-action@v2.3.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # the below token should have repo scope and must be manually added by you in the repository's secret - PERSONAL_ACCESS_TOKEN : ${{ secrets.PERSONAL_ACCESS_TOKEN }} + # This token is required only if you have configured to store the signatures in a remote repository/organization + PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} with: path-to-signatures: 'signatures/version1/cla.json' path-to-document: 'https://github.com/sandialabs/seacas/blob/master/SEACAS-CLA.md' @@ -22,14 +29,13 @@ jobs: branch: 'master' allowlist: user1,bot*,*@sandia.gov - #below are the optional inputs - If the optional inputs are not given, then default values will be taken + # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken #remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository) - #remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) + #remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository) #create-file-commit-message: 'For example: Creating file for storing CLA Signatures' - #signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo' + #signed-commit-message: 'For example: $contributorName has signed the CLA in $owner/$repo#$pullRequestNo' #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign' #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA' #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.' #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true) #use-dco-flag: true - If you are using DCO instead of CLA - diff --git a/.github/workflows/intel-build.yml b/.github/workflows/intel-build.yml index 28790814f9..669c25f897 100644 --- a/.github/workflows/intel-build.yml +++ b/.github/workflows/intel-build.yml @@ -35,13 +35,12 @@ jobs: sudo apt-get update - name: install run: | + sudo apt-get install -y intel-basekit sudo apt-get install -y intel-oneapi-common-vars sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic sudo apt-get install -y intel-oneapi-compiler-fortran sudo apt-get install -y intel-oneapi-mpi sudo apt-get install -y intel-oneapi-mpi-devel - sudo apt-get install -y intel-oneapi-mkl - sudo apt-get install -y ninja-build - name: Install System dependencies shell: bash -l {0} @@ -90,13 +89,12 @@ jobs: sudo apt-get update - name: install run: | + sudo apt-get install -y intel-basekit sudo apt-get install -y intel-oneapi-common-vars sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic sudo apt-get install -y intel-oneapi-compiler-fortran sudo apt-get install -y intel-oneapi-mpi sudo apt-get install -y intel-oneapi-mpi-devel - sudo apt-get install -y intel-oneapi-mkl - sudo apt-get install -y ninja-build - name: Install System dependencies shell: bash -l {0} diff --git a/README.md b/README.md index af95904b01..b72db76dcc 100644 --- a/README.md +++ b/README.md @@ -327,4 +327,4 @@ a separate license: | [pdqsort](https://github.com/orlp/pdqsort) | `packages/seacas/libraries/ioss/src` | [Zlib License](https://github.com/orlp/pdqsort/blob/master/license.txt) | ## Contact information - Greg Sjaardema (, ) + Greg Sjaardema (, ) \ No newline at end of file diff --git a/TPL/adios2/runcmake.sh b/TPL/adios2/runcmake.sh index fb0e1e4fbe..1ab409a53d 100755 --- a/TPL/adios2/runcmake.sh +++ b/TPL/adios2/runcmake.sh @@ -28,11 +28,10 @@ ${RPATH} \ -D CMAKE_INSTALL_PREFIX:PATH=${INSTALL_PATH} \ -D CMAKE_INSTALL_LIBDIR:PATH=lib \ -D ADIOS2_USE_MPI:BOOL=${MPI} \ +-D ADIOS2_HAVE_MPI:BOOL=${MPI} \ -D ADIOS2_BUILD_EXAMPLES:BOOL=OFF \ --D ADIOS2_BUILD_TESTING:BOOL=OFF \ -D INSTALL_GTEST:BOOL=OFF \ -D ADIOS2_USE_Fortran:BOOL=OFF \ --D ADIOS_USE_Profiling=OFF \ $EXTRA_ARGS \ .. diff --git a/TPL/boost/keep-me-around b/TPL/boost/keep-me-around new file mode 100644 index 0000000000..e69de29bb2 diff --git a/TPL/faodel/runcmake.sh b/TPL/faodel/runcmake.sh index 428e383a23..47c73b8413 100644 --- a/TPL/faodel/runcmake.sh +++ b/TPL/faodel/runcmake.sh @@ -6,14 +6,11 @@ if [ "X$ACCESS" == "X" ] ; then echo "ACCESS set to ${ACCESS}" fi INSTALL_PATH=${INSTALL_PATH:-${ACCESS}} - . ${ACCESS}/TPL/compiler.sh if [ "X$BOOST_ROOT" == "X" ] ; then - BOOST_ROOT=$(cd ../../../..; pwd) echo "Faodel requires these Boost packages: atomic log log_setup serialization" echo "Please set BOOST_ROOT." - exit 0 fi rm -f CMakeCache.txt @@ -27,7 +24,7 @@ cmake .. \ -DCMAKE_INSTALL_PREFIX=${INSTALL_PATH} \ -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ -DGTEST_ROOT=${GTEST_ROOT} \ -DBOOST_ROOT=${BOOST_ROOT} \ -DFaodel_NETWORK_LIBRARY=nnti \ diff --git a/TPL/netcdf/runcmake.sh b/TPL/netcdf/runcmake.sh index 00c9256b1b..7ab3326a29 100755 --- a/TPL/netcdf/runcmake.sh +++ b/TPL/netcdf/runcmake.sh @@ -67,6 +67,8 @@ cmake .. -DCMAKE_C_COMPILER:FILEPATH=${CC} \ -DENABLE_MMAP:BOOL=ON \ -DENABLE_DAP:BOOL=OFF \ -DENABLE_V2_API:BOOL=OFF \ + -DENABLE_FILTER_TESTING:BOOL=OFF \ + -DENABLE_TESTS:BOOL=OFF \ ${LOCAL_ZLIB} \ ${LOCAL_SZIP} \ ${EXTRA_DEPS} \ diff --git a/cmake-config b/cmake-config index ae04d09510..6181884365 100755 --- a/cmake-config +++ b/cmake-config @@ -160,8 +160,8 @@ then if [ "$COMPILER" == "intel" ] then - CXX=icpx - CC=icx + CXX=icpc + CC=icc FC=ifort CFLAGS="-Wall -Wunused" CXXFLAGS="-Wall -Wextra -Wunused" @@ -382,6 +382,9 @@ then LD_EXT="so" fi else +# NOTE: Some systems may need `curl` added to Seacas_EXTRA_LINK_FLAGS` +# If you see missing symbols containing `_curl`, try adding `curl` +# EXTRA_LIB="-DSeacas_EXTRA_LINK_FLAGS=curl;z;dl -DSEACASExodus_ENABLE_SHARED:BOOL=OFF" EXTRA_LIB="-DSeacas_EXTRA_LINK_FLAGS=z;dl -DSEACASExodus_ENABLE_SHARED:BOOL=OFF" LD_EXT="a" fi diff --git a/cmake/tribits/CHANGELOG.md b/cmake/tribits/CHANGELOG.md index 5a982fcfff..b3f1edd1ef 100644 --- a/cmake/tribits/CHANGELOG.md +++ b/cmake/tribits/CHANGELOG.md @@ -2,6 +2,43 @@ ChangeLog for TriBITS ---------------------------------------- +## 2023-06-22: + +* **Added:** Packages are now determined to be missing if their dependencies + file `/cmake/Dependencies.cmake` is missing. If the package + directory `` exists but the dependencies file is missing, the + package is determined to be missing but a warning is printed. (This expands + behavior to gracefully deal with a situation where a package source + directory is only partially removed, such as with `git rm -r `, + but the base directory still exists. Therefore, this allows the project to + gracefully configure with the package being considered missing and avoids a + fatal error in this case.) + +## 2023-06-02: + +* **Added/Deprecated:** External packages/TPLs can now be (and should be) + listed in the `[TEST|LIB]_[REQUIRED|OPTIONAL]_PACKAGES` arguments/lists in + the macro `tribits_package_define_dependencies()` and the + `[TEST|LIB]_[REQUIRED|OPTIONAL]_TPLS` arguments/lists are deprecated (but + with no deprecation warning yet). This makes it easier to write + `/cmake/Dependencies.cmake` files for packages where the set of + internal and external upstream dependent packages is dynamic and changes + depending on the TriBITS project where these package are configured under. + (And conceptually, a downstream package should not care if an upstream + dependent package is pulled in as an external package or built as an + internal package.) + +## 2023-05-03: + +* **Added:** Added support for non-fully TriBITS-compatible external packages. + Now, a `Config.cmake` file need not define + `::all_libs` targets for all of its upstream dependencies. The + updated macro `tribits_process_enabled_tpls()` will find any missing + upstream external packages/TPLs as needed (see updated documentation in the + section "TriBITS-Compliant External Packages" in the "TriBITS Users Guide" + and the section "Processing of external packages/TPLs and TriBITS-compliant + external packages" in the "TriBITS Maintainers Guide"). + ## 2023-02-24: * **Changed:** Upgraded minimum required CMake version from 3.17 to 3.23. diff --git a/cmake/tribits/README.DIRECTORY_CONTENTS.rst b/cmake/tribits/README.DIRECTORY_CONTENTS.rst index 80067d5a83..a0f3d8ab74 100644 --- a/cmake/tribits/README.DIRECTORY_CONTENTS.rst +++ b/cmake/tribits/README.DIRECTORY_CONTENTS.rst @@ -22,9 +22,10 @@ TriBITS refactorings of TriBITS. .. _TriBITS Core: -**core/**: Core TriBITS package-based architecture for CMake projects. This -only depends on raw CMake and contains just the minimal support for building, -testing, installing, and deployment. Only depends on CMake and nothing else. +**core/**: Core TriBITS test support and package-based architecture for CMake +projects. This only depends on raw CMake and contains just the minimal support +for building, testing, installing, and deployment. This CMake code depends +only on CMake and nothing else. **python_utils/**: Some basic Python utilities that are not specific to TriBITS but are used in TriBITS CI and testing support software. There are @@ -86,3 +87,49 @@ subdirectory. It supports the argument ``--components`` with values ``core``, * ``examples`` => (external tribits installation) * ``doc`` => ``core``, ``ci_support``, ``examples`` * ``devtools_install`` => ``python_utils`` + + +TriBITS Core Directory Contents +............................... + +The TriBITS ``core/`` directory is broken down into several subdirectories of +its own: + +**core/utils**: General CMake utilities that are not specific to the TriBITS +system and can be reused in any CMake project. + +**core/common**: As small set of common modules that the different TriBITS +Core module files in different directories depend on. These include things +like common TriBITS constants and TriBITS CMake policies. + +**core/test_support**: Modules that help define CTest tests using functions +like `tribits_add_test()`_ and `tribits_add_advanced_test()`_. These can be +used in CMake projects that are not full-blown TriBITS projects. + +**core/config_tests**: Some basic configure-time tests used by the TriBITS +package architecture framework. + +**core/std_tpls**: Some ``Find.cmake`` files for key external +dependencies handled as TriBITS TPLs but are more central to the TriBITS +system. (Examples include CUDA and MPI support.) + +**core/installation**: A collection of ``*.cmake.in`` and related Cmake code +supporting installations. + +**core/package_arch**: Modules for the full-blown TriBITS package architecture +framework including package dependency management, multi-repository support, +installations (including the generation of ``Config.cmake`` files), +etc. + +The dependencies between these different TriBITS `core` subdirectories are: + +* ``core/utils`` => (external CMake) +* ``core/common`` => ``core/utils`` +* ``core/test_support`` => ``core/utils``, ``core/common`` +* ``core/config_tests`` => (external CMake) +* ``core/std_tpls`` => (external CMake) +* ``core/installation`` <=> ``core/package_arch`` (bidirectional) +* ``core/package_arch`` => ``core/utils``, ``core/common``, + ``core/test_support``, ``core/config_tests``, ``core/std_tpls``, + ``core/installation`` + diff --git a/cmake/tribits/ci_support/CDashQueryAnalyzeReport.py b/cmake/tribits/ci_support/CDashQueryAnalyzeReport.py index 157866a1b8..dc20a2f54e 100644 --- a/cmake/tribits/ci_support/CDashQueryAnalyzeReport.py +++ b/cmake/tribits/ci_support/CDashQueryAnalyzeReport.py @@ -40,9 +40,11 @@ try: # Python 2 from urllib2 import urlopen + from urllib2 import quote as urlquote except ImportError: # Python 3 from urllib.request import urlopen + from urllib.parse import quote as urlquote import sys import hashlib @@ -716,41 +718,45 @@ def getAndCacheCDashQueryDataOrReadFromCache( return cdashQueryData +def normalizeUrlStrings(*args): + return [urlquote(x) for x in args] + + # Construct full cdash/api/v1/index.php query URL to pull data down given the # pieces def getCDashIndexQueryUrl(cdashUrl, projectName, date, filterFields): + # for legacy reasons, this function assumes we normalized projectName + projectName, = normalizeUrlStrings(projectName,) if date: dateArg = "&date="+date else: dateArg = "" return cdashUrl+"/api/v1/index.php?project="+projectName+dateArg \ - + "&"+filterFields + + "&"+filterFields # Construct full cdash/index.php browser URL given the pieces def getCDashIndexBrowserUrl(cdashUrl, projectName, date, filterFields): + # for legacy reasons, this function assumes we normalized projectName + projectName, = normalizeUrlStrings(projectName,) if date: dateArg = "&date="+date else: dateArg = "" return cdashUrl+"/index.php?project="+projectName+dateArg \ - + "&"+filterFields + + "&"+filterFields # Construct full cdash/api/v1/queryTests.php query URL given the pieces def getCDashQueryTestsQueryUrl(cdashUrl, projectName, date, filterFields): + # for legacy reasons, this function assumes we normalized projectName + projectName, = normalizeUrlStrings(projectName,) if date: dateArg = "&date="+date else: dateArg = "" cdashTestUrl = cdashUrl+"/api/v1/queryTests.php?project="+projectName+dateArg+"&"+filterFields - return replaceNonUrlCharsInUrl(cdashTestUrl) - - -# Replace non-URL chars and return new URL string -def replaceNonUrlCharsInUrl(url): - urlNew = url - urlNew = urlNew.replace(' ', '%20') - # ToDo: Replace other chars as needed - return urlNew + return cdashTestUrl # Construct full cdash/queryTests.php browser URL given the pieces def getCDashQueryTestsBrowserUrl(cdashUrl, projectName, date, filterFields): + # for legacy reasons, this function assumes we normalized projectName + projectName, = normalizeUrlStrings(projectName,) if date: dateArg = "&date="+date else: dateArg = "" return cdashUrl+"/queryTests.php?project="+projectName+dateArg+"&"+filterFields @@ -1701,29 +1707,33 @@ def __call__(self, testDict): dateRangeEndDateStr = self.__date beginEndUrlFields = "begin="+dateRangeBeginDateStr+"&end="+dateRangeEndDateStr + # normalize names for query + projectName_url, buildName_url, testname_url, site_url = normalizeUrlStrings( + projectName, buildName, testname, site) + # Define queryTests.php query filters for test history testHistoryQueryFilters = \ beginEndUrlFields+"&"+\ "filtercombine=and&filtercombine=&filtercount=3&showfilters=1&filtercombine=and"+\ - "&field1=buildname&compare1=61&value1="+buildName+\ - "&field2=testname&compare2=61&value2="+testname+\ - "&field3=site&compare3=61&value3="+site + "&field1=buildname&compare1=61&value1="+buildName_url+\ + "&field2=testname&compare2=61&value2="+testname_url+\ + "&field3=site&compare3=61&value3="+site_url # URL used to get the history of the test in JSON form testHistoryQueryUrl = \ - getCDashQueryTestsQueryUrl(cdashUrl, projectName, None, testHistoryQueryFilters) + getCDashQueryTestsQueryUrl(cdashUrl, projectName_url, None, testHistoryQueryFilters) # URL to embed in email to show the history of the test to humans testHistoryBrowserUrl = \ - getCDashQueryTestsBrowserUrl(cdashUrl, projectName, None, testHistoryQueryFilters) + getCDashQueryTestsBrowserUrl(cdashUrl, projectName_url, None, testHistoryQueryFilters) # URL for to the build summary on index.php page buildHistoryEmailUrl = getCDashIndexBrowserUrl( - cdashUrl, projectName, None, + cdashUrl, projectName_url, None, beginEndUrlFields+"&"+\ "filtercombine=and&filtercombine=&filtercount=2&showfilters=1&filtercombine=and"+\ - "&field1=buildname&compare1=61&value1="+buildName+\ - "&field2=site&compare2=61&value2="+site + "&field1=buildname&compare1=61&value1="+buildName_url+\ + "&field2=site&compare2=61&value2="+site_url ) # ToDo: Replace this with the the URL to just this one build the index.php # page. To do that, get the build stamp from the list of builds on CDash diff --git a/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake b/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake index f55d03364c..2d13260c0b 100644 --- a/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake +++ b/cmake/tribits/ci_support/TribitsDumpDepsXmlScript.cmake @@ -100,16 +100,16 @@ endif() get_filename_component( ${PROJECT_NAME}_TRIBITS_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE ) message("-- Setting ${PROJECT_NAME}_TRIBITS_DIR=${${PROJECT_NAME}_TRIBITS_DIR}") +include("${CMAKE_CURRENT_LIST_DIR}/../core/common/TribitsConstants.cmake") +tribits_asesrt_minimum_cmake_version() +include("${CMAKE_CURRENT_LIST_DIR}/../core/common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) + set( CMAKE_MODULE_PATH "${${PROJECT_NAME}_TRIBITS_DIR}/core/utils" "${${PROJECT_NAME}_TRIBITS_DIR}/core/package_arch" "${${PROJECT_NAME}_TRIBITS_DIR}/ci_support" ) -include(TribitsConstants) -tribits_asesrt_minimum_cmake_version() -include(TribitsCMakePolicies NO_POLICY_SCOPE) - include(TribitsGlobalMacros) include(TribitsPrintDependencyInfo) include(TribitsWriteXmlDependenciesFiles) diff --git a/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake b/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake index d0afd980bd..36853a8d98 100644 --- a/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake +++ b/cmake/tribits/ci_support/TribitsGetExtraReposForCheckinTest.cmake @@ -82,11 +82,12 @@ set(${PROJECT_NAME}_CHECK_EXTRAREPOS_EXIST ${CHECK_EXTRAREPOS_EXIST}) # B) Include files from TriBITS # +include("${CMAKE_CURRENT_LIST_DIR}/../core/common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) + set( CMAKE_MODULE_PATH "${${PROJECT_NAME}_TRIBITS_DIR}/core/utils" "${${PROJECT_NAME}_TRIBITS_DIR}/core/package_arch" ) -include(TribitsCMakePolicies NO_POLICY_SCOPE) include(Split) include(AppendStringVar) include(SetDefaultAndFromEnv) # Used in ExtraRepositoriesList.cmake file? diff --git a/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake b/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake index 2360acf162..0173750f19 100644 --- a/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake +++ b/cmake/tribits/ci_support/TribitsWriteXmlDependenciesFiles.cmake @@ -45,6 +45,9 @@ ################################################################################ +include(TribitsConfigureTiming) + + # @MACRO: tribits_write_xml_dependency_files() # # Usage:: diff --git a/cmake/tribits/ci_support/cdash_analyze_and_report.py b/cmake/tribits/ci_support/cdash_analyze_and_report.py index 6556b97615..201502a9ec 100755 --- a/cmake/tribits/ci_support/cdash_analyze_and_report.py +++ b/cmake/tribits/ci_support/cdash_analyze_and_report.py @@ -542,6 +542,10 @@ def getTestHistory(self, testLOD): # D.2.a) Get list of dicts of builds off cdash/index.phpp # + # @arghdos: note, we do not have to normalize the URLs from the input + # options because they are currently taken from the cdash site already + # (i.e., they are already in normalized form). + cdashIndexBuildsBrowserUrl = CDQAR.getCDashIndexBrowserUrl( inOptions.cdashSiteUrl, inOptions.cdashProjectName, inOptions.date, inOptions.cdashBuildsFilters) diff --git a/cmake/tribits/common_tpls/utils/ParseLibraryList.cmake b/cmake/tribits/common_tpls/utils/ParseLibraryList.cmake index 3f1423b312..74affbecc9 100644 --- a/cmake/tribits/common_tpls/utils/ParseLibraryList.cmake +++ b/cmake/tribits/common_tpls/utils/ParseLibraryList.cmake @@ -100,7 +100,7 @@ function(parse_library_list) endforeach() - # Now set output vairables + # Now set output variables set(${PARSE_ARGS_DEBUG} "${_debug_libs}" PARENT_SCOPE) set(${PARSE_ARGS_OPT} "${_opt_libs}" PARENT_SCOPE) set(${PARSE_ARGS_GENERAL} "${_gen_libs}" PARENT_SCOPE) diff --git a/cmake/tribits/core/package_arch/TribitsCMakePolicies.cmake b/cmake/tribits/core/common/TribitsCMakePolicies.cmake similarity index 100% rename from cmake/tribits/core/package_arch/TribitsCMakePolicies.cmake rename to cmake/tribits/core/common/TribitsCMakePolicies.cmake diff --git a/cmake/tribits/core/package_arch/TribitsConstants.cmake b/cmake/tribits/core/common/TribitsConstants.cmake similarity index 100% rename from cmake/tribits/core/package_arch/TribitsConstants.cmake rename to cmake/tribits/core/common/TribitsConstants.cmake diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake index ec989628f8..567d22f4c2 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutable.cmake @@ -38,9 +38,9 @@ # @HEADER -include(TribitsAddExecutableTestHelpers) +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsAddExecutableTestHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsAddTestHelpers.cmake") include(TribitsCommonArgsHelpers) -include(TribitsAddTestHelpers) include(TribitsGeneralMacros) include(TribitsLibIsTestOnly) include(TribitsReportInvalidTribitsUsage) diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake b/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake index 73148b8a8a..7328f18558 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddExecutableAndTest.cmake @@ -38,8 +38,9 @@ # @HEADER +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsAddTest.cmake") + include(TribitsAddExecutable) -include(TribitsAddTest) include(TribitsDeprecatedHelpers) diff --git a/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake b/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake index 30036149db..0e249f4f9c 100644 --- a/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake +++ b/cmake/tribits/core/package_arch/TribitsAddLibrary.cmake @@ -271,7 +271,7 @@ include(TribitsSetAndIncDirs) # ``${CMAKE_INSTALL_PREFIX}/lib/`` (actual install directory is given by # ``${PROJECT}_INSTALL_LIB_DIR``, see `Setting the install prefix`_). # However, this install target will not get created if -# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE`` and +# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FALSE`` and # ``BUILD_SHARD_LIBS=OFF``. But when ``BUILD_SHARD_LIBS=ON``, the install # target will get added. Also, this install target will *not* get added if # ``TESTONLY`` or ``NO_INSTALL_LIB_OR_HEADERS`` are passed in. @@ -280,7 +280,7 @@ include(TribitsSetAndIncDirs) # added using ``install(FILES

...)``, but only if ``TESTONLY`` and # ``NO_INSTALL_LIB_OR_HEADERS`` are not passed in as well. Also, the install # target for the headers will not get added if -# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE``. If this +# `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FALSE``. If this # install target is added, then the headers get installed into the flat # directory ``${${PROJECT_NAME}_INSTALL_INCLUDE_DIR}/`` (default is # ``${CMAKE_INSTALL_PREFIX}/include/``, see `Setting the install prefix`_). diff --git a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake index cc6da7aba6..814533ea35 100644 --- a/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake +++ b/cmake/tribits/core/package_arch/TribitsAdjustPackageEnables.cmake @@ -853,7 +853,7 @@ macro(tribits_set_package_and_related_upstream_packages_to_external packageName tribits_set_upstream_dep_packages_as_external(${packageName} ${subpackageTriggeredParentPackageExternal}) - tribits_set_package_as_processed_by_downstream_tribits_external_package(${packageName}) + tribits_mark_package_as_upstream_of_tribits_compliant_external_package(${packageName}) endmacro() # NOTE: In the above macro, if ${packageName} is made EXTERNAL because it one @@ -1317,10 +1317,16 @@ macro(tribits_set_upstream_dep_packages_as_external packageName endmacro() -# Mark a package as being processed by a downstream TriBITS-compliant external -# package +# Mark a package as being upstream of a TriBITS-compliant external package +# (and therefore should be processed by a downstream TriBITS-complaint +# package) +# +# NOTE: These packages are initially marked by setting +# ``${packageName}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=TRUE``. +# If this packages are not actually defined by a downstream TriBITS-compliant +# external package, then this variable will be set to ``FALSE`` later. # -macro(tribits_set_package_as_processed_by_downstream_tribits_external_package packageName) +macro(tribits_mark_package_as_upstream_of_tribits_compliant_external_package packageName) set_default(${packageName}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE FALSE) @@ -1344,10 +1350,10 @@ macro(tribits_set_package_as_processed_by_downstream_tribits_external_package p endif() if (packageEnable AND (NOT ${packageName}_IS_TRIBITS_COMPLIANT)) message("-- " - "NOTE: ${packageName} is ${directOrIndirectStr} downstream from a" + "NOTE: ${packageName} is ${directOrIndirectStr} upstream from a" " TriBITS-compliant external package${downstreamPkgStr}") endif() - set(${packageName}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE TRUE) + set(${packageName}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE TRUE) break() endif() @@ -1358,6 +1364,7 @@ macro(tribits_set_package_as_processed_by_downstream_tribits_external_package p endmacro() + # Macro that sets ``_ENABLE_=ON`` if not already # enabled for all enabled subpackages of a parent package. # @@ -1424,13 +1431,6 @@ macro(tribits_set_internal_package_to_external depPkgName) endmacro() -macro(tribits_set_as_processed_by_downstream_tribits_external_package packageName - depPkgName - ) - -endmacro() - - # Function to return if is to be treated as an EXTERNAL package # in processing of the package # diff --git a/cmake/tribits/core/package_arch/TribitsConfigureTiming.cmake b/cmake/tribits/core/package_arch/TribitsConfigureTiming.cmake new file mode 100644 index 0000000000..00db385c17 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsConfigureTiming.cmake @@ -0,0 +1,97 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# 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 Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE +# 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. +# +# ************************************************************************ +# @HEADER + + +include(TimingUtils) + + +# Optionally start CMake code configure timing +# +function(tribits_config_code_start_timer START_TIMER_SECONDS_VAR_OUT) + if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING) + timer_get_raw_seconds(START_TIMER_SECONDS) + set(${START_TIMER_SECONDS_VAR_OUT} ${START_TIMER_SECONDS} PARENT_SCOPE) + endif() +endfunction() + + +# Optionally stop CMake code configure timing +# +function(tribits_config_code_stop_timer START_TIMER_SECONDS_VAR_IN + TIMER_STR + ) + if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING) + timer_get_raw_seconds(TIMER_STOP_SECONDS) + timer_print_rel_time(${${START_TIMER_SECONDS_VAR_IN}} + ${TIMER_STOP_SECONDS} + "${TIMER_STR}") + endif() +endfunction() + + +# Optionally start CMake code **package** configure timing +# +function(tribits_package_config_code_start_timer START_TIMER_SECONDS_VAR_OUT) + if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING + AND + ( ${PROJECT_NAME}_ENABLE_PACKAGE_CONFIGURE_TIMING + OR ${TRIBITS_PACKAGE}_PACKAGE_CONFIGURE_TIMING ) + ) + timer_get_raw_seconds(START_TIMER_SECONDS) + set(${START_TIMER_SECONDS_VAR_OUT} ${START_TIMER_SECONDS} PARENT_SCOPE) + endif() +endfunction() + + +# Optionally stop CMake code **package** configure timing +# +function(tribits_package_config_code_stop_timer START_TIMER_SECONDS_VAR_IN + TIMER_STR + ) + if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING + AND + ( ${PROJECT_NAME}_ENABLE_PACKAGE_CONFIGURE_TIMING + OR ${TRIBITS_PACKAGE}_PACKAGE_CONFIGURE_TIMING ) + ) + timer_get_raw_seconds(TIMER_STOP_SECONDS) + timer_print_rel_time(${${START_TIMER_SECONDS_VAR_IN}} + ${TIMER_STOP_SECONDS} + "${TIMER_STR}") + endif() +endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake b/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake index f4e1e3bc75..ffeef4bdbb 100644 --- a/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake +++ b/cmake/tribits/core/package_arch/TribitsCopyFilesToBinaryDir.cmake @@ -38,7 +38,6 @@ # @HEADER -include(TribitsAddTestHelpers) include(CMakeParseArguments) diff --git a/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake b/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake index a136e8f341..b35afaea47 100644 --- a/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake +++ b/cmake/tribits/core/package_arch/TribitsFindMostRecentFileTimestamp.cmake @@ -37,6 +37,9 @@ # ************************************************************************ # @HEADER + +include(TribitsConfigureTiming) + include(CMakeParseArguments) diff --git a/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake b/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake index 0dc079655a..8236e47a5b 100644 --- a/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGeneralMacros.cmake @@ -46,62 +46,6 @@ include(TribitsDeprecatedHelpers) include(TribitsGetPackageEnableStatus) -# Optionally start CMake code configure timing -# -function(tribits_config_code_start_timer START_TIMER_SECONDS_VAR_OUT) - if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING) - timer_get_raw_seconds(START_TIMER_SECONDS) - set(${START_TIMER_SECONDS_VAR_OUT} ${START_TIMER_SECONDS} PARENT_SCOPE) - endif() -endfunction() - - -# Optionally stop CMake code configure timing -# -function(tribits_config_code_stop_timer START_TIMER_SECONDS_VAR_IN - TIMER_STR - ) - if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING) - timer_get_raw_seconds(TIMER_STOP_SECONDS) - timer_print_rel_time(${${START_TIMER_SECONDS_VAR_IN}} - ${TIMER_STOP_SECONDS} - "${TIMER_STR}") - endif() -endfunction() - - -# Optionally start CMake code **package** configure timing -# -function(tribits_package_config_code_start_timer START_TIMER_SECONDS_VAR_OUT) - if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING - AND - ( ${PROJECT_NAME}_ENABLE_PACKAGE_CONFIGURE_TIMING - OR ${TRIBITS_PACKAGE}_PACKAGE_CONFIGURE_TIMING ) - ) - timer_get_raw_seconds(START_TIMER_SECONDS) - set(${START_TIMER_SECONDS_VAR_OUT} ${START_TIMER_SECONDS} PARENT_SCOPE) - endif() -endfunction() - - -# Optionally stop CMake code **package** configure timing -# -function(tribits_package_config_code_stop_timer START_TIMER_SECONDS_VAR_IN - TIMER_STR - ) - if (${PROJECT_NAME}_ENABLE_CONFIGURE_TIMING - AND - ( ${PROJECT_NAME}_ENABLE_PACKAGE_CONFIGURE_TIMING - OR ${TRIBITS_PACKAGE}_PACKAGE_CONFIGURE_TIMING ) - ) - timer_get_raw_seconds(TIMER_STOP_SECONDS) - timer_print_rel_time(${${START_TIMER_SECONDS_VAR_IN}} - ${TIMER_STOP_SECONDS} - "${TIMER_STR}") - endif() -endfunction() - - # Set the combined directory name taking into account '.' repos. # function(tribits_get_repo_name REPO_DIR REPO_NAME_OUT) diff --git a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake index 5315bb0a6a..63149a3750 100644 --- a/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsGlobalMacros.cmake @@ -38,11 +38,14 @@ # @HEADER # Standard TriBITS system includes -include(TribitsConstants) + +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsConstants.cmake") + +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsTestCategories.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsAddTestHelpers.cmake") + include(TribitsSetupMPI) -include(TribitsTestCategories) include(TribitsGeneralMacros) -include(TribitsAddTestHelpers) include(TribitsVerbosePrintVar) include(TribitsProcessEnabledTpls) include(TribitsInstallHeaders) @@ -52,6 +55,7 @@ include(TribitsReadAllProjectDepsFilesCreateDepsGraph) include(TribitsAdjustPackageEnables) include(TribitsGitRepoVersionInfo) include(TribitsSetUpEnabledOnlyDependencies) +include(TribitsConfigureTiming) # Standard TriBITS utilities includes include(TribitsAddOptionAndDefine) @@ -463,13 +467,6 @@ macro(tribits_define_global_options_and_define_extra_repos) "Make the ${PROJECT_NAME} configure process verbose." ) - if ("${${PROJECT_NAME}_TRACE_ADD_TEST_DEFAULT}" STREQUAL "") - set(${PROJECT_NAME}_TRACE_ADD_TEST_DEFAULT ${${PROJECT_NAME}_VERBOSE_CONFIGURE}) - endif() - advanced_set(${PROJECT_NAME}_TRACE_ADD_TEST ${${PROJECT_NAME}_TRACE_ADD_TEST_DEFAULT} - CACHE BOOL - "Show a configure time trace of every test added or not added any why (one line)." ) - advanced_option(${PROJECT_NAME}_DUMP_LINK_LIBS "Dump the link libraries for every library and executable created." "${${PROJECT_NAME}_VERBOSE_CONFIGURE}" ) @@ -1133,106 +1130,6 @@ macro(tribits_setup_installation_paths) endmacro() -# -# Macros to process repository specializaiton call-back functions -# -# NOTE: The Tribits system promises to only include these call-back files once -# (in order) and to only the call call-back macros they provide once (in -# order). -# - - -macro(create_empty_tribits_repository_setup_extra_options) - macro(tribits_repository_setup_extra_options) - endmacro() -endmacro() - - -macro(tribits_repository_setup_extra_options_runner REPO_NAME) - set(CALLBACK_SETUP_EXTRA_OPTIONS_FILE - "${${REPO_NAME}_SOURCE_DIR}/cmake/CallbackSetupExtraOptions.cmake") - #print_var(CALLBACK_SETUP_EXTRA_OPTIONS_FILE) - if (EXISTS ${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("Processing call-back file and macros in" - " '${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}'") - endif() - # Define the callback macros as empty in case it is not defined - # in this file. - create_empty_tribits_repository_setup_extra_options() - # Include the file which will define the callback macros - set(REPOSITORY_NAME ${REPO_NAME}) - tribits_trace_file_processing(REPOSITORY INCLUDE - "${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}") - include(${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}) - # Call the callback macros to inject repository-specific behavir - tribits_repository_setup_extra_options() - # Set back the callback macros to empty to ensure that nonone calls them - create_empty_tribits_repository_setup_extra_options() - endif() -endmacro() - - -macro(create_empty_tribits_repository_define_packaging) - macro(tribits_repository_define_packaging) - endmacro() -endmacro() - - -macro(tribits_repository_define_packaging_runner REPO_NAME) - set(CALLBACK_DEFINE_PACKAGING_FILE - "${${REPO_NAME}_SOURCE_DIR}/cmake/CallbackDefineRepositoryPackaging.cmake") - #print_var(CALLBACK_DEFINE_PACKAGING_FILE) - if (EXISTS ${CALLBACK_DEFINE_PACKAGING_FILE}) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("Processing call-back file and macros in" - " '${CALLBACK_DEFINE_PACKAGING_FILE}'") - endif() - # Define the callback macros as empty in case it is not defined - # in this file. - create_empty_tribits_repository_define_packaging() - # Include the file which will define the callback macros - tribits_trace_file_processing(REPOSITORY INCLUDE - "${CALLBACK_DEFINE_PACKAGING_FILE}") - include(${CALLBACK_DEFINE_PACKAGING_FILE}) - # Call the callback macros to inject repository-specific behavir - tribits_repository_define_packaging() - # Set back the callback macros to empty to ensure that nonone calls them - create_empty_tribits_repository_define_packaging() - endif() -endmacro() - - -macro(create_empty_tribits_project_define_packaging) - macro(tribits_project_define_packaging) - endmacro() -endmacro() - - -macro(tribits_project_define_packaging_runner) - set(CALLBACK_DEFINE_PACKAGING_FILE - "${PROJECT_SOURCE_DIR}/cmake/CallbackDefineProjectPackaging.cmake") - #print_var(CALLBACK_DEFINE_PACKAGING_FILE) - if (EXISTS ${CALLBACK_DEFINE_PACKAGING_FILE}) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("Processing call-back file and macros in" - " '${CALLBACK_DEFINE_PACKAGING_FILE}'") - endif() - # Define the callback macros as empty in case it is not defined - # in this file. - create_empty_tribits_project_define_packaging() - # Include the file which will define the callback macros - tribits_trace_file_processing(PROJECT INCLUDE - "${CALLBACK_DEFINE_PACKAGING_FILE}") - include(${CALLBACK_DEFINE_PACKAGING_FILE}) - # Call the callback macros to inject project-specific behavir - tribits_project_define_packaging() - # Set back the callback macros to empty to ensure that nonone calls them - create_empty_tribits_project_define_packaging() - endif() -endmacro() - - # Read in the Project's native repositories. # # On output, the variable ${PRJOECT_NAME}_NATIVE_REPOSITORIES is set. @@ -2171,17 +2068,20 @@ macro(tribits_configure_enabled_packages) tribits_trace_file_processing(PACKAGE ADD_SUBDIR "${TRIBITS_PACKAGE_CMAKELIST_FILE}") if (NOT ${TRIBITS_PACKAGE}_SOURCE_DIR STREQUAL ${PROJECT_NAME}_SOURCE_DIR) - add_subdirectory(${${TRIBITS_PACKAGE}_SOURCE_DIR} ${${TRIBITS_PACKAGE}_BINARY_DIR}) + add_subdirectory(${${TRIBITS_PACKAGE}_SOURCE_DIR} + ${${TRIBITS_PACKAGE}_BINARY_DIR}) else() include("${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() - if (NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS) + if ((NOT ${PACKAGE_NAME}_TRIBITS_PACKAGE_POSTPROCESS) AND + (NOT TARGET ${PACKAGE_NAME}::all_libs) + ) tribits_report_invalid_tribits_usage( "ERROR: Forgot to call tribits_package_postprocess() in" " ${TRIBITS_PACKAGE_CMAKELIST_FILE}") endif() - list(APPEND ENABLED_PACKAGE_LIBS_TARGETS ${TRIBITS_PACKAGE}_libs) + list(APPEND ENABLED_PACKAGE_LIBS_TARGETS ${TRIBITS_PACKAGE}::all_libs) list(APPEND ${PROJECT_NAME}_LIBRARIES ${${TRIBITS_PACKAGE}_LIBRARIES}) tribits_package_config_code_stop_timer(PROCESS_THIS_PACKAGE_TIME_START_SECONDS @@ -2297,150 +2197,6 @@ macro(tribits_configure_enabled_packages) endmacro() -# Set up for packaging and distribution -# -macro(tribits_setup_packaging_and_distribution) - - tribits_config_code_start_timer(CPACK_SETUP_TIME_START_SECONDS) - - # K.1) Run callback function for the base project. - - tribits_project_define_packaging_runner() - # The above must define the basic project settings for CPACK that are - # specific to the project and should not be provided by the user. - - # K.2) Removing any packages or packages not enabled from the tarball - - if (${PROJECT_NAME}_EXCLUDE_DISABLED_SUBPACKAGES_FROM_DISTRIBUTION) - set(tribitsPackageList ${${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES}) - else() - set(tribitsPackageList ${${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES}) - endif() - - tribits_get_sublist_nonenabled(tribitsPackageList nonEnabledTribitsPackage "") - - foreach(TRIBITS_PACKAGE ${nonEnabledTribitsPackage}) - - # Determine if this is a package to not ignore - find_list_element(TRIBITS_CPACK_PACKAGES_TO_NOT_IGNORE - ${TRIBITS_PACKAGE} TRIBITS_PACKAGE_DONT_IGNORE) - - if (NOT TRIBITS_PACKAGE_DONT_IGNORE) - - # Checking if we have a relative path to the package's files. Since the - # exclude is a regular expression any "../" will be interpreted as / which would never match the package's actual - # directory. There isn't a direct way in cmake to convert a relative - # path into an absolute path with string operations so as a way of - # making sure that we get the correct path of the package we use a - # find_path for the CMakeLists.txt file for the package. Since the - # package has to have this file to work correctly it should be - # guaranteed to be there. - string(REGEX MATCH "[.][.]/" RELATIVE_PATH_CHARS_MATCH - ${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}) - if ("${RELATIVE_PATH_CHARS_MATCH}" STREQUAL "") - set(CPACK_SOURCE_IGNORE_FILES - "${PROJECT_SOURCE_DIR}/${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}/" - ${CPACK_SOURCE_IGNORE_FILES}) - else() - find_path(ABSOLUTE_PATH CMakeLists.txt PATHS - "${PROJECT_SOURCE_DIR}/${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}" - NO_DEFAULT_PATH) - if ("${ABSOLUTE_PATH}" STREQUAL "ABSOLUTE_PATH-NOTFOUND") - message(AUTHOR_WARNING "Relative path found for disabled package" - " ${TRIBITS_PACKAGE} but package was missing a CMakeLists.txt file." - " This disabled package will likely not be excluded from a source release") - endif() - set(CPACK_SOURCE_IGNORE_FILES ${ABSOLUTE_PATH} ${CPACK_SOURCE_IGNORE_FILES}) - endif() - endif() - - endforeach() - - # Add excludes for VC files/dirs - set(CPACK_SOURCE_IGNORE_FILES - ${CPACK_SOURCE_IGNORE_FILES} - /[.]git/ - [.]gitignore$ - ) - - # Print the set of excluded files - if(${PROJECT_NAME}_VERBOSE_CONFIGURE OR - ${PROJECT_NAME}_DUMP_CPACK_SOURCE_IGNORE_FILES - ) - message("Exclude files when building source packages") - foreach(item ${CPACK_SOURCE_IGNORE_FILES}) - message(${item}) - endforeach() - endif() - - # K.3) Set up install component dependencies - - tribits_get_sublist_enabled( - ${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES - enabledInternalToplevelPackages "") - - foreach(pkgName ${enabledInternalToplevelPackages}) - if(NOT "${${pkgName}_LIB_ENABLED_DEPENDENCIES}" STREQUAL "") - string(TOUPPER ${pkgName} upperPkgName) - set(CPACK_COMPONENT_${upperPkgName}_DEPENDS ${${pkgName}_LIB_ENABLED_DEPENDENCIES}) - # ToDo: The above needs to be changed to the list of *internal* enabled - # package dependencies! (But there are no tests for this currently and - # I am not sure who is using this.) - endif() - endforeach() - - # K.4) Resetting the name to avoid overwriting registry keys when installing - - if(WIN32) - set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${${PROJECT_NAME}_VERSION}") - if (TPL_ENABLE_MPI) - set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-mpi") - ELSE () - set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-serial") - endif() - set(CPACK_GENERATOR "NSIS") - set(CPACK_NSIS_MODIFY_PATH OFF) - endif() - - # K.5) Determine the source generator - if ("${${PROJECT_NAME}_CPACK_SOURCE_GENERATOR_DEFAULT}" STREQUAL "") - set(${PROJECT_NAME}_CPACK_SOURCE_GENERATOR_DEFAULT "TGZ") - endif() - set(${PROJECT_NAME}_CPACK_SOURCE_GENERATOR - ${${PROJECT_NAME}_CPACK_SOURCE_GENERATOR_DEFAULT} - CACHE STRING - "The types of source generators to use for CPACK_SOURCE_GENERATOR.") - set(CPACK_SOURCE_GENERATOR ${${PROJECT_NAME}_CPACK_SOURCE_GENERATOR}) - - # K.6) Loop through the Repositories and run their callback functions. - foreach(REPO ${${PROJECT_NAME}_ALL_REPOSITORIES}) - tribits_get_repo_name_dir(${REPO} REPO_NAME REPO_DIR) - if (${PROJECT_NAME}_VERBOSE_CONFIGURE) - message("Processing packaging call-backs for ${REPO_NAME}") - endif() - tribits_repository_define_packaging_runner(${REPO_NAME}) - endforeach() - - # K.7) Include RepoVersion.txt if generated - set(PROJECT_REPO_VERSION_FILE - "${CMAKE_CURRENT_BINARY_DIR}/${${PROJECT_NAME}_REPO_VERSION_FILE_NAME}") - if (EXISTS "${PROJECT_REPO_VERSION_FILE}") - foreach(SOURCE_GEN ${CPACK_SOURCE_GENERATOR}) - set(CPACK_INSTALL_COMMANDS ${CPACK_INSTALL_COMMANDS} - "${CMAKE_COMMAND} -E copy '${PROJECT_REPO_VERSION_FILE}' '${CMAKE_CURRENT_BINARY_DIR}/_CPack_Packages/Linux-Source/${SOURCE_GEN}/${CPACK_PACKAGE_NAME}-${${PROJECT_NAME}_VERSION}-Source/${${PROJECT_NAME}_REPO_VERSION_FILE_NAME}'") - endforeach() - endif() - - # K.8) Finally process with CPack - include(CPack) - - tribits_config_code_stop_timer(CPACK_SETUP_TIME_START_SECONDS - "Total time to set up for CPack packaging") - -endmacro() - - # Create custom 'install_package_by_package' target # function(tribits_add_install_package_by_package_target) @@ -2488,104 +2244,6 @@ macro(tribits_setup_for_installation) endmacro() - -# @MACRO: tribits_exclude_files() -# -# Exclude package files/dirs from the source distribution by appending -# ``CPACK_SOURCE_IGNORE_FILES``. -# -# Usage:: -# -# tribits_exclude_files( ...) -# -# This is called in the top-level parent package's -# `/CMakeLists.txt`_ file and each file or directory name -# ```` is actually interpreted by CMake/CPack as a regex that is -# prefixed by the project's and package's source directory names so as to not -# exclude files and directories of the same name and path from other packages. -# If ```` is an absolute path it is not prefixed but is appended to -# ``CPACK_SOURCE_IGNORE_FILES`` unmodified. -# -# In general, do **NOT** put in excludes for files and directories that are -# not under this package's source tree. If the given package is not enabled, -# then this command will never be called! For example, don't put in excludes -# for PackageB's files in PackageA's ``CMakeLists.txt`` file because if -# PackageB is enabled but PackageA is not, the excludes for PackageB will -# never get added to ``CPACK_SOURCE_IGNORE_FILES``. -# -# Also, be careful to note that the ```` arguments are actually regexes -# and one must be very careful to understand how CPack will use these regexes -# to match files that get excluded from the tarball. For more details, see -# `Creating Source Distributions`_. -# -macro(tribits_exclude_files) - - if (NOT "${${PACKAGE_NAME}_PARENT_PACKAGE}" STREQUAL "") - message(FATAL_ERROR - "ERROR: tribits_exclude_files() was called in a subpackage CmakeLists.txt file!" - " Instead, move this call to the file" - " ${${${PACKAGE_NAME}_PARENT_PACKAGE}_SOURCE_DIR}/CMakeLists.txt" - " and adjust the paths accordingly!" ) - endif() - - set(FILES_TO_EXCLUDE ${ARGN}) - - # Need to add "///" to each file to prevent - # someone from trying to exclude a file like "readme" and having it - # inadvertently exclude a file matching that name in another package. - set(MODIFIED_FILES_TO_EXCLUDE "") - - set(${PROJECT_NAME}_SOURCE_PATH ${${PROJECT_NAME}_SOURCE_DIR}) - - foreach(FILE ${FILES_TO_EXCLUDE}) - #Ensure that if the full path was specified for the file that we don't add - #"///" again. - set(MATCH_STRING "${${PACKAGE_NAME}_SOURCE_DIR}") - string(REGEX MATCH ${MATCH_STRING} MATCHED ${FILE} ) - if(NOT MATCHED) - list(APPEND MODIFIED_FILES_TO_EXCLUDE - "${${PACKAGE_NAME}_SOURCE_DIR}/${FILE}") - else() - list(APPEND MODIFIED_FILES_TO_EXCLUDE ${FILE}) - endif() - endforeach() - -#Leaving in for debugging purposes -# message("List of files being excluded for package ${PACKAGE_NAME}") -# foreach(NEW_FILE ${MODIFIED_FILES_TO_EXCLUDE}) -# message(${NEW_FILE}) -# endforeach() - - list(APPEND CPACK_SOURCE_IGNORE_FILES ${MODIFIED_FILES_TO_EXCLUDE}) - if (NOT ${PROJECT_NAME}_BINARY_DIR STREQUAL ${PACKAGE_NAME}_BINARY_DIR) - set(CPACK_SOURCE_IGNORE_FILES ${CPACK_SOURCE_IGNORE_FILES} PARENT_SCOPE) - endif() - -endmacro() - - -# Exclude files only for the packages that will not be supporting autotools. -# -macro(tribits_exclude_autotools_files) # PACKAGE_NAME LIST_RETURN) - set(AUTOTOOLS_FILES - configure.ac$ - configure$ - Makefile.am$ - Makefile.in$ - bootstrap$ - .*[.]m4$ - config/ - ) - - set(FILES_TO_EXCLUDE) - foreach(FILE ${AUTOTOOLS_FILES}) - list(APPEND FILES_TO_EXCLUDE ${FILE} \(.*/\)*${FILE}) - endforeach() - - tribits_exclude_files(${FILES_TO_EXCLUDE}) - -endmacro() - # LocalWords: # LocalWords: Sandia SANDIA Redistributions # LocalWords: tribits TriBITS TRIBITS diff --git a/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake b/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake index c1bf530397..7ac01b81ed 100644 --- a/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake +++ b/cmake/tribits/core/package_arch/TribitsInstallHeaders.cmake @@ -76,7 +76,7 @@ include(CMakeParseArguments) # If specified, then ``COMPONENT `` will be passed into # ``install()``. Otherwise, ``COMPONENT ${PROJECT_NAME}`` will get used. # -# If `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FASLE``, then the +# If `${PROJECT_NAME}_INSTALL_LIBRARIES_AND_HEADERS`_ is ``FALSE``, then the # headers will not get installed. # function(tribits_install_headers) diff --git a/cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake b/cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake index 914825ffad..e820d6222e 100644 --- a/cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake +++ b/cmake/tribits/core/package_arch/TribitsInternalPackageWriteConfigFile.cmake @@ -84,12 +84,12 @@ function(tribits_write_package_client_export_files PACKAGE_NAME) tribits_write_flexible_package_client_export_files(${EXPORT_FILES_ARGS}) - tribits_write_package_client_export_files_install_targets(${EXPORT_FILES_ARGS}) + tribits_write_package_client_export_files_export_and_install_targets(${EXPORT_FILES_ARGS}) endfunction() -# @FUNCTION: tribits_write_package_client_export_files_install_targets() +# @FUNCTION: tribits_write_package_client_export_files_export_and_install_targets() # # Create the ``ConfigTargets.cmake`` file and install rules and the # install() target for the previously generated @@ -98,7 +98,7 @@ endfunction() # # Usage:: # -# tribits_write_package_client_export_files_install_targets( +# tribits_write_package_client_export_files_export_and_install_targets( # PACKAGE_NAME # PACKAGE_CONFIG_FOR_BUILD_BASE_DIR # PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR @@ -107,7 +107,7 @@ endfunction() # The install() commands must be in a different subroutine or CMake will not # allow you to call the routine, even if you if() it out! # -function(tribits_write_package_client_export_files_install_targets) +function(tribits_write_package_client_export_files_export_and_install_targets) cmake_parse_arguments( #prefix @@ -333,10 +333,10 @@ endfunction() # @FUNCTION: tribits_write_flexible_package_client_export_files() # -# Utility function for writing ``${PACKAGE_NAME}Config.cmake`` files for -# package ``${PACKAGE_NAME}`` with some greater flexibility than what is -# provided by the function ``tribits_write_package_client_export_files()`` and -# to allow unit testing the generation of these files.. +# Utility function for writing the ``${PACKAGE_NAME}Config.cmake`` files for +# the build dir and/or for the install dir for the package ```` +# with some flexibility . (See NOTE below for what is actually generated and +# what is *NOT* generated.) # # Usage:: # @@ -352,7 +352,8 @@ endfunction() # ``PACKAGE_NAME `` # # Gives the name of the TriBITS package for which the export files should -# be created. +# be created. (This must match the export set for the libraries for the +# generated/exported ``ConfigTargets.cmake`` file.) # # ``EXPORT_FILE_VAR_PREFIX `` # @@ -362,28 +363,39 @@ endfunction() # # ``PACKAGE_CONFIG_FOR_BUILD_BASE_DIR `` # -# If specified, then the package's ``Config.cmake`` file and -# supporting files will be written under the directory -# ``/`` (and any subdirs that does exist -# will be created). The generated file ``Config.cmake`` is -# for usage of the package in the build tree (not the install tree) and -# points to include directories and libraries in the build tree. +# If specified, then the package's ``Config.cmake`` file will +# be written under the directory ``/`` (and +# any subdirs that do not exist will be created). The generated file +# ``Config.cmake`` is for usage of the package in the build +# tree (not the install tree) and points to include directories and +# libraries in the build tree. (NOTE: The included +# ``Targets.cmake`` file is *NOT* generated in this +# function.) # # ``PACKAGE_CONFIG_FOR_INSTALL_BASE_DIR `` # # If specified, then the package's ``Config_install.cmake`` -# file and supporting files will be written under the directory -# ``/`` (and any subdirs that does exist +# file will be written under the directory +# ``/`` (and any subdirs that do not exist # will be created). The file ``${PACKAGE_NAME}Config_install.cmake`` is # meant to be installed renamed as ``Config.cmake`` in the # install tree and it points to installed include directories and -# libraries. -# -# NOTE: This function does *not* contain any ``install()`` command itself -# because CMake will not allow those to even be present in scripting mode that -# is used for unit testing this function. Instead, the commands to install -# the files are added by the function -# ``tribits_write_package_client_export_files_install_targets()``. +# libraries. (NOTE: The included ``Targets.cmake`` +# file is *NOT* generated in this function.) +# +# NOTE: This function does *not* generate the ``Config.cmake`` +# files (which will be created later using ``export()`` or ``include()`) which +# are included in these generated package config files and this function. +# Also, this function does *not* invoke the ``install()`` command to install +# the package config file for the install directory. The ``export()`` and +# ``install()`` project commands are bot allowed in `cmake -P` scripting mode +# that is used for unit testing this function. Instead, the commands to +# generate the ``Targets.cmake`` files and install the package +# config file for the install tree are produced by the function +# ``tribits_write_package_client_export_files_export_and_install_targets()`` +# which is called after this function. This allows this function +# ``tribits_write_package_client_export_files()`` to be run in unit testing +# with a `cmake -P` script. # function(tribits_write_flexible_package_client_export_files) @@ -525,25 +537,35 @@ function(tribits_append_dependent_package_config_file_includes_and_enables_str p # Include configurations of dependent packages string(APPEND configFileStr "\n# Include configuration of dependent packages\n") + set(DOLLAR "$") + set(externalPkgsDir + "${DOLLAR}{CMAKE_CURRENT_LIST_DIR}/../../${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}") foreach(depPkg IN LISTS ${packageName}_LIB_ENABLED_DEPENDENCIES) - set(packageConfigBaseDir "") # Initially, no add include() + set(findDepPkgCode "") # Start out not including anything if (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "INTERNAL") - set(packageConfigBaseDir "\${CMAKE_CURRENT_LIST_DIR}/../${depPkg}") + set(findDepPkgCode + " include(\"${DOLLAR}{CMAKE_CURRENT_LIST_DIR}/../${depPkg}/${depPkg}Config.cmake\")\n") elseif (${depPkg}_PACKAGE_BUILD_STATUS STREQUAL "EXTERNAL") if (NOT "${${depPkg}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}" STREQUAL "") - set(packageConfigBaseDir "${${depPkg}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}") + set(findDepPkgCode + " include(\"${${depPkg}_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR}/${depPkg}Config.cmake\")\n") + elseif (${depPkg}_FINDMOD STREQUAL "TRIBITS_PKG") + assert_defined(${depPkg}_CONFIG) + string(APPEND findDepPkgCode + " include(\"${${depPkg}_CONFIG}\")\n" + " set(${depPkg}_CONFIG \"${${depPkg}_CONFIG}\")\n") else() - set(packageConfigBaseDir - "\${CMAKE_CURRENT_LIST_DIR}/../../${${PROJECT_NAME}_BUILD_DIR_EXTERNAL_PKGS_DIR}/${depPkg}") + set(findDepPkgCode + " include(\"${externalPkgsDir}/${depPkg}/${depPkg}Config.cmake\")\n") endif() else() message(FATAL_ERROR "ERROR:" " ${depPkg}_PACKAGE_BUILD_STATUS='${${depPkg}_PACKAGE_BUILD_STATUS}' invalid!") endif() - if (packageConfigBaseDir) + if (findDepPkgCode) string(APPEND configFileStr "if (NOT TARGET ${depPkg}::all_libs)\n" - " include(\"${packageConfigBaseDir}/${depPkg}Config.cmake\")\n" + "${findDepPkgCode}" "endif()\n" ) endif() diff --git a/cmake/tribits/core/package_arch/TribitsPackageDefineDependencies.cmake b/cmake/tribits/core/package_arch/TribitsPackageDefineDependencies.cmake index c2136eb745..a5584fb85a 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageDefineDependencies.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageDefineDependencies.cmake @@ -57,12 +57,12 @@ include(TribitsGeneralMacros) # [LIB_OPTIONAL_TPLS ...] # [TEST_REQUIRED_TPLS ...] # [TEST_OPTIONAL_TPLS ...] -# [REGRESSION_EMAIL_LIST ] # [SUBPACKAGES_DIRS_CLASSIFICATIONS_OPTREQS # # # ... # ] +# [REGRESSION_EMAIL_LIST ] # ) # # Every argument in this macro is optional (that is, an package can have no @@ -84,9 +84,9 @@ include(TribitsGeneralMacros) # ``TEST_REQUIRED_PACKAGES`` # # List of additional upstream packages that must be enabled in order to -# build and/or run the tests and/or examples in this package. If any -# of these upstream packages are not enabled, then there will be no -# tests or examples defined or run for this package. +# build and/or run the tests and/or examples in this package. If any of +# these upstream packages are not enabled, then there will be no tests or +# examples defined or run for this package. # # ``TEST_OPTIONAL_PACKAGES`` # @@ -94,39 +94,52 @@ include(TribitsGeneralMacros) # tests in this package. These upstream packages need not be enabled in # order to run some basic tests or examples for this package. Typically, # extra tests that depend on optional test packages involve integration -# testing of some type. +# testing of some type. Not enabling these optional upstream packages +# will result in diminished tests or examples. # # ``LIB_REQUIRED_TPLS`` # -# List of required upstream TPLs that must be enabled in order to build -# and use the libraries (or capabilities) in this package. +# **DEPRECATED:** List of required upstream TPLs that must be enabled in +# order to build and use the libraries (or capabilities) in this package. +# (Add these to ``LIB_REQUIRED_PACKAGES`` instead.) # # ``LIB_OPTIONAL_TPLS`` # -# List of additional optional upstream TPLs that can be used in this -# package if enabled. These upstream TPLs need not be enabled in order to -# use this package but not enabling one or more of these optional upstream -# TPLs will result in diminished capabilities of this package. +# **DEPRECATED:** List of additional optional upstream TPLs that can be +# used in this package if enabled. These upstream TPLs need not be +# enabled in order to use this package but not enabling one or more of +# these optional upstream TPLs will result in diminished capabilities of +# this package. (Add these to ``LIB_OPTIONAL_PACKAGES`` instead.) # # ``TEST_REQUIRED_TPLS`` # -# List of additional upstream TPLs that must be enabled in order to build -# and/or run the tests and/or examples in this package. If any of -# these upstream TPLs are not enabled, then there will be no tests or -# examples defined or run for this package. +# **DEPRECATED:** List of additional upstream TPLs that must be enabled in +# order to build and/or run the tests and/or examples in this package. If +# any of these upstream TPLs are not enabled, then there will be no tests +# or examples defined or run for this package. (Add these to +# ``TEST_REQUIRED_PACKAGES`` instead.) # # ``TEST_OPTIONAL_TPLS`` # -# List of additional optional upstream TPLs that can be used by the tests -# in this package. These upstream TPLs need not be enabled in order to -# run basic tests for this package. Typically, extra tests that depend -# on optional TPLs involve integration testing or some additional testing -# of some type. +# **DEPRECATED:** List of additional optional upstream TPLs that can be +# used by the tests in this package. These upstream TPLs need not be +# enabled in order to run basic tests for this package. Typically, extra +# tests that depend on optional TPLs involve integration testing or some +# additional testing of some type. (Add these to +# ``TEST_OPTIONAL_PACKAGES`` instead.) +# +# NOTE: The ``XXX_TPLS`` arguments/lists are **deprecated**. At the package +# level, there is no distinction between upstream internal and external +# packages (i.e. TPLs) so all upstream package dependencies can (and should) +# be listed in the ``XXX_PACKAGES`` arguments/lists. (There is no change in +# behavior listing upstream packages in ``XXX_PACKAGES`` or the ``XXX_TPLS`` +# arguments/lists.) # # Only upstream packages can be listed (as defined by the order the packages # are listed in `tribits_repository_define_packages()`_ in the -# `/PackagesList.cmake`_ file). Otherwise an error will occur and -# processing will stop. Misspelled package names are caught as well. +# `/PackagesList.cmake`_ or `/TPLsList.cmake`_ files). +# Otherwise an error will occur and processing will stop. Misspelled package +# names are caught as well. # # Only direct package dependencies need to be listed. Indirect package # dependencies are automatically handled. For example, if this package @@ -136,14 +149,10 @@ include(TribitsGeneralMacros) # The dependency on ``PKG1`` will be taken care of automatically by the # TriBITS dependency management system. # -# However, currently, all TPL dependencies must be listed, even the indirect -# ones. This is a requirement that will be dropped in a future version of -# TriBITS. -# # The packages listed in ``LIB_REQUIRED_PACKAGES`` are implicitly also # dependencies in ``TEST_REQUIRED_PACKAGES``. Likewise # ``LIB_OPTIONAL_PACKAGES`` are implicitly also dependencies in -# ``TEST_OPTIONAL_PACKAGES``. Same goes for TPL dependencies. +# ``TEST_OPTIONAL_PACKAGES``. # # The upstream dependencies within a single list do not need to be listed in # any order. For example if ``PKG2`` depends on ``PKG1``, and this given @@ -153,9 +162,7 @@ include(TribitsGeneralMacros) # # or:: # -# "LIB_REQUIRED_PACKAGES PKG1 PKG2 -# -# Likewise the order that dependent TPLs are listed is not significant. +# LIB_REQUIRED_PACKAGES PKG1 PKG2 # # If some upstream packages are allowed to be missing, this can be specified # by calling the macro `tribits_allow_missing_external_packages()`_. @@ -199,27 +206,6 @@ include(TribitsGeneralMacros) # argument is missing, then the email list that CDash errors go to is # determined by other means (see `CDash regression email addresses`_). # -# NOTE: All this macro really does is to just define the variables: -# -# * ``LIB_REQUIRED_DEP_PACKAGES`` -# * ``LIB_OPTIONAL_DEP_PACKAGES`` -# * ``TEST_REQUIRED_DEP_PACKAGES`` -# * ``TEST_OPTIONAL_DEP_PACKAGES`` -# * ``LIB_REQUIRED_DEP_TPLS`` -# * ``LIB_OPTIONAL_DEP_TPLS`` -# * ``TEST_REQUIRED_DEP_TPLS`` -# * ``TEST_OPTIONAL_DEP_TPLS`` -# * ``REGRESSION_EMAIL_LIST`` -# * ``SUBPACKAGES_DIRS_CLASSIFICATIONS_OPTREQS`` -# -# which are then read by the TriBITS cmake code to build the package -# dependency graph. The advantage of using this macro instead of just -# directly setting the variables is that an package only needs to list -# dependencies that exist. Otherwise, the ``Dependencies.cmake`` file will -# need to set all of the above local variables, even those that are empty. -# This is an error checking property of the TriBITS system to avoid misspelling -# the names of these variables. -# macro(tribits_package_define_dependencies) cmake_parse_arguments( diff --git a/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake b/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake index 0f4a956dd7..5f2e31595b 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageDependencies.cmake @@ -50,7 +50,8 @@ include_guard() -include(TribitsCMakePolicies NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsCMakePolicies.cmake" + NO_POLICY_SCOPE) include(TribitsParseArgumentsHelpers) include(MessageWrapper) diff --git a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake index 0a091c4d2d..d7931c4067 100644 --- a/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake +++ b/cmake/tribits/core/package_arch/TribitsPackageMacros.cmake @@ -51,13 +51,14 @@ include(PrependGlobalSet) include(RemoveGlobalDuplicates) include(TribitsGatherBuildTargets) +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsAddTest.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../test_support/TribitsAddAdvancedTest.cmake") + include(TribitsAddOptionAndDefine) include(TribitsPkgExportCacheVars) include(TribitsLibraryMacros) include(TribitsAddExecutable) include(TribitsAddExecutableAndTest) -include(TribitsAddTest) -include(TribitsAddAdvancedTest) include(TribitsCopyFilesToBinaryDir) include(TribitsReportInvalidTribitsUsage) diff --git a/cmake/tribits/core/package_arch/TribitsPackagingSupport.cmake b/cmake/tribits/core/package_arch/TribitsPackagingSupport.cmake new file mode 100644 index 0000000000..e4dc246368 --- /dev/null +++ b/cmake/tribits/core/package_arch/TribitsPackagingSupport.cmake @@ -0,0 +1,354 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# 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 Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE +# 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. +# +# ************************************************************************ +# @HEADER + + +# TriBITS package_arch includes +include(TribitsConfigureTiming) +include(TribitsGetPackageSublists) + +# TriBITS utils includes +include(FindListElement) + + +# @MACRO: tribits_exclude_files() +# +# Exclude package files/dirs from the source distribution by appending +# ``CPACK_SOURCE_IGNORE_FILES``. +# +# Usage:: +# +# tribits_exclude_files( ...) +# +# This is called in the top-level parent package's +# `/CMakeLists.txt`_ file and each file or directory name +# ```` is actually interpreted by CMake/CPack as a regex that is +# prefixed by the project's and package's source directory names so as to not +# exclude files and directories of the same name and path from other packages. +# If ```` is an absolute path it is not prefixed but is appended to +# ``CPACK_SOURCE_IGNORE_FILES`` unmodified. +# +# In general, do **NOT** put in excludes for files and directories that are +# not under this package's source tree. If the given package is not enabled, +# then this command will never be called! For example, don't put in excludes +# for PackageB's files in PackageA's ``CMakeLists.txt`` file because if +# PackageB is enabled but PackageA is not, the excludes for PackageB will +# never get added to ``CPACK_SOURCE_IGNORE_FILES``. +# +# Also, be careful to note that the ```` arguments are actually regexes +# and one must be very careful to understand how CPack will use these regexes +# to match files that get excluded from the tarball. For more details, see +# `Creating Source Distributions`_. +# +macro(tribits_exclude_files) + + if (NOT "${${PACKAGE_NAME}_PARENT_PACKAGE}" STREQUAL "") + message(FATAL_ERROR + "ERROR: tribits_exclude_files() was called in a subpackage CmakeLists.txt file!" + " Instead, move this call to the file" + " ${${${PACKAGE_NAME}_PARENT_PACKAGE}_SOURCE_DIR}/CMakeLists.txt" + " and adjust the paths accordingly!" ) + endif() + + set(FILES_TO_EXCLUDE ${ARGN}) + + # Need to add "///" to each file to prevent + # someone from trying to exclude a file like "readme" and having it + # inadvertently exclude a file matching that name in another package. + set(MODIFIED_FILES_TO_EXCLUDE "") + + set(${PROJECT_NAME}_SOURCE_PATH ${${PROJECT_NAME}_SOURCE_DIR}) + + foreach(FILE ${FILES_TO_EXCLUDE}) + #Ensure that if the full path was specified for the file that we don't add + #"///" again. + set(MATCH_STRING "${${PACKAGE_NAME}_SOURCE_DIR}") + string(REGEX MATCH ${MATCH_STRING} MATCHED ${FILE} ) + if(NOT MATCHED) + list(APPEND MODIFIED_FILES_TO_EXCLUDE + "${${PACKAGE_NAME}_SOURCE_DIR}/${FILE}") + else() + list(APPEND MODIFIED_FILES_TO_EXCLUDE ${FILE}) + endif() + endforeach() + +#Leaving in for debugging purposes +# message("List of files being excluded for package ${PACKAGE_NAME}") +# foreach(NEW_FILE ${MODIFIED_FILES_TO_EXCLUDE}) +# message(${NEW_FILE}) +# endforeach() + + list(APPEND CPACK_SOURCE_IGNORE_FILES ${MODIFIED_FILES_TO_EXCLUDE}) + if (NOT ${PROJECT_NAME}_BINARY_DIR STREQUAL ${PACKAGE_NAME}_BINARY_DIR) + set(CPACK_SOURCE_IGNORE_FILES ${CPACK_SOURCE_IGNORE_FILES} PARENT_SCOPE) + endif() + +endmacro() + + +# Set up for packaging and distribution +# +macro(tribits_setup_packaging_and_distribution) + + tribits_config_code_start_timer(CPACK_SETUP_TIME_START_SECONDS) + + # K.1) Run callback function for the base project. + + tribits_project_define_packaging_runner() + # The above must define the basic project settings for CPACK that are + # specific to the project and should not be provided by the user. + + # K.2) Removing any packages or packages not enabled from the tarball + + if (${PROJECT_NAME}_EXCLUDE_DISABLED_SUBPACKAGES_FROM_DISTRIBUTION) + set(tribitsPackageList ${${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES}) + else() + set(tribitsPackageList ${${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES}) + endif() + + tribits_get_sublist_nonenabled(tribitsPackageList nonEnabledTribitsPackage "") + + foreach(TRIBITS_PACKAGE ${nonEnabledTribitsPackage}) + + # Determine if this is a package to not ignore + find_list_element(TRIBITS_CPACK_PACKAGES_TO_NOT_IGNORE + ${TRIBITS_PACKAGE} TRIBITS_PACKAGE_DONT_IGNORE) + + if (NOT TRIBITS_PACKAGE_DONT_IGNORE) + + # Checking if we have a relative path to the package's files. Since the + # exclude is a regular expression any "../" will be interpreted as / which would never match the package's actual + # directory. There isn't a direct way in cmake to convert a relative + # path into an absolute path with string operations so as a way of + # making sure that we get the correct path of the package we use a + # find_path for the CMakeLists.txt file for the package. Since the + # package has to have this file to work correctly it should be + # guaranteed to be there. + string(REGEX MATCH "[.][.]/" RELATIVE_PATH_CHARS_MATCH + ${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}) + if ("${RELATIVE_PATH_CHARS_MATCH}" STREQUAL "") + list(PREPEND CPACK_SOURCE_IGNORE_FILES + "${PROJECT_SOURCE_DIR}/${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}/") + else() + find_path(ABSOLUTE_PATH CMakeLists.txt PATHS + "${PROJECT_SOURCE_DIR}/${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}" + NO_DEFAULT_PATH) + if ("${ABSOLUTE_PATH}" STREQUAL "ABSOLUTE_PATH-NOTFOUND") + message(AUTHOR_WARNING "Relative path found for disabled package" + " ${TRIBITS_PACKAGE} but package was missing a CMakeLists.txt file." + " This disabled package will likely not be excluded from a source release") + endif() + list(PREPEND CPACK_SOURCE_IGNORE_FILES "${ABSOLUTE_PATH}") + endif() + endif() + + endforeach() + + # Add excludes for VC files/dirs + list(APPEND CPACK_SOURCE_IGNORE_FILES + /[.]git/ + [.]gitignore$ + ) + + # K.3) Set up install component dependencies + + tribits_get_sublist_enabled( + ${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES + enabledInternalToplevelPackages "") + + foreach(pkgName ${enabledInternalToplevelPackages}) + if(NOT "${${pkgName}_LIB_ENABLED_DEPENDENCIES}" STREQUAL "") + string(TOUPPER ${pkgName} upperPkgName) + set(CPACK_COMPONENT_${upperPkgName}_DEPENDS ${${pkgName}_LIB_ENABLED_DEPENDENCIES}) + # ToDo: The above needs to be changed to the list of *internal* enabled + # package dependencies! (But there are no tests for this currently and + # I am not sure who is using this.) + endif() + endforeach() + + # K.4) Resetting the name to avoid overwriting registry keys when installing + + if(WIN32) + set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${${PROJECT_NAME}_VERSION}") + if (TPL_ENABLE_MPI) + set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-mpi") + ELSE () + set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-serial") + endif() + set(CPACK_GENERATOR "NSIS") + set(CPACK_NSIS_MODIFY_PATH OFF) + endif() + + # K.5) Determine the source generator + if ("${${PROJECT_NAME}_CPACK_SOURCE_GENERATOR_DEFAULT}" STREQUAL "") + set(${PROJECT_NAME}_CPACK_SOURCE_GENERATOR_DEFAULT "TGZ") + endif() + set(${PROJECT_NAME}_CPACK_SOURCE_GENERATOR + ${${PROJECT_NAME}_CPACK_SOURCE_GENERATOR_DEFAULT} + CACHE STRING + "The types of source generators to use for CPACK_SOURCE_GENERATOR.") + set(CPACK_SOURCE_GENERATOR ${${PROJECT_NAME}_CPACK_SOURCE_GENERATOR}) + + # K.6) Loop through the Repositories and run their callback functions. + foreach(REPO ${${PROJECT_NAME}_ALL_REPOSITORIES}) + tribits_get_repo_name_dir(${REPO} REPO_NAME REPO_DIR) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("Processing packaging call-backs for ${REPO_NAME}") + endif() + tribits_repository_define_packaging_runner(${REPO_NAME}) + endforeach() + + # K.7) Include RepoVersion.txt if generated + set(PROJECT_REPO_VERSION_FILE + "${CMAKE_CURRENT_BINARY_DIR}/${${PROJECT_NAME}_REPO_VERSION_FILE_NAME}") + if (EXISTS "${PROJECT_REPO_VERSION_FILE}") + foreach(SOURCE_GEN ${CPACK_SOURCE_GENERATOR}) + set(CPACK_INSTALL_COMMANDS ${CPACK_INSTALL_COMMANDS} + "${CMAKE_COMMAND} -E copy '${PROJECT_REPO_VERSION_FILE}' '${CMAKE_CURRENT_BINARY_DIR}/_CPack_Packages/Linux-Source/${SOURCE_GEN}/${CPACK_PACKAGE_NAME}-${${PROJECT_NAME}_VERSION}-Source/${${PROJECT_NAME}_REPO_VERSION_FILE_NAME}'") + endforeach() + endif() + + # Print the set of excluded files + if(${PROJECT_NAME}_VERBOSE_CONFIGURE OR + ${PROJECT_NAME}_DUMP_CPACK_SOURCE_IGNORE_FILES + ) + message("Exclude files when building source packages:") + foreach(item IN LISTS CPACK_SOURCE_IGNORE_FILES) + message(${item}) + endforeach() + endif() + + # K.8) Finally process with CPack + include(CPack) + + tribits_config_code_stop_timer(CPACK_SETUP_TIME_START_SECONDS + "Total time to set up for CPack packaging") + +endmacro() + + +macro(tribits_project_define_packaging_runner) + set(CALLBACK_DEFINE_PACKAGING_FILE + "${PROJECT_SOURCE_DIR}/cmake/CallbackDefineProjectPackaging.cmake") + #print_var(CALLBACK_DEFINE_PACKAGING_FILE) + if (EXISTS ${CALLBACK_DEFINE_PACKAGING_FILE}) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("Processing call-back file and macros in" + " '${CALLBACK_DEFINE_PACKAGING_FILE}'") + endif() + # Define the callback macros as empty in case it is not defined + # in this file. + create_empty_tribits_project_define_packaging() + # Include the file which will define the callback macros + tribits_trace_file_processing(PROJECT INCLUDE + "${CALLBACK_DEFINE_PACKAGING_FILE}") + include(${CALLBACK_DEFINE_PACKAGING_FILE}) + # Call the callback macros to inject project-specific behavir + tribits_project_define_packaging() + # Set back the callback macros to empty to ensure that no-one calls them + create_empty_tribits_project_define_packaging() + endif() +endmacro() + + +macro(create_empty_tribits_repository_setup_extra_options) + macro(tribits_repository_setup_extra_options) + endmacro() +endmacro() + + +macro(tribits_repository_setup_extra_options_runner REPO_NAME) + set(CALLBACK_SETUP_EXTRA_OPTIONS_FILE + "${${REPO_NAME}_SOURCE_DIR}/cmake/CallbackSetupExtraOptions.cmake") + #print_var(CALLBACK_SETUP_EXTRA_OPTIONS_FILE) + if (EXISTS ${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("Processing call-back file and macros in" + " '${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}'") + endif() + # Define the callback macros as empty in case it is not defined + # in this file. + create_empty_tribits_repository_setup_extra_options() + # Include the file which will define the callback macros + set(REPOSITORY_NAME ${REPO_NAME}) + tribits_trace_file_processing(REPOSITORY INCLUDE + "${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}") + include(${CALLBACK_SETUP_EXTRA_OPTIONS_FILE}) + # Call the callback macros to inject repository-specific behavir + tribits_repository_setup_extra_options() + # Set back the callback macros to empty to ensure that nonone calls them + create_empty_tribits_repository_setup_extra_options() + endif() +endmacro() + + +macro(create_empty_tribits_repository_define_packaging) + macro(tribits_repository_define_packaging) + endmacro() +endmacro() + + +macro(tribits_repository_define_packaging_runner REPO_NAME) + set(CALLBACK_DEFINE_PACKAGING_FILE + "${${REPO_NAME}_SOURCE_DIR}/cmake/CallbackDefineRepositoryPackaging.cmake") + #print_var(CALLBACK_DEFINE_PACKAGING_FILE) + if (EXISTS ${CALLBACK_DEFINE_PACKAGING_FILE}) + if (${PROJECT_NAME}_VERBOSE_CONFIGURE) + message("Processing call-back file and macros in" + " '${CALLBACK_DEFINE_PACKAGING_FILE}'") + endif() + # Define the callback macros as empty in case it is not defined + # in this file. + create_empty_tribits_repository_define_packaging() + # Include the file which will define the callback macros + tribits_trace_file_processing(REPOSITORY INCLUDE + "${CALLBACK_DEFINE_PACKAGING_FILE}") + include(${CALLBACK_DEFINE_PACKAGING_FILE}) + # Call the callback macros to inject repository-specific behavir + tribits_repository_define_packaging() + # Set back the callback macros to empty to ensure that nonone calls them + create_empty_tribits_repository_define_packaging() + endif() +endmacro() + + +macro(create_empty_tribits_project_define_packaging) + macro(tribits_project_define_packaging) + endmacro() +endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake index b161a9edef..bcc591d638 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessEnabledTpls.cmake @@ -43,13 +43,20 @@ include(TribitsExternalPackageWithImportedTargetsFindTplModuleHelpers) include(TribitsExternalPackageWriteConfigFile) include(TribitsTplFindIncludeDirsAndLibraries) include(TribitsGeneralMacros) +include(TribitsConfigureTiming) # Standard TriBITS utilities includes include(AppendStringVar) include(TribitsStandardizePaths) +include(TribitsCreateReverseList) -# Gather information from enabled TPLs +# @MACRO: tribits_process_enabled_tpls() +# +# Gather information and targets from enabled TPLs +# +# For more info, see `Processing of external packages/TPLs and +# TriBITS-compliant external packages`_. # macro(tribits_process_enabled_tpls) @@ -65,10 +72,13 @@ macro(tribits_process_enabled_tpls) if (projectHasTribitsCompliantExternalPackages) message("") message("Getting information for all enabled TriBITS-compliant" - " or upstream external packages/TPLs ...") + " or upstream external packages/TPLs in reverse order ...") message("") - foreach(TPL_NAME IN LISTS ${PROJECT_NAME}_enabledExternalTopLevelPackages) + tribits_create_reverse_list(${PROJECT_NAME}_enabledExternalTopLevelPackages + ${PROJECT_NAME}_reverseEnabledExternalTopLevelPackages) + + foreach(TPL_NAME IN LISTS ${PROJECT_NAME}_reverseEnabledExternalTopLevelPackages) if (${TPL_NAME}_IS_TRIBITS_COMPLIANT OR ${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE ) @@ -108,16 +118,37 @@ macro(tribits_process_enabled_tribits_compliant_or_upstream_tpl TPL_NAME) message("${tplProcessingString}") if (NOT ${PROJECT_NAME}_TRACE_DEPENDENCY_HANDLING_ONLY) - if (NOT ${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE) + if ( (NOT TARGET ${TPL_NAME}::all_libs) AND ${TPL_NAME}_IS_TRIBITS_COMPLIANT ) tribits_process_enabled_tribits_compliant_tpl(${TPL_NAME}) - else() + set(${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE FALSE) + elseif (TARGET ${TPL_NAME}::all_libs) + message("-- " + "The external package/TPL ${TPL_NAME} was defined by a downstream" + " TriBITS-compliant external package already processed") + elseif (${TPL_NAME}_FINDMOD AND (NOT ${TPL_NAME}_FINDMOD STREQUAL "TRIBITS_PKG")) message("-- " - "The external package/TPL ${TPL_NAME} will be read in by a downstream" - " TriBITS-compliant external package") + "The external package/TPL ${TPL_NAME} was *NOT* defined by a downstream" + " TriBITS-compliant external package and must be found again in below loop") + set(${TPL_NAME}_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE FALSE) + else() + message(FATAL_ERROR + "Error, the external package/TPL ${TPL_NAME} was *NOT* defined by a downstream" + " TriBITS-compliant external package and has not find module!") endif() endif() endmacro() +# NOTE: Above, handles the case where an upstream external package/TPL should +# have been defined a downstream external package that was already processed +# but it was not defined (because the downstream packages was not a fully +# TriBITS-compliant external package). For a TriBITS-compliant external +# package/TPL that should have been defined by a downstream TriBITS-compliant +# an external package/TPL, the first if-statement above takes care of that +# case by calling find_package(${TPL_NAME}) (because ${TPL_NAME}::all_libs +# will not be defined). However, if the upstream external package/TPL is +# *NOT* TriBITS-compliant, then it may be a legacy TriBITS TPL which means +# that it must be processed in ascending order in order to build the +# downstream TriBITS TPLs correctly. # @MACRO: tribits_process_enabled_standard_tpl() @@ -160,13 +191,19 @@ function(tribits_get_enabled_tpl_processing_string TPL_NAME tplProcessingStrin endfunction() -# Process an enabled TPL defined using a TriBITS-compliant external -# packages Config.cmake file +# Process an enabled TPL defined using a TriBITS-compliant external package +# Config.cmake file # macro(tribits_process_enabled_tribits_compliant_tpl TPL_NAME) message("-- " "Calling find_package(${TPL_NAME}) for TriBITS-compliant external package") find_package(${TPL_NAME} CONFIG REQUIRED) + if (${TPL_NAME}_DIR) + message("-- " "Found ${TPL_NAME}_DIR='${${TPL_NAME}_DIR}'") + else() + message(FATAL_ERROR + "ERROR! Failed to find TriBITS-compliant external package ${TPL_NAME}!") + endif() endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake index 447f98265c..4fd5f1d96b 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessPackagesAndDirsLists.cmake @@ -535,7 +535,8 @@ macro(tribits_process_packages_and_dirs_lists REPOSITORY_NAME REPOSITORY_DIR) endif() - if (EXISTS ${PACKAGE_ABS_DIR}) + set(packageDependenciesFile "${PACKAGE_ABS_DIR}/cmake/Dependencies.cmake") + if (EXISTS "${packageDependenciesFile}") set(PACKAGE_EXISTS TRUE) else() set(PACKAGE_EXISTS FALSE) @@ -557,9 +558,16 @@ macro(tribits_process_packages_and_dirs_lists REPOSITORY_NAME REPOSITORY_DIR) ) message( "\n***" - "\n*** Error, the package ${TRIBITS_PACKAGE} directory ${PACKAGE_ABS_DIR} does not exist!" + "\n*** Error, the package ${TRIBITS_PACKAGE} dependencies file" + " '${packageDependenciesFile}' does *NOT* exist!" "\n***\n" ) message(FATAL_ERROR "Stopping due to above error!") + elseif((NOT PACKAGE_EXISTS) AND (EXISTS "${PACKAGE_ABS_DIR}") + AND (${PROJECT_NAME}_ASSERT_DEFINED_DEPENDENCIES STREQUAL "WARNING") + ) + message(WARNING "${TRIBITS_PACKAGE}: Package base directory '${PACKAGE_ABS_DIR}'" + " exists but the dependencies file '${packageDependenciesFile}' does *NOT*" + " exist! Package is being ignored anyway!") endif() if (PACKAGE_EXISTS OR ${PROJECT_NAME}_IGNORE_PACKAGE_EXISTS_CHECK) diff --git a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake index f5e5a6e55d..a30a094045 100644 --- a/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake +++ b/cmake/tribits/core/package_arch/TribitsProcessTplsLists.cmake @@ -38,7 +38,7 @@ # @HEADER -include(TribitsConstants) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsConstants.cmake") include(TribitsListHelpers) include(PrintVar) diff --git a/cmake/tribits/core/package_arch/TribitsProject.cmake b/cmake/tribits/core/package_arch/TribitsProject.cmake index 035e089e3a..c2385f1665 100644 --- a/cmake/tribits/core/package_arch/TribitsProject.cmake +++ b/cmake/tribits/core/package_arch/TribitsProject.cmake @@ -66,7 +66,7 @@ if (${PROJECT_NAME}_VERBOSE_CONFIGURE) endif() # Overrides that we have for CMake functions -include(TribitsCMakePolicies NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) include(TribitsProjectImpl) diff --git a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake index f27caa3e66..8eab07d42c 100644 --- a/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake +++ b/cmake/tribits/core/package_arch/TribitsProjectImpl.cmake @@ -47,6 +47,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${${PROJECT_NAME}_TRIBITS_DIR}/core/utils + ${${PROJECT_NAME}_TRIBITS_DIR}/core/common + ${${PROJECT_NAME}_TRIBITS_DIR}/core/test_support ${${PROJECT_NAME}_TRIBITS_DIR}/core/package_arch ${${PROJECT_NAME}_TRIBITS_DIR}/core/config_tests ${${PROJECT_NAME}_TRIBITS_DIR}/core/modules @@ -57,10 +59,11 @@ if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("CMAKE_MODULE_PATH='${CMAKE_MODULE_PATH}'") endif() -include(TribitsConstants) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsConstants.cmake") tribits_asesrt_minimum_cmake_version() -include(TribitsCMakePolicies NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) +# TriBITS package_arch includes include(TribitsIncludeDirectories) include(TribitsFindPythonInterp) include(TribitsGlobalMacros) @@ -68,7 +71,10 @@ include(TribitsConfigureCTestCustom) include(TribitsGenerateResourceSpecFile) include(TribitsPackageDependencies) include(TribitsPrintDependencyInfo) +include(TribitsPackagingSupport) +include(TribitsConfigureTiming) +# TriBITS utils includes include(AdvancedSet) include(AdvancedOption) include(TimingUtils) diff --git a/cmake/tribits/core/package_arch/TribitsReadAllProjectDepsFilesCreateDepsGraph.cmake b/cmake/tribits/core/package_arch/TribitsReadAllProjectDepsFilesCreateDepsGraph.cmake index 2b71d82885..14175ee5ad 100644 --- a/cmake/tribits/core/package_arch/TribitsReadAllProjectDepsFilesCreateDepsGraph.cmake +++ b/cmake/tribits/core/package_arch/TribitsReadAllProjectDepsFilesCreateDepsGraph.cmake @@ -39,11 +39,12 @@ # Standard TriBITS system includes -include(TribitsConstants) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsConstants.cmake") include(TribitsProcessExtraRepositoriesList) include(TribitsProcessPackagesAndDirsLists) include(TribitsProcessTplsLists) include(TribitsReadDepsFilesCreateDepsGraph) +include(TribitsConfigureTiming) # Standard TriBITS utilities includes include(TimingUtils) diff --git a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake index 4c193adeff..43b0063368 100644 --- a/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake +++ b/cmake/tribits/core/package_arch/TribitsReadDepsFilesCreateDepsGraph.cmake @@ -182,8 +182,7 @@ macro(tribits_read_all_package_deps_files_create_deps_graph) set(${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES "") # Packages and subpackages foreach(TRIBITS_PACKAGE IN LISTS ${PROJECT_NAME}_DEFINED_INTERNAL_TOPLEVEL_PACKAGES) - tribits_read_toplevel_package_deps_files_add_to_graph(${TRIBITS_PACKAGE} - ${${TRIBITS_PACKAGE}_REL_SOURCE_DIR}) + tribits_read_toplevel_package_deps_files_add_to_graph(${TRIBITS_PACKAGE}) endforeach() list(LENGTH ${PROJECT_NAME}_DEFINED_INTERNAL_PACKAGES @@ -456,15 +455,21 @@ macro(tribits_process_package_dependencies_lists packageName) set(${packageName}_LIB_DEFINED_DEPENDENCIES "") set(${packageName}_TEST_DEFINED_DEPENDENCIES "") + # Append the XXX_TPLS list on the end of the XXX_PACKAGES list + list(APPEND LIB_REQUIRED_DEP_PACKAGES ${LIB_REQUIRED_DEP_TPLS}) + list(APPEND LIB_OPTIONAL_DEP_PACKAGES ${LIB_OPTIONAL_DEP_TPLS}) + list(APPEND TEST_REQUIRED_DEP_PACKAGES ${TEST_REQUIRED_DEP_TPLS}) + list(APPEND TEST_OPTIONAL_DEP_PACKAGES ${TEST_OPTIONAL_DEP_TPLS}) + set(LIB_REQUIRED_DEP_TPLS "") + set(LIB_OPTIONAL_DEP_TPLS "") + set(TEST_REQUIRED_DEP_TPLS "") + set(TEST_OPTIONAL_DEP_TPLS "") + # Fill the backward dependency vars tribits_set_dep_packages(${packageName} LIB REQUIRED PACKAGES) tribits_set_dep_packages(${packageName} LIB OPTIONAL PACKAGES) - tribits_set_dep_packages(${packageName} LIB REQUIRED TPLS) - tribits_set_dep_packages(${packageName} LIB OPTIONAL TPLS) tribits_set_dep_packages(${packageName} TEST REQUIRED PACKAGES) tribits_set_dep_packages(${packageName} TEST OPTIONAL PACKAGES) - tribits_set_dep_packages(${packageName} TEST REQUIRED TPLS) - tribits_set_dep_packages(${packageName} TEST OPTIONAL TPLS) # Fill forward deps lists #63 tribits_append_forward_dep_packages(${packageName} LIB) @@ -512,7 +517,7 @@ macro(tribits_set_dep_packages packageName testOrLib requiredOrOptional pkgs if (${depPkg} STREQUAL ${packageName}) tribits_abort_on_self_dep("${packageName}" "${inputListType}") endif() - tribits_is_pkg_defined(${depPkg} ${pkgsOrTpls} depPkgIsDefined) + tribits_is_pkg_defined(${depPkg} depPkgIsDefined) if (depPkgIsDefined) list(APPEND ${packageName}_${testOrLib}_DEFINED_DEPENDENCIES ${depPkg}) if ("${requiredOrOptional}" STREQUAL "REQUIRED") @@ -534,18 +539,12 @@ endmacro() # Determine if a (internal or external) package is defined or not # -function(tribits_is_pkg_defined depPkg pkgsOrTpls depPkgIsDefinedOut) +function(tribits_is_pkg_defined depPkg depPkgIsDefinedOut) set(depPkgIsDefined FALSE) - if (pkgsOrTpls STREQUAL "PACKAGES") - if (${depPkg}_SOURCE_DIR) - set(depPkgIsDefined TRUE) - endif() - elseif(pkgsOrTpls STREQUAL "TPLS") - if (${depPkg}_FINDMOD) - set(depPkgIsDefined TRUE) - endif() - else() - message(FATAL_ERROR "Invalid value for pkgsOrTpls = '${pkgsOrTpls}'") + if (${depPkg}_SOURCE_DIR) + set(depPkgIsDefined TRUE) + elseif(${depPkg}_FINDMOD) + set(depPkgIsDefined TRUE) endif() set(${depPkgIsDefinedOut} ${depPkgIsDefined} PARENT_SCOPE) endfunction() diff --git a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst index f30a089c67..32e2d10d31 100644 --- a/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst +++ b/cmake/tribits/core/package_arch/TribitsSystemDataStructuresMacrosFunctions.rst @@ -334,7 +334,9 @@ the dependencies for each external package/TPL and internal package: This list of all **define direct** extra package test required and optional upstream external package/TPL and internal package dependencies. This list is set regardless if the package ``${PACKAGE_NAME}`` is enabled - or not. + or not. NOTE: This list does **not** contain the items in the list + `${PACKAGE_NAME}_LIB_DEFINED_DEPENDENCIES`_ (but those are implicitly also + required/optional test dependencies as well). .. _${PACKAGE_NAME}_TEST_ENABLED_DEPENDENCIES: @@ -460,76 +462,89 @@ Processing of external packages/TPLs and TriBITS-compliant external packages +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The processing of external packages/TPLs is influenced by whether the external -package is a regular TriBITS TPL or is a TriBITS-compliant external -package. Here, a **TriBITS-Compliant External Package** has a -``Config.cmake`` file that satisfies the following properties: - -* Has the target ``::all_libs``. -* Calls ``find_dependency()`` for all upstream packages it depends on. -* Every upstream dependent package ```` has the target - ``::all_libs``. - -That means that when calling ``find_package()`` for a TriBITS-compliant +package is a regular TriBITS TPL (i.e with a ``FindTPL.cmake`` +modules) or is a TriBITS-compliant external package. Here, a +**TriBITS-Compliant External Package** has a ``Config.cmake`` file +that satisfies the following properties: + +* Has the target ``::all_libs`` which is a fully specified modern + CMake target. +* Calls ``find_dependency()`` or the equivalent for all upstream packages that + it depends on. +* Every upstream dependent package ```` has the target + ``::all_libs``. (But a minimally TriBITS-compliant external + package need not define this for all of its upstream dependencies.) + +That means that when calling ``find_package()`` for a fully TriBITS-compliant external package, there is no need to worry about finding any of its upstream dependent external packages. That means that any external packages/TPLs -defined a TriBITS project which is upstream from a TriBITS-compliant -external package will be uniquely defined by calling ``find_package()`` on the -most downstream TriBITS-compliant external package that depends on it. -Therefore, defining the external packages and their targets in this set of -external packages just involves calling ``find_package()`` on the terminal -TriBITS-compliant external packages (i.e. TriBITS-compliant -external packages that don't have any downstream dependencies that are -external packages). Then the remaining subset of external packages/TPLs that -don't have a downstream TriBITS-compliant external package dependency -will be defined as usual. (ToDo: Put in a more detailed examples explaining -how this works.) +defined a TriBITS project which is upstream from a TriBITS-compliant external +package will be uniquely defined by calling ``find_package()`` on the most +downstream TriBITS-compliant external package that depends on it. Therefore, +defining the external packages and their targets in this set of external +packages just involves calling ``find_package()`` on the terminal +TriBITS-compliant external packages (i.e. TriBITS-compliant external packages +that don't have any downstream dependencies that are external packages). Then +the remaining subset of external packages/TPLs that don't have a downstream +TriBITS-compliant external package dependency will be defined as usual. +(However, as mentioned above, some of these are not fully TriBITS compliant and +don't fully define the ``::all_libs`` for all of their upstream +dependencies (see below).) + +By having all fully TriBITS-compliant external packages, an external +dependency is never found more than once. The variables that are set internally to define these different subsets of external packages/TPLs are: * ``_IS_TRIBITS_COMPLIANT``: Set the ``TRUE`` if the package - ```` provides the ``::all_libs`` target for itself and all - of its upstream dependent (internal or external) packages (whether this - package is treated as an internal or external package). + ```` provides the ``::all_libs`` by just calling + ``find_package( CONFIG REQUIRED)``. * ``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE``: Set to - ``TRUE`` if the external package/TPL will be processed by downstream TriBITS - compliant package. In this case, we just print that we are skipping the - find operation and explain why. + ``TRUE`` if the external package/TPL should be (or was after the fact) + defined by a downstream TriBITS-compliant external package. An external package with ``_IS_TRIBITS_COMPLIANT=TRUE`` **AND** ``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE`` is the one for which ``find_package( CONFIG REQUIRED)`` will be called and does not have any downstream packages that are being treated as external -packages. +packages. Also, ``find_package( CONFIG REQUIRED)`` will be called on +TriBITS-compliant external packages if ``::all_libs`` was not defined +by a downstream non fully TriBITS-compliant external package. -The variable ``_IS_TRIBITS_COMPLIANT`` is set right when the -packages are initially defined by reading in the various input files. That -is, all initially internal packages that are listed in a +The variable ``_IS_TRIBITS_COMPLIANT`` is set right when the packages +are initially defined by reading in the various input files. That is, all +initially internal packages that are listed in a `/PackagesList.cmake`_ file will have -``_IS_TRIBITS_COMPLIANT=TRUE`` set. While all external -packages/TPLs listed in a `/TPLsList.cmake`_ file will have -``_IS_TRIBITS_COMPLIANT=FALSE`` set (except for those tagged -with ``TRIBITS_PKG`` which will have -``_IS_TRIBITS_COMPLIANT=FALSE`` set). - -NOTE: When a TriBITS TPL (i.e. ``_IS_TRIBITS_COMPLIANT=FALSE``) -is being processed, we can't assume where its -``Config.cmake`` file exists so we must find upstream -dependencies using ``set(_DIR ...)`` and -``find_dependency( CONFIG REQUIRED)``. - -So the first loop over external packages/TPLs will be those external -packages/TPLs that have ``_IS_TRIBITS_COMPLIANT=TRUE`` **OR** -``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=TRUE``. And we -only call ``find_package()`` for those TriBITS-compliant external -packages that have ``_IS_TRIBITS_COMPLIANT=TRUE`` **AND** -``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE``. - -The second loop are those external packages/TPLs that don't have a downstream -TriBITS-compliant external package which are all of those external -packages for which ``_IS_TRIBITS_COMPLIANT=FALSE`` **AND** -``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE``. +``_IS_TRIBITS_COMPLIANT=TRUE`` set while all external packages/TPLs +listed in a `/TPLsList.cmake`_ file will have +``_IS_TRIBITS_COMPLIANT=FALSE`` set (except for those tagged with +``TRIBITS_PKG`` which will have ``_IS_TRIBITS_COMPLIANT=FALSE`` set). + +The processing of external packages/TPLs is done in two loops: + +* The first loop over external packages/TPLs will be those external + packages/TPLs that have ``_IS_TRIBITS_COMPLIANT=TRUE`` **OR** + ``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=TRUE``. And we + only call ``find_package()`` for those TriBITS-compliant external packages + that have ``_IS_TRIBITS_COMPLIANT=TRUE`` **AND** don't have + ``::all_libs`` already defined. This is a reverse loop to give an + opportunity for downstream TriBITS-compliant external packages to define + their upstream external packages/TPLs. NOTE: If + ``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE`` was set to + ``TRUE`` before this loop starts, it will be set to ``FALSE`` for + non-TriBITS-compliant external packages + (i.e. ``_IS_TRIBITS_COMPLIANT=FALSE``). + +* The second loop processes remaining external packages/TPLs that where not + defined by a downstream TriBITS-compliant external package in the first + loop. These are all TriBITS TPLs for which + ``_IS_TRIBITS_COMPLIANT=FALSE`` **AND** + ``_PROCESSED_BY_DOWNSTREAM_TRIBITS_EXTERNAL_PACKAGE=FALSE`` **AND** + for which ``_FINDMOD`` is not empty and is not ``TRIBITS_PKG``. + +For more details, see the implementation in `tribits_process_enabled_tpls()`_. Other package-related variables diff --git a/cmake/tribits/core/package_arch/tribits_get_version_date.cmake b/cmake/tribits/core/package_arch/tribits_get_version_date.cmake index 3b941efc4d..c2bcbd1e83 100644 --- a/cmake/tribits/core/package_arch/tribits_get_version_date.cmake +++ b/cmake/tribits/core/package_arch/tribits_get_version_date.cmake @@ -11,7 +11,7 @@ # -P tribits_get_version_date.cmake # -cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) # A) Validate input diff --git a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake b/cmake/tribits/core/test_support/TribitsAddAdvancedTest.cmake similarity index 97% rename from cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake rename to cmake/tribits/core/test_support/TribitsAddAdvancedTest.cmake index 4c3ad13b8a..b9af5d0748 100644 --- a/cmake/tribits/core/package_arch/TribitsAddAdvancedTest.cmake +++ b/cmake/tribits/core/test_support/TribitsAddAdvancedTest.cmake @@ -37,14 +37,16 @@ # ************************************************************************ # @HEADER -include(TribitsCMakePolicies NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsConstants.cmake") -include(TribitsAddAdvancedTestHelpers) -include(TribitsConstants) +set(tribitsAddAdvancedTestModuleDir "${CMAKE_CURRENT_LIST_DIR}") -include(TribitsPrintList) -include(AppendStringVar) -include(PrintVar) +include("${CMAKE_CURRENT_LIST_DIR}/TribitsAddAdvancedTestHelpers.cmake") + +include("${CMAKE_CURRENT_LIST_DIR}/../utils/TribitsPrintList.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/AppendStringVar.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/PrintVar.cmake") # @FUNCTION: tribits_add_advanced_test() @@ -373,7 +375,7 @@ include(PrintVar) # instead. **WARNING:** If you want to run such tests using valgrind, you # have to use the raw executable as the ```` argument and *not* # the script. For example, if you have a python script -# ``my_python_test.py`` with ``/usr/bin/env pyhton`` at the top, you can't +# ``my_python_test.py`` with ``/usr/bin/env python`` at the top, you can't # just use:: # # CMND /my_python_test.py ARGS "" "" ... @@ -853,12 +855,11 @@ include(PrintVar) # # The function ``tribits_add_advanced_test()`` can be used to add tests in # non-TriBITS projects. To do so, one just needs to set the variables -# ``PROJECT_NAME``, ``PACKAGE_NAME`` (which could be the same as -# ``PROJECT_NAME``), ``${PACKAGE_NAME}_ENABLE_TESTS=TRUE``, and -# ``${PROJECT_NAME}_TRIBITS_DIR`` (pointing to the TriBITS location). For example, -# a valid project can be a simple as:: +# ``${PROJECT_NAME}_ENABLE_TESTS=TRUE`` and ``${PROJECT_NAME}_TRIBITS_DIR`` +# (pointing to the TriBITS location). For example, a valid project can be a +# simple as:: # -# cmake_minimum_required(VERSION 3.23.0) +# cmake_minimum_required(VERSION 3.22.0) # set(PROJECT_NAME TAATDriver) # project(${PROJECT_NAME} NONE) # set(${PROJECT_NAME}_TRACE_ADD_TEST TRUE) @@ -866,36 +867,40 @@ include(PrintVar) # "Location of TriBITS to use." ) # set(PACKAGE_NAME ${PROJECT_NAME}) # set(${PACKAGE_NAME}_ENABLE_TESTS TRUE) -# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} -# ${TRIBITS_DIR}/core/utils -# ${TRIBITS_DIR}/core/package_arch ) -# include(TribitsAddAdvancedTest) +# include("${${PROJECT_NAME}_TRIBITS_DIR}/core/test_support/TribitsAddAdvancedTest.cmake") # include(CTest) # enable_testing() # -# tribits_add_advanced_test( -# TAAT_COPY_FILES_TO_TEST_DIR_bad_file_name +# tribits_add_advanced_test( HelloWorld # OVERALL_WORKING_DIRECTORY TEST_NAME # TEST_0 CMND echo ARGS "Hello World!" # PASS_REGULAR_EXPRESIOIN "Hello World" # ) # +# Above, one can replace:: +# +# include("${${PROJECT_NAME}_TRIBITS_DIR}/core/test_support/TribitsAddAdvancedTest.cmake") +# +# with:: +# +# list(PREPEND CMAKE_MODULE_PATH "${${PROJECT_NAME}_TRIBITS_DIR}/core/test_support") +# include(TribitsAddAdvancedTest) +# +# and it will have the same effect. +# function(tribits_add_advanced_test TEST_NAME_IN) if (${PROJECT_NAME}_VERBOSE_CONFIGURE) message("\nPACKAGE_ADD_ADVANCED_TEST: ${TEST_NAME_IN}\n") endif() + tribits_set_tribits_package_name() + global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT) global_set(MESSAGE_WRAPPER_INPUT) # Set the full TEST_NAME - if (PACKAGE_NAME) - set(TEST_NAME ${PACKAGE_NAME}_${TEST_NAME_IN}) - else() - set(TEST_NAME ${TEST_NAME_IN}) - endif() - + set(TEST_NAME ${PACKAGE_NAME}_${TEST_NAME_IN}) # # A) Parse the overall arguments and figure out how many tests @@ -1518,6 +1523,8 @@ function(tribits_add_advanced_test TEST_NAME_IN) # F.2) Write the cmake -P script # + set(coreUtilsDir "${tribitsAddAdvancedTestModuleDir}/../utils") + cmake_path(NORMAL_PATH coreUtilsDir) string(APPEND TEST_SCRIPT_STR "\n" "set(PROJECT_NAME ${PROJECT_NAME})\n" @@ -1548,9 +1555,7 @@ function(tribits_add_advanced_test TEST_NAME_IN) "# Test invocation\n" "#\n" "\n" - "set(CMAKE_MODULE_PATH ${${PROJECT_NAME}_TRIBITS_DIR}/${TRIBITS_CMAKE_UTILS_DIR})\n" - "\n" - "include(DriveAdvancedTest)\n" + "include(\"${coreUtilsDir}/DriveAdvancedTest.cmake\")\n" "\n" "drive_advanced_test()\n" ) diff --git a/cmake/tribits/core/package_arch/TribitsAddAdvancedTestHelpers.cmake b/cmake/tribits/core/test_support/TribitsAddAdvancedTestHelpers.cmake similarity index 98% rename from cmake/tribits/core/package_arch/TribitsAddAdvancedTestHelpers.cmake rename to cmake/tribits/core/test_support/TribitsAddAdvancedTestHelpers.cmake index 8c2e11df36..c7fb556b4d 100644 --- a/cmake/tribits/core/package_arch/TribitsAddAdvancedTestHelpers.cmake +++ b/cmake/tribits/core/test_support/TribitsAddAdvancedTestHelpers.cmake @@ -38,7 +38,7 @@ # @HEADER -include(TribitsAddTestHelpers) +include("${CMAKE_CURRENT_LIST_DIR}/TribitsAddTestHelpers.cmake") # Set default ax number of TEST_ blocks in tribits_add_advanced_test() diff --git a/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake b/cmake/tribits/core/test_support/TribitsAddExecutableTestHelpers.cmake similarity index 92% rename from cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake rename to cmake/tribits/core/test_support/TribitsAddExecutableTestHelpers.cmake index 78f98f0bac..c2bc95d0dd 100644 --- a/cmake/tribits/core/package_arch/TribitsAddExecutableTestHelpers.cmake +++ b/cmake/tribits/core/test_support/TribitsAddExecutableTestHelpers.cmake @@ -37,22 +37,23 @@ # ************************************************************************ # @HEADER -include(TribitsCMakePolicies NO_POLICY_SCOPE) +include_guard() -include(AdvancedSet) -include(MessageWrapper) +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) + +include("${CMAKE_CURRENT_LIST_DIR}/../utils/AdvancedSet.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/MessageWrapper.cmake") advanced_set( ${PROJECT_NAME}_CMAKE_EXECUTABLE_SUFFIX ".exe" CACHE STRING "Default exec suffix on all platforms (can be overridden by each executable added)." ) -# + # Process the COMM arguments # # NOTE: The COMM array arguments is passed as ${ARGN} # - -function( tribits_process_comm_args ADD_SERIAL_FEATURE_OUT ADD_MPI_FEATURE_OUT ) +function(tribits_process_comm_args ADD_SERIAL_FEATURE_OUT ADD_MPI_FEATURE_OUT ) set(COMM_ARRAY ${ARGN}) diff --git a/cmake/tribits/core/package_arch/TribitsAddTest.cmake b/cmake/tribits/core/test_support/TribitsAddTest.cmake similarity index 99% rename from cmake/tribits/core/package_arch/TribitsAddTest.cmake rename to cmake/tribits/core/test_support/TribitsAddTest.cmake index 6f388fdaca..9e23d71c3c 100644 --- a/cmake/tribits/core/package_arch/TribitsAddTest.cmake +++ b/cmake/tribits/core/test_support/TribitsAddTest.cmake @@ -37,8 +37,9 @@ # ************************************************************************ # @HEADER -include(TribitsCMakePolicies NO_POLICY_SCOPE) -include(TribitsAddTestHelpers) + +include("${CMAKE_CURRENT_LIST_DIR}/../common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) +include("${CMAKE_CURRENT_LIST_DIR}/TribitsAddTestHelpers.cmake") # @FUNCTION: tribits_add_test() @@ -817,6 +818,8 @@ function(tribits_add_test EXE_NAME) message("TRIBITS_ADD_TEST: ${EXE_NAME} ${ARGN}") endif() + tribits_set_tribits_package_name() + global_set(TRIBITS_ADD_TEST_ADD_TEST_INPUT) global_set(TRIBITS_SET_TEST_PROPERTIES_INPUT) global_set(MESSAGE_WRAPPER_INPUT) @@ -935,8 +938,6 @@ function(tribits_add_test EXE_NAME) tribits_add_test_adjust_directory( ${EXE_BINARY_NAME} "${PARSE_DIRECTORY}" EXECUTABLE_PATH) - #message("TRIBITS_ADD_TEST: ${EXE_NAME}: EXECUTABLE_PATH = ${EXECUTABLE_PATH}") - # # D) Determine if we will add the serial or MPI tests based on input COMM # and TPL_ENABLE_MPI diff --git a/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake b/cmake/tribits/core/test_support/TribitsAddTestHelpers.cmake similarity index 96% rename from cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake rename to cmake/tribits/core/test_support/TribitsAddTestHelpers.cmake index 715bca20f9..98190718a4 100644 --- a/cmake/tribits/core/package_arch/TribitsAddTestHelpers.cmake +++ b/cmake/tribits/core/test_support/TribitsAddTestHelpers.cmake @@ -37,19 +37,25 @@ # ************************************************************************ # @HEADER +include_guard() -include(TribitsAddExecutableTestHelpers) -include(TribitsGeneralMacros) -include(TribitsTestCategories) - -include(CMakeParseArguments) -include(GlobalSet) -include(AppendGlobalSet) -include(AppendStringVarWithSep) -include(PrintVar) -include(AdvancedSet) -include(MessageWrapper) -include(TribitsGetCategoriesString) +include("${CMAKE_CURRENT_LIST_DIR}/TribitsAddExecutableTestHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/TribitsSetTribitsPackageName.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/TribitsTestCategories.cmake") + +include("${CMAKE_CURRENT_LIST_DIR}/../utils/GlobalSet.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/AppendGlobalSet.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/AppendStringVarWithSep.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/PrintVar.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/AdvancedSet.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/MessageWrapper.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/TribitsGetCategoriesString.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/TribitsSetCacheVarAndDefault.cmake") + + +tribits_advanced_set_cache_var_and_default(${PROJECT_NAME}_TRACE_ADD_TEST BOOL + "${${PROJECT_NAME}_VERBOSE_CONFIGURE}" + "Show a configure-time trace of every test added or not added any why (one line).") # Do initialization for test helpers diff --git a/cmake/tribits/core/test_support/TribitsSetTribitsPackageName.cmake b/cmake/tribits/core/test_support/TribitsSetTribitsPackageName.cmake new file mode 100644 index 0000000000..2a08b4bebf --- /dev/null +++ b/cmake/tribits/core/test_support/TribitsSetTribitsPackageName.cmake @@ -0,0 +1,55 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# 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 Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE +# 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. +# +# ************************************************************************ +# @HEADER + + +include("${CMAKE_CURRENT_LIST_DIR}/../utils/MessageWrapper.cmake") + + +# Set the TriBITS package name var if it has not already been set +# +macro(tribits_set_tribits_package_name) + if ("${PACKAGE_NAME}" STREQUAL "") + if (NOT "${PROJECT_NAME}" STREQUAL "") + set(PACKAGE_NAME ${PROJECT_NAME}) + else() + message_wrapper(FATAL_ERROR "Error! Can't set default PACKAGE_NAME because" + " PROJECT_NAME is not set!") + endif() + endif() +endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsTestCategories.cmake b/cmake/tribits/core/test_support/TribitsTestCategories.cmake similarity index 94% rename from cmake/tribits/core/package_arch/TribitsTestCategories.cmake rename to cmake/tribits/core/test_support/TribitsTestCategories.cmake index acd55cee15..a6f053d639 100644 --- a/cmake/tribits/core/package_arch/TribitsTestCategories.cmake +++ b/cmake/tribits/core/test_support/TribitsTestCategories.cmake @@ -37,10 +37,10 @@ # ************************************************************************ # @HEADER -include(FindListElement) -include(MessageWrapper) -include(Join) -include(TribitsDeprecatedHelpers) +include("${CMAKE_CURRENT_LIST_DIR}/../utils/FindListElement.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/MessageWrapper.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/Join.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/TribitsDeprecatedHelpers.cmake") # Define the valid categories that will be recognized in the CATEGORIES keyword diff --git a/cmake/tribits/core/utils/AppendGlobalSet.cmake b/cmake/tribits/core/utils/AppendGlobalSet.cmake index 51251dc326..04d95f2b54 100644 --- a/cmake/tribits/core/utils/AppendGlobalSet.cmake +++ b/cmake/tribits/core/utils/AppendGlobalSet.cmake @@ -37,8 +37,8 @@ # ************************************************************************ # @HEADER -include(GlobalSet) -include(AssertDefined) +include("${CMAKE_CURRENT_LIST_DIR}/GlobalSet.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/AssertDefined.cmake") # @FUNCTION: append_global_set() diff --git a/cmake/tribits/core/utils/AppendStringVar.cmake b/cmake/tribits/core/utils/AppendStringVar.cmake index dbd0c1fb5d..bac3a6bac8 100644 --- a/cmake/tribits/core/utils/AppendStringVar.cmake +++ b/cmake/tribits/core/utils/AppendStringVar.cmake @@ -37,9 +37,11 @@ # ************************************************************************ # @HEADER -include(ConcatStrings) -include(PrintVar) -include(TribitsDeprecatedHelpers) +include_guard() + +include("${CMAKE_CURRENT_LIST_DIR}/ConcatStrings.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/PrintVar.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/TribitsDeprecatedHelpers.cmake") # @FUNCTION: append_string_var() diff --git a/cmake/tribits/core/utils/AppendStringVarWithSep.cmake b/cmake/tribits/core/utils/AppendStringVarWithSep.cmake index c671ff582e..6e8ccf9fb6 100644 --- a/cmake/tribits/core/utils/AppendStringVarWithSep.cmake +++ b/cmake/tribits/core/utils/AppendStringVarWithSep.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -include(ConcatStrings) +include("${CMAKE_CURRENT_LIST_DIR}/ConcatStrings.cmake") # @FUNCTION: append_string_var_with_sep() diff --git a/cmake/tribits/core/utils/ConcatStrings.cmake b/cmake/tribits/core/utils/ConcatStrings.cmake index a2fdc3c41a..cf5fd64e6e 100644 --- a/cmake/tribits/core/utils/ConcatStrings.cmake +++ b/cmake/tribits/core/utils/ConcatStrings.cmake @@ -37,7 +37,7 @@ # ************************************************************************ # @HEADER -include(PrintVar) +include("${CMAKE_CURRENT_LIST_DIR}/PrintVar.cmake") # @FUNCTION: concat_strings() diff --git a/cmake/tribits/core/utils/DriveAdvancedTest.cmake b/cmake/tribits/core/utils/DriveAdvancedTest.cmake index 87a4a82308..6ccb55fd7a 100644 --- a/cmake/tribits/core/utils/DriveAdvancedTest.cmake +++ b/cmake/tribits/core/utils/DriveAdvancedTest.cmake @@ -37,11 +37,13 @@ # ************************************************************************ # @HEADER -include(PrintVar) -include(AppendStringVar) -include(Join) -include(TimingUtils) -include(TribitsGetCategoriesString) +include_guard() + +include("${CMAKE_CURRENT_LIST_DIR}/PrintVar.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/AppendStringVar.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/Join.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/TimingUtils.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/TribitsGetCategoriesString.cmake") function(print_current_date_time PREFIX_STR) diff --git a/cmake/tribits/core/utils/MessageWrapper.cmake b/cmake/tribits/core/utils/MessageWrapper.cmake index bdcd9e5e29..220f9c8ff6 100644 --- a/cmake/tribits/core/utils/MessageWrapper.cmake +++ b/cmake/tribits/core/utils/MessageWrapper.cmake @@ -39,7 +39,7 @@ include_guard() -include(GlobalSet) +include("${CMAKE_CURRENT_LIST_DIR}/GlobalSet.cmake") # @FUNCTION: message_wrapper() # diff --git a/cmake/tribits/core/utils/TimingUtils.cmake b/cmake/tribits/core/utils/TimingUtils.cmake index a83445663f..ac6351ab9d 100644 --- a/cmake/tribits/core/utils/TimingUtils.cmake +++ b/cmake/tribits/core/utils/TimingUtils.cmake @@ -44,7 +44,7 @@ # platforms so call with care. # -include(Split) +include("${CMAKE_CURRENT_LIST_DIR}/Split.cmake") # @FUNCTION: timer_get_raw_seconds() diff --git a/cmake/tribits/core/utils/TribitsDeprecatedHelpers.cmake b/cmake/tribits/core/utils/TribitsDeprecatedHelpers.cmake index 0ae57138e0..ee6c7fae22 100644 --- a/cmake/tribits/core/utils/TribitsDeprecatedHelpers.cmake +++ b/cmake/tribits/core/utils/TribitsDeprecatedHelpers.cmake @@ -37,8 +37,10 @@ # ************************************************************************ # @HEADER -include(MessageWrapper) -include(TribitsParseArgumentsHelpers) +include_guard() + +include("${CMAKE_CURRENT_LIST_DIR}/MessageWrapper.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/TribitsParseArgumentsHelpers.cmake") set(TRIBITS_HANDLE_TRIBITS_DEPRECATED_CODE_VALUES_THAT_CALL_MESSAGE diff --git a/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake b/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake index 75327668f6..9058db674d 100644 --- a/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake +++ b/cmake/tribits/core/utils/TribitsParseArgumentsHelpers.cmake @@ -46,7 +46,7 @@ ################################################################################ -include(MessageWrapper) +include("${CMAKE_CURRENT_LIST_DIR}/MessageWrapper.cmake") # @FUNCTION: tribits_check_for_unparsed_arguments() diff --git a/cmake/tribits/core/utils/TribitsSetCacheVarAndDefault.cmake b/cmake/tribits/core/utils/TribitsSetCacheVarAndDefault.cmake new file mode 100644 index 0000000000..a90c45aad4 --- /dev/null +++ b/cmake/tribits/core/utils/TribitsSetCacheVarAndDefault.cmake @@ -0,0 +1,89 @@ +# @HEADER +# ************************************************************************ +# +# TriBITS: Tribal Build, Integrate, and Test System +# Copyright 2013 Sandia Corporation +# +# Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +# the U.S. Government retains certain rights in this software. +# +# 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 Corporation nor the names of the +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE +# 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. +# +# ************************************************************************ +# @HEADER + +include_guard() + + +# @MACRO: tribits_advanced_set_cache_var_and_default() +# +# Set an advanced cache variable with a default value (passing in a default +# default value). +# +# Usage:: +# +# tribits_advanced_set_cache_var_and_default( +# ) +# +# If the variable ``_DEFAULT`` already exists with a value, that +# is used as the default cache variable. Otherwise, +# ``_DEFAULT`` is set set to ```` first. +# +macro(tribits_advanced_set_cache_var_and_default cacheVarName cacheVarType + defaultDefaultVal docString + ) + tribits_set_cache_var_and_default("${cacheVarName}" "${cacheVarType}" + "${defaultDefaultVal}" "${docString}") + mark_as_advanced(${cacheVarName}) +endmacro() + + +# @MACRO: tribits_set_cache_var_and_default() +# +# Set a cache variable with a default value (passing in a default default +# value). +# +# Usage:: +# +# tribits_set_cache_var_and_default( +# ) +# +# If the variable ``_DEFAULT`` already exists with a value, that +# is used as the default cache variable. Otherwise, +# ``_DEFAULT`` is set set to ```` first. +# +macro(tribits_set_cache_var_and_default cacheVarName cacheVarType + defaultDefaultVal docString + ) + if ("${${cacheVarName}_DEFAULT}" STREQUAL "") + set(${cacheVarName}_DEFAULT "${defaultDefaultVal}") + endif() + set(${cacheVarName} "${${cacheVarName}_DEFAULT}" + CACHE ${cacheVarType} + "${docString}" ) +endmacro() diff --git a/cmake/tribits/core/package_arch/TribitsSortListAccordingToMasterList.cmake b/cmake/tribits/core/utils/TribitsSortListAccordingToMasterList.cmake similarity index 62% rename from cmake/tribits/core/package_arch/TribitsSortListAccordingToMasterList.cmake rename to cmake/tribits/core/utils/TribitsSortListAccordingToMasterList.cmake index 5d079a4174..4b01327027 100644 --- a/cmake/tribits/core/package_arch/TribitsSortListAccordingToMasterList.cmake +++ b/cmake/tribits/core/utils/TribitsSortListAccordingToMasterList.cmake @@ -37,40 +37,28 @@ # ************************************************************************ # @HEADER -include(PrintVar) -include(AppendSet) +include("${CMAKE_CURRENT_LIST_DIR}/../utils/PrintVar.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/../utils/AppendSet.cmake") + +# Do an in-place sort of a list of items according to the ordering in a master +# list. # -# Function that does an in-place sort of a list of items according to the -# ordering in a master list -# -# NOTE: This function has wost-case N^2 complexity as the number of packages N -# or TPLs increases. It actually has N * n complexity where N is the total -# number of packages/TPLs and n is the number of passed-in packages/TPLs. -# However, since N is not likely to ever be more than a few hundred, this is -# likely not going to be a big performance problem. If this does become a -# performance problem, list(SORT ...) could be used but would require some -# work to build up the datastructures to make this very efficient. +# NOTE: This function has worst-case complexity N*n where N is the number of +# elements in the ```` and n is the number of elements in the +# ```` list. # +function(tribits_sort_list_according_to_master_list masterList listVarInOut) -function(tribits_sort_list_according_to_master_list MASTER_LIST LIST_VAR_INOUT) - - #message("TRIBITS_SORT_LIST_ACCORDING_TO_MASTER_LIST:") - #print_var(MASTER_LIST) - #print_var(LIST_VAR_INOUT) - #print_var(${LIST_VAR_INOUT}) + set(sortedList) - set(SORTED_LIST) - - foreach(ITEM ${MASTER_LIST}) - list(FIND ${LIST_VAR_INOUT} ${ITEM} ITEM_IDX) - if (NOT ITEM_IDX EQUAL -1) - list(APPEND SORTED_LIST ${ITEM}) + foreach(item ${masterList}) + list(FIND ${listVarInOut} ${item} itemIdx) + if (NOT itemIdx EQUAL -1) + list(APPEND sortedList ${item}) endif() endforeach() - #print_var(SORTED_LIST) - - set(${LIST_VAR_INOUT} ${SORTED_LIST} PARENT_SCOPE) + set(${listVarInOut} ${sortedList} PARENT_SCOPE) endfunction() diff --git a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake index 563f5de65c..2515e9892b 100644 --- a/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake +++ b/cmake/tribits/ctest_driver/TribitsCTestDriverCore.cmake @@ -50,7 +50,7 @@ message("*******************************") message("") -cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) set(THIS_CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_DIR}") @@ -137,6 +137,10 @@ if ("${CTEST_BINARY_DIRECTORY}" STREQUAL "") set(CTEST_BINARY_DIRECTORY $ENV{PWD}/BUILD) endif() +include("${CMAKE_CURRENT_LIST_DIR}/../core/common/TribitsConstants.cmake") +tribits_asesrt_minimum_cmake_version() +include("${CMAKE_CURRENT_LIST_DIR}/../core/common/TribitsCMakePolicies.cmake" NO_POLICY_SCOPE) + # # Set CMAKE_MODULE_PATH # @@ -144,15 +148,13 @@ set( CMAKE_MODULE_PATH "${TRIBITS_PROJECT_ROOT}" "${TRIBITS_PROJECT_ROOT}/cmake" "${${PROJECT_NAME}_TRIBITS_DIR}/core/utils" + "${${PROJECT_NAME}_TRIBITS_DIR}/core/common" + "${${PROJECT_NAME}_TRIBITS_DIR}/core/test_support" "${${PROJECT_NAME}_TRIBITS_DIR}/core/package_arch" "${${PROJECT_NAME}_TRIBITS_DIR}/ci_support" "${${PROJECT_NAME}_TRIBITS_DIR}/ctest_driver" ) -include(TribitsConstants) -tribits_asesrt_minimum_cmake_version() -include(TribitsCMakePolicies NO_POLICY_SCOPE) - include(Split) include(PrintVar) include(MultilineSet) diff --git a/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake b/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake index 1aa1aaf339..38c47bf820 100644 --- a/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake +++ b/cmake/tribits/ctest_driver/TribitsGetCTestTestXmlDir.cmake @@ -14,7 +14,7 @@ # then prints the directory /Testing/ to STDOUT. # -cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) if ("${PROJECT_NAME}" STREQUAL "") message(FATAL_ERROR "Error, PROJECT_NAME must be set!") diff --git a/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake b/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake index 4caf72774e..283e32e229 100644 --- a/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake +++ b/cmake/tribits/ctest_driver/tribits_ctest_update_commands.cmake @@ -18,7 +18,7 @@ # 3.12) crash in that case. # -cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) message("\ncmake -P tribits_ctest_update_commands.cmake:") message("-- GIT_EXE=${GIT_EXE}") diff --git a/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake b/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake index 2c3fcf206c..8040574e56 100644 --- a/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake +++ b/cmake/tribits/ctest_driver/tribits_ctest_update_commands_wrapper.cmake @@ -7,7 +7,7 @@ # the output (and does not send it to CDash). # -cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.22.0 FATAL_ERROR) message("\ncmake -P tribits_ctest_update_commands_wrapper.cmake:") message("-- OUTPUT_FILE=${OUTPUT_FILE}\n") diff --git a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst index b0acf3131b..06600479e9 100644 --- a/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst +++ b/cmake/tribits/doc/build_ref/TribitsBuildReferenceBody.rst @@ -1333,7 +1333,7 @@ c) **Setting up to run MPI programs:** MPI test and example executables are passed to CTest ``add_test()`` as:: - add_test( + add_test(NAME COMMAND ${MPI_EXEC} ${MPI_EXEC_PRE_NUMPROCS_FLAGS} ${MPI_EXEC_NUMPROCS_FLAG} ${MPI_EXEC_POST_NUMPROCS_FLAGS} @@ -1994,9 +1994,10 @@ external packages has several consequences: (Otherwise, a configure error will result from the mismatch.) * The definition of any TriBITS external packages/TPLs that are enabled - upstream dependencies from any of these internally defined packages being - treated as external packages will be defined by the calls to - ``find_package()`` and will **not** be found again. + upstream dependencies from any of these external packages should be defined + automatically and will **not** be found again. (But there can be exceptions + for minimally TriBITS-compliant external packages; see the section + "TriBITS-Compliant External Packages" in the "TriBITS Users Guide".) The logic for treating internally defined packages as external packages will be printed in the CMake configure output in the section ``Adjust the set of @@ -2016,22 +2017,35 @@ the terminal TriBITS-compliant external packages. This is shown in the CMake output in the section ``Getting information for all enabled TriBITS-compliant or upstream external packages/TPLs`` and looks like:: - Getting information for all enabled TriBITS-compliant or upstream external packages/TPLs ... + Getting information for all enabled TriBITS-compliant or upstream external packages/TPLs in reverse order ... - Processing enabled external package/TPL: (...) - -- The external package/TPL will be read in by a downstream TriBITS-compliant external package - Processing enabled external package/TPL: (...) - -- The external package/TPL will be read in by a downstream TriBITS-compliant external package - Processing enabled external package/TPL: (...) - -- The external package/TPL will be read in by a downstream TriBITS-compliant external package Processing enabled external package/TPL: (...) -- Calling find_package( for TriBITS-compliant external package + Processing enabled external package/TPL: (...) + -- The external package/TPL was defined by a downstream TriBITS-compliant external package already processed + Processing enabled external package/TPL: (...) + -- The external package/TPL was defined by a downstream TriBITS-compliant external package already processed + Processing enabled external package/TPL: (...) + -- The external package/TPL was defined by a downstream TriBITS-compliant external package already processed In the above example ````, ```` and ```` are all direct or indirect dependencies of ```` and therefore calling just ``find_package()`` fully defines those TriBITS-compliant external packages as well. +All remaining TPLs that are not defined in that first reverse loop are defined +in a second forward loop over regular TPLs:: + + Getting information for all remaining enabled external packages/TPLs ... + +NOTE: The case is also supported where a TriBITS-compliant external package +like ```` does not define all of it upstream dependencies (i.e. does not +define the ``::all_libs`` target) and these external packages/TPLs will +be found again. This allows the possibility of finding different/inconsistent +upstream dependencies but this is allowed to accommodate some packages with +non-TriBITS CMake build systems that don't create fully TriBITS-compliant +external packages. + xSDK Configuration Options -------------------------- @@ -4168,14 +4182,23 @@ match files to exclude, set:: -D _DUMP_CPACK_SOURCE_IGNORE_FILES=ON +Extra directories or files can be excluded from the reduced source tarball by +adding the configure argument:: + + "-DCPACK_SOURCE_IGNORE_FILES=;;..." + +NOTE: The entries in ``CPACK_SOURCE_IGNORE_FILES`` are regexes and **not** +file globs, so be careful when specifying these or more files and directories +will be excluded from the reduced source tarball that intended/desired. + While a set of default CPack source generator types is defined for this project (see the ``CMakeCache.txt`` file), it can be overridden using, for example:: -D _CPACK_SOURCE_GENERATOR="TGZ;TBZ2" -(see CMake documentation to find out the types of supported CPack source -generators on your system). +(See CMake documentation to find out the types of CPack source generators +supported on your system.) NOTE: When configuring from an untarred source tree that has missing packages, one must configure with:: @@ -4205,7 +4228,7 @@ just using the standard ``ctest -D Experimental`` command are: For more details, see `tribits_ctest_driver()`_. To use the ``dashboard`` target, first, configure as normal but add cache vars -for the the build and test parallel levels with:: +for the build and test parallel levels with:: -DCTEST_BUILD_FLAGS=-j4 -DCTEST_PARALLEL_LEVEL=4 diff --git a/cmake/tribits/doc/guides/.gitignore b/cmake/tribits/doc/guides/.gitignore index 7f018678f2..6c3878b7fb 100644 --- a/cmake/tribits/doc/guides/.gitignore +++ b/cmake/tribits/doc/guides/.gitignore @@ -4,6 +4,9 @@ /TriBITS.README.DIRECTORY_CONTENTS.rst.tmp /TribitsCommonTPLsList.txt /TribitsCommonTPLsList.txt.tmp +/TribitsExampleProject2_Package1_CMakeLists.raw.external.cmake* +/TribitsExampleProject2_Package1_CMakeLists.raw.internal.cmake* +/TribitsExampleProject2_Package1_CMakeLists.raw.tribits_test.cmake* /TribitsGitVersion.txt /TribitsGitVersion.txt.tmp /TribitsHelloWorldDirAndFiles.txt diff --git a/cmake/tribits/doc/guides/Makefile.common_generated_files b/cmake/tribits/doc/guides/Makefile.common_generated_files index c6a352d122..6984ee3c63 100644 --- a/cmake/tribits/doc/guides/Makefile.common_generated_files +++ b/cmake/tribits/doc/guides/Makefile.common_generated_files @@ -27,6 +27,7 @@ COMMON_DEPENDENT_FILES = \ ../get-tribits-packages-from-files-list.txt \ ../install_devtools-help.txt \ ../TriBITS.README.DIRECTORY_CONTENTS.rst \ + $(wildcard ../*.cmake) \ TribitsMacroFunctionDoc.rst \ UtilsMacroFunctionDoc.rst diff --git a/cmake/tribits/doc/guides/TribitsGuidesBody.rst b/cmake/tribits/doc/guides/TribitsGuidesBody.rst index b8f77bd5b0..210e4cc805 100644 --- a/cmake/tribits/doc/guides/TribitsGuidesBody.rst +++ b/cmake/tribits/doc/guides/TribitsGuidesBody.rst @@ -1379,7 +1379,7 @@ The variable ``HAVE_SIMPLECXX___INT64`` is set up in the base file ``SimpleCxx/CMakeLists.txt`` (see `/CMakeLists.txt`_ below). For an explanation of ``HAVE_SIMPLECXX_DEBUG``, see `tribits_add_debug_option()`_. For an explanation of ``HAVE_SIMPLECXX_SIMPLETPL``, see `How to add a new -TriBITS external package/TPL dependency`_. For an explanation of +TriBITS Package dependency`_. For an explanation of ``@SIMPLECXX_DEPRECATED_DECLARATIONS@``, see `Setting up support for deprecated code handling`_. @@ -1617,7 +1617,7 @@ are defined before a Package's ``CMakeLists.txt`` file is processed: **NOTE:** The value of this variable also determines the value of the macro define variable name - `HAVE__`_. + `HAVE__`_. .. _${PACKAGE_NAME}_ENABLE_TESTS: @@ -1643,23 +1643,23 @@ The following local **TriBITS Package Optional Dependency Macro Variables** are defined in the top-level project scope before a Package's ``CMakeLists.txt`` file is processed: - .. _HAVE__: + .. _HAVE__: - ``HAVE__`` + ``HAVE__`` Set to ``ON`` if support for optional upstream package ``${OPTIONAL_DEP_PACKAGE}`` is enabled in downstream package ``${PACKAGE_NAME}`` (i.e. `${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}`_ = ``ON``) and is set to ``FALSE`` otherwise. Here, ```` and - ```` are the upper-case names for the packages + ```` are the upper-case names for the packages ``${PACKAGE_NAME}`` and ``${OPTIONAL_DEP_PACKAGE_NAME}``, respectively. For example, if optional support for upstream package ``Triutils`` is enabled in downstream package ``EpetraExt`` in `ReducedMockTrilinos`_, then ``EpetraExt_ENABLE_TriUtils=ON`` and ``HAVE_EPETRAEXT_TRIUTILS=ON``. This variable is meant to be used in:: - #cmakedefine HAVE__ + #cmakedefine HAVE__ in configured header files (e.g. `/cmake/_config.h.in`_). For example, for @@ -2615,33 +2615,20 @@ packages** as imposed by downstream TriBITS internal packages are: CMake macros or functions that downstream CMake packages may need to use the upstream package ````. -* All of the upstream dependencies (listed in the ``INTERFACE_LINK_LIBRARIES`` - property recursively) are also `TriBITS-compliant packages`_ +* [Optional] All of the upstream dependencies (listed in the + ``INTERFACE_LINK_LIBRARIES`` property recursively) are also + `TriBITS-compliant packages`_ The TriBITS system will also set the variable: * ``_IS_TRIBITS_COMPLIANT``: Set to ``TRUE`` -for all packages that are determined to be TriBITS-compliant packages. +for all packages that are determined to be TriBITS-compliant packages and +satisfy the above criteria. The above are all that is needed by downstream TriBITS packages to build and link against their upstream dependencies. -If a TriBITS package provides any CTest tests/examples, then it must also -satsify the following requirements: - -* Test names must be prefixed with the package name ``_``. - -* Tests should only be added if the variable ``_ENABLE_TESTS`` is - true. - -* Examples (that run as CTest tests) should only be added if the variable - ``_ENABLE_EXAMPLES`` is true. - -* The test ``PROCESSORS`` and other test properties must be set in a way - consistent with `tribits_add_test()`_ so as to run in parallel with other - tests and not overwhelm the computing resources on the machine. - Additional requirements are placed on TriBITS-compliant packages depending on if they are defined as internal CMake packages (i.e. `TriBITS-compliant internal packages`_) or are pulled in as external pre-built/pre-installed @@ -2672,15 +2659,38 @@ The requirements for **TriBITS-compliant internal packages** are: directory ``/lib/cmake//`` allowing the installed package to be used by downstream CMake packages/projects. -* All of the upstream dependencies (recursively) are also `TriBITS-compliant - packages`_ +* [Optional] All of the upstream dependencies (recursively) are also + `TriBITS-compliant packages`_. + +If a TriBITS package provides any CTest tests/examples, then it must also +satisfy the following requirements: + +* Test names must be prefixed with the package name ``_``. + +* Tests should only be added if the variable ``_ENABLE_TESTS`` is + true. + +* Examples (that run as CTest tests) should only be added if the variable + ``_ENABLE_EXAMPLES`` is true. + +* The ``PROCESSORS`` test property and other test properties must be set in a + way consistent with `tribits_add_test()`_ so as to run in parallel with + other tests and not overwhelm the computing resources on the machine. + +* The test ```` must not be added if the cache variable + ``_DISABLE`` is set to ``TRUE`` or if the cache variable + ``_SET_DISABLED_AND_MSG`` is set to non-empty (and the message + string should be printed to STDOUT). TriBITS internal packages that are defined using the TriBITS framework using -the TriBITS-provided macros and functions such as `tribits_add_library()`_ are -automatically `TriBITS-compliant internal packages`_ and when they are -installed they automatically provide `TriBITS-compliant external packages`_. +the TriBITS-provided macros and functions such as `tribits_add_library()`_ and +have tests defined using the functions `tribits_add_test()`_ and +`tribits_add_advanced_test()`_ are automatically `TriBITS-compliant internal +packages`_. And when these TriBITS-implemented internal packages are +installed, they automatically provide `TriBITS-compliant external packages`_. But it is possible for a CMake package to write its own raw CMake code to -satisfy these basic requirements for both internal and external packages. +satisfy these basic requirements for both internal and (installed) external +packages. .. _TriBITS-Compliant External Package: @@ -2692,8 +2702,9 @@ For packages that are installed on the system and not built in the current CMake project, a streamlined type of `TriBITS External Package/TPL`_ is a *TriBITS-compliant external package*. These special types of external package's don't need to provide a `FindTPL.cmake`_ find module. -Instead, they are fully defined by calling ``find_package()`` to -locate and load their ``Config.cmake`` package config file. +Instead, they are fully defined by calling ``find_package()`` or +``include(/Config.cmake)`` to load their +``Config.cmake`` package config file. The requirements for **TriBITS-compliant external packages** are: @@ -2708,18 +2719,23 @@ The requirements for **TriBITS-compliant external packages** are: ``_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE``: Points to the file ``Config.cmake`` (i.e. ``${CMAKE_CURRENT_LIST_FILE}``) - * ``_DIR`` or - ``_TRIBITS_COMPLIANT_PACKAGE_CONFIG_FILE_DIR`` Points to the base - directory for ``Config.cmake`` - (i.e. ``${CMAKE_CURRENT_LIST_DIR}``) - -* All of the upstream dependencies (recursively) are also provided as - `TriBITS-compliant external packages`_ with +* [Optional] All of the upstream dependencies (recursively) are also provided + as `TriBITS-compliant external packages`_ with ``Config.cmake`` files (see above) and all of the targets and variables for a TriBITS-compliant external package are defined when the ``Config.cmake`` file is included (or pulled in with ``find_package()`` or ``find_dependency()``). +NOTE: TriBITS-compliant external packages that provide TriBITS-compliant +external packages for all of their upstream dependencies are said to be *fully +TriBITS-compliant external packages* while those that support the minimal +requirements are said to be *minimally TriBITS-compliant external packages*. +The TriBITS external package/TPL system is robust enough to deal with +minimally TriBITS-compliant external packages. Any TriBITS external +packages/TPLs upstream from a minimally TriBITS-compliant external package +will be found again in the current TriBITS project. (In these cases, it is up +to the user to make sure that the same upstream packages are found.) + Example TriBITS Projects ========================= @@ -2954,6 +2970,28 @@ should be copied from this example project as they represent best practice when using TriBITS for the typical use cases. +TribitsExampleProject2 +---------------------- + +``TribitsExampleProject2`` in an example `TriBITS Project`_ and `TriBITS +Repository`_ contained in the TriBITS source tree under:: + + tribits/examples/TribitsExampleProject2/ + +This example TriBITS project provides some examples for a few other features +and testing scenarios. It contains three internal packages ``Package1``, +``Package2``, and ``Package3`` as shown in its ``PackagesList.cmake`` file: + +.. include:: ../../examples/TribitsExampleProject2/PackagesList.cmake + :literal: + +and supports four external packages/TPLs ``Tpl1``, ``Tpl2``, ``Tpl3``, and +``Tpl4`` as shown in its ``TPLsList.cmake`` file: + +.. include:: ../../examples/TribitsExampleProject2/TPLsList.cmake + :literal: + + MockTrilinos ------------- @@ -5954,14 +5992,14 @@ links. How to add a new TriBITS Package dependency ----------------------------------------------- +------------------------------------------- It is often the case where one will want to add a new dependency for an -existing `downstream`_ package to an existing `upstream`_ `TriBITS Package`_. -This can either be a required dependency or an optional dependency. Here, we -will refer to the downstream package as ```` with base directory -```` and will refer to the upstream package as -````. +existing `downstream`_ package to an existing `upstream`_ (internal or +external) `TriBITS Package`_. This can either be a required dependency or an +optional dependency. Here, we will refer to the downstream package as +```` with base directory ```` and will refer to the +upstream (internal or external) package as ````. The process for adding a new dependency to an existing upstream package is as follows: @@ -5986,9 +6024,9 @@ as follows: typically a C/C++ processor macro will be added to the package's configured `/cmake/_config.h.in`_ file using the line:: - #cmakedefine HAVE__ + #cmakedefine HAVE__ - (see `HAVE__`_.) + (see `HAVE__`_.) .. _Warning, do not add optional defines for tests/examples to configured header files: @@ -6017,21 +6055,29 @@ as follows: #include "_config.h" - #if HAVE__ + #if HAVE__ # include "_" #endif 4) **For an optional dependency, use CMake if() statements based on - ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}:** When a package + ${PACKAGE_NAME}_ENABLE_:** When a package ``PACKAGE_NAME`` has an optional dependency on an upstream package - ``OPTIONAL_DEP_PACKAGE_NAME`` and needs to put in optional logic in a - CMakeLists.txt file, then the if() statements should use the variable - `${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}`_ and **not** the - variable ``${PROJECT_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}``. For - example, to optionally enable a test that depends on the enable of the - optional upstream dep package, one would use:: - - if (${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}) + ```` and needs to put in optional logic in a + ``CMakeLists.txt`` file, then the ``if()`` statements should use the + variable ``${PACKAGE_NAME}_ENABLE_`` and **not** the + variable ``${PROJECT_NAME}_ENABLE_`` or + ``TPL_ENABLE_`` (if ```` is an + external package/TPL). For example, to optionally enable a test that + depends on the enable of the optional upstream dependent package + ````, one would use:: + + tribits_add_test( ... + EXCLUDE_IF_NOT_TRUE ${PACKAGE_NAME}_ENABLE_ + ) + + or:: + + if (${PACKAGE_NAME}_ENABLE_) tribits_add_test( ... ) endif() @@ -6045,100 +6091,13 @@ package library and executable links. See documentation in the functions argument to these functions, for more details. -How to add a new TriBITS external package/TPL dependency --------------------------------------------------------- - -It is often the case where one will want to add a new dependency for an -existing `downstream`_ package to an existing `upstream`_ `TriBITS external -package/TPL`_. This can either be a required dependency or an optional -dependency. Here, we will refer to the downstream package as -```` with base directory ```` and will refer to the -upstream TPL as ````. - -The process for adding a new dependency to an existing upstream TPL is as -follows: - -1) **Add the name of the upstream TPL to the downstream package's - Dependencies.cmake file:** Add ```` to the call of - `tribits_package_define_dependencies()`_ in the downstream package's - `/cmake/Dependencies.cmake`_ file. If this is to be a required - library dependency, then ```` is added to the - ``LIB_REQUIRED_TPLs`` argument. Alternatively, if this is to be an - optional library dependency, then ```` is added to the - ``LIB_OPTIONAL_TPL`` argument. (For example, see the file - ``packages/Teuchos/cmake/Dependencies.cmake`` file in the - `ReducedMockTrilinos`_ project.) If only the test and/or example sources, - and not the package's core library sources, will have the required or - optional dependency, then ```` is added to the arguments - ``TEST_REQUIRED_TPLs`` or ``TEST_OPTIONAL_TPLS``, respectively. - -2) **For an optional dependency, add `HAVE_` preprocessor macro to the - package's configured header file:** If this is an optional dependency, - typically a C/C++ processor macro will be added to the package's configured - `/cmake/_config.h.in`_ file using the line:: - - #cmakedefine HAVE__ - - (see `HAVE__`_.) - - **WARNING:** If this is a test-only and/or example-only dependency then - please do **not** add a ``#cmakedefine`` to the package's core - `/cmake/_config.h.in`_ file. See `Warning, do not - add optional defines for tests/examples to configured header files`_. - -3) **Use the features of the upstream TPL in the source files of the - downstream package sources and/or tests/examples:** Usage of the features - of the upstream package ```` in the downstream package - ```` will typically involve adding ``#include - _`` in the package's C/C++ source (or test/example) - files (or the equivalent in Fortran). If it is an optional dependency, - then these includes will typically be protected using preprocessor ifdefs, - for example, as:: - - #include "_config.h" - - #if HAVE__ - # include "_" - #endif - -4) **For an optional dependency, use CMake if() statements based on - ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}:** When a package - ``PACKAGE_NAME`` has an optional dependency on TPL - ``OPTIONAL_DEP_PACKAGE_NAME`` and needs to put in optional logic in a - CMakeLists.txt file, then the if() statements should use the variable - `${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}`_ and **not** the - variable ``${PROJECT_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}``. For - example, to optionally enable a test that depends on the enable of the - optional TPL, one could use:: - - if (${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME}) - tribits_add_test( ... ) - endif() - - or:: - - tribits_add_test( - EXCLUDE_IF_NOT_TRUE ${PACKAGE_NAME}_ENABLE_${OPTIONAL_DEP_PACKAGE_NAME} - [other args] - ) - - .. ToDo: Find an example to point to in TribitsExampleProject. - -NOTE: TriBITS will automatically add the include directories for the upstream -TPL to the compile lines for the downstream package source builds and will add -the libraries for the upstream TPL to the link lines to the downstream package -library and executable links. See documentation in the functions -`tribits_add_library()`_ and `tribits_add_executable()`_, and the ``DEPLIBS`` -argument to these functions, for more details. - - How to tentatively enable an external package/TPL ------------------------------------------------- A TriBITS package can request the tentative enable of any of its optional -external packagse/TPLs (see `How to add a new TriBITS external package/TPL -dependency`_). This is done by calling `tribits_tpl_tentatively_enable()`_ in -the package's `/cmake/Dependencies.cmake`_ file. For example:: +external packagse/TPLs (see `How to add a new TriBITS Package dependency`_). +This is done by calling `tribits_tpl_tentatively_enable()`_ in the package's +`/cmake/Dependencies.cmake`_ file. For example:: tribits_package_define_dependencies( ... @@ -6303,6 +6262,243 @@ file as well. Then every ``CMakeLists.txt`` file in subdirectories just calls ``include_tribits_build()``. That is it. +How to implement a TriBITS-compliant internal package using raw CMake +--------------------------------------------------------------------- + +As described in `TriBITS-Compliant Internal Packages`_, it is possible to +create a raw CMake build system for a CMake package that can build under a +parent TriBITS CMake project. The raw CMake code for such a package must +provide the ``::all_libs`` target both in the current CMake build +system and also in the generated ``Config.cmake`` file for the build +directory and in the installed ``Config.cmake`` file. Every such +TriBITS-compliant internal package therefore is **also capable of installing a +TriBITS-compliant external package** ``Config.cmake`` file (see `How +to implement a TriBITS-compliant external package using raw CMake`_). + +.. ToDo: Consider listing out the key features of a raw CMake build system + that is needed for a TriBITS-compliant internal package. + +A raw CMake build system for a TriBITS-compliant internal package is +demonstrated in the `TribitsExampleProject2`_ project ``Package1`` package. +The base ``CMakeLists.txt`` file for building ``Package1`` with a raw CMake +build system (called ``package1/CMakeLists.raw.cmake`` in that directory) +looks like: + +.. include:: TribitsExampleProject2_Package1_CMakeLists.raw.internal.cmake + :literal: + +As shown above, this simple CMake package contains the basic features of any +CMake project/package including calling the ``cmake_minimum_required()`` and +``project()`` commands as well as including ``GNUInstallDirs``. In this +example, the project/package being built ``Package1`` has a dependency on an +external upstream package ``Tpl1`` pulled in with ``find_package(Tpl1)``. +Also in this example, the package has native tests it defines with +``include(CTest)`` and ``add_subdirectory()`` (if ``Package1_ENABLE_TESTS`` is +set to ``ON``). + +The file ``package1/src/CMakeLists.raw.cmake`` (which gets included from +``package1/src/CMakeLists.txt``) creates a library and executable for the +package and has the contents: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/src/CMakeLists.raw.cmake + :literal: + +This creates a single installable library target ``Package1_package1`` which +is aliased as ``Package1::package1`` in the current CMake project and sets up +to create the IMPORTED target ``Package1::package1`` in the generated +``Package1ConfigTarget.cmake`` file, which gets included in the installed +``Package1Config.cmake`` (``Config.cmake``) file (as recommenced in +the book "Professional CMake", see below). In addition, the above code +creates the installable executable ``package1-prg``. + +The ``Package1::all_libs`` (``::all_libs``) target is defined and set +up inside of the included file +``package1/cmake/raw/DefineAllLibsTarget.cmake`` which contains the code: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/cmake/raw/DefineAllLibsTarget.cmake + :literal: + +The above code contains the ALIAS library target ``Package1::all_libs`` +(``::all_libs``) for the current CMake project as well as sets up for +the IMPORTED target ``Package1::all_libs`` (``::all_libs``) getting +put in the generated ``Package1ConfigTargets.cmake`` file (see below). + +The ``Package1Config.cmake`` (``Config.cmake``) file for the build +directory is generated inside of the included file +``package1/cmake/raw/GeneratePackageConfigFileForBuildDir.cmake`` which has +the contents: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForBuildDir.cmake + :literal: + +The above code uses the ``export(EXPORT ...)`` command to generate the file +``Package1ConfigTargets.cmake`` for the build directory which provides the +IMPORTED targets ``Package1::package1`` and ``Package1::all_libs``. The +command ``configure_file(...)`` generates the ``Package1Config.cmake`` file +that includes it for the build directory +``/cmake_packages/Package1/``. (NOTE: The above code only runs when +the package is being built from inside of a TriBITS project which defines the +command ``tribits_package``. So this code gets skipped when building +``Package1`` as a stand-alone raw CMake project.) + +Finally, the code for generating and installing the ``Package1Config.cmake`` +file for the install directory ``CMAKE_PREFIX_PATH=`` is specified +in the included file +``package1/cmake/raw/GeneratePackageConfigFileForInstallDir.cmake`` with the +contents: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForInstallDir.cmake + :literal: + +The above uses the command ``install(EXPORT ...)`` to have CMake automatically +generate and install the file ``Package1ConfigTargets.cmake`` in the install +directory ``/libs/cmake/Package1/`` which provides the IMPORTED +targets ``Package1::package1`` and ``Package1::all_libs``. The command +``configure_file()`` is used to generate the file +``Package1Config.install.cmake`` in the build directory from the template file +``Package1Config.cmake.in``. Finally, the ``install()`` command is used in +the file ``GeneratePackageConfigFileForInstallDir.cmake`` to set up the +installation of the ``Package1Config.cmake`` file. + +Note, the template file ``package1/cmake/raw/Package1Config.cmake.in`` (which +is unique to ``Package1``) is: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/cmake/raw/Package1Config.cmake.in + :literal: + +As shown in the all of the above code, there is a lot of boilerplate CMake +code needed to correctly define the targets such that they get put into the +installed ``Package1Config.cmake`` file using the correct namespace +``Package1::`` and care must be taken to ensure that a consistent "export set" +is used for this purpose. (For more details, see the book "Professional +CMake".) + +**NOTE:** One should compare the above raw CMakeLists files to the more +compact TriBITS versions for the base ``package1/CMakeLists.txt`` file (called +``package1/CMakeLists.tribits.cmake`` in the base directory ``pacakge1/``): + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/CMakeLists.tribits.cmake + :literal: + +and the TriBITS ``package1/src/CMakeLists.txt`` file (called +``package1/src/CMakeLists.tribits.cmake``): + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/src/CMakeLists.tribits.cmake + :literal: + +This shows the amount of boilerplate code that TriBITS addresses automatically +(which reduces the overhead of finer-grained packages and avoids common +mistakes with tedious low-level CMake code). + + +How to implement a TriBITS-compliant external package using raw CMake +--------------------------------------------------------------------- + +As described in `TriBITS-Compliant External Packages`_, it is possible to +create a raw CMake build system for a CMake package such that once it is +installed, satisfies the requirements for a TriBITS-compliant external +package. These installed packages provide a ``Config.cmake`` file +that provides the required targets and behaviors as if it was produced by a +TriBITS project. For most existing raw CMake projects that already produce a +"Professional CMake" compliant ``Config.cmake`` file, that usually +just means adding the IMPORTED target called ``::all_libs`` to the +installed ``Config.cmake`` file. + +A raw CMake build system for a TriBITS-compliant external package is +demonstrated in the `TribitsExampleProject2`_ project ``Package1`` package. +The base ``package1/CMakeLists.txt`` file for building ``Package1`` with a raw +CMake build system (called ``package1/CMakeLists.raw.cmake``) for implementing +a TriBITS-compliant internal package looks like: + +.. include:: TribitsExampleProject2_Package1_CMakeLists.raw.external.cmake + :literal: + +Note that the raw build system this example is identical to the build system +for the raw TriBITS-compliant internal package described in `How to implement +a TriBITS-compliant internal package using raw CMake`_. The only differences +are: + +1) The ``Package1Config.cmake`` (``Config.cmake``) file does **not** + need to be generated for the build directory and therefore the code in + ``cmake/raw/GeneratePackageConfigFileForBuildDir.cmake`` does **not** need + to be included. + +2) The ALIAS library target ``Package1::all_libs`` (``::all_libs``) + does **not** need to be generated (but should be to be "Professional CMake" + compliant). + +Other than that, see `How to implement a TriBITS-compliant internal package +using raw CMake`_ for how to implement a TriBITS-compliant external package. + + +How to use TriBITS testing support in non-TriBITS project +--------------------------------------------------------- + +The TriBITS test support functions `tribits_add_test()`_ and +`tribits_add_advanced_test()`_ can be used from any raw (i.e. non-TriBITS) +CMake project. To do so, one just needs to include the TriBITS modules: + +* ``/core/test_support/TribitsAddTest.cmake`` +* ``/core/test_support/TribitsAddAdvancedTest.cmake`` + +and set the variable ``${PROJECT_NAME}_ENABLE_TESTS`` to ``ON``. For an +MPI-enabled CMake project, the CMake variables ``MPI_EXEC``, +``MPI_EXEC_PRE_NUMPROCS_FLAGS``, ``MPI_EXEC_NUMPROCS_FLAG`` and +``MPI_EXEC_POST_NUMPROCS_FLAGS`` must also be set which define the MPI runtime +program launcher command-line used in the TriBITS testing functions:: + + ${MPI_EXEC} ${MPI_EXEC_PRE_NUMPROCS_FLAGS} + ${MPI_EXEC_NUMPROCS_FLAG} + ${MPI_EXEC_POST_NUMPROCS_FLAGS} + + +(NOTE: These variables are defined automatically in a TriBITS project when +``TPL_ENABLE_MPI`` is set to ``ON``.) + +This is demonstrated in the `TribitsExampleProject2`_ project ``Package1`` +package. The base ``pacakge1/CMakeLists.txt`` file for building ``Package1`` +with a raw CMake build system using TriBITS testing functions (called +``package1/CMakeLists.raw.cmake``) looks like: + +.. include:: TribitsExampleProject2_Package1_CMakeLists.raw.tribits_test.cmake + :literal: + +The only difference between this base ``package1/CMakeLists.txt`` file and one +for a raw CMake project is the inclusion of the file +``package1/cmake/raw/EnableTribitsTestSupport.cmake`` which has the contents: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/cmake/raw/EnableTribitsTestSupport.cmake + :literal: + +The key lines are:: + + include("${Package1_TRIBITS_DIR}/core/test_support/TribitsAddTest.cmake") + include("${Package1_TRIBITS_DIR}/core/test_support/TribitsAddAdvancedTest.cmake") + +This defines the CMake functions `tribits_add_test()`_ and +`tribits_add_advanced_test()`_, respectively. + +The above code demonstrates that ``CMAKE_MODULE_PATH`` does **not** need to be +updated to use these TriBITS ``test_support`` modules. However, one is free +to update ``CMAKE_MODULE_PATH`` and then include the modules by name only +like:: + + list(PREPEND CMAKE_MODULE_PATH "${Package1_TRIBITS_DIR}/core/test_support") + include(TribitsAddTest) + include(TribitsAddAdvancedTest) + +Once these TriBITS modules are included, one can use the TriBITS functions as +demonstrated in the file ``package1/test/CMakeLists.tribits.cmake`` (which is +included from the file ``package1/test/CMakeLists.txt``) and has the contents: + +.. include:: ../../examples/TribitsExampleProject2/packages/package1/test/CMakeLists.tribits.cmake + :literal: + +Note that in this example, the executable ``package1-prg`` was already +created. If new test libraries and executables need to be created, then the +raw CMake commands to create those will need to be added as well. + + How to check for and tweak TriBITS "ENABLE" cache variables ----------------------------------------------------------- diff --git a/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst index 6a71292c45..3723c3b7c8 100644 --- a/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/TribitsSystemMacroFunctionDocTemplate.rst @@ -34,6 +34,7 @@ understand the internals of TriBITS. @MACRO: tribits_parse_subpackages_append_packages_add_options() + @MACRO: tribits_prep_to_read_dependencies() + @MACRO: tribits_process_all_repository_deps_setup_files() + +@MACRO: tribits_process_enabled_tpls() + @MACRO: tribits_process_package_dependencies_lists() + @MACRO: tribits_process_packages_and_dirs_lists() + @MACRO: tribits_process_project_dependency_setup_file() + @@ -50,6 +51,6 @@ understand the internals of TriBITS. @MACRO: tribits_save_off_dependency_vars() + @MACRO: tribits_set_dep_packages() + @FUNCTION: tribits_trace_file_processing() + -@FUNCTION: tribits_write_package_client_export_files_install_targets() + +@FUNCTION: tribits_write_package_client_export_files_export_and_install_targets() + @MACRO: tribits_write_xml_dependency_files() + @FUNCTION: tribits_write_xml_dependency_files_if_supported() + diff --git a/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst b/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst index acc98214c1..79bb6ea0df 100644 --- a/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst +++ b/cmake/tribits/doc/guides/UtilsMacroFunctionDocTemplate.rst @@ -39,9 +39,11 @@ @FUNCTION: timer_get_rel_seconds() + @FUNCTION: timer_print_rel_time() + @FUNCTION: tribits_add_enum_cache_var() + +@MACRO: tribits_advanced_set_cache_var_and_default() + @FUNCTION: tribits_deprecated() + @FUNCTION: tribits_deprecated_command() + @MACRO: tribits_create_reverse_list() + +@MACRO: tribits_set_cache_var_and_default() + @FUNCTION: tribits_strip_quotes_from_str() + @FUNCTION: unittest_compare_const() + @FUNCTION: unittest_has_substr_const() + diff --git a/cmake/tribits/doc/guides/generate-guide.sh b/cmake/tribits/doc/guides/generate-guide.sh index ce7a2c6565..da7e128ebe 100755 --- a/cmake/tribits/doc/guides/generate-guide.sh +++ b/cmake/tribits/doc/guides/generate-guide.sh @@ -112,7 +112,7 @@ function tribits_extract_rst_cmake_doc { echo "Extracting TriBITS documentation from *.cmake files ..." echo ../../../python_utils/extract_rst_cmake_doc.py \ - --extract-from=../../../core/package_arch/,../../../ci_support/,../../../core/utils/,../../../ctest_driver/ \ + --extract-from=../../../ctest_driver/,../../../ci_support/,../../../core/package_arch/,../../../core/test_support/,../../../core/utils/ \ --rst-file-pairs=../TribitsMacroFunctionDocTemplate.rst:TribitsMacroFunctionDoc.rst.tmp,../UtilsMacroFunctionDocTemplate.rst:UtilsMacroFunctionDoc.rst.tmp,../TribitsSystemMacroFunctionDocTemplate.rst:TribitsSystemMacroFunctionDoc.rst.tmp \ ${extra_args} \ --file-name-path-base-dir=../../.. \ @@ -152,6 +152,30 @@ function tribits_extract_other_doc { &> TribitsHelloWorldDirAndFiles.txt.tmp update_if_different TribitsHelloWorldDirAndFiles.txt tmp + echo + echo "Generating TribitsExampleProject2/Package1 CMakeList file variants ..." + echo + + cat ../../examples/TribitsExampleProject2/packages/package1/CMakeLists.raw.cmake \ + | grep -v EnableTribitsTestSupport \ + | grep -v GeneratePackageConfigFileForBuildDir \ + &> TribitsExampleProject2_Package1_CMakeLists.raw.external.cmake.tmp + update_if_different TribitsExampleProject2_Package1_CMakeLists.raw.external.cmake tmp + + cat ../../examples/TribitsExampleProject2/packages/package1/CMakeLists.raw.cmake \ + | grep -v EnableTribitsTestSupport \ + &> TribitsExampleProject2_Package1_CMakeLists.raw.internal.cmake.tmp + update_if_different TribitsExampleProject2_Package1_CMakeLists.raw.internal.cmake tmp + + cat ../../examples/TribitsExampleProject2/packages/package1/CMakeLists.raw.cmake \ + | grep -v "that TriBITS does automatically" \ + | grep -v DefineAllLibsTarget \ + | grep -v GeneratePackageConfigFileForBuildDir \ + | grep -v GeneratePackageConfigFileForInstallDir \ + &> TribitsExampleProject2_Package1_CMakeLists.raw.tribits_test.cmake.tmp + update_if_different \ + TribitsExampleProject2_Package1_CMakeLists.raw.tribits_test.cmake tmp + echo echo "Generating output for 'checkin-test.py --help' ..." echo @@ -246,8 +270,8 @@ function make_final_doc_in_subdir { if [[ "${skip_final_generation}" == "0" ]] ; then cd $dir_name echo $PWD - make - cd - + time make + cd - > /dev/null else echo echo "Skipping final generation of '${dir_name}' on request!" diff --git a/cmake/tribits/doc/utils/gen_doc_utils.sh b/cmake/tribits/doc/utils/gen_doc_utils.sh index 639aa68ddf..253418e44b 100644 --- a/cmake/tribits/doc/utils/gen_doc_utils.sh +++ b/cmake/tribits/doc/utils/gen_doc_utils.sh @@ -51,7 +51,8 @@ function generate_git_version_file { echo echo "Generating git version" echo - echo `git describe --match="$_TRIBITS_TAG_PREFIX*"` > TribitsGitVersion.txt + git describe --always --match="$_TRIBITS_TAG_PREFIX*" > TribitsGitVersion.txt || \ + echo "$_TRIBITS_TAG_PREFIX.{Unknown version}" > TribitsGitVersion.txt else echo "$_TRIBITS_TAG_PREFIX.{Unknown version}" > TribitsGitVersion.txt fi diff --git a/cmake/tribits/examples/ReducedMockTrilinos/extraRepos/DependsOnLAPACK/cmake/Dependencies.cmake b/cmake/tribits/examples/ReducedMockTrilinos/extraRepos/DependsOnLAPACK/cmake/Dependencies.cmake index 3f688dcd49..da10035235 100644 --- a/cmake/tribits/examples/ReducedMockTrilinos/extraRepos/DependsOnLAPACK/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/ReducedMockTrilinos/extraRepos/DependsOnLAPACK/cmake/Dependencies.cmake @@ -1,3 +1,3 @@ tribits_package_define_dependencies( - LIB_REQUIRED_TPLS LAPACK + LIB_REQUIRED_PACKAGES LAPACK ) diff --git a/cmake/tribits/examples/ReducedMockTrilinos/packages/epetra/cmake/Dependencies.cmake b/cmake/tribits/examples/ReducedMockTrilinos/packages/epetra/cmake/Dependencies.cmake index e3a218cf82..d08c7ab682 100644 --- a/cmake/tribits/examples/ReducedMockTrilinos/packages/epetra/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/ReducedMockTrilinos/packages/epetra/cmake/Dependencies.cmake @@ -1,4 +1,4 @@ tribits_package_define_dependencies( - LIB_REQUIRED_TPLS BLAS LAPACK - LIB_OPTIONAL_TPLS MPI + LIB_REQUIRED_PACKAGES BLAS LAPACK + LIB_OPTIONAL_PACKAGES MPI ) diff --git a/cmake/tribits/examples/ReducedMockTrilinos/packages/epetraext/cmake/Dependencies.cmake b/cmake/tribits/examples/ReducedMockTrilinos/packages/epetraext/cmake/Dependencies.cmake index 1cd83d35ef..d0b518696b 100644 --- a/cmake/tribits/examples/ReducedMockTrilinos/packages/epetraext/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/ReducedMockTrilinos/packages/epetraext/cmake/Dependencies.cmake @@ -1,15 +1,14 @@ if (SHOW_TEST_REQUIRED_PACKAGE_DEP) - set(TEST_REQUIRED_PACKAGES_ARGS TEST_REQUIRED_PACKAGES Triutils) + set(TEST_REQUIRED_PACKAGES Triutils) endif() if (SHOW_TEST_REQUIRED_TPL_DEP) - set(TEST_REQUIRED_TPLS_ARGS TEST_REQUIRED_TPLS AMD) + set(TEST_REQUIRED_PACKAGES ${TEST_REQUIRED_PACKAGES} AMD) endif() tribits_package_define_dependencies( LIB_REQUIRED_PACKAGES Teuchos Epetra LIB_OPTIONAL_PACKAGES Triutils - LIB_OPTIONAL_TPLS UMFPACK AMD PETSC - ${TEST_REQUIRED_PACKAGES_ARGS} - ${TEST_REQUIRED_TPLS_ARGS} + LIB_OPTIONAL_PACKAGES UMFPACK AMD PETSC + TEST_REQUIRED_PACKAGES ${TEST_REQUIRED_PACKAGES} ) diff --git a/cmake/tribits/examples/ReducedMockTrilinos/packages/teuchos/cmake/Dependencies.cmake b/cmake/tribits/examples/ReducedMockTrilinos/packages/teuchos/cmake/Dependencies.cmake index 1d5eb60933..6e5f9d4aa3 100644 --- a/cmake/tribits/examples/ReducedMockTrilinos/packages/teuchos/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/ReducedMockTrilinos/packages/teuchos/cmake/Dependencies.cmake @@ -1,4 +1,4 @@ tribits_package_define_dependencies( - LIB_REQUIRED_TPLS BLAS LAPACK - LIB_OPTIONAL_TPLS Boost MPI + LIB_REQUIRED_PACKAGES BLAS LAPACK + LIB_OPTIONAL_PACKAGES Boost MPI ) diff --git a/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake b/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake index cbed66bcd7..ebb23e1789 100644 --- a/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake +++ b/cmake/tribits/examples/TribitsExampleApp2/AppHelperFuncs.cmake @@ -37,7 +37,7 @@ macro(getTribitsExProj2StuffForAppByPackage) # Find each package and gather up all the ::all_libs targets set(APP_DEPS_LIB_TARGETS "") foreach (packageName IN LISTS ${PROJECT_NAME}_USE_COMPONENTS) - find_package(${packageName} REQUIRED) + find_package(${packageName} CONFIG REQUIRED) message("Found ${packageName}!") list(APPEND APP_DEPS_LIB_TARGETS ${packageName}::all_libs) endforeach() @@ -59,7 +59,8 @@ endmacro() # macro(getTribitsExProj2StuffForAppByProject) - find_package(TribitsExProj2 REQUIRED COMPONENTS ${${PROJECT_NAME}_USE_COMPONENTS}) + find_package(TribitsExProj2 CONFIG REQUIRED + COMPONENTS ${${PROJECT_NAME}_USE_COMPONENTS}) message("\nFound TribitsExProj2! Here are the details: ") message(" TribitsExProj2_DIR = ${TribitsExProj2_DIR}") diff --git a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake index 13461825af..4ee6c7ee90 100644 --- a/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/TribitsExampleProject/packages/simple_cxx/cmake/Dependencies.cmake @@ -1,5 +1,5 @@ tribits_package_define_dependencies( - LIB_REQUIRED_TPLS HeaderOnlyTpl - LIB_OPTIONAL_TPLS SimpleTpl MPI + LIB_REQUIRED_PACKAGES HeaderOnlyTpl + LIB_OPTIONAL_PACKAGES SimpleTpl MPI REGRESSION_EMAIL_LIST simplecxx-regressions@someurl.none ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.raw.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.raw.cmake new file mode 100644 index 0000000000..ad2a181827 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.raw.cmake @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) + +if (COMMAND tribits_package) + message("Configuring raw CMake package Package1") +else() + message("Configuring raw CMake project Package1") +endif() + +# Standard project-level stuff +project(Package1 LANGUAGES C CXX) +include(GNUInstallDirs) +find_package(Tpl1 CONFIG REQUIRED) +add_subdirectory(src) +if (Package1_ENABLE_TESTS) + include(CTest) + include("${CMAKE_CURRENT_LIST_DIR}/cmake/raw/EnableTribitsTestSupport.cmake") + add_subdirectory(test) +endif() + +# Stuff that TriBITS does automatically +include("${CMAKE_CURRENT_LIST_DIR}/cmake/raw/DefineAllLibsTarget.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/cmake/raw/GeneratePackageConfigFileForBuildDir.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/cmake/raw/GeneratePackageConfigFileForInstallDir.cmake") diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.tribits.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.tribits.cmake new file mode 100644 index 0000000000..2c2fc1f8a6 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.tribits.cmake @@ -0,0 +1,5 @@ +message("Configuring package Package1 as full TriBITS package") +tribits_package(Package1) +add_subdirectory(src) +tribits_add_test_directories(test) +tribits_package_postprocess() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt index bf2638c61f..c8511aab35 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/CMakeLists.txt @@ -1,4 +1,18 @@ -tribits_package(Package1) -add_subdirectory(src) -tribits_add_test_directories(test) -tribits_package_postprocess() +cmake_minimum_required(VERSION 3.23.0 FATAL_ERROR) + +set(Package1_USE_RAW_CMAKE OFF CACHE BOOL + "Use raw CMake for package build, even if TriBITS could be used.") + +# Macro to select the TriBITS or the raw CMake build system +macro(include_cmakelists_file) + if ((NOT COMMAND tribits_project) OR Package1_USE_RAW_CMAKE) + include("${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.raw.cmake" + NO_POLICY_SCOPE) + else() + include("${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.tribits.cmake" + NO_POLICY_SCOPE) + endif() +endmacro() + +# Pull in the base CMakeLists.txt file variant +include_cmakelists_file() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake index 64ccf196ee..5383950e6a 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/Dependencies.cmake @@ -1,3 +1,3 @@ tribits_package_define_dependencies( - LIB_REQUIRED_TPLS Tpl1 + LIB_REQUIRED_PACKAGES Tpl1 ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/DefineAllLibsTarget.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/DefineAllLibsTarget.cmake new file mode 100644 index 0000000000..902b1cdf15 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/DefineAllLibsTarget.cmake @@ -0,0 +1,11 @@ +# Generate the all_libs target(s) +add_library(Package1_all_libs INTERFACE) +set_target_properties(Package1_all_libs + PROPERTIES EXPORT_NAME all_libs) +target_link_libraries(Package1_all_libs + INTERFACE Package1_package1) +install(TARGETS Package1_all_libs + EXPORT ${PROJECT_NAME} + COMPONENT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +add_library(Package1::all_libs ALIAS Package1_all_libs) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/EnableTribitsTestSupport.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/EnableTribitsTestSupport.cmake new file mode 100644 index 0000000000..c4449e5432 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/EnableTribitsTestSupport.cmake @@ -0,0 +1,10 @@ +set(Package1_USE_TRIBITS_TEST_FUNCTIONS OFF CACHE BOOL + "Use TriBITS testing functions") +set(Package1_TRIBITS_DIR "" CACHE PATH + "Path to TriBITS implementation base dir (e.g. TriBITS/tribits)") +if (Package1_USE_TRIBITS_TEST_FUNCTIONS AND Package1_TRIBITS_DIR) + # Pull in and turn on TriBITS testing support + include("${Package1_TRIBITS_DIR}/core/test_support/TribitsAddTest.cmake") + include("${Package1_TRIBITS_DIR}/core/test_support/TribitsAddAdvancedTest.cmake") + set(Package1_ENABLE_TESTS ON) +endif() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForBuildDir.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForBuildDir.cmake new file mode 100644 index 0000000000..9f937dcda5 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForBuildDir.cmake @@ -0,0 +1,13 @@ +if (COMMAND tribits_package) + # Generate Package1Config.cmake file for the build tree (for internal + # TriBITS-compliant package) + set(packageBuildDirCMakePackagesDir + "${${CMAKE_PROJECT_NAME}_BINARY_DIR}/cmake_packages/${PROJECT_NAME}") + export(EXPORT ${PROJECT_NAME} + NAMESPACE ${PROJECT_NAME}:: + FILE "${packageBuildDirCMakePackagesDir}/${PROJECT_NAME}ConfigTargets.cmake" ) + configure_file( + "${CMAKE_CURRENT_LIST_DIR}/Package1Config.cmake.in" + "${packageBuildDirCMakePackagesDir}/${PROJECT_NAME}/Package1Config.cmake" + @ONLY ) +endif() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForInstallDir.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForInstallDir.cmake new file mode 100644 index 0000000000..535685e614 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/GeneratePackageConfigFileForInstallDir.cmake @@ -0,0 +1,15 @@ +# Generate and install the Package1Config.cmake file for the install tree +# (needed for both internal and external TriBITS package) +set(pkgConfigInstallDir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +install(EXPORT ${PROJECT_NAME} + DESTINATION "${pkgConfigInstallDir}" + NAMESPACE ${PROJECT_NAME}:: + FILE ${PROJECT_NAME}ConfigTargets.cmake ) +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/raw/Package1Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Package1Config.install.cmake" + @ONLY ) +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Package1Config.install.cmake" + RENAME "Package1Config.cmake" + DESTINATION "${pkgConfigInstallDir}" ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/Package1Config.cmake.in b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/Package1Config.cmake.in new file mode 100644 index 0000000000..63cffb7867 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/cmake/raw/Package1Config.cmake.in @@ -0,0 +1,3 @@ +set(Tpl1_DIR "@Tpl1_DIR@") +find_package(Tpl1 CONFIG REQUIRED) +include("${CMAKE_CURRENT_LIST_DIR}/Package1ConfigTargets.cmake") diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.raw.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.raw.cmake new file mode 100644 index 0000000000..f15cdc5898 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.raw.cmake @@ -0,0 +1,23 @@ +# Create and install library 'package1' +add_library(Package1_package1 Package1.hpp Package1.cpp) +target_include_directories(Package1_package1 + PUBLIC $) +target_link_libraries(Package1_package1 + PRIVATE tpl1::tpl1 ) +set_target_properties(Package1_package1 PROPERTIES + EXPORT_NAME package1) +add_library(Package1::package1 ALIAS Package1_package1) +install(TARGETS Package1_package1 + EXPORT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) +install( + FILES Package1.hpp + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) + +# Create and install executable 'package1-prg' +add_executable(package1-prg Package1_Prg.cpp) +target_link_libraries(package1-prg PRIVATE Package1::package1) +install( + TARGETS package1-prg + EXPORT ${PROJECT_NAME} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.tribits.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.tribits.cmake new file mode 100644 index 0000000000..8e69c53a57 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.tribits.cmake @@ -0,0 +1,4 @@ +tribits_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +tribits_add_library(package1 HEADERS Package1.hpp SOURCES Package1.cpp) +tribits_add_executable(package1-prg NOEXEPREFIX NOEXESUFFIX + SOURCES Package1_Prg.cpp INSTALLABLE ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt index b74162bb25..870958046e 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/CMakeLists.txt @@ -1,22 +1 @@ -set(HEADERS "") -set(SOURCES "") - -tribits_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -append_set(HEADERS - Package1.hpp - ) -append_set(SOURCES - Package1.cpp - ) - -tribits_add_library( - package1 - HEADERS ${HEADERS} - SOURCES ${SOURCES} - ) - -tribits_add_executable(package1-prg NOEXEPREFIX NOEXESUFFIX - SOURCES Package1_Prg.cpp - INSTALLABLE - ) +include_cmakelists_file() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp index 2ce91f102a..33d4dc0cef 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/src/Package1_Prg.cpp @@ -1,9 +1,13 @@ #include +#include #include "Package1.hpp" -int main() +int main(int argc, char* argv[]) { std::cout << "Package1 Deps: " << Package1::deps() << "\n"; + for (int arg_i = 0; arg_i < argc; ++arg_i) { + std::cout << argv[arg_i+1] << "\n"; + } return 0; } diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.raw.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.raw.cmake new file mode 100644 index 0000000000..fef3221526 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.raw.cmake @@ -0,0 +1,19 @@ +add_test(NAME Package1_Prg COMMAND package1-prg) +set_tests_properties(Package1_Prg + PROPERTIES PASS_REGULAR_EXPRESSION "Package1 Deps: tpl1") + +add_test(NAME Package1_Prg-advanced COMMAND package1-prg something_extra) +set_tests_properties(Package1_Prg-advanced + PROPERTIES PASS_REGULAR_EXPRESSION "something_extra") + +# NOTE: With raw CMake/CTest, it is not possible to require the matches of +# multiple regexes (i.e. not the require the match of *both* "Package1 Deps: +# tpl1" and "something_extra"). Also, it is not possible to require a +# non-zero return code in addition to requiring a regex match the output. +# These more advanced features of tribits_add_advanced_test() would need to be +# provided by writing a wrapper script (e.g. using a Python script, a cmake -P +# script, etc.). Also, these tests don't support other features like: b) +# allow tests to be disabled for a variety of reasons like number of MPI +# processes required, incompatible system, disable cache variables -D +# _DISABLE=ON, etc.; b) printing which tests got added or did +# not get added and why when _TRACE_ADD_TEST=ON, etc. diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.tribits.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.tribits.cmake new file mode 100644 index 0000000000..48d1f6e192 --- /dev/null +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.tribits.cmake @@ -0,0 +1,14 @@ +tribits_add_test(package1-prg NOEXEPREFIX NOEXESUFFIX + NAME Prg DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../src" NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "Package1 Deps: tpl1" ) + +tribits_add_advanced_test(Prg-advanced + TEST_0 + EXEC package1-prg DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../src" + NOEXEPREFIX NOEXESUFFIX + ARGS "something_extra" + PASS_REGULAR_EXPRESSION_ALL + "Package1 Deps: tpl1" + "something_extra" + ALWAYS_FAIL_ON_NONZERO_RETURN + ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt index afef4e708a..11b72aec01 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package1/test/CMakeLists.txt @@ -1,6 +1,11 @@ -tribits_add_test(package1-prg NOEXEPREFIX NOEXESUFFIX - NAME Prg - DIRECTORY ${PACKAGE_BINARY_DIR}/src - NUM_MPI_PROCS 1 - PASS_REGULAR_EXPRESSION "Package1 Deps: tpl1" - ) +if ((NOT COMMAND tribits_project) OR Package1_USE_RAW_CMAKE) + if (Package1_USE_TRIBITS_TEST_FUNCTIONS AND (COMMAND tribits_add_test)) + message("-- Using TriBITS Test Functions in raw CMake Package1 build!") + include("${CMAKE_CURRENT_LIST_DIR}/CMakeLists.tribits.cmake") + else() + message("-- Using Raw CMake add_test() in raw CMake Package1 build!") + include("${CMAKE_CURRENT_LIST_DIR}/CMakeLists.raw.cmake") + endif() +else() + include("${CMAKE_CURRENT_LIST_DIR}/CMakeLists.tribits.cmake") +endif() diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake index 46c260a264..e299aef0d7 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package2/cmake/Dependencies.cmake @@ -1,4 +1,4 @@ tribits_package_define_dependencies( LIB_REQUIRED_PACKAGES Package1 - LIB_OPTIONAL_TPLS Tpl3 + LIB_OPTIONAL_PACKAGES Tpl3 ) diff --git a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake index 6e9a0e1e47..b2c5eec262 100644 --- a/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake +++ b/cmake/tribits/examples/TribitsExampleProject2/packages/package3/cmake/Dependencies.cmake @@ -1,6 +1,4 @@ tribits_package_define_dependencies( - LIB_REQUIRED_PACKAGES Package1 - LIB_OPTIONAL_PACKAGES Package2 - LIB_REQUIRED_TPLS Tpl2 - LIB_OPTIONAL_TPLS Tpl4 + LIB_REQUIRED_PACKAGES Package1 Tpl2 + LIB_OPTIONAL_PACKAGES Package2 Tpl4 ) diff --git a/cmake/tribits/python_utils/gitdist-setup.sh b/cmake/tribits/python_utils/gitdist-setup.sh index 0df08515dc..928c058838 100644 --- a/cmake/tribits/python_utils/gitdist-setup.sh +++ b/cmake/tribits/python_utils/gitdist-setup.sh @@ -44,7 +44,7 @@ if [[ "${existing_gitdist}" == "" ]] ; then fi function gitdist_repo_versions { - gitdist "$@" --dist-no-color log -1 --pretty=format:"%H [%cd] <%ae>%n%s" | grep -v "^$" + gitdist "$@" --dist-no-color log --color=never -1 --pretty=format:"%H [%cd] <%ae>%n%s" | grep -v "^$" } export -f gitdist_repo_versions @@ -60,7 +60,7 @@ function gitdist_show_full_repo_state { echo echo "Repo remotes:" echo - gitdist --dist-no-color "$@" remote -v | grep "\(Git Repo\|push\)" + gitdist --dist-no-color "$@" remote -v | grep --color=never "\(Git Repo\|push\)" } export -f gitdist_show_full_repo_state @@ -73,7 +73,7 @@ alias gitdist-show-full-repo-state=gitdist_show_full_repo_state # Setup for completions for git command and gitdist options commands complete -o default -o nospace -F _git \ - -W "dist-repo-status --dist-help --dist-use-git --dist-repos --dist-not-repos --dist-version-file --dist-version-file2 --dist-no-color --dist-debug --dist-no-opt --dist-mod-only --dist-legend" \ + -W "dist-repo-status --dist-help --dist-use-git --dist-repos --dist-not-repos --dist-version-file --dist-version-file2 --dist-no-color --dist-debug --dist-no-opt --dist-mod-only" \ gitdist gitdist-mod complete -o default -o nospace \ -W "--dist-use-git --dist-repos --dist-not-repos --dist-mod-only" \ @@ -82,5 +82,5 @@ complete -o default -o nospace \ -W "--dist-use-git --dist-repos --dist-not-repos --dist-mod-only" \ gitdist_show_full_repo_state gitdist-show-full-repo-state complete -o default -o nospace \ - -W "--dist-repos --dist-not-repos --dist-mod-only" \ + -W "--dist-repos --dist-not-repos --dist-mod-only --dist-legend" \ gitdist-status diff --git a/cmake/tribits/python_utils/gitdist.py b/cmake/tribits/python_utils/gitdist.py index db20c7ddfa..6800e2e20c 100755 --- a/cmake/tribits/python_utils/gitdist.py +++ b/cmake/tribits/python_utils/gitdist.py @@ -36,7 +36,7 @@ def s(x): distRepoStatusLegend = r"""Legend: * ID: Repository ID, zero based (order git commands are run) * Repo Dir: Relative to base repo (base repo shown first with '(Base)') -* Branch: Current branch (or detached HEAD) +* Branch: Current branch, or (if detached HEAD) tag name or SHA1 * Tracking Branch: Tracking branch (or empty if no tracking branch exists) * C: Number local commits w.r.t. tracking branch (empty if zero or no TB) * M: Number of tracked modified (uncommitted) files (empty if zero) @@ -333,7 +333,7 @@ def getHelpTopicsStr(): |----|-----------------------|--------|-----------------|---|----|---| | 0 | BaseRepo (Base) | dummy | | | | | | 1 | ExtraRepo1 | master | origin/master | 1 | 2 | | - | 2 | ExtraRepo1/ExtraRepo2 | HEAD | | | 25 | 4 | + | 2 | ExtraRepo1/ExtraRepo2 | abc123 | | | 25 | 4 | | 3 | ExtraRepo3 | master | origin/master | | | | ---------------------------------------------------------------------- @@ -341,6 +341,13 @@ def getHelpTopicsStr(): """+distRepoStatusLegend+\ r""" + +In the case of a detached head state, as shown above with the repo +'ExtraRepo3', the SHA1 (e.g. 'abc123') was printed instead of 'HEAD'. +However, if the repo is in the detached head state but a tag happens to point +to the current commit (e.g. 'git tag --points-at' returns non-empy), then the +tag name (e.g. 'v1.2.3') is printed instead of the SHA1 of the commit. + One can also show the status of only changed repos with the command: $ gitdist dist-repo-status --dist-mod-only # alias 'gitdist-mod-status' @@ -351,7 +358,7 @@ def getHelpTopicsStr(): | ID | Repo Dir | Branch | Tracking Branch | C | M | ? | |----|-----------------------|--------|-----------------|---|----|---| | 1 | ExtraRepo1 | master | origin/master | 1 | 2 | | - | 2 | ExtraRepo1/ExtraRepo2 | HEAD | | | 25 | 4 | + | 2 | ExtraRepo1/ExtraRepo2 | abc123 | | | 25 | 4 | ---------------------------------------------------------------------- (see the alias 'gitdist-mod-status' in --dist-help=aliases). @@ -396,13 +403,13 @@ def getHelpTopicsStr(): with this script listing three lines per repo (e.g. as shown above) using (for example): - $ gitdist --dist-no-color log -1 --pretty=format:"%h [%ad] <%ae>%n%s" \ + $ gitdist --dist-no-color log --color=never -1 --pretty=format:"%h [%ad] <%ae>%n%s" \ | grep -v "^$" &> RepoVersion.txt (which is defined as the alias 'gitdist-repo-versions' in the file 'gitdist-setup.sh') or two lines per repo using (for example): - $ gitdist --dist-no-color log -1 --pretty=format:"%h [%ad] <%ae>" \ + $ gitdist --dist-no-color log --color=never -1 --pretty=format:"%h [%ad] <%ae>" \ | grep -v "^$" &> RepoVersion.txt This allows checking out consistent versions of the set git repos, diffing two @@ -495,7 +502,7 @@ def getHelpTopicsStr(): $ alias gitdist-status="gitdist dist-repo-status" $ alias gitdist-mod="gitdist --dist-mod-only" $ alias gitdist-mod-status="gitdist dist-repo-status --dist-mod-only" - $ alias gitdist-repo-versions="gitdist --dist-no-color log -1 \ + $ alias gitdist-repo-versions="gitdist --dist-no-color log --color=never -1 \ --pretty=format:\"%h [%ad] <%ae>%n%s\" | grep -v \"^$\"" These are added by sourcing the provided file 'gitdist-setup.sh' (which should @@ -844,7 +851,8 @@ def createTable(tableData, utf8=False): if mockSttySize: sttySize = mockSttySize else: - sttySize = os.popen("stty size", "r").read() + with os.popen("stty size", "r") as subprocess: + sttySize = subprocess.read() rows, columns = sttySize.split() except: shrink = False @@ -1071,7 +1079,7 @@ def getCmndOutput(cmnd, rtnCode=False): child = subprocess.Popen(cmnd, shell=True, stdout=subprocess.PIPE, stderr = subprocess.STDOUT) output = child.stdout.read() - child.wait() + child.communicate() if rtnCode: return (s(output), child.returncode) return s(output) @@ -1304,7 +1312,10 @@ def getCommandlineOps(): clp.add_option( noColorArgName, dest="useColor", action="store_false", - help="If set, don't use color in the output for gitdist (better for output to a file).", + help="If set, don't use color in the output for gitdist and set" + +" '-c color.status=never' before the git command (like 'status')." + +" NOTE: user should also pass in --color=never for git commands " + +" accept that argument. (Better for output to a file).", default=True ) clp.add_option( @@ -1544,7 +1555,12 @@ def runRepoCmnd(options, cmndLineArgsArray, repoDirName, baseDir, \ repoDirName, repoVersionDict, repoVersionDict2) cmndLineArgsArrayDefaultBranch = replaceDefaultBranchInCmndLineArgs( \ cmndLineArgsArrayRepo, repoDirName, defaultBranchDict) - egCmndArray = [ options.useGit ] + cmndLineArgsArrayDefaultBranch + egCmndArray = [ options.useGit ] + if options.useColor: + egCmndArray.extend(['-c', 'color.status=always']) + else: + egCmndArray.extend(['-c', 'color.status=never']) + egCmndArray.extend(cmndLineArgsArrayDefaultBranch) runCmnd(options, egCmndArray) @@ -1566,6 +1582,20 @@ def repoExistsAndNotExcluded(options, extraRepo, notReposList): return True +# Get the identifier for the current commit in the repo +def getRepoVersionIdentifier(options, getCmndOutputFunc, showMoreHeadDetails): + branch = getLocalBranch(options, getCmndOutputFunc) + if showMoreHeadDetails != "SHOW_MORE_HEAD_DETAILS": + return branch + if branch != "HEAD": + return branch + tagName = getCmndOutputFunc(options.useGit + " tag --points-at").strip() + if tagName != "": + return tagName + sha1 = getCmndOutputFunc(options.useGit + " log --pretty=%h -1").strip() + return sha1 + + # Get the tracking branch for a repo def getLocalBranch(options, getCmndOutputFunc): (resp, rtnCode) = getCmndOutputFunc( @@ -1655,7 +1685,9 @@ def getNumModifiedAndUntracked(options, getCmndOutputFunc): class RepoStatsStruct: - def __init__(self, branch, trackingBranch, numCommits, numModified, numUntracked): + def __init__(self, branch, trackingBranch, numCommits, numModified, + numUntracked \ + ): self.branch = branch self.trackingBranch = trackingBranch self.numCommits = numCommits @@ -1689,21 +1721,16 @@ def hasLocalChanges(self): return False -def getRepoStats(options, getCmndOutputFunc=None): +def getRepoStats(options, getCmndOutputFunc=None, showMoreHeadDetails=""): if not getCmndOutputFunc: getCmndOutputFunc = getCmndOutput - branch = getLocalBranch(options, getCmndOutputFunc) + branch = getRepoVersionIdentifier(options, getCmndOutputFunc, showMoreHeadDetails) trackingBranch = getTrackingBranch(options, getCmndOutputFunc) - numCommits = getNumCommitsWrtTrackingBranch(options, - trackingBranch, - getCmndOutputFunc) + numCommits = getNumCommitsWrtTrackingBranch(options, trackingBranch, getCmndOutputFunc) (numModified, numUntracked) = getNumModifiedAndUntracked(options, - getCmndOutputFunc) - return RepoStatsStruct(branch, - trackingBranch, - numCommits, - numModified, - numUntracked) + getCmndOutputFunc) + return RepoStatsStruct(branch, trackingBranch, numCommits, + numModified, numUntracked) class RepoVersionStruct: @@ -1894,7 +1921,7 @@ def getRepoName(repoDir, baseRepoName): # Get repo stats repoStats = None if options.modifiedOnly or distRepoStatus: - repoStats = getRepoStats(options) + repoStats = getRepoStats(options, showMoreHeadDetails="SHOW_MORE_HEAD_DETAILS") repoVersions = None if distRepoVersionTable: repoVersions = getRepoVersions(options) diff --git a/install-tpl.sh b/install-tpl.sh index 102849a391..e0c922b27d 100755 --- a/install-tpl.sh +++ b/install-tpl.sh @@ -69,7 +69,14 @@ BB=$(check_valid BB) CRAY=${CRAY:-NO} CRAY=$(check_valid CRAY) -# Which TPLS? (NetCDF always, PnetCDF if MPI=ON) +MPI=${MPI:-NO} +MPI=$(check_valid MPI) + +# Which TPLS? (NetCDF always, but can be disabled if using an external version, PnetCDF if MPI=ON) +NETCDF=${NETCDF:-YES} +NETCDF=$(check_valid NETCDF) +PNETCDF=${PNETCDF:-${MPI}} +PNETCDF=$(check_valid PNETCDF) HDF5=${HDF5:-YES} HDF5=$(check_valid HDF5) CGNS=${CGNS:-${HDF5}} @@ -115,22 +122,23 @@ USE_AEC=$(check_valid USE_AEC) KOKKOS=${KOKKOS:-NO} KOKKOS=$(check_valid KOKKOS) -H5VERSION=${H5VERSION:-V112} +H5VERSION=${H5VERSION:-V114} FAODEL=${FAODEL:-NO} FAODEL=$(check_valid FAODEL) +BOOST=${BOOST:-NO} +BOOST=$(check_valid BOOST) + ADIOS2=${ADIOS2:-NO} ADIOS2=$(check_valid ADIOS2) CATALYST2=${CATALYST2:-NO} CATALYST2=$(check_valid CATALYST2) -GTEST=${GTEST:-NO} +GTEST=${GTEST:-${FAODEL}} GTEST=$(check_valid GTEST) -MPI=${MPI:-NO} -MPI=$(check_valid MPI) SUDO=${SUDO:-} JOBS=${JOBS:-2} @@ -178,7 +186,7 @@ if [ $# -gt 0 ]; then echo " ACCESS = ${txtgrn}${ACCESS}${txtcyn} (Automatically set to current directory)" echo " INSTALL_PATH = ${txtgrn}${INSTALL_PATH}${txtcyn}" echo " OS = ${txtgrn}${OS}${txtcyn} (Automatically set)" - echo " COMPILER = ${COMPILER} (gnu clang intel ibm)" + echo " COMPILER = ${COMPILER} (gnu clang intel ibm gnubrew gnumacport clangmacport nvidia)" echo " MPI = ${MPI} (Parallel Build?)" echo "" echo " FORCE = ${FORCE}" @@ -188,6 +196,8 @@ if [ $# -gt 0 ]; then echo " DEBUG = ${DEBUG}" echo " USE_PROXY = ${USE_PROXY}" echo "" + echo " NETCDF = ${NETCDF}" + echo " PNETCDF = ${PNETCDF}" echo " HDF5 = ${HDF5}" echo " H5VERSION = ${H5VERSION}" echo " CGNS = ${CGNS}" @@ -413,9 +423,9 @@ then hdf_version="1.13.1" hdf_base="1.13" elif [ "${H5VERSION}" == "V114" ]; then - hdf_version="1.14.1" + hdf_version="1.14.2" hdf_base="1.14" - hdf_suffix="-2" + hdf_suffix="" elif [ "${H5VERSION}" == "develop" ]; then hdf_version="develop" else @@ -473,7 +483,7 @@ then fi # =================== INSTALL PnetCDF if parallel build =============== -if [ "$MPI" == "YES" ] +if [ "$PNETCDF" == "YES" ] && [ "$MPI" == "YES" ] then # PnetCDF currently only builds static library... if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/lib/libpnetcdf.a ] @@ -523,6 +533,8 @@ then fi # =================== INSTALL NETCDF =============== +if [ "$NETCDF" == "YES" ] +then if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/lib/libnetcdf.${LD_EXT} ] then echo "${txtgrn}+++ NetCDF${txtrst}" @@ -572,6 +584,7 @@ then else echo "${txtylw}+++ NetCDF already installed. Skipping download and installation.${txtrst}" fi +fi # =================== INSTALL CGNS =============== if [ "$CGNS" == "YES" ] && [ "$HDF5" == "YES" ] then @@ -753,7 +766,7 @@ then echo "${txtgrn}+++ FMT${txtrst}" cd $ACCESS || exit cd TPL/fmt || exit - fmt_version="10.0.0" + fmt_version="10.1.0" if [ "$DOWNLOAD" == "YES" ] then @@ -837,7 +850,7 @@ fi # =================== INSTALL ADIOS2 =============== if [ "$ADIOS2" == "YES" ] then - if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/lib/libadios2.${LD_EXT} ] + if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/lib/libadios2_c.${LD_EXT} ] then echo "${txtgrn}+++ ADIOS2${txtrst}" cd $ACCESS || exit @@ -853,7 +866,6 @@ then then echo "${txtgrn}+++ Configuring, Building, and Installing...${txtrst}" cd ADIOS2 || exit - git checkout v2.5.0 rm -rf build mkdir build cd build || exit @@ -999,10 +1011,37 @@ then fi fi +# =================== INSTALL BOOST =============== +if [ "$BOOST" == "YES" ] +then + if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/include/boost ] + then + # FAODEL Requires Boost... For now, just download and install + echo "${txtgrn}+++ Installing Boost as dependency of Faodel${txtrst}" + cd $ACCESS || exit + cd TPL/boost || exit + BOOST_VER="1_82_0" + if [ "$DOWNLOAD" == "YES" ] + then + wget --no-check-certificate "https://boostorg.jfrog.io/artifactory/main/release/1.82.0/source/boost_${BOOST_VER}.tar.bz2" + tar xf boost_${BOOST_VER}.tar.bz2 + fi + if [ "$BUILD" == "YES" ] + then + echo "${txtgrn}+++ Configuring, Building, and Installing...${txtrst}" + cd boost_${BOOST_VER} + ./bootstrap.sh --prefix=${INSTALL_PATH} + ./b2 -a install + fi + else + echo "${txtylw}+++ Boost already installed. Skipping download and installation.${txtrst}" + fi +fi + # =================== INSTALL FAODEL =============== if [ "$FAODEL" == "YES" ] then - if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/lib/libkelpie.a ] + if [ "$FORCE" == "YES" ] || ! [ -e $INSTALL_PATH/lib/libkelpie.${LD_EXT} ] then faodel_base="faodel" echo "${txtgrn}+++ Faodel${txtrst}" @@ -1012,7 +1051,7 @@ then then echo "${txtgrn}+++ Downloading...${txtrst}" rm -rf faodel* - git clone git@github.com:faodel/faodel.git + git clone https://github.com/sandialabs/faodel.git fi if [ "$BUILD" == "YES" ] diff --git a/packages/seacas/CMakeLists.txt b/packages/seacas/CMakeLists.txt index 046f1e7ac0..b9eb3ab2be 100644 --- a/packages/seacas/CMakeLists.txt +++ b/packages/seacas/CMakeLists.txt @@ -28,6 +28,11 @@ IF (NOT CMAKE_CXX_STANDARD MATCHES "^${${PROJECT_NAME}_CMAKE_CXX_STANDARDS_ALLOW "${${PROJECT_NAME}_CMAKE_CXX_STANDARDS_ALLOWED}") ENDIF () +if ( CYGWIN ) + # This seems to be needed to get `realpath` defined in the IOSS build... + set(CMAKE_CXX_EXTENSIONS ON) +endif() + set(SEACASExodus_ENABLE_STATIC_DEFAULT "OFF") set(SEACASExodus_ENABLE_SHARED_DEFAULT "OFF") diff --git a/packages/seacas/README.md b/packages/seacas/README.md index 5c2a78f721..96d53e54ce 100644 --- a/packages/seacas/README.md +++ b/packages/seacas/README.md @@ -1,206 +1,16 @@ -# SEACAS [[Documentation](http://sandialabs.github.io/seacas-docs/)] [[Wiki](https://github.com/sandialabs/seacas/wiki)] -[![Codacy Badge](https://app.codacy.com/project/badge/Grade/838c6d845e9e4ce4a7cd02bd06b4d2ad)](https://www.codacy.com/gh/gsjaardema/seacas/dashboard?utm_source=github.com&utm_medium=referral&utm_content=gsjaardema/seacas&utm_campaign=Badge_Grade) -[![Analysis Status](https://scan.coverity.com/projects/2205/badge.svg?flat=1)](https://scan.coverity.com/projects/gsjaardema-seacas) -[![Spack Version](https://img.shields.io/spack/v/adios2.svg)](https://spack.readthedocs.io/en/latest/package_list.html#seacas) -[![Appveyor Build](https://ci.appveyor.com/api/projects/status/pis4gok72yh0wwfs/branch/master?svg=true)](https://ci.appveyor.com/project/gsjaardema/seacas/branch/master) -[![Github Actions -- CI Serial](https://github.com/sandialabs/seacas/actions/workflows/build_test.yml/badge.svg)](https://github.com/sandialabs/seacas) -[![Github Actions -- CI Variants](https://github.com/sandialabs/seacas/actions/workflows/build_variant.yml/badge.svg)](https://github.com/sandialabs/seacas) -[![Github Actions -- CI Intel](https://github.com/sandialabs/seacas/actions/workflows/intel-build.yml/badge.svg)](https://github.com/sandialabs/seacas) -[![Github Actions -- CI MSYS2](https://github.com/sandialabs/seacas/actions/workflows/msys2.yml/badge.svg)](https://github.com/sandialabs/seacas) +## Documentation +See SEACAS (including Exodus) documentation at http://sandialabs.github.io/seacas-docs/ -* [Get the sources](#get-the-sources) -* [Build instructions](#build-instructions) -* [Configure, Build, and Install SEACAS](#configure-build-and-install-seacas) -* [Parallel Build](#parallel-build) -* [Testing](#testing) -* [Exodus](#exodus) -* [Trilinos](#trilinos) -* [SPACK](#spack) -* [License](#license) -* [Contact information](#contact-information) -* NOTE: The old imake-based build has been removed. +## Installation +Installation directions are available at http://github.com/sandialabs/seacas -## Get the sources -```sh -git clone https://github.com/sandialabs/seacas.git -``` -This will create a directory that will be referred to as _seacas_ in -the instructions that follow. You can rename this directory to any -other name you desire. Set an environment variable pointing to this -location by doing: +## Contact -```sh -cd seacas && export ACCESS=`pwd` -``` +Greg Sjaardema, +Sandia National Laboratories, +, -## Build instructions +We appreciate feedback from users of this package. Please send +comments, suggestions, and bug reports to Greg Sjaardema +, -### Automatically download and build dependencies (Third-Party Libraries) - -There are a few externally developed third-party libraries (TPL) that -are required (or optional) to build SEACAS: HDF5, NetCDF, CGNS, MatIO, -Kokkos, and (if MPI set) PnetCDF libraries. You can build the -libraries using the `install-tpl.sh` script, or you can install them -manually as detailed in -[TPL-Manual-Install.md](TPL-Manual-Install.md). - -* To use the script, simply type `./install-tpl.sh` -* The default behavior can be modified via a few environment variables: - -| Variable | Values | Default | Description | -|-----------------|:---------------:|:-------:|-------------| -| INSTALL_PATH | path to install | pwd | Root of install path; default is current location | -| COMPILER | clang, gnu, intel, ibm | gnu | What compiler should be used for non-parallel build. Must have C++-14 capability. | -| MPI | YES, NO | NO | If YES, then build parallel capability | -| FORCE | YES, NO | NO | Force downloading and building even if lib is already installed. | -| BUILD | YES, NO | YES | Should TPLs be built and installed. | -| DOWNLOAD | YES, NO | YES | Should TPLs be downloaded. | -| USE_PROXY | YES, NO | NO | Sandia specific -- use proxy when downloading tar files | -| DEBUG | YES, NO | NO | Build debug executable; default is optimized -| SHARED | YES, NO | YES | Build shared libraries if YES, archive (.a) if NO | -| CRAY | YES, NO | YES | Is this a Cray system (special parallel options) | -| NEEDS_ZLIB | YES, NO | NO | If system does not have zlib installed, download and install it (HDF5 compression). | -| USE\_ZLIB\_NG | YES, NO | NO | Should the improved [zlib-ng](https://github.com/zlib-ng/zlib-ng) library be used to provide ZLIB capability | -| NEEDS_SZIP | YES, NO | NO | If system does not have szip installed, download and install it (HDF5 compression). | -| USE\_64BIT\_INT | YES, NO | NO | In CGNS, enable 64-bit integers | -| CGNS | YES, NO | YES | Should CGNS TPL be built. | -| MATIO | YES, NO | YES | Should matio TPL be built. | -| METIS | YES, NO | NO | Should metis TPL be built (parallel decomposition). | -| PARMETIS | YES, NO | NO | Should parmetis TPL be built (parallel decomposition). | -| ADIOS2 | YES, NO | NO | Should adios2 TPL be built. | -| CATALYST2 | YES, NO | NO | Should catalyst 2 TPL be built. | -| KOKKOS | YES, NO | NO | Should Kokkos TPL be built. | -| GNU_PARALLEL | YES, NO | YES | Should GNU parallel script be built. | -| FMT | YES, NO | YES | Should Lib::FMT TPL be built. | -| H5VERSION | V114, V110, V18 | V110 | Use HDF5-1.14.X, HDF5-1.10.X or HDF5-1.8.X | -| BB | YES, NO | NO | Enable Burst Buffer support in PnetCDF | -| JOBS | {count} | 2 | Number of "jobs" used for simultaneous compiles | -| SUDO | "" or sudo | "" | If need to be superuser to install | -* NOTE: The `DOWNLOAD` and `BUILD` options can be used to download all TPL source; move to a system with no outside internet access and then build/install the TPLs. -* The arguments can either be set in the environment as: `export COMPILER=gnu`, or passed on the script invocation line: `COMPILER=gnu ./install-tpl.sh` - -## Configure, Build, and Install SEACAS -At this time, you should have all external TPL libraries built and -installed into `${ACCESS}/lib` and `${ACCESS}/include`. You are now ready -to configure the SEACAS CMake build. - -* `cd $ACCESS` -* `mkdir build` -* `cd build` -* edit the `${ACCESS}cmake-config` file and adjust compilers and other settings as needed. -* enter the command `../cmake-config` and cmake should configure everything for the build. -* `make && make install` -* If everything works, your applications should be in `${ACCESS}/bin` -* To install in a different location, do `INSTALL_PATH={path_to_install} ../cmake-config` -* The default behavior can be modified via a few environment variables: - -| Variable | Values | Default | Description | -|-----------------|:---------------:|:-------:|-------------| -| INSTALL_PATH | path to install | pwd | Root of install path; default is current location | -| BUILDDIR | {dir} | `pwd`/build | Directory to do config and build | -| COMPILER | clang, gnu, intel, ibm | gnu | What compiler should be used for non-parallel build | -| SHARED | YES, NO | YES | Build and use shared libraries is YES | -| APPLICATIONS | YES, NO | YES | Should all SEACAS applications be built (see `cmake-config`) | -| LEGACY | YES, NO | YES | Should the legacy SEACAS applications be built (see `cmake-config`) | -| FORTRAN | YES, NO | YES | Should fortran libraries and applications be built (see `cmake-config`) | -| ZOLTAN | YES, NO | YES | Should zoltan library and nem_slice be built | -| BUILD_TYPE | debug, release | release | what type of build | -| DEBUG | -none- | | If specified, then do a debug build. Can't be used with `BUILD_TYPE` | -| HAVE_X11 | YES, NO | YES | Does the system have X11 libraries and include files; used for blot, fastq | -| THREADSAFE | YES, NO | NO | Compile a thread-safe IOSS and Exodus library | -| USE_SRUN | YES, NO | NO | If MPI enabled, then use srun instead of mpiexec to run parallel tests | -| DOXYGEN | YES, NO | NO | Run doxygen on several packages during build to generate documentation | -| OMIT_DEPRECATED | YES, NO | NO | Should the deprecated code be omitted; NO will enable deprecated code | -| EXTRA_WARNINGS | YES, NO | NO | Build with extra warnings enabled; see list in `cmake-config` | -| SANITIZER | many | NO | If not NO, build using specified sanitizer; see list in `cmake-config` | -| GENERATOR | many | "Unix Makefiles" | what generator should CMake use; see cmake doc | -* The arguments can either be set in the environment as: `export COMPILER=gnu`, or passed on the script invocation line: `COMPILER=gnu ./install-tpl.sh` - -## Parallel Build - -For some areas of use, a parallel version of SEACAS is required. This -will build a "parallel-aware" version of the exodus library and a -parallel version of the Ioss library. - -The only modification to the serial build described above is to make -sure that the mpicc parallel C compiler is in your path and to add the -`MPI=YES` argument to the `install-tpl.sh` script invocation when -building the TPLs. For example: -```sh - MPI=YES ./install-tpl.sh -``` -This will download all requested libraries and build them with -parallel capability enabled (if applicable). You can then continue -with the steps outlined in the previous section. - -## Testing -There are a few unit tests for zoltan, exodus, ioss, and aprepro that can be run via `make test` or `ctest` if you configured with `-D Seacas_ENABLE_TESTS=YES`. - -There is also a system-level test that just verifies that the applications can read and write exodus files correctly. This test runs off of the installed applications. To run do: - -* `make install` -* `cd ../SEACAS-Test` -* `make clean; make` - -This will run through several of the SEACAS applications creating a mesh (exodus file) and then performing various manipulations on the mesh. If the test runs successfully, there is some hope that everything has built and is running correctly. - -## Exodus -If you only want the exodus library, then follow most of the above instructions with the following exceptions: - -* Clone entire source tree as above. (There used to be a zip file, but difficult to keep up-to-date) -* You only need the netcdf and optionally hdf5 libraries -* Use the `cmake-exodus` file instead of `cmake-config`. -* This will build, by default, a shared exodus library and also install the exodus.py and exomerge.py Python interfaces. - -## Trilinos - -Although SEACAS is included in Trilinos -(https://github.com/trilinos/Trilinos), it is also possible to use the -SEACAS code from this repository to override the possibly older SEACAS -code in Trilinos. The steps are to directly pull SEACAS from github -under Trilinos and then build SEACAS under Trilinos with that version -using `SEACAS_SOURCE_DIR_OVERRIDE`. Here is how you do it: - -```sh -cd Trilinos/ -git clone https://github.com/sandialabs/seacas.git -cd BUILD/ -cmake -DSEACAS_SOURCE_DIR_OVERRIDE:STRING=seacas/packages/seacas -DTrilinos_ENABLE_SEACAS [other options] .. -``` - -## SPACK - -The SPACK package manager (https://spack.io/) can be used to install -SEACAS and all dependent third-party libraries. SEACAS is a supported -package in SPACK as of December 2018. - -```sh -git clone https://github.com/spack/spack.git -. spack/share/spack/setup-env.sh -spack install seacas~mpi # Serial build (most common) -``` - -Enter `spack info seacas` to see information on supported variants and other information about the SEACAS package. - -## License - -SEACAS is licensed under the Modified BSD License. See the [LICENSE](LICENSE) file for details. - -The following externally-developed software routines are used in some of the SEACAS applications and are under -a separate license: - -| Routine | Where Used | License | -|---------|-------------|:-------:| -| getline | `packages/seacas/libraries/aprepro_lib/apr_getline_int.c` | [MIT](https://opensource.org/licenses/MIT) | -| getline | `packages/seacas/libraries/suplib_c/getline.c` | [BSD](https://opensource.org/licenses/BSD-3-Clause) | -| [GetLongOpt](https://searchcode.com/codesearch/view/64130032/) | `packages/seacas/libraries/suplib_cpp/GetLongOpt.C` | public domain | -| [adler hash](https://en.wikipedia.org/wiki/Adler-32) | `packages/seacas/libraries/suplib_c/adler.c` | [zlib](https://opensource.org/licenses/zlib) | -| [MurmurHash](https://github.com/aappleby/smhasher) | `packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.C` | public domain | -| [json include file](http://jsoncpp.sourceforge.net) | `packages/seacas/libraries/ioss/src/visualization/` | [MIT](https://opensource.org/licenses/MIT) | -| [terminal_color](https://github.com/matovitch/trmclr) | `packages/seacas/libraries/aprepro_lib` | [zlib](https://opensource.org/licenses/zlib) | -| [Tessil Hash](https://github.com/Tessil/) | `packages/seacas/libraries/ioss/src/hash` | [MIT](https://opensource.org/licenses/MIT) | -| [doctest](https://github.com/doctest/doctest) | `packages/seacas/libraries/ioss/src/doctest.h` | [MIT](https://opensource.org/licenses/MIT) | -| [pdqsort](https://github.com/orlp/pdqsort) | `packages/seacas/libraries/ioss/src` | [Zlib License](https://github.com/orlp/pdqsort/blob/master/license.txt) | -## Contact information - - Greg Sjaardema (, ) \ No newline at end of file diff --git a/packages/seacas/applications/algebra/ag_eval.f b/packages/seacas/applications/algebra/ag_eval.f index 3425fd050c..9e648c7bcc 100644 --- a/packages/seacas/applications/algebra/ag_eval.f +++ b/packages/seacas/applications/algebra/ag_eval.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -18,7 +18,7 @@ SUBROUTINE EVAL (STEP1, WSTEP1, MAXNE, MAXSTK, C -- C --Parameters: C -- STEP1 - IN - true iff evaluating the first selected time step -C -- WSTEP1 - IN - true iff evalutaing the first selected whole time step +C -- WSTEP1 - IN - true iff evaluating the first selected whole time step C -- MAXNE - IN - the VARVAL and STACK dimension C -- MAXSTK - IN - the maximum STACK size C -- IXNODE - IN - the indices of the zoomed nodes (iff ISZOOM) diff --git a/packages/seacas/applications/algebra/ag_rweval.f b/packages/seacas/applications/algebra/ag_rweval.f index f762e5219e..ee73197176 100644 --- a/packages/seacas/applications/algebra/ag_rweval.f +++ b/packages/seacas/applications/algebra/ag_rweval.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -228,7 +228,7 @@ SUBROUTINE RWEVAL (NDBIN, NDBOUT, A, ia, C, NPTIMS, NUMSTO, RETURN END IF -C delete corrdinate arrays - no longer needed +C delete coordinate arrays - no longer needed IF (ISZOOM) THEN CALL MDDEL ('XN') CALL MDDEL ('YN') diff --git a/packages/seacas/applications/aprepro/aprepro.C b/packages/seacas/applications/aprepro/aprepro.C index d1a8791910..8516f64e21 100644 --- a/packages/seacas/applications/aprepro/aprepro.C +++ b/packages/seacas/applications/aprepro/aprepro.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions +// Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -93,9 +93,15 @@ int main(int argc, char *argv[]) else { std::fstream infile(input_files[0], std::fstream::in); if (!infile.good()) { - std::cerr << "APREPRO: ERROR: Could not open file: " << input_files[0] << '\n' - << " Error Code: " << strerror(errno) << '\n'; - return EXIT_FAILURE; + if (!aprepro.ap_options.include_path.empty() && input_files[0][0] != '/') { + std::string filename = aprepro.ap_options.include_path + "/" + input_files[0]; + infile.open(filename, std::fstream::in); + } + if (!infile.good()) { + std::cerr << "APREPRO: ERROR: Could not open file: " << input_files[0] << '\n' + << " Error Code: " << strerror(errno) << '\n'; + return EXIT_FAILURE; + } } // Read and parse a file. The entire file will be parsed and @@ -162,5 +168,8 @@ int main(int argc, char *argv[]) if (aprepro.ap_options.dumpvars_json) { aprepro.dumpsym_json(); } + if (aprepro.get_error_count() > 0) { + exit_status = EXIT_FAILURE; + } return exit_status; } diff --git a/packages/seacas/applications/aprepro/test-array.gold b/packages/seacas/applications/aprepro/test-array.gold index 69874dee39..9b65097169 100644 --- a/packages/seacas/applications/aprepro/test-array.gold +++ b/packages/seacas/applications/aprepro/test-array.gold @@ -1,8 +1,6 @@ 27 21 -0 -0 a[0,0] = 0 a[0,1] = 1 a[0,2] = 1 @@ -24,8 +22,6 @@ a[0,17] = 0 a[0,18] = 0 a[0,19] = 0 a[0,20] = 0 -0 -0 a[1,0] = 1 a[1,1] = 0.99987325 a[1,2] = 0.9998324 @@ -47,8 +43,6 @@ a[1,17] = 0.00027661075 a[1,18] = 0.00027661075 a[1,19] = -0.0057027978 a[1,20] = -5.5178336e-05 -1 -0 a[2,0] = 2 a[2,1] = 0.99845402 a[2,2] = 0.99795569 @@ -70,8 +64,6 @@ a[2,17] = 0.0009683687 a[2,18] = 0.0009683687 a[2,19] = -0.019904266 a[2,20] = -0.00019329815 -2 -0 a[3,0] = 3 a[3,1] = 0.98850008 a[3,2] = 0.98478703 @@ -93,8 +85,6 @@ a[3,17] = 0.0026867021 a[3,18] = 0.0026867021 a[3,19] = -0.054060764 a[3,20] = -0.0005387864 -3 -0 a[4,0] = 4 a[4,1] = 0.93725124 a[4,2] = 0.91675084 @@ -116,8 +106,6 @@ a[4,17] = 0.0068817499 a[4,18] = 0.0068817499 a[4,19] = -0.12385676 a[4,20] = -0.0014128781 -4 -0 a[5,0] = 5 a[5,1] = 0.78303105 a[5,2] = 0.70605164 @@ -139,8 +127,6 @@ a[5,17] = 0.017841674 a[5,18] = 0.017841674 a[5,19] = -0.2249124 a[5,20] = -0.0039246734 -5 -0 a[6,0] = 6 a[6,1] = 0.58749345 a[6,2] = 0.38695099 @@ -162,8 +148,6 @@ a[6,17] = 0.04687771 a[6,18] = 0.04687771 a[6,19] = -0.36388926 a[6,20] = -0.011322374 -6 -0 a[7,0] = 7 a[7,1] = 0.46344872 a[7,2] = 0.10229219 @@ -185,8 +169,6 @@ a[7,17] = 0.091142312 a[7,18] = 0.091142312 a[7,19] = -0.5376443 a[7,20] = -0.023508048 -7 -0 a[8,0] = 8 a[8,1] = 0.33229323 a[8,2] = -0.16617592 @@ -208,8 +190,6 @@ a[8,17] = 0.14188296 a[8,18] = 0.14188296 a[8,19] = -0.65939491 a[8,20] = -0.038766269 -8 -0 a[9,0] = 9 a[9,1] = 0.17891649 a[9,2] = -0.38710265 @@ -231,8 +211,6 @@ a[9,17] = 0.19927048 a[9,18] = 0.19927048 a[9,19] = -0.67346847 a[9,20] = -0.058633647 -9 -0 a[10,0] = 10 a[10,1] = -0.13164902 a[10,2] = -0.34780142 @@ -254,8 +232,6 @@ a[10,17] = 0.21231109 a[10,18] = 0.21231109 a[10,19] = -0.16937775 a[10,20] = -0.070083742 -10 -0 a[11,0] = 11 a[11,1] = -0.3035429 a[11,2] = -0.27338056 @@ -277,8 +253,6 @@ a[11,17] = 0.12496344 a[11,18] = 0.12496344 a[11,19] = 0.14814128 a[11,20] = -0.034715875 -11 -0 a[12,0] = 12 a[12,1] = -0.44522164 a[12,2] = -0.17411905 @@ -300,8 +274,6 @@ a[12,17] = 0.013153708 a[12,18] = 0.013153708 a[12,19] = 0.41583551 a[12,20] = 0.01075339 -12 -0 a[13,0] = 13 a[13,1] = -0.45323429 a[13,2] = -0.16423295 @@ -323,8 +295,6 @@ a[13,17] = 0.0070692183 a[13,18] = 0.0070692183 a[13,19] = 0.42910234 a[13,20] = 0.013542511 -13 -0 a[14,0] = 14 a[14,1] = -0.45726698 a[14,2] = -0.15867506 @@ -346,8 +316,6 @@ a[14,17] = 0.0041556594 a[14,18] = 0.0041556594 a[14,19] = 0.43539545 a[14,20] = 0.014960681 -14 -0 a[15,0] = 15 a[15,1] = -0.45911461 a[15,2] = -0.15590224 @@ -369,8 +337,6 @@ a[15,17] = 0.0028475236 a[15,18] = 0.0028475236 a[15,19] = 0.4381761 a[15,20] = 0.015623524 -15 -0 a[16,0] = 16 a[16,1] = -0.46066116 a[16,2] = -0.1534213 @@ -392,8 +358,6 @@ a[16,17] = 0.0017609882 a[16,18] = 0.0017609882 a[16,19] = 0.44044676 a[16,20] = 0.016190051 -16 -0 a[17,0] = 17 a[17,1] = -0.46131249 a[17,2] = -0.15232075 @@ -415,8 +379,6 @@ a[17,17] = 0.0013045344 a[17,18] = 0.0013045344 a[17,19] = 0.44138589 a[17,20] = 0.01643313 -17 -0 a[18,0] = 18 a[18,1] = -0.46186461 a[18,2] = -0.15135669 @@ -438,8 +400,6 @@ a[18,17] = 0.0009176024 a[18,18] = 0.0009176024 a[18,19] = 0.44217335 a[18,20] = 0.01664184 -18 -0 a[19,0] = 19 a[19,1] = -0.46209974 a[19,2] = -0.15093647 @@ -461,8 +421,6 @@ a[19,17] = 0.0007527215 a[19,18] = 0.0007527215 a[19,19] = 0.44250617 a[19,20] = 0.016731567 -19 -0 a[20,0] = 20 a[20,1] = -0.46230071 a[20,2] = -0.15057238 @@ -484,8 +442,6 @@ a[20,17] = 0.00061170959 a[20,18] = 0.00061170959 a[20,19] = 0.44278939 a[20,20] = 0.016808699 -20 -0 a[21,0] = 21 a[21,1] = -0.46247259 a[21,2] = -0.15025718 @@ -507,8 +463,6 @@ a[21,17] = 0.0004910241 a[21,18] = 0.0004910241 a[21,19] = 0.4430307 a[21,20] = 0.016875009 -21 -0 a[22,0] = 22 a[22,1] = -0.46261969 a[22,2] = -0.14998454 @@ -530,8 +484,6 @@ a[22,17] = 0.00038766956 a[22,18] = 0.00038766956 a[22,19] = 0.44323651 a[22,20] = 0.016932021 -22 -0 a[23,0] = 23 a[23,1] = -0.46274565 a[23,2] = -0.14974888 @@ -553,8 +505,6 @@ a[23,17] = 0.00029910796 a[23,18] = 0.00029910796 a[23,19] = 0.44341222 a[23,20] = 0.01698104 -23 -0 a[24,0] = 24 a[24,1] = -0.46285356 a[24,2] = -0.14954531 @@ -576,8 +526,6 @@ a[24,17] = 0.00022318514 a[24,18] = 0.00022318514 a[24,19] = 0.44356236 a[24,20] = 0.01702319 -24 -0 a[25,0] = 25 a[25,1] = -0.46294605 a[25,2] = -0.14936957 @@ -599,8 +547,6 @@ a[25,17] = 0.00015806979 a[25,18] = 0.00015806979 a[25,19] = 0.44369076 a[25,20] = 0.017059434 -25 -0 a[26,0] = 26 a[26,1] = -0.46310439 a[26,2] = -0.1490659 @@ -622,34 +568,33 @@ a[26,17] = 4.649547e-05 a[26,18] = 4.649547e-05 a[26,19] = 0.44390995 a[26,20] = 0.017121745 -26 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 - 1 0.999873 0.999832 0.999907 0.999898 0.999925 0.999847 0.999944 0.999944 0.999832 0.999963 -0.00452743 0.0057028 -0.00585599 0.0019344 -0.000780655 -0.00883995 0.000276611 0.000276611 -0.0057028 -5.51783e-05 - 2 0.998454 0.997956 0.99886 0.998754 0.999085 0.998137 0.99932 0.99932 0.997956 0.999545 -0.0158135 0.0199043 -0.0204344 0.00676292 -0.00273061 -0.0308503 0.000968369 0.000968369 -0.0199043 -0.000193298 - 3 0.9885 0.984787 0.991559 0.990719 0.9932 0.986176 0.994937 0.994937 0.984787 0.996607 -0.0431721 0.0540608 -0.0554122 0.0185875 -0.0075306 -0.0837226 0.0026867 0.0026867 -0.0540608 -0.000538786 - 4 0.937251 0.916751 0.955005 0.948911 0.963021 0.925509 0.972207 0.972207 0.916751 0.981228 -0.101638 0.123857 -0.125722 0.0453522 -0.0186964 -0.190875 0.00688175 0.00688175 -0.123857 -0.00141288 - 5 0.783031 0.706052 0.858357 0.816945 0.874477 0.753076 0.901742 0.901742 0.706052 0.931506 -0.201385 0.224912 -0.21633 0.101573 -0.0439245 -0.337204 0.0178417 0.0178417 -0.224912 -0.00392467 - 6 0.587493 0.386951 0.791377 0.618137 0.778518 0.566564 0.80515 0.80515 0.386951 0.852702 -0.359302 0.363889 -0.286077 0.222437 -0.0993392 -0.487505 0.0468777 0.0468777 -0.363889 -0.0113224 - 7 0.463449 0.102292 0.808299 0.440292 0.736982 0.484754 0.728381 0.728381 0.102292 0.773159 -0.542376 0.537644 -0.331173 0.388923 -0.173033 -0.627366 0.0911423 0.0911423 -0.537644 -0.023508 - 8 0.332293 -0.166176 0.816825 0.238693 0.677847 0.396021 0.613956 0.613956 -0.166176 0.643172 -0.69547 0.659395 -0.373148 0.543102 -0.248479 -0.740677 0.141883 0.141883 -0.659395 -0.0387663 - 9 0.178916 -0.387103 0.777598 0.024505 0.586197 0.247539 0.41731 0.41731 -0.387103 0.371602 -0.788217 0.673468 -0.431381 0.653529 -0.321609 -0.80977 0.19927 0.19927 -0.673468 -0.0586336 - 10 -0.131649 -0.347801 0.435212 -0.162899 0.373888 -0.185893 0.14518 0.14518 -0.347801 -0.0563094 -0.490017 0.169378 -0.466717 0.450316 -0.315911 -0.495294 0.212311 0.212311 -0.169378 -0.0700837 - 11 -0.303543 -0.273381 0.41333 -0.217871 0.221594 -0.338191 0.0702492 0.0702492 -0.273381 -0.031344 -0.317064 -0.148141 -0.501882 0.190653 -0.251762 -0.407793 0.124963 0.124963 0.148141 -0.0347159 - 12 -0.445222 -0.174119 0.394445 -0.253131 0.0399691 -0.462478 -0.0267525 -0.0267525 -0.174119 -0.0101022 -0.134017 -0.415836 -0.531824 -0.0904316 -0.163274 -0.312139 0.0131537 0.0131537 0.415836 0.0107534 - 13 -0.453234 -0.164233 0.387393 -0.256267 0.0297529 -0.470572 -0.0329712 -0.0329712 -0.164233 -0.0096751 -0.120799 -0.429102 -0.533969 -0.107166 -0.159858 -0.29943 0.00706922 0.00706922 0.429102 0.0135425 - 14 -0.457267 -0.158675 0.382818 -0.258147 0.0248439 -0.474706 -0.0361136 -0.0361136 -0.158675 -0.00953276 -0.113859 -0.435395 -0.535098 -0.115565 -0.158604 -0.291894 0.00415566 0.00415566 0.435395 0.0149607 - 15 -0.459115 -0.155902 0.380363 -0.259097 0.0226342 -0.476617 -0.0375729 -0.0375729 -0.155902 -0.00948304 -0.110537 -0.438176 -0.535614 -0.119457 -0.158158 -0.288026 0.00284752 0.00284752 0.438176 0.0156235 - 16 -0.460661 -0.153421 0.378067 -0.259946 0.020795 -0.478225 -0.0388134 -0.0388134 -0.153421 -0.00944873 -0.107645 -0.440447 -0.536038 -0.122765 -0.157855 -0.284504 0.00176099 0.00176099 0.440447 0.0161901 - 17 -0.461312 -0.152321 0.377019 -0.26032 0.020021 -0.478906 -0.0393434 -0.0393434 -0.152321 -0.00943625 -0.106387 -0.441386 -0.536212 -0.124177 -0.15775 -0.282924 0.00130453 0.00130453 0.441386 0.0164331 - 18 -0.461865 -0.151357 0.376085 -0.260647 0.0193641 -0.479484 -0.0397972 -0.0397972 -0.151357 -0.0094266 -0.105297 -0.442173 -0.536357 -0.125387 -0.157671 -0.28153 0.000917602 0.000917602 0.442173 0.0166418 - 19 -0.4621 -0.150936 0.375674 -0.260788 0.019084 -0.479731 -0.0399919 -0.0399919 -0.150936 -0.00942274 -0.104825 -0.442506 -0.536418 -0.125907 -0.157641 -0.28092 0.000752721 0.000752721 0.442506 0.0167316 - 20 -0.462301 -0.150572 0.375316 -0.260911 0.0188443 -0.479942 -0.0401591 -0.0401591 -0.150572 -0.00941956 -0.104418 -0.442789 -0.53647 -0.126353 -0.157617 -0.28039 0.00061171 0.00061171 0.442789 0.0168087 - 21 -0.462473 -0.150257 0.375004 -0.261016 0.018639 -0.480123 -0.0403027 -0.0403027 -0.150257 -0.00941693 -0.104067 -0.443031 -0.536514 -0.126736 -0.157597 -0.279931 0.000491024 0.000491024 0.443031 0.016875 - 22 -0.46262 -0.149985 0.374733 -0.261108 0.0184632 -0.480278 -0.0404261 -0.0404261 -0.149985 -0.00941475 -0.103765 -0.443237 -0.536551 -0.127065 -0.157582 -0.279532 0.00038767 0.00038767 0.443237 0.016932 - 23 -0.462746 -0.149749 0.374498 -0.261186 0.0183125 -0.480411 -0.0405321 -0.0405321 -0.149749 -0.00941293 -0.103504 -0.443412 -0.536582 -0.127347 -0.157569 -0.279187 0.000299108 0.000299108 0.443412 0.016981 - 24 -0.462854 -0.149545 0.374294 -0.261254 0.0181832 -0.480524 -0.0406231 -0.0406231 -0.149545 -0.0094114 -0.103279 -0.443562 -0.536609 -0.12759 -0.157558 -0.278889 0.000223185 0.000223185 0.443562 0.0170232 - 25 -0.462946 -0.14937 0.374117 -0.261313 0.0180723 -0.480622 -0.0407014 -0.0407014 -0.14937 -0.00941012 -0.103086 -0.443691 -0.536632 -0.127799 -0.15755 -0.278631 0.00015807 0.00015807 0.443691 0.0170594 - 26 -0.463104 -0.149066 0.373812 -0.261413 0.0178823 -0.480789 -0.0408358 -0.0408358 -0.149066 -0.00940798 -0.102752 -0.44391 -0.536671 -0.128158 -0.157536 -0.278185 4.64955e-05 4.64955e-05 0.44391 0.0171217 + 1 0.99987325 0.9998324 0.99990651 0.99989789 0.99992499 0.99984721 0.99994427 0.99994427 0.9998324 0.99996271 -0.0045274345 0.0057027978 -0.0058559869 0.0019343975 -0.00078065548 -0.0088399481 0.00027661075 0.00027661075 -0.0057027978 -5.5178336e-05 + 2 0.99845402 0.99795569 0.99886038 0.99875437 0.99908526 0.99813713 0.99932017 0.99932017 0.99795569 0.99954507 -0.015813503 0.019904266 -0.020434428 0.0067629179 -0.0027306099 -0.030850279 0.0009683687 0.0009683687 -0.019904266 -0.00019329815 + 3 0.98850008 0.98478703 0.99155875 0.99071948 0.99319953 0.98617577 0.9949374 0.9949374 0.98478703 0.99660735 -0.043172077 0.054060764 -0.055412197 0.018587476 -0.0075305988 -0.083722618 0.0026867021 0.0026867021 -0.054060764 -0.0005387864 + 4 0.93725124 0.91675084 0.95500497 0.94891136 0.9630209 0.9255086 0.97220689 0.97220689 0.91675084 0.98122817 -0.10163823 0.12385676 -0.12572195 0.045352196 -0.018696437 -0.19087532 0.0068817499 0.0068817499 -0.12385676 -0.0014128781 + 5 0.78303105 0.70605164 0.85835725 0.81694487 0.87447745 0.75307557 0.9017422 0.9017422 0.70605164 0.93150588 -0.20138474 0.2249124 -0.21632996 0.10157337 -0.04392447 -0.33720391 0.017841674 0.017841674 -0.2249124 -0.0039246734 + 6 0.58749345 0.38695099 0.79137664 0.61813726 0.7785177 0.56656449 0.80515035 0.80515035 0.38695099 0.85270233 -0.3593023 0.36388926 -0.28607711 0.22243683 -0.099339161 -0.48750546 0.04687771 0.04687771 -0.36388926 -0.011322374 + 7 0.46344872 0.10229219 0.80829933 0.44029196 0.73698231 0.48475397 0.72838129 0.72838129 0.10229219 0.77315948 -0.54237647 0.5376443 -0.33117305 0.38892284 -0.17303342 -0.62736563 0.091142312 0.091142312 -0.5376443 -0.023508048 + 8 0.33229323 -0.16617592 0.8168248 0.23869311 0.67784736 0.39602058 0.61395585 0.61395585 -0.16617592 0.64317238 -0.69546982 0.65939491 -0.37314835 0.54310201 -0.24847898 -0.74067666 0.14188296 0.14188296 -0.65939491 -0.038766269 + 9 0.17891649 -0.38710265 0.77759846 0.024504973 0.58619655 0.24753853 0.41731032 0.41731032 -0.38710265 0.37160176 -0.78821686 0.67346847 -0.4313815 0.65352921 -0.32160908 -0.80977014 0.19927048 0.19927048 -0.67346847 -0.058633647 + 10 -0.13164902 -0.34780142 0.43521191 -0.16289891 0.37388776 -0.1858933 0.14518026 0.14518026 -0.34780142 -0.056309359 -0.49001652 0.16937775 -0.46671727 0.4503163 -0.31591122 -0.49529438 0.21231109 0.21231109 -0.16937775 -0.070083742 + 11 -0.3035429 -0.27338056 0.41332959 -0.21787127 0.22159388 -0.33819096 0.070249167 0.070249167 -0.27338056 -0.031344002 -0.31706446 -0.14814128 -0.50188227 0.19065277 -0.25176215 -0.40779282 0.12496344 0.12496344 0.14814128 -0.034715875 + 12 -0.44522164 -0.17411905 0.39444488 -0.253131 0.039969083 -0.46247794 -0.026752493 -0.026752493 -0.17411905 -0.010102207 -0.13401686 -0.41583551 -0.53182392 -0.09043161 -0.1632736 -0.31213863 0.013153708 0.013153708 0.41583551 0.01075339 + 13 -0.45323429 -0.16423295 0.38739292 -0.25626728 0.029752934 -0.47057195 -0.032971178 -0.032971178 -0.16423295 -0.0096751029 -0.12079852 -0.42910234 -0.53396874 -0.10716627 -0.15985789 -0.29942973 0.0070692183 0.0070692183 0.42910234 0.013542511 + 14 -0.45726698 -0.15867506 0.38281814 -0.25814655 0.024843886 -0.47470613 -0.03611364 -0.03611364 -0.15867506 -0.0095327622 -0.11385876 -0.43539545 -0.53509827 -0.11556516 -0.15860438 -0.29189408 0.0041556594 0.0041556594 0.43539545 0.014960681 + 15 -0.45911461 -0.15590224 0.38036274 -0.25909681 0.022634211 -0.47661652 -0.03757291 -0.03757291 -0.15590224 -0.0094830365 -0.11053679 -0.4381761 -0.53561397 -0.11945747 -0.15815753 -0.28802619 0.0028475236 0.0028475236 0.4381761 0.015623524 + 16 -0.46066116 -0.1534213 0.37806694 -0.25994574 0.020794998 -0.47822516 -0.038813403 -0.038813403 -0.1534213 -0.0094487263 -0.10764499 -0.44044676 -0.53603753 -0.12276455 -0.15785521 -0.28450448 0.0017609882 0.0017609882 0.44044676 0.016190051 + 17 -0.46131249 -0.15232075 0.37701862 -0.26032025 0.020020999 -0.47890567 -0.039343381 -0.039343381 -0.15232075 -0.0094362538 -0.10638658 -0.44138589 -0.53621194 -0.12417743 -0.15774968 -0.28292397 0.0013045344 0.0013045344 0.44138589 0.01643313 + 18 -0.46186461 -0.15135669 0.37608528 -0.26064663 0.019364133 -0.47948413 -0.039797192 -0.039797192 -0.15135669 -0.0094265965 -0.10529653 -0.44217335 -0.53635716 -0.12538742 -0.15767126 -0.28153034 0.0009176024 0.0009176024 0.44217335 0.01664184 + 19 -0.46209974 -0.15093647 0.37567407 -0.26078828 0.019083993 -0.47973095 -0.039991917 -0.039991917 -0.15093647 -0.0094227387 -0.10482499 -0.44250617 -0.53641813 -0.12590669 -0.15764111 -0.28092024 0.0007527215 0.0007527215 0.44250617 0.016731567 + 20 -0.46230071 -0.15057238 0.37531563 -0.26091069 0.018844288 -0.47994216 -0.040159119 -0.040159119 -0.15057238 -0.0094195623 -0.10441818 -0.44278939 -0.53646977 -0.12635262 -0.15761694 -0.28039033 0.00061170959 0.00061170959 0.44278939 0.016808699 + 21 -0.46247259 -0.15025718 0.37500374 -0.26101639 0.018639044 -0.48012298 -0.040302721 -0.040302721 -0.15025718 -0.009416934 -0.10406733 -0.4430307 -0.53651357 -0.12673565 -0.15759747 -0.27993062 0.0004910241 0.0004910241 0.4430307 0.016875009 + 22 -0.46261969 -0.14998454 0.37473275 -0.26110761 0.018463203 -0.48027787 -0.040426076 -0.040426076 -0.14998454 -0.0094147496 -0.10376482 -0.44323651 -0.53655077 -0.12706471 -0.15758171 -0.27953225 0.00038766956 0.00038766956 0.44323651 0.016932021 + 23 -0.46274565 -0.14974888 0.37449762 -0.2611863 0.018312477 -0.48041061 -0.040532058 -0.040532058 -0.14974888 -0.0094129267 -0.10350408 -0.44341222 -0.53658239 -0.12734745 -0.15756888 -0.27918738 0.00029910796 0.00029910796 0.44341222 0.01698104 + 24 -0.46285356 -0.14954531 0.37429385 -0.26125414 0.01818322 -0.4805244 -0.040623125 -0.040623125 -0.14954531 -0.0094114 -0.1032794 -0.44356236 -0.53660931 -0.12759042 -0.1575584 -0.27888908 0.00022318514 0.00022318514 0.44356236 0.01702319 + 25 -0.46294605 -0.14936957 0.37411743 -0.26131261 0.018072332 -0.48062199 -0.040701387 -0.040701387 -0.14936957 -0.0094101171 -0.10308583 -0.44369076 -0.53663226 -0.12779925 -0.15754978 -0.27863125 0.00015806979 0.00015806979 0.44369076 0.017059434 + 26 -0.46310439 -0.1490659 0.37381151 -0.26141341 0.017882259 -0.4807892 -0.040835831 -0.040835831 -0.1490659 -0.009407976 -0.10275225 -0.44390995 -0.53667124 -0.12815802 -0.15753586 -0.2781851 4.649547e-05 4.649547e-05 0.44390995 0.017121745 @@ -685,10 +630,17 @@ sum = e + e = 1552 1624 e+e-2*e = 0 0 0 0 -scale = 1 1.04639 - 1.81186 1.89691 +scale = 1 1.046391753 + 1.81185567 1.896907216 17 27 + + 2.3 5.7 11.13 17.19 23.29 31.37 41.43 47.53 59.61 67.71 + + + 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 + + diff --git a/packages/seacas/applications/aprepro/test-array.i b/packages/seacas/applications/aprepro/test-array.i index 7ac22eb3db..22871f0e25 100644 --- a/packages/seacas/applications/aprepro/test-array.i +++ b/packages/seacas/applications/aprepro/test-array.i @@ -1,13 +1,10 @@ {a = csv_array("rect.csv")} {_therow = rows(a)} {_col = cols(a)} -{_r = 0} -{loop(_therow)} -{_c = 0} -{loop(_col)} -a[{_r},{_c}] = {a[_r,_c++]} +{loop(_therow, _r)} +{loop(_col, _c)} +a[{_r},{_c}] = {a[_r,_c]} {endloop} -{_r++} {endloop} {print_array(a)} @@ -15,13 +12,10 @@ a[{_r},{_c}] = {a[_r,_c++]} {NOECHO} {_therow = rows(b)} {_col = cols(b)} -{_r = 0} -{loop(_therow)} -{_c = 0} -{loop(_col)} -{b[_r,_c] = 10*(_r+1) + _c++ + 1} +{loop(_therow, _r)} +{loop(_col, _c)} +{b[_r,_c] = 10*(_r+1) + _c + 1} {endloop} -{_r++} {endloop} {ECHO} b = {print_array(b)} @@ -30,13 +24,10 @@ b = {print_array(b)} {NOECHO} {_therow = rows(c)} {_col = cols(c)} -{_r = 0} -{loop(_therow)} -{_c = 0} -{loop(_col)} -{c[_r,_c] = 10*(_r+1) + _c++ + 1} +{loop(_therow, _r)} +{loop(_col, _c)} +{c[_r,_c] = 10*(_r+1) + _c + 1} {endloop} -{_r++} {endloop} {ECHO} c = {print_array(c)} @@ -62,4 +53,11 @@ scale = {print_array(e*1/e[0,0])} {asub = csv_array("rect.csv", 10)} {asub_rows = rows(asub)} {a_rows = rows(a)} + +{std = array_from_string('2.3 5.7 11.13 17.19 23.29 31.37 41.43 47.53 59.61 67.71',' ')} +{print_array(transpose(std))} + +{st = array_from_string('2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71',' ')} +{print_array(transpose(st))} + {DUMP()} diff --git a/packages/seacas/applications/aprepro/test-array.stderr.gold b/packages/seacas/applications/aprepro/test-array.stderr.gold index 5e8e8ba5e8..04b6b88ddb 100644 --- a/packages/seacas/applications/aprepro/test-array.stderr.gold +++ b/packages/seacas/applications/aprepro/test-array.stderr.gold @@ -1,8 +1,6 @@ $ Variable = Value -$ {_c = 3} $ {_col = 3} -$ {_r = 2} $ {_therow = 2} $ {a (array) rows = 27, cols = 21} $ {a_rows = 27} @@ -13,3 +11,5 @@ $ {c (array) rows = 2, cols = 3} $ {d (array) rows = 3, cols = 3} $ {e (array) rows = 2, cols = 2} $ {et (array) rows = 2, cols = 2} +$ {st (array) rows = 20, cols = 1} +$ {std (array) rows = 10, cols = 1} diff --git a/packages/seacas/applications/aprepro/test.inp_app b/packages/seacas/applications/aprepro/test.inp_app index e0a89193e2..e89ca173fb 100644 --- a/packages/seacas/applications/aprepro/test.inp_app +++ b/packages/seacas/applications/aprepro/test.inp_app @@ -148,19 +148,19 @@ $ Test if - else lines {endif} $ ======================================================================== $ Test switch -{ switch(PI) } +{switch(PI)} This is in a switch, but prior to any case, it should not run {a = 0.5} Should not execute - {case (1) } +{case (1)} This should not echo {a = 1} -{ case (2) } +{case (2)} This should not echo {a = 2} - {case (PI)} +{case (PI)} This should echo {a = PI} @@ -171,7 +171,7 @@ This should not echo since a previous case matched. {default} {a=4} -{ endswitch } +{endswitch} This should be equal to PI -- {PI} $ Test int and [] (shortcut for int) @@ -179,15 +179,14 @@ $ Test int and [] (shortcut for int) {[5.01]} {[-5.01]} $ Test looping - print sin, cos from 0 to 90 by 5 -{_angle = -5} -{Loop(19)} -{_angle += 5} {_sa=sind(_angle)} {_ca=cosd(_angle)} {hypot(_sa, _ca)} +{Loop(19, _angle, 0, 5)} +{_angle} {_sa=sind(_angle)} {_ca=cosd(_angle)} {hypot(_sa, _ca)} {EndLoop} $$$$ Test formatting and string concatenation -{_i = 0} {_SAVE = _FORMAT} +{_SAVE = _FORMAT} {loop(20)} -{IO(++_i)} Using the format {_FORMAT = "%." // tostring(_i) // "g"}, PI = {PI} +{IO(__loop_1+1)} Using the format {_FORMAT = "%." // tostring(__loop_1+1) // "g"}, PI = {PI} {endloop} Reset format to default: {_FORMAT = _SAVE} @@ -201,12 +200,12 @@ $$$$ Test string rescanning and executing Original String: {Test} Rescanned String: -{rescan(Test)} +{rescan(Test)} Original String: {Test2} Print Value of variable T = {T} Rescanned String: -{rescan(Test2)} +{rescan(Test2)} Print Value of variable T = {T} Original String: {t1 = "atan2(0,-1)"} @@ -227,9 +226,8 @@ string = {_string = " one two, three"} delimiter "{_delm = " ,"}" word count = { iwords = word_count(_string,_delm)} -{_n = 0} - {loop(iwords)} -word {++_n} = "{get_word(_n,_string,_delm)}" + {loop(iwords, _n, 1)} +word {_n} = "{get_word(_n,_string,_delm)}" {endloop} $ Check parsing of escaped braces... @@ -246,4 +244,11 @@ $ Test extract {ex_found = extract("The test string is found", "test", "")} {ex_null = extract("The test string is not found", "xxxx", "yyyy")} +$ Test string tokenization optimization +{list1 ='51,52,53,54,61,62,63,64'} +{list2 ='71,72,73,74,81,82,83,84'} +{loop(8, _i, 1)} +Word {_i} of list1 and list2 are {get_word(_i,list1,',')} and {get_word(_i,list2,',')} +{endloop} + $End of test file diff --git a/packages/seacas/applications/aprepro/test_standard.out b/packages/seacas/applications/aprepro/test_standard.out index 5dc9cfdc28..547666f429 100644 --- a/packages/seacas/applications/aprepro/test_standard.out +++ b/packages/seacas/applications/aprepro/test_standard.out @@ -89,7 +89,6 @@ $ Test int and [] (shortcut for int) 5 -5 $ Test looping - print sin, cos from 0 to 90 by 5 --5 0 0 1 1 5 0.08715574275 0.9961946981 1 10 0.1736481777 0.984807753 1 @@ -111,7 +110,7 @@ $ Test looping - print sin, cos from 0 to 90 by 5 90 1 6.123233996e-17 1 $$$$ Test formatting and string concatenation -0 %.10g +%.10g 1 Using the format %.1g, PI = 3 2 Using the format %.2g, PI = 3.1 3 Using the format %.3g, PI = 3.14 @@ -169,7 +168,6 @@ string = one two, three delimiter " ," word count = 3 -0 word 1 = "one" word 2 = "two" word 3 = "three" @@ -188,4 +186,16 @@ $ Test extract test string is found +$ Test string tokenization optimization +51,52,53,54,61,62,63,64 +71,72,73,74,81,82,83,84 +Word 1 of list1 and list2 are 51 and 71 +Word 2 of list1 and list2 are 52 and 72 +Word 3 of list1 and list2 are 53 and 73 +Word 4 of list1 and list2 are 54 and 74 +Word 5 of list1 and list2 are 61 and 81 +Word 6 of list1 and list2 are 62 and 82 +Word 7 of list1 and list2 are 63 and 83 +Word 8 of list1 and list2 are 64 and 84 + $End of test file diff --git a/packages/seacas/applications/blot/bl_rotate.f b/packages/seacas/applications/blot/bl_rotate.f index e8af2cce11..1dd61aa287 100644 --- a/packages/seacas/applications/blot/bl_rotate.f +++ b/packages/seacas/applications/blot/bl_rotate.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -13,7 +13,7 @@ SUBROUTINE BL_ROTATE (NUM, NPROT, ROTMAT, ROTCEN, C -- Written by Amy Gilkey - revised 09/09/87 C -- C --ROTATE rotates the 3D coordinates by subtracting the rotation center -C --and multipling by the rotation matrix. +C --and multiplying by the rotation matrix. C -- C --Parameters: C -- NUM - IN - the number of nodes to rotate diff --git a/packages/seacas/applications/conjoin/CJ_ExodusFile.h b/packages/seacas/applications/conjoin/CJ_ExodusFile.h index 81ab7d0fb7..2e7315ed51 100644 --- a/packages/seacas/applications/conjoin/CJ_ExodusFile.h +++ b/packages/seacas/applications/conjoin/CJ_ExodusFile.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -27,7 +27,7 @@ namespace Excn { static int output(); static int io_word_size() { return ioWordSize_; } - operator int() const; + operator int() const; static int max_name_length() { return maximumNameLength_; } private: diff --git a/packages/seacas/applications/conjoin/CJ_Internals.C b/packages/seacas/applications/conjoin/CJ_Internals.C index 2f5531b143..cefcd9b141 100644 --- a/packages/seacas/applications/conjoin/CJ_Internals.C +++ b/packages/seacas/applications/conjoin/CJ_Internals.C @@ -29,11 +29,8 @@ namespace { if ((ex_int64_status(exoid) & type) != 0U) { return NC_INT64; } - return NC_INT; } - bool lessOffset(const Excn::Block &b1, const Excn::Block &b2) { return b1.offset_ < b2.offset_; } - int define_netcdf_vars(int exoid, const char *type, size_t count, const char *dim_num, const char *stat_var, const char *id_var, const char *name_var); @@ -134,7 +131,8 @@ int Excn::Internals::write_meta_data(const Mesh &mesh, const std::vector sorted_blocks(blocks); if (!order_ok) { - std::sort(sorted_blocks.begin(), sorted_blocks.end(), lessOffset); + std::sort(sorted_blocks.begin(), sorted_blocks.end(), + [](const Block &b1, const Block &b2) { return b1.offset_ < b2.offset_; }); // Now, update the position_ field based on the sorted order. for (size_t i = 0; i < blocks.size(); i++) { @@ -261,22 +259,12 @@ int Excn::Internals::write_meta_data(const Mesh &mesh, const std::vector int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData & /*unused*/) { - int numdimdim = 0; - int numnoddim = 0; - int numelemdim = 0; - int timedim = 0; - int namestrdim = 0; - int varid = 0; - - int map_type = get_type(exodusFilePtr, EX_MAPS_INT64_DB); - - std::string errmsg; - // define some attributes... int status = nc_put_att_text(exodusFilePtr, NC_GLOBAL, ATT_TITLE, mesh.title.length() + 1, mesh.title.c_str()); if (status != NC_NOERR) { - errmsg = fmt::format("Error: failed to define title attribute to file id {}", exodusFilePtr); + std::string errmsg = + fmt::format("Error: failed to define title attribute to file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } @@ -289,8 +277,8 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta status = nc_put_att_int(exodusFilePtr, NC_GLOBAL, ATT_MAX_NAME_LENGTH, NC_INT, 1, ¤t_len); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = fmt::format("Error: failed to define ATT_MAX_NAME_LENGTH attribute to file id {}", - exodusFilePtr); + std::string errmsg = fmt::format( + "Error: failed to define ATT_MAX_NAME_LENGTH attribute to file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } @@ -300,36 +288,42 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta if (maximumNameLength < 32) { maximumNameLength = 32; } - status = nc_def_dim(exodusFilePtr, DIM_STR_NAME, maximumNameLength + 1, &namestrdim); + int namestrdim = 0; + status = nc_def_dim(exodusFilePtr, DIM_STR_NAME, maximumNameLength + 1, &namestrdim); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = fmt::format("Error: failed to define name string length in file id {}", exodusFilePtr); + std::string errmsg = + fmt::format("Error: failed to define name string length in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } // ...and some dimensions.. - status = nc_def_dim(exodusFilePtr, DIM_NUM_DIM, mesh.dimensionality, &numdimdim); + int numdimdim = 0; + status = nc_def_dim(exodusFilePtr, DIM_NUM_DIM, mesh.dimensionality, &numdimdim); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = + std::string errmsg = fmt::format("Error: failed to define number of dimensions in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } + int timedim = 0; if ((status = nc_def_dim(exodusFilePtr, DIM_TIME, NC_UNLIMITED, &timedim)) != NC_NOERR) { - errmsg = fmt::format("Error: failed to define time dimension in file id {}", exodusFilePtr); + std::string errmsg = + fmt::format("Error: failed to define time dimension in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } + int varid = 0; { - int dim[] = {timedim}; - if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, dim, - &varid)) != NC_NOERR) { - errmsg = fmt::format("Error: failed to define whole time step variable in file id {}", - exodusFilePtr); + std::array dim{timedim}; + if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, + dim.data(), &varid)) != NC_NOERR) { + std::string errmsg = fmt::format( + "Error: failed to define whole time step variable in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } @@ -342,28 +336,31 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta ex__compress_variable(exodusFilePtr, varid, -2); /* don't compress, but do set collective io */ } + int map_type = get_type(exodusFilePtr, EX_MAPS_INT64_DB); + int numnoddim = 0; if (mesh.nodeCount > 0) { status = nc_def_dim(exodusFilePtr, DIM_NUM_NODES, mesh.nodeCount, &numnoddim); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = fmt::format("Error: failed to define number of nodes in file id {}", exodusFilePtr); + std::string errmsg = + fmt::format("Error: failed to define number of nodes in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } // Define the node map here to avoid a later redefine call - int dims[] = {numnoddim}; - status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numnoddim}; + status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { - errmsg = + std::string errmsg = fmt::format("Error: node numbering map already exists in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); } else { - errmsg = fmt::format("Error: failed to create node numbering map array in file id {}", - exodusFilePtr); + std::string errmsg = fmt::format( + "Error: failed to create node numbering map array in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); } return EX_FATAL; @@ -372,29 +369,30 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta } if (mesh.elementCount > 0) { - status = nc_def_dim(exodusFilePtr, DIM_NUM_ELEM, mesh.elementCount, &numelemdim); + int numelemdim = 0; + status = nc_def_dim(exodusFilePtr, DIM_NUM_ELEM, mesh.elementCount, &numelemdim); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = + std::string errmsg = fmt::format("Error: failed to define number of elements in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return EX_FATAL; } // Define the element map here to avoid a later redefine call - int dims[1] = {numelemdim}; - varid = 0; - status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numelemdim}; + varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { - errmsg = + std::string errmsg = fmt::format("Error: element numbering map already exists in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); } else { - errmsg = fmt::format("Error: failed to create element numbering map in file id {}", - exodusFilePtr); + std::string errmsg = fmt::format( + "Error: failed to create element numbering map in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); } return EX_FATAL; @@ -533,10 +531,10 @@ int Excn::Internals::put_metadata(const std::vector &blocks) return EX_FATAL; } - int dims[] = {numelbdim, numattrdim}; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, dims, - &varid); + std::array dims{numelbdim, numattrdim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = @@ -548,9 +546,10 @@ int Excn::Internals::put_metadata(const std::vector &blocks) ex__compress_variable(exodusFilePtr, varid, 2); // Attribute name array... - int adims[] = {numattrdim, namestrdim}; + std::array adims{numattrdim, namestrdim}; - status = nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, adims, &varid); + status = + nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, adims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define attribute name array for element block {}" @@ -562,11 +561,11 @@ int Excn::Internals::put_metadata(const std::vector &blocks) } // element connectivity array - int dims[] = {numelbdim, nelnoddim}; + std::array dims{numelbdim, nelnoddim}; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); int connid; - status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims, &connid); + status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to create connectivity array for block {} in file id {}", @@ -685,11 +684,11 @@ template int Excn::Internals::put_metadata(const std::vector int Excn::Internals::put_metadata(const std::vector int Excn::Internals::put_metadata(const std::vector int Excn::Internals::put_metadata(const std::vector int Excn::Internals::put_metadata(const std::vector> &sidese namespace { int put_int_array(int exoid, const char *var_type, const std::vector &array) { - std::string errmsg; - int var_id; - int status; - - status = nc_inq_varid(exoid, var_type, &var_id); + int var_id; + int status = nc_inq_varid(exoid, var_type, &var_id); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = fmt::format("Error: failed to locate {} in file id {}", var_type, exoid); + std::string errmsg = fmt::format("Error: failed to locate {} in file id {}", var_type, exoid); ex_err_fn(exoid, __func__, errmsg.c_str(), status); return EX_FATAL; } @@ -966,7 +962,8 @@ namespace { status = nc_put_var_int(exoid, var_id, array.data()); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); - errmsg = fmt::format("Error: failed to write {} array in file id {}", var_type, exoid); + std::string errmsg = + fmt::format("Error: failed to write {} array in file id {}", var_type, exoid); ex_err_fn(exoid, __func__, errmsg.c_str(), status); return EX_FATAL; } @@ -1019,14 +1016,14 @@ namespace { { std::string errmsg; int status; - int dim[2]; int varid; if (nodes > 0) { // node coordinate arrays -- separate storage... - dim[0] = node_dim; + std::array dim{node_dim}; if (dimension > 0) { - status = nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, dim, &varid); + status = nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, dim.data(), + &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define node x coordinate array in file id {}", @@ -1038,7 +1035,8 @@ namespace { } if (dimension > 1) { - status = nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, dim, &varid); + status = nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, dim.data(), + &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define node y coordinate array in file id {}", @@ -1050,7 +1048,8 @@ namespace { } if (dimension > 2) { - status = nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, dim, &varid); + status = nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, dim.data(), + &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define node z coordinate array in file id {}", @@ -1063,10 +1062,8 @@ namespace { } // coordinate names array - dim[0] = dim_dim; - dim[1] = str_dim; - - status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dim, &varid); + std::array dim{dim_dim, str_dim}; + status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = @@ -1080,13 +1077,10 @@ namespace { int define_netcdf_vars(int exoid, const char *type, size_t count, const char *dim_num, const char *stat_var, const char *id_var, const char *name_var) { - int dimid = 0; - int varid = 0; - int dim[2]; - int namestrdim = 0; std::string errmsg; - int status = nc_inq_dimid(exoid, DIM_STR_NAME, &namestrdim); + int namestrdim = 0; + int status = nc_inq_dimid(exoid, DIM_STR_NAME, &namestrdim); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to get string name dimension in file id {}", exoid); @@ -1094,7 +1088,8 @@ namespace { return EX_FATAL; } - status = nc_def_dim(exoid, dim_num, count, &dimid); + int dimid = 0; + status = nc_def_dim(exoid, dim_num, count, &dimid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define number of {}s in file id {}", type, exoid); @@ -1103,8 +1098,9 @@ namespace { } // id status array: - dim[0] = dimid; - status = nc_def_var(exoid, stat_var, NC_INT, 1, dim, &varid); + std::array dim{dimid}; + int varid = 0; + status = nc_def_var(exoid, stat_var, NC_INT, 1, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define side {} status in file id {}", type, exoid); @@ -1114,7 +1110,7 @@ namespace { // id array: int ids_type = get_type(exoid, EX_IDS_INT64_DB); - status = nc_def_var(exoid, id_var, ids_type, 1, dim, &varid); + status = nc_def_var(exoid, id_var, ids_type, 1, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define {} property in file id {}", type, exoid); @@ -1132,10 +1128,8 @@ namespace { return EX_FATAL; } - dim[0] = dimid; - dim[1] = namestrdim; - - status = nc_def_var(exoid, name_var, NC_CHAR, 2, dim, &varid); + std::array dims{dimid, namestrdim}; + status = nc_def_var(exoid, name_var, NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define {} name array in file id {}", type, exoid); diff --git a/packages/seacas/applications/conjoin/CJ_SystemInterface.C b/packages/seacas/applications/conjoin/CJ_SystemInterface.C index 8bed747b51..b5952c3039 100644 --- a/packages/seacas/applications/conjoin/CJ_SystemInterface.C +++ b/packages/seacas/applications/conjoin/CJ_SystemInterface.C @@ -155,7 +155,7 @@ bool Excn::SystemInterface::parse_options(int argc, char **argv) "\nThe following options were specified via the CONJOIN_OPTIONS environment variable:\n" "\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } if (options_.retrieve("help") != nullptr) { diff --git a/packages/seacas/applications/conjoin/CJ_Version.h b/packages/seacas/applications/conjoin/CJ_Version.h index e0a949599a..60bea34e5d 100644 --- a/packages/seacas/applications/conjoin/CJ_Version.h +++ b/packages/seacas/applications/conjoin/CJ_Version.h @@ -9,6 +9,6 @@ static std::array qainfo{ "conjoin", - "1.4.9", - "2021/03/05", + "1.4.10", + "2023/08/18", }; diff --git a/packages/seacas/applications/conjoin/Conjoin.C b/packages/seacas/applications/conjoin/Conjoin.C index 8827530dd2..3858f733aa 100644 --- a/packages/seacas/applications/conjoin/Conjoin.C +++ b/packages/seacas/applications/conjoin/Conjoin.C @@ -53,6 +53,7 @@ #include "CJ_Version.h" namespace { + bool check_variable_params(size_t p, Excn::Variables &vars); template void clear(std::vector &vec) { vec.clear(); @@ -312,8 +313,9 @@ namespace { // SEE: http://lemire.me/blog/2017/04/10/removing-duplicates-from-lists-quickly template size_t unique(std::vector &out) { - if (out.empty()) + if (out.empty()) { return 0; + } size_t pos = 1; T oldv = out[0]; for (size_t i = 1; i < out.size(); ++i) { @@ -697,6 +699,20 @@ int conjoin(Excn::SystemInterface &interFace, T /* dummy */, INT /* dummy int */ filter_truth_table(id, global, glob_ssets, sideset_vars, interFace.sset_var_names()); } + // Check that the variable counts are the same on the subsequent files... + // Error out if there is a difference... + bool found_error = false; + for (size_t p = 1; p < part_count; p++) { + found_error |= check_variable_params(p, global_vars); + found_error |= check_variable_params(p, nodal_vars); + found_error |= check_variable_params(p, element_vars); + found_error |= check_variable_params(p, nodeset_vars); + found_error |= check_variable_params(p, sideset_vars); + } + if (found_error) { + return 1; + } + // There is a slightly tricky situation here. The truthTable block order // is based on the ordering of the blocks on the input databases. // These blocks may have been reordered on output to make the 'offset' @@ -988,8 +1004,8 @@ namespace { char *qa_record[1][4]; }; - int num_qa_records = ex_inquire_int(id, EX_INQ_QA); - auto qaRecord = new qa_element[num_qa_records + 1]; + int num_qa_records = ex_inquire_int(id, EX_INQ_QA); + std::vector qaRecord(num_qa_records + 1); for (int i = 0; i < num_qa_records + 1; i++) { for (int j = 0; j < 4; j++) { qaRecord[i].qa_record[0][j] = new char[MAX_STR_LENGTH + 1]; @@ -1020,7 +1036,6 @@ namespace { delete[] qaRecord[i].qa_record[0][j]; } } - delete[] qaRecord; } template @@ -2010,6 +2025,38 @@ namespace { } } + bool check_variable_params(size_t p, Excn::Variables &vars) + { + // Determines the number of variables of type 'type()' that will + // be written to the output database. The 'variable_list' vector + // specifies a possibly empty list of variable names that the user + // wants transferred to the output database. If 'variable_list' is + // empty, then all variables of that type will be transferred; if + // the 'variable_list' size is 1 and it contains the string 'NONE', + // then no variables of that type will be transferred; if size is 1 + // and it contains the string 'ALL', then all variables of that type + // will be transferred. + // + // Returns the number of variables which will be output Also creates + // a 'var_index'. The var_index is zero-based and of size + // 'input_variable_count'. If: + // var_index[i] ==0, variable not written to output database + // var_index[i] > 0, variable written; is variable 'var_index[i]' + + // If 'type' is ELEMENT or NODE, then reserve space for the 'status' variable. + int extra = vars.addStatus ? 1 : 0; + int num_vars; + auto id = Excn::ExodusFile(p); + ex_get_variable_param(id, vars.type(), &num_vars); + if ((size_t)num_vars != vars.index_.size() - extra) { + fmt::print("ERROR: Part mesh {} has a different number of {} variables ({}) than the root " + "part mesh ({}) which is not allowed.\n", + p, vars.label(), num_vars, vars.index_.size() - extra); + return true; + } + return false; + } + template void put_mesh_summary(const Excn::Mesh &mesh) { // Write out Mesh info diff --git a/packages/seacas/applications/cpup/CP_SystemInterface.C b/packages/seacas/applications/cpup/CP_SystemInterface.C index 68c7bc4a91..60fc8873f0 100644 --- a/packages/seacas/applications/cpup/CP_SystemInterface.C +++ b/packages/seacas/applications/cpup/CP_SystemInterface.C @@ -221,7 +221,7 @@ bool Cpup::SystemInterface::parse_options(int argc, char **argv) "\t{}\n\n", options); } - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } int option_index = options_.parse(argc, argv); diff --git a/packages/seacas/applications/cpup/cpup.C b/packages/seacas/applications/cpup/cpup.C index d9a86d315d..59b38a3186 100644 --- a/packages/seacas/applications/cpup/cpup.C +++ b/packages/seacas/applications/cpup/cpup.C @@ -243,13 +243,13 @@ template void cpup(Cpup::SystemInterface &interFace, INT /*dummy* all_blocks[name] = block; // Build map of unique blocks in the mesh. - auto name_proc = Iocgns::Utils::decompose_name(name, true); - global_block[name_proc.first]; + auto [part_name, proc] = Iocgns::Utils::decompose_name(name, true); + global_block[part_name]; // Set the zgc 'from_decomp' property... for (const auto &zgc : block->m_zoneConnectivity) { - auto zgc_name_proc = Iocgns::Utils::decompose_name(zgc.m_donorName, true); - if (zgc_name_proc.first == name_proc.first) { + const auto [zgc_name, zgc_proc] = Iocgns::Utils::decompose_name(zgc.m_donorName, true); + if (zgc_name == part_name) { zgc.m_fromDecomp = true; } } @@ -356,9 +356,9 @@ template void cpup(Cpup::SystemInterface &interFace, INT /*dummy* for (const auto &prt : part_mesh) { const auto &pblocks = prt->get_structured_blocks(); for (const auto &pblock : pblocks) { - const auto &name = pblock->name(); - auto name_proc = Iocgns::Utils::decompose_name(name, true); - if (name_proc.first == block->name()) { + const auto &name = pblock->name(); + auto [part_name, part_proc] = Iocgns::Utils::decompose_name(name, true); + if (part_name == block->name()) { Ioss::NameList fields = pblock->field_describe(Ioss::Field::TRANSIENT); for (const auto &field_name : fields) { @@ -460,11 +460,11 @@ namespace { for (const auto &part : part_mesh) { const auto &blocks = part->get_structured_blocks(); for (const auto &block : blocks) { - auto name_proc = Iocgns::Utils::decompose_name(block->name(), true); + const auto [part_name, proc] = Iocgns::Utils::decompose_name(block->name(), true); for (const auto &zgc : block->m_zoneConnectivity) { if (!zgc.m_fromDecomp) { - auto &gzgc = global_zgc[std::make_pair(name_proc.first, zgc.m_connectionName)]; + auto &gzgc = global_zgc[std::make_pair(part_name, zgc.m_connectionName)]; if (gzgc.m_connectionName.empty()) { // First time this ZGC has been found. Copy from the per-proc instance and update... gzgc.m_connectionName = zgc.m_connectionName; @@ -511,11 +511,11 @@ namespace { for (const auto &part : part_mesh) { const auto &blocks = part->get_structured_blocks(); for (const auto &block : blocks) { - Ioss::IJK_t offset = block->get_ijk_offset(); - auto name_proc = Iocgns::Utils::decompose_name(block->name(), true); - const auto &sb_bc = block->m_boundaryConditions; + Ioss::IJK_t offset = block->get_ijk_offset(); + const auto [part_name, proc] = Iocgns::Utils::decompose_name(block->name(), true); + const auto &sb_bc = block->m_boundaryConditions; for (const auto &bc : sb_bc) { - auto &gbc = global_bc[std::make_pair(name_proc.first, bc.m_bcName)]; + auto &gbc = global_bc[std::make_pair(part_name, bc.m_bcName)]; if (gbc.m_bcName.empty()) { gbc.m_bcName = bc.m_bcName; gbc.m_famName = bc.m_famName; @@ -557,9 +557,9 @@ namespace { for (const auto &part : part_mesh) { const auto &pblocks = part->get_structured_blocks(); for (const auto &pblock : pblocks) { - const auto &name = pblock->name(); - auto name_proc = Iocgns::Utils::decompose_name(name, true); - if (name_proc.first == block->name()) { + const auto &name = pblock->name(); + const auto [part_name, proc] = Iocgns::Utils::decompose_name(name, true); + if (part_name == block->name()) { if (pblock->field_exists(field_name)) { pblock->get_field_data(field_name, input); transfer_cell_field(pblock, input, output); @@ -594,9 +594,9 @@ namespace { for (const auto &part : part_mesh) { const auto &pblocks = part->get_structured_blocks(); for (const auto &pblock : pblocks) { - const auto &name = pblock->name(); - auto name_proc = Iocgns::Utils::decompose_name(name, true); - if (name_proc.first == block->name()) { + const auto &name = pblock->name(); + const auto [part_name, proc] = Iocgns::Utils::decompose_name(name, true); + if (part_name == block->name()) { auto &inb = pblock->get_node_block(); if (inb.field_exists(field_name)) { inb.get_field_data(field_name, input); @@ -655,21 +655,21 @@ namespace { for (const auto &part : part_mesh) { const auto &blocks = part->get_structured_blocks(); for (const auto &block : blocks) { - auto ijk_o = block->get_ijk_offset(); - auto ijk_g = block->get_ijk_global(); - auto name_proc = Iocgns::Utils::decompose_name(block->name(), true); - auto &cur_global = global_block[name_proc.first]; - cur_global[0] = std::max(ijk_o[0] + ijk_g[0], cur_global[0]); - cur_global[1] = std::max(ijk_o[1] + ijk_g[1], cur_global[1]); - cur_global[2] = std::max(ijk_o[2] + ijk_g[2], cur_global[2]); + auto ijk_o = block->get_ijk_offset(); + auto ijk_g = block->get_ijk_global(); + const auto [part_name, proc] = Iocgns::Utils::decompose_name(block->name(), true); + auto &cur_global = global_block[part_name]; + cur_global[0] = std::max(ijk_o[0] + ijk_g[0], cur_global[0]); + cur_global[1] = std::max(ijk_o[1] + ijk_g[1], cur_global[1]); + cur_global[2] = std::max(ijk_o[2] + ijk_g[2], cur_global[2]); } } for (const auto &part : part_mesh) { const auto &blocks = part->get_structured_blocks(); for (const auto &block : blocks) { - auto name_proc = Iocgns::Utils::decompose_name(block->name(), true); - auto &cur_global = global_block[name_proc.first]; + const auto [part_name, proc] = Iocgns::Utils::decompose_name(block->name(), true); + auto &cur_global = global_block[part_name]; block->set_ijk_global(cur_global); } if (debug_level & 4) { @@ -788,9 +788,9 @@ namespace { for (const auto &part : part_mesh) { const auto &pblocks = part->get_structured_blocks(); for (const auto &pblock : pblocks) { - const auto &name = pblock->name(); - auto name_proc = Iocgns::Utils::decompose_name(name, true); - if (name_proc.first == block->name()) { + const auto &name = pblock->name(); + const auto [part_name, proc] = Iocgns::Utils::decompose_name(name, true); + if (part_name == block->name()) { std::vector lcoord; pblock->get_field_data(fields[dim], lcoord); transfer_nodal_field(pblock, lcoord, coord); diff --git a/packages/seacas/applications/ejoin/EJ_SystemInterface.C b/packages/seacas/applications/ejoin/EJ_SystemInterface.C index 9752438416..13bbca0768 100644 --- a/packages/seacas/applications/ejoin/EJ_SystemInterface.C +++ b/packages/seacas/applications/ejoin/EJ_SystemInterface.C @@ -272,7 +272,7 @@ bool SystemInterface::parse_options(int argc, char **argv) "\nThe following options were specified via the EJOIN_OPTIONS environment variable:\n" "\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } outputName_ = options_.get_option_value("output", outputName_); diff --git a/packages/seacas/applications/ejoin/EJ_mapping.C b/packages/seacas/applications/ejoin/EJ_mapping.C index 86fa21a8b7..e19268b630 100644 --- a/packages/seacas/applications/ejoin/EJ_mapping.C +++ b/packages/seacas/applications/ejoin/EJ_mapping.C @@ -162,8 +162,9 @@ void build_reverse_node_map(Ioss::Region & /*global*/, RegionVector &part_mesh, if (cur_pos == global_node_map.end() || *cur_pos != global_node) { auto iter = std::lower_bound(global_node_map.begin(), global_node_map.end(), global_node); if (iter == global_node_map.end()) { - fmt::print("{}\n", fmt::group_digits(global_node)); - SMART_ASSERT(iter != global_node_map.end()); + fmt::print(stderr, "ERROR: Could not find global node {} in global node map.\n", + fmt::group_digits(global_node)); + exit(EXIT_FAILURE); } cur_pos = iter; } @@ -213,8 +214,8 @@ void build_local_element_map(RegionVector &part_mesh, std::vector &local_el size_t offset = 0; for (auto &p : part_mesh) { - const Ioss::ElementBlockContainer &ebs = p->get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = p->get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const auto *eb = *i++; @@ -255,12 +256,9 @@ void generate_element_ids(RegionVector &part_mesh, const std::vector &local bool has_map = false; size_t offset = 0; for (auto &p : part_mesh) { - const Ioss::ElementBlockContainer &ebs = p->get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); - - while (i != ebs.end()) { - Ioss::ElementBlock *eb = *i++; - INT num_elem = eb->entity_count(); + const auto &ebs = p->get_element_blocks(); + for (auto *eb : ebs) { + INT num_elem = eb->entity_count(); if (!entity_is_omitted(eb)) { std::vector part_ids; eb->get_field_data("ids", part_ids); diff --git a/packages/seacas/applications/ejoin/EJ_vector3d.C b/packages/seacas/applications/ejoin/EJ_vector3d.C index 1a96a09b7e..4778bf3a38 100644 --- a/packages/seacas/applications/ejoin/EJ_vector3d.C +++ b/packages/seacas/applications/ejoin/EJ_vector3d.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -90,7 +90,7 @@ vector3d operator/(const vector3d &lhs, double scalar) return tmp /= scalar; } - return vector3d(HUGE_VAL, HUGE_VAL, HUGE_VAL); + return {HUGE_VAL, HUGE_VAL, HUGE_VAL}; } vector3d &vector3d::operator/=(double scalar) diff --git a/packages/seacas/applications/ejoin/EJ_vector3d.h b/packages/seacas/applications/ejoin/EJ_vector3d.h index 01415102cc..0afb3c9195 100644 --- a/packages/seacas/applications/ejoin/EJ_vector3d.h +++ b/packages/seacas/applications/ejoin/EJ_vector3d.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -47,7 +47,7 @@ vector3d operator-(const vector3d &lhs, const vector3d &rhs); //---------------------------------------------------------------------------- inline vector3d vector3d::cross(const vector3d &from) const { - return vector3d(y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x); + return {y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x}; } //---------------------------------------------------------------------------- inline vector3d &vector3d::operator+=(const vector3d &from) diff --git a/packages/seacas/applications/ejoin/EJoin.C b/packages/seacas/applications/ejoin/EJoin.C index d1054dc8ee..7d1e18f97a 100644 --- a/packages/seacas/applications/ejoin/EJoin.C +++ b/packages/seacas/applications/ejoin/EJoin.C @@ -501,8 +501,8 @@ double ejoin(SystemInterface &interFace, std::vector &part_mesh, } else { if (global_times.size() != times.size()) { - fmt::print(stderr, "ERROR: Time step sizes must match."); - SMART_ASSERT(global_times.size() == times.size())(global_times.size())(times.size())(p); + fmt::print(stderr, "ERROR: Time step sizes must match. (Global = {}, Part {} = {}", + global_times.size(), p, times.size()); exit(EXIT_FAILURE); } @@ -1010,7 +1010,7 @@ namespace { // Assuming (with checks) that the output side blocks will be // iterated in same order as input side blocks... - Ioss::SideBlockContainer::const_iterator II = out_eb.begin(); + auto II = out_eb.begin(); for (const auto &pm : part_mesh) { size_t element_offset = pm->get_property("element_offset").get_int(); @@ -1201,7 +1201,7 @@ namespace { // Assuming (with checks) that the output side blocks will be // iterated in same order as input side blocks... - Ioss::SideBlockContainer::const_iterator II = out_eb.begin(); + auto II = out_eb.begin(); for (const auto &pm : part_mesh) { const Ioss::SideSetContainer &is = pm->get_sidesets(); @@ -1438,29 +1438,29 @@ namespace { if (!variable_list.empty() && variable_list[0].first == "none") { return; } - const Ioss::SideSetContainer &os = output_region.get_sidesets(); + const auto &os = output_region.get_sidesets(); Ioss::SideBlockContainer out_eb; // Put all output side blocks in the same list... for (const auto &oss : os) { - const Ioss::SideBlockContainer &obs = oss->get_side_blocks(); + const auto &obs = oss->get_side_blocks(); std::copy(obs.begin(), obs.end(), std::back_inserter(out_eb)); } // Assuming (with checks) that the output side blocks will be // iterated in same order as input side blocks... - Ioss::SideBlockContainer::const_iterator II = out_eb.begin(); + auto II = out_eb.begin(); for (const auto &pm : part_mesh) { - const Ioss::SideSetContainer &is = pm->get_sidesets(); + const auto &is = pm->get_sidesets(); for (const auto &iss : is) { if (!entity_is_omitted(iss)) { - size_t id = iss->get_property("id").get_int(); - const Ioss::SideBlockContainer &ebs = iss->get_side_blocks(); + size_t id = iss->get_property("id").get_int(); + const auto &ebs = iss->get_side_blocks(); for (const auto &eb : ebs) { SMART_ASSERT((pm->name() + "_" + eb->name() == (*II)->name()) || (eb->name() == (*II)->name())); - Ioss::NameList fields = eb->field_describe(Ioss::Field::TRANSIENT); + auto fields = eb->field_describe(Ioss::Field::TRANSIENT); for (const auto &field_name : fields) { if (valid_variable(field_name, id, variable_list)) { Ioss::Field field = eb->get_field(field_name); @@ -1478,7 +1478,7 @@ namespace { Ioss::Field::RoleType role, const std::string &prefix) { // Check for transient fields... - Ioss::NameList fields = ige->field_describe(role); + auto fields = ige->field_describe(role); // Iterate through results fields and transfer to output // database... If a prefix is specified, only transfer fields diff --git a/packages/seacas/applications/epu/EP_ExodusFile.h b/packages/seacas/applications/epu/EP_ExodusFile.h index a399ec457e..55f545d60e 100644 --- a/packages/seacas/applications/epu/EP_ExodusFile.h +++ b/packages/seacas/applications/epu/EP_ExodusFile.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -26,9 +26,9 @@ namespace Excn { static bool create_output(const SystemInterface &si, int cycle); static void close_all(); - static int output(); - static int io_word_size() { return ioWordSize_; } - operator int() const; + static int output(); + static int io_word_size() { return ioWordSize_; } + operator int() const; static int max_name_length() { return maximumNameLength_; } static void unlink_temporary_files(); diff --git a/packages/seacas/applications/epu/EP_Internals.C b/packages/seacas/applications/epu/EP_Internals.C index 57b90eef85..9a7a5c4d1d 100644 --- a/packages/seacas/applications/epu/EP_Internals.C +++ b/packages/seacas/applications/epu/EP_Internals.C @@ -10,6 +10,7 @@ #include // for Internals, Redefine #include // for sort +#include #include #include // for size_t #include // for int64_t @@ -17,9 +18,8 @@ #include // for strlen, memset #include #include // for SMART_ASSERT - -#include // for string, basic_string -#include // for vector +#include // for string, basic_string +#include // for vector #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) @@ -495,11 +495,10 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta } { - int dim[1]; - int varid = 0; - dim[0] = timedim; - if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, dim, - &varid)) != NC_NOERR) { + std::array dim{timedim}; + int varid = 0; + if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, + dim.data(), &varid)) != NC_NOERR) { errmsg = fmt::format("Error: failed to define whole time step variable in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); @@ -525,10 +524,9 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta // Define the node map here to avoid a later redefine call if (mesh.needNodeMap) { - int dims[1]; - int varid = 0; - dims[0] = numnoddim; - status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numnoddim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -560,10 +558,9 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta // Define the element map here to avoid a later redefine call if (mesh.needElementMap) { - int dims[1]; - dims[0] = numelemdim; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numelemdim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -638,7 +635,6 @@ int Excn::Internals::put_metadata(const Mesh &mesh, const CommunicationMeta template int Excn::Internals::put_metadata(const std::vector &blocks) { std::string errmsg; - int dims[2]; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); @@ -735,11 +731,10 @@ template int Excn::Internals::put_metadata(const std::vector return EX_FATAL; } - dims[0] = numelbdim; - dims[1] = numattrdim; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, dims, - &varid); + std::array dims{numelbdim, numattrdim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = @@ -754,7 +749,8 @@ template int Excn::Internals::put_metadata(const std::vector dims[0] = numattrdim; dims[1] = namestrdim; - status = nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, dims, &varid); + status = + nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format( @@ -766,11 +762,10 @@ template int Excn::Internals::put_metadata(const std::vector } // element connectivity array - dims[0] = numelbdim; - dims[1] = nelnoddim; + std::array dims{numelbdim, nelnoddim}; int connid; - status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims, &connid); + status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to create connectivity array for block {} in file id {}", @@ -840,7 +835,6 @@ int Excn::Internals::put_metadata(const std::vector> &nodesets } std::string errmsg; - int dims[2]; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); @@ -896,10 +890,10 @@ int Excn::Internals::put_metadata(const std::vector> &nodesets } // define variable to store node set node list here instead of in expns - dims[0] = dimid; - int varid = 0; - status = - nc_def_var(exodusFilePtr, VAR_NODE_NS(cur_num_node_sets + 1), bulk_type, 1, dims, &varid); + std::array dims{dimid}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_NODE_NS(cur_num_node_sets + 1), bulk_type, 1, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -932,7 +926,7 @@ int Excn::Internals::put_metadata(const std::vector> &nodesets // create variable for distribution factors status = nc_def_var(exodusFilePtr, VAR_FACT_NS(cur_num_node_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims, &varid); + nc_flt_code(exodusFilePtr), 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -993,7 +987,6 @@ int Excn::Internals::put_metadata(const std::vector> &sidesets } std::string errmsg; - int dims[2]; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); @@ -1047,10 +1040,10 @@ int Excn::Internals::put_metadata(const std::vector> &sidesets return EX_FATAL; } - dims[0] = dimid; - int varid = 0; - status = - nc_def_var(exodusFilePtr, VAR_ELEM_SS(cur_num_side_sets + 1), bulk_type, 1, dims, &varid); + std::array dims{dimid}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ELEM_SS(cur_num_side_sets + 1), bulk_type, 1, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1068,8 +1061,8 @@ int Excn::Internals::put_metadata(const std::vector> &sidesets ex__compress_variable(exodusFilePtr, varid, 1); // create side list variable for side set - status = - nc_def_var(exodusFilePtr, VAR_SIDE_SS(cur_num_side_sets + 1), bulk_type, 1, dims, &varid); + status = nc_def_var(exodusFilePtr, VAR_SIDE_SS(cur_num_side_sets + 1), bulk_type, 1, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1108,7 +1101,7 @@ int Excn::Internals::put_metadata(const std::vector> &sidesets // create distribution factor list variable for side set dims[0] = dimid; status = nc_def_var(exodusFilePtr, VAR_FACT_SS(cur_num_side_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims, &varid); + nc_flt_code(exodusFilePtr), 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1171,7 +1164,6 @@ int Excn::Internals::put_metadata(const std::vector> &edgebl } std::string errmsg; - int dims[2]; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); @@ -1240,12 +1232,10 @@ int Excn::Internals::put_metadata(const std::vector> &edgebl } // element connectivity array - dims[0] = num_edges_in_edgeblock_dim; - dims[1] = num_nodes_per_edge_dim; - - int connid; - status = - nc_def_var(exodusFilePtr, VAR_EBCONN(cur_num_edge_blocks + 1), bulk_type, 2, dims, &connid); + std::array dims{num_edges_in_edgeblock_dim, num_nodes_per_edge_dim}; + int connid; + status = nc_def_var(exodusFilePtr, VAR_EBCONN(cur_num_edge_blocks + 1), bulk_type, 2, + dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = @@ -1311,7 +1301,6 @@ int Excn::Internals::put_metadata(const std::vector> &facebl } std::string errmsg; - int dims[2]; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); @@ -1380,12 +1369,11 @@ int Excn::Internals::put_metadata(const std::vector> &facebl } // element connectivity array - dims[0] = num_faces_in_faceblock_dim; - dims[1] = num_nodes_per_face_dim; + std::array dims{num_faces_in_faceblock_dim, num_nodes_per_face_dim}; int connid; - status = - nc_def_var(exodusFilePtr, VAR_FBCONN(cur_num_face_blocks + 1), bulk_type, 2, dims, &connid); + status = nc_def_var(exodusFilePtr, VAR_FBCONN(cur_num_face_blocks + 1), bulk_type, 2, + dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = @@ -1520,14 +1508,14 @@ namespace { { std::string errmsg; int status; - int dim[2]; int varid; if (nodes > 0) { // node coordinate arrays -- separate storage... - dim[0] = node_dim; + std::array dim{node_dim}; if (dimension > 0) { - status = nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, dim, &varid); + status = nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, dim.data(), + &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define node x coordinate array in file id {}", @@ -1539,7 +1527,8 @@ namespace { } if (dimension > 1) { - status = nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, dim, &varid); + status = nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, dim.data(), + &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define node y coordinate array in file id {}", @@ -1551,7 +1540,8 @@ namespace { } if (dimension > 2) { - status = nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, dim, &varid); + status = nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, dim.data(), + &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define node z coordinate array in file id {}", @@ -1564,10 +1554,8 @@ namespace { } // coordinate names array - dim[0] = dim_dim; - dim[1] = str_dim; - - status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dim, &varid); + std::array dims{dim_dim, str_dim}; + status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = @@ -1581,9 +1569,8 @@ namespace { int define_netcdf_vars(int exoid, const char *type, size_t count, const char *dim_num, const char *stat_var, const char *id_var, const char *name_var) { - int dimid = 0; - int varid = 0; - int dim[2]; + int dimid = 0; + int varid = 0; int namestrdim = 0; std::string errmsg; @@ -1604,8 +1591,8 @@ namespace { } // id status array: - dim[0] = dimid; - status = nc_def_var(exoid, stat_var, NC_INT, 1, dim, &varid); + std::array dim{dimid}; + status = nc_def_var(exoid, stat_var, NC_INT, 1, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define side {} status in file id {}", type, exoid); @@ -1615,7 +1602,7 @@ namespace { // id array: int ids_type = get_type(exoid, EX_IDS_INT64_DB); - status = nc_def_var(exoid, id_var, ids_type, 1, dim, &varid); + status = nc_def_var(exoid, id_var, ids_type, 1, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define {} property in file id {}", type, exoid); @@ -1633,10 +1620,8 @@ namespace { return EX_FATAL; } - dim[0] = dimid; - dim[1] = namestrdim; - - status = nc_def_var(exoid, name_var, NC_CHAR, 2, dim, &varid); + std::array dims{dimid, namestrdim}; + status = nc_def_var(exoid, name_var, NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); errmsg = fmt::format("Error: failed to define {} name array in file id {}", type, exoid); diff --git a/packages/seacas/applications/epu/EP_Internals.h b/packages/seacas/applications/epu/EP_Internals.h index 40f27376ab..1eccd8e184 100644 --- a/packages/seacas/applications/epu/EP_Internals.h +++ b/packages/seacas/applications/epu/EP_Internals.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -92,8 +92,7 @@ namespace Excn { { public: Internals(int exoid, int maximum_name_length) - : exodusFilePtr(exoid), nodeMapVarID(), elementMapVarID(), commIndexVar(0), - elemCommIndexVar(0), maximumNameLength(maximum_name_length) + : exodusFilePtr(exoid), maximumNameLength(maximum_name_length) { } @@ -126,11 +125,11 @@ namespace Excn { int put_non_define_data(const std::vector> &edgeblocks); int put_non_define_data(const std::vector> &faceblocks); - int exodusFilePtr; - int nodeMapVarID[3]; - int elementMapVarID[2]; - int commIndexVar; - int elemCommIndexVar; - int maximumNameLength; + int exodusFilePtr{}; + int nodeMapVarID[3]{}; + int elementMapVarID[2]{}; + int commIndexVar{}; + int elemCommIndexVar{}; + int maximumNameLength{}; }; } // namespace Excn diff --git a/packages/seacas/applications/epu/EP_ParallelDisks.C b/packages/seacas/applications/epu/EP_ParallelDisks.C index f5496b983e..6a25543b4b 100644 --- a/packages/seacas/applications/epu/EP_ParallelDisks.C +++ b/packages/seacas/applications/epu/EP_ParallelDisks.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2021 National Technology & Engineering Solutions + * Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -18,12 +18,6 @@ #include #endif -/*****************************************************************************/ -Excn::ParallelDisks::ParallelDisks() = default; - -/*****************************************************************************/ -Excn::ParallelDisks::~ParallelDisks() = default; - /*****************************************************************************/ void Excn::ParallelDisks::rename_file_for_mp(const std::string &rootdir, const std::string &subdir, std::string &name, int node, int numproc) const diff --git a/packages/seacas/applications/epu/EP_ParallelDisks.h b/packages/seacas/applications/epu/EP_ParallelDisks.h index 5b5216dcec..1a9d7e855c 100644 --- a/packages/seacas/applications/epu/EP_ParallelDisks.h +++ b/packages/seacas/applications/epu/EP_ParallelDisks.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -18,17 +18,14 @@ namespace Excn { //: processors onto disk files. public: - ParallelDisks(); - ~ParallelDisks(); + ParallelDisks() = default; + ~ParallelDisks() = default; + ParallelDisks(const ParallelDisks &) = delete; + ParallelDisks &operator=(const ParallelDisks &) = delete; static void Create_IO_Filename(std::string & /*name*/, int processor, int num_processors); void rename_file_for_mp(const std::string &rootdir, const std::string &subdir, std::string &name, int node, int numproc) const; - - private: - // not defined (the parallel disks object is unique!) - ParallelDisks(const ParallelDisks &); - ParallelDisks &operator=(const ParallelDisks &); }; } // namespace Excn diff --git a/packages/seacas/applications/epu/EP_SystemInterface.C b/packages/seacas/applications/epu/EP_SystemInterface.C index 97150ff740..6293ac3c4b 100644 --- a/packages/seacas/applications/epu/EP_SystemInterface.C +++ b/packages/seacas/applications/epu/EP_SystemInterface.C @@ -266,7 +266,7 @@ bool Excn::SystemInterface::parse_options(int argc, char **argv) "\t{}\n\n", options); } - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } int option_index = options_.parse(argc, argv); @@ -663,13 +663,13 @@ namespace { StringVector name_id = SLIB::tokenize(*I, ":"); std::string var_name = LowerCase(name_id[0]); if (name_id.size() == 1) { - (*variable_list).push_back(std::make_pair(var_name, 0)); + (*variable_list).emplace_back(var_name, 0); } else { for (size_t i = 1; i < name_id.size(); i++) { // Convert string to integer... int id = std::stoi(name_id[i]); - (*variable_list).push_back(std::make_pair(var_name, id)); + (*variable_list).emplace_back(var_name, id); } } ++I; diff --git a/packages/seacas/applications/epu/EP_Variables.h b/packages/seacas/applications/epu/EP_Variables.h index 26d1fa7f1a..546be4d8a4 100644 --- a/packages/seacas/applications/epu/EP_Variables.h +++ b/packages/seacas/applications/epu/EP_Variables.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -20,7 +20,7 @@ namespace Excn { struct Variables { - explicit Variables(ObjectType otype) : objectType(otype), outputCount(0), addProcessorId(false) + explicit Variables(ObjectType otype) : objectType(otype) { SMART_ASSERT(otype == Excn::ObjectType::EBLK || otype == Excn::ObjectType::NSET || otype == Excn::ObjectType::SSET || otype == Excn::ObjectType::NODE || @@ -69,8 +69,8 @@ namespace Excn { bool add_processor_id() const { return addProcessorId; } ObjectType objectType; - int outputCount; - bool addProcessorId; + int outputCount{0}; + bool addProcessorId{false}; IntVector index_{}; std::string type_{}; }; diff --git a/packages/seacas/applications/epu/epu.C b/packages/seacas/applications/epu/epu.C index 01d1c1b0c9..0cb8c9999f 100644 --- a/packages/seacas/applications/epu/epu.C +++ b/packages/seacas/applications/epu/epu.C @@ -1755,8 +1755,8 @@ namespace { char *qa_record[1][4]; }; - int num_qa_records = ex_inquire_int(id, EX_INQ_QA); - auto *qaRecord = new qa_element[num_qa_records + 1]; + int num_qa_records = ex_inquire_int(id, EX_INQ_QA); + std::vector qaRecord(num_qa_records + 1); for (int i = 0; i < num_qa_records + 1; i++) { for (int j = 0; j < 4; j++) { qaRecord[i].qa_record[0][j] = new char[MAX_STR_LENGTH + 1]; @@ -1793,7 +1793,6 @@ namespace { delete[] qaRecord[i].qa_record[0][j]; } } - delete[] qaRecord; } template @@ -1893,9 +1892,9 @@ namespace { gnodes.reserve(node_cmap.size()); gprocs.reserve(node_cmap.size()); - for (auto &np : node_cmap) { - gnodes.push_back(np.first); - gprocs.push_back(np.second); + for (auto &[node, proc] : node_cmap) { + gnodes.push_back(node); + gprocs.push_back(proc); } // NOTE: This is inefficient in general since going in and out of define mode. @@ -4567,10 +4566,10 @@ namespace { std::string var_name; int out_position = -1; - for (const auto &variable_name : variable_names) { - if (variable_name.second > 0) { - if (var_name != variable_name.first) { - var_name = variable_name.first; + for (const auto &[variable_name, variable_block] : variable_names) { + if (variable_block > 0) { + if (var_name != variable_name) { + var_name = variable_name; // Find which exodus variable matches this name out_position = -1; for (size_t j = 0; j < exo_names.size(); j++) { @@ -4593,7 +4592,7 @@ namespace { // Find out which block corresponds to the specified id. int block = -1; for (size_t b = 0; b < global.count(vars.objectType); b++) { - if (glob_blocks[b].id == variable_name.second) { + if (glob_blocks[b].id == variable_block) { block = b; break; } @@ -4604,7 +4603,7 @@ namespace { fmt::print( errmsg, "ERROR: (EPU) User-specified block id of {} for variable '{}' does not exist.\n", - variable_name.second, variable_name.first); + variable_block, variable_name); throw std::runtime_error(errmsg.str()); } @@ -4612,7 +4611,7 @@ namespace { if (global.truthTable[static_cast(vars.objectType)][truth_table_loc] == 0) { std::ostringstream errmsg; fmt::print(errmsg, "ERROR: (EPU) Variable '{}' does not exist on block {}.\n", - variable_name.first, variable_name.second); + variable_name, variable_block); throw std::runtime_error(errmsg.str()); } global.truthTable[static_cast(vars.objectType)][truth_table_loc] = 1; diff --git a/packages/seacas/applications/exo2mat/exo2mat.C b/packages/seacas/applications/exo2mat/exo2mat.C index 43e5617974..91b72d25f8 100644 --- a/packages/seacas/applications/exo2mat/exo2mat.C +++ b/packages/seacas/applications/exo2mat/exo2mat.C @@ -366,7 +366,7 @@ namespace { Mat_VarCreate(var_name.c_str(), MAT_C_CELL, MAT_T_CELL, 2, dims, nullptr, 0); assert(cell_array); - std::vector scr(num_vars * num_time_steps * num_entity); + std::vector scr(static_cast(num_vars) * num_time_steps * num_entity); dims[0] = num_entity; dims[1] = num_time_steps; size_t offset = 0; @@ -475,7 +475,7 @@ namespace { types[i] = std::string(type); num_elem_in_block[i] = num_elem; num_node_per_elem[i] = num_node; - conn_size += num_elem * num_node; + conn_size += static_cast(num_elem) * num_node; } std::vector connect(conn_size); @@ -534,7 +534,7 @@ namespace { types += type.data(); types += "\n"; num_elem_in_block[i] = num_elem; - connect.resize(num_elem * num_node); + connect.resize(static_cast(num_elem) * num_node); ex_get_conn(exo_file, EX_ELEM_BLOCK, ids[i], connect.data(), nullptr, nullptr); std::string str = fmt::sprintf("blk%02d", i + 1); PutInt(str, num_node, num_elem, connect.data()); @@ -757,7 +757,7 @@ namespace { num_sideset_sides[i] = n1; num_sideset_dfac[i] = n2; - bool has_ss_dfac = !(n2 == 0 || n1 == n2); + bool has_ss_dfac = (n2 != 0 && n1 != n2); if (!has_ss_dfac) { num_sideset_dfac[i] = num_sideset_nodes[i]; } @@ -1212,7 +1212,7 @@ int main(int argc, char *argv[]) dims[1] = num_nodal_vars; matvar_t *cell_array = Mat_VarCreate("nvar", MAT_C_CELL, MAT_T_CELL, 2, dims, nullptr, 0); assert(cell_array); - std::vector scr(num_nodal_vars * num_time_steps * num_nodes); + std::vector scr(static_cast(num_nodal_vars) * num_time_steps * num_nodes); dims[0] = num_nodes; dims[1] = num_time_steps; size_t offset = 0; diff --git a/packages/seacas/applications/exodiff/ED_SystemInterface.C b/packages/seacas/applications/exodiff/ED_SystemInterface.C index aca898a814..e3c37b3b08 100644 --- a/packages/seacas/applications/exodiff/ED_SystemInterface.C +++ b/packages/seacas/applications/exodiff/ED_SystemInterface.C @@ -585,7 +585,7 @@ bool SystemInterface::parse_options(int argc, char **argv) "\nThe following options were specified via the EXODIFF_OPTIONS environment variable:\n" "\t\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } if (options_.retrieve("summary") != nullptr) { @@ -632,14 +632,14 @@ bool SystemInterface::parse_options(int argc, char **argv) const char *temp = options_.retrieve("TimeStepOffset"); if (temp != nullptr) { errno = 0; - time_step_offset = strtol(temp, NULL, 10); + time_step_offset = strtol(temp, nullptr, 10); SMART_ASSERT(errno == 0); } else { const char *temp2 = options_.retrieve("T"); if (temp2 != nullptr) { errno = 0; - time_step_offset = strtol(temp2, NULL, 10); + time_step_offset = strtol(temp2, nullptr, 10); SMART_ASSERT(errno == 0); } } @@ -833,7 +833,7 @@ bool SystemInterface::parse_options(int argc, char **argv) const char *temp = options_.retrieve("max_warnings"); if (temp != nullptr) { errno = 0; - max_warnings = strtol(temp, NULL, 10); + max_warnings = strtol(temp, nullptr, 10); SMART_ASSERT(errno == 0); } } diff --git a/packages/seacas/applications/exodiff/create_file.C b/packages/seacas/applications/exodiff/create_file.C index 081f6f940c..19ddb039fe 100644 --- a/packages/seacas/applications/exodiff/create_file.C +++ b/packages/seacas/applications/exodiff/create_file.C @@ -267,7 +267,6 @@ namespace { std::vector vars(names.size()); for (unsigned i = 0; i < names.size(); ++i) { vars[i] = const_cast(names[i].c_str()); - SMART_ASSERT(vars[i] != nullptr); } ex_put_variable_names(file_id, type, names.size(), vars.data()); } diff --git a/packages/seacas/applications/exodiff/edge_block.h b/packages/seacas/applications/exodiff/edge_block.h index f82ebf35df..f730cd9148 100644 --- a/packages/seacas/applications/exodiff/edge_block.h +++ b/packages/seacas/applications/exodiff/edge_block.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -16,16 +16,15 @@ template class Edge_Block : public Exo_Entity Edge_Block(); Edge_Block(int file_id, size_t id); Edge_Block(int file_id, size_t id, size_t ne); + Edge_Block(const Edge_Block &) = delete; // Not written. + const Edge_Block &operator=(const Edge_Block &) = delete; // Not written. + ~Edge_Block() override; size_t Edge_Index(size_t position) const; - int Check_State() const; - private: - Edge_Block(const Edge_Block &) = delete; // Not written. - const Edge_Block &operator=(const Edge_Block &) = delete; // Not written. - + int Check_State() const override; void entity_load_params() override; EXOTYPE exodus_type() const override; diff --git a/packages/seacas/applications/exodiff/exoII_read.C b/packages/seacas/applications/exodiff/exoII_read.C index 31f086eff5..b55bd3ec70 100644 --- a/packages/seacas/applications/exodiff/exoII_read.C +++ b/packages/seacas/applications/exodiff/exoII_read.C @@ -33,7 +33,9 @@ namespace { template ExoII_Read::ExoII_Read() = default; -template ExoII_Read::ExoII_Read(const std::string &fname) : file_name(fname) {} +template ExoII_Read::ExoII_Read(std::string fname) : file_name(std::move(fname)) +{ +} template ExoII_Read::~ExoII_Read() { @@ -1005,7 +1007,7 @@ template void ExoII_Read::Get_Init_Data() coord_names.clear(); for (int i = 0; i < dimension; ++i) { - coord_names.push_back(coords[i]); + coord_names.emplace_back(coords[i]); } free_name_array(coords, 3); diff --git a/packages/seacas/applications/exodiff/exoII_read.h b/packages/seacas/applications/exodiff/exoII_read.h index 8fe5ab78a1..3cef8ec061 100644 --- a/packages/seacas/applications/exodiff/exoII_read.h +++ b/packages/seacas/applications/exodiff/exoII_read.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -32,7 +32,7 @@ template class ExoII_Read { public: ExoII_Read(); - explicit ExoII_Read(const std::string &fname); + explicit ExoII_Read(std::string fname); virtual ~ExoII_Read(); const ExoII_Read &operator=(const ExoII_Read &) = delete; ExoII_Read(const ExoII_Read &) = delete; diff --git a/packages/seacas/applications/exodiff/exo_block.h b/packages/seacas/applications/exodiff/exo_block.h index b35cb404a0..04eabb23c8 100644 --- a/packages/seacas/applications/exodiff/exo_block.h +++ b/packages/seacas/applications/exodiff/exo_block.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -34,12 +34,11 @@ template class Exo_Block : public Exo_Entity const INT *Connectivity(size_t elmt_index) const; // 1-offset connectivity // Misc: - int Check_State() const; - int64_t offset() const { return offset_; } void offset(int64_t off) { offset_ = off; } private: + int Check_State() const override; void entity_load_params() override; EXOTYPE exodus_type() const override; diff --git a/packages/seacas/applications/exodiff/exo_entity.C b/packages/seacas/applications/exodiff/exo_entity.C index 0f1d1231e7..f005bf6798 100644 --- a/packages/seacas/applications/exodiff/exo_entity.C +++ b/packages/seacas/applications/exodiff/exo_entity.C @@ -56,14 +56,6 @@ Exo_Entity::~Exo_Entity() } } -int Exo_Entity::Check_State() const -{ - SMART_ASSERT(id_ >= EX_INVALID_ID); - - SMART_ASSERT(!(id_ == EX_INVALID_ID && numEntity > 0)); - return 1; -} - void Exo_Entity::initialize(int file_id, size_t id) { fileId = file_id; @@ -81,7 +73,6 @@ bool Exo_Entity::is_valid_var(size_t var_index) const SMART_ASSERT((int)var_index < numVars); if (truth_ == nullptr) { get_truth_table(); - SMART_ASSERT(truth_ != nullptr); } return (truth_[var_index] != 0); @@ -109,7 +100,6 @@ std::string Exo_Entity::Load_Results(int time_step, int var_index) if (truth_ == nullptr) { get_truth_table(); - SMART_ASSERT(truth_ != nullptr); } if (truth_[var_index] != 0) { @@ -166,7 +156,6 @@ std::string Exo_Entity::Load_Results(int t1, int t2, double proportion, int var_ if (truth_ == nullptr) { get_truth_table(); - SMART_ASSERT(truth_ != nullptr); } if (truth_[var_index] != 0) { diff --git a/packages/seacas/applications/exodiff/exo_entity.h b/packages/seacas/applications/exodiff/exo_entity.h index b6e3782086..6a1d7b38ab 100644 --- a/packages/seacas/applications/exodiff/exo_entity.h +++ b/packages/seacas/applications/exodiff/exo_entity.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -37,8 +37,6 @@ class Exo_Entity size_t Id() const { return id_; } size_t Index() const { return index_; } - int Check_State() const; - void initialize(int file_id, size_t id); bool is_valid_var(size_t var_index) const; @@ -65,9 +63,6 @@ class Exo_Entity // Return "block", "nodelist", "surface", depending on underlying type. virtual const char *short_label() const = 0; - // Return EX_ELEM_BLOCK, EX_NODE_SET, ... of underlying type - virtual EXOTYPE exodus_type() const = 0; - protected: std::string name_{}; int fileId{-1}; @@ -76,6 +71,10 @@ class Exo_Entity size_t numEntity{0}; // Number of items (nodes, sides, elements) private: + // Return EX_ELEM_BLOCK, EX_NODE_SET, ... of underlying type + virtual EXOTYPE exodus_type() const = 0; + + virtual int Check_State() const = 0; virtual void entity_load_params() = 0; void internal_load_params(); diff --git a/packages/seacas/applications/exodiff/exodiff.C b/packages/seacas/applications/exodiff/exodiff.C index 65b66f7bb1..3b4b1bb4e8 100644 --- a/packages/seacas/applications/exodiff/exodiff.C +++ b/packages/seacas/applications/exodiff/exodiff.C @@ -1063,8 +1063,7 @@ bool Equal_Values(const double *values, size_t count, double *value) { SMART_ASSERT(values != nullptr); *value = values[0]; - return (std::adjacent_find(values, values + count, std::not_equal_to()) == - values + count); + return (std::adjacent_find(values, values + count, std::not_equal_to<>()) == values + count); } template diff --git a/packages/seacas/applications/exodiff/face_block.h b/packages/seacas/applications/exodiff/face_block.h index db1e574ff7..9d7e4804b6 100644 --- a/packages/seacas/applications/exodiff/face_block.h +++ b/packages/seacas/applications/exodiff/face_block.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -17,15 +17,13 @@ template class Face_Block : public Exo_Entity Face_Block(int file_id, size_t id); Face_Block(int file_id, size_t id, size_t ne); ~Face_Block() override; + Face_Block(const Face_Block &) = delete; // Not written. + const Face_Block &operator=(const Face_Block &) = delete; // Not written. size_t Face_Index(size_t position) const; - int Check_State() const; - private: - Face_Block(const Face_Block &) = delete; // Not written. - const Face_Block &operator=(const Face_Block &) = delete; // Not written. - + int Check_State() const override; void entity_load_params() override; EXOTYPE exodus_type() const override; diff --git a/packages/seacas/applications/exodiff/node_set.h b/packages/seacas/applications/exodiff/node_set.h index 1ce5cb614b..cd7a56b589 100644 --- a/packages/seacas/applications/exodiff/node_set.h +++ b/packages/seacas/applications/exodiff/node_set.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -29,9 +29,8 @@ template class Node_Set : public Exo_Entity const double *Distribution_Factors() const; void Free_Distribution_Factors() const; - int Check_State() const; - private: + int Check_State() const override; void entity_load_params() override; EXOTYPE exodus_type() const override; diff --git a/packages/seacas/applications/exodiff/side_set.h b/packages/seacas/applications/exodiff/side_set.h index 362b3f940c..27ce8c3b07 100644 --- a/packages/seacas/applications/exodiff/side_set.h +++ b/packages/seacas/applications/exodiff/side_set.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -17,6 +17,8 @@ template class Side_Set : public Exo_Entity Side_Set(int file_id, size_t id); Side_Set(int file_id, size_t id, size_t ns, size_t ndf = 0); ~Side_Set() override; + Side_Set(const Side_Set &) = delete; + const Side_Set &operator=(const Side_Set &) = delete; void apply_map(const std::vector &elmt_map); const INT *Elements() const; @@ -28,13 +30,10 @@ template class Side_Set : public Exo_Entity const double *Distribution_Factors() const; void Free_Distribution_Factors() const; - int Check_State() const; size_t Distribution_Factor_Count() const { return num_dist_factors; } private: - Side_Set(const Side_Set &); // Not written. - const Side_Set &operator=(const Side_Set &); // Not written. - + int Check_State() const override; void load_sides(const std::vector &elmt_map) const; void load_df() const; void entity_load_params() override; diff --git a/packages/seacas/applications/exodiff/stringx.C b/packages/seacas/applications/exodiff/stringx.C index 4f54870be5..a3a366fdbf 100644 --- a/packages/seacas/applications/exodiff/stringx.C +++ b/packages/seacas/applications/exodiff/stringx.C @@ -82,7 +82,7 @@ std::string extract_token(std::string &s, const char *delimiters) // action outside of this block of code. // Find the closing quote - auto cq = s.find_first_of("\"", p + 1); + auto cq = s.find_first_of('\"', p + 1); // No closing quote found. Error out. SMART_ASSERT(cq < s.size()); diff --git a/packages/seacas/applications/exomatlab/EML_SystemInterface.C b/packages/seacas/applications/exomatlab/EML_SystemInterface.C index 146daf9334..4055f39430 100644 --- a/packages/seacas/applications/exomatlab/EML_SystemInterface.C +++ b/packages/seacas/applications/exomatlab/EML_SystemInterface.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -100,14 +100,15 @@ bool SystemInterface::parse_options(int argc, char **argv) "\nThe following options were specified via the EXOMATLAB_OPTIONS environment " "variable:\n\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } if (options_.retrieve("help") != nullptr) { options_.usage(); fmt::print(stderr, "\n\tCan also set options via EXOMATLAB_OPTIONS environment variable.\n" - "\n\tDocumentation: https://sandialabs.github.io/seacas-docs/sphinx/html/index.html#exomatlab\n" + "\n\tDocumentation: " + "https://sandialabs.github.io/seacas-docs/sphinx/html/index.html#exomatlab\n" "\n\t->->-> Send email to gdsjaar@sandia.gov for exomatlab support.<-<-<-\n"); exit(EXIT_SUCCESS); @@ -246,13 +247,13 @@ namespace { StringVector name_id = SLIB::tokenize(*I, ":"); std::string var_name = LowerCase(name_id[0]); if (name_id.size() == 1) { - (*variable_list).push_back(std::make_pair(var_name, 0)); + (*variable_list).emplace_back(var_name, 0); } else { for (size_t i = 1; i < name_id.size(); i++) { // Convert string to integer... int id = std::stoi(name_id[i]); - (*variable_list).push_back(std::make_pair(var_name, id)); + (*variable_list).emplace_back(var_name, id); } } ++I; diff --git a/packages/seacas/applications/exomatlab/exomatlab.C b/packages/seacas/applications/exomatlab/exomatlab.C index fcdc7e535f..2c27a3bf33 100644 --- a/packages/seacas/applications/exomatlab/exomatlab.C +++ b/packages/seacas/applications/exomatlab/exomatlab.C @@ -42,10 +42,8 @@ namespace { Ioss::GroupingEntity *entity) { fmt::print("\n{} variables on exodus data base:\n", type); - Ioss::NameList::const_iterator IF; - for (IF = fields.begin(); IF != fields.end(); ++IF) { - std::string field_name = *IF; - const Ioss::VariableType *var_type = entity->get_field(field_name).raw_storage(); + for (const auto &field_name : fields) { + const Ioss::VariableType *var_type = entity->get_field(field_name).raw_storage(); fmt::print("\t{}\t{}\n", field_name, var_type->name()); } } @@ -67,7 +65,7 @@ int main(int argc, char *argv[]) bool ok = false; codename = argv[0]; - size_t ind = codename.find_last_of("/", codename.size()); + size_t ind = codename.find_last_of('/', codename.size()); if (ind != std::string::npos) { codename = codename.substr(ind + 1, codename.size()); } @@ -180,10 +178,8 @@ namespace { fmt::print(out_stream, "% number of curves\nnvars = {}\n", fields.size() + 1); - size_t namelen = 4; // length of 'time' - Ioss::NameList::const_iterator IF; - for (IF = fields.begin(); IF != fields.end(); ++IF) { - std::string field_name = *IF; + size_t namelen = 4; // length of 'time' + for (const auto &field_name : fields) { if (field_name.length() > namelen) { namelen = field_name.length(); } @@ -191,8 +187,7 @@ namespace { fmt::print(out_stream, "names= [\n'{:<{}}';\n", "TIME", namelen); - for (IF = fields.begin(); IF != fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : fields) { fmt::print(out_stream, "'{:<{}}';\n", field_name, namelen); } fmt::print(out_stream, "];\n"); @@ -247,9 +242,8 @@ namespace { // Output field values... std::vector data(1); - for (IF = fields.begin(); IF != fields.end(); ++IF) { - std::string field_name = *IF; - int comp_count = region.get_field(field_name).raw_storage()->component_count(); + for (const auto &field_name : fields) { + int comp_count = region.get_field(field_name).raw_storage()->component_count(); fmt::print(out_stream, "{} = zeros({}, {});\n", field_name, comp_count, num_steps); fmt::print(out_stream, "{} = [\n", field_name); for (int istep = st_min; istep <= st_max; istep++) { diff --git a/packages/seacas/applications/exotec2/exotec2.c b/packages/seacas/applications/exotec2/exotec2.c index 1e04992eb6..d3548d955d 100644 --- a/packages/seacas/applications/exotec2/exotec2.c +++ b/packages/seacas/applications/exotec2/exotec2.c @@ -18,7 +18,7 @@ static void banner() { time_t time_val; struct tm *time_structure; - char * asc_time; + char *asc_time; time_val = time((time_t *)NULL); time_structure = localtime(&time_val); diff --git a/packages/seacas/applications/fastq/addrow.f b/packages/seacas/applications/fastq/addrow.f index 334e5218d5..7322fb126c 100644 --- a/packages/seacas/applications/fastq/addrow.f +++ b/packages/seacas/applications/fastq/addrow.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -91,13 +91,13 @@ SUBROUTINE ADDROW (MXND, MXCORN, MXLOOP, MLN, MAXPRM, NUID, XN, IF (NEND .EQ. NBEGIN) THEN -C A CIRCLUAR ROW THAT ENDS AT A ROW END (TEAR DROP SHAPE) NEEDS STARTED +C A CIRCULAR ROW THAT ENDS AT A ROW END (TEAR DROP SHAPE) NEEDS STARTED IF (LNODES (1, N1) .EQ. 1) THEN NEND = N0 NADJ1 = NNN + 1 -C A CIRCLUAR ROW THAT HAS NO END, CORNER, OR REVERSAL (CIRCLE SHAPE) +C A CIRCULAR ROW THAT HAS NO END, CORNER, OR REVERSAL (CIRCLE SHAPE) C NEEDS STARTED ELSEIF (LNODES (1, N1) .EQ. 3) THEN @@ -126,7 +126,7 @@ SUBROUTINE ADDROW (MXND, MXCORN, MXLOOP, MLN, MAXPRM, NUID, XN, ENDIF N1 = N2 -C A CIRCLUAR ROW THAT ENDS AT A ROW CORNER NEEDS STARTED +C A CIRCULAR ROW THAT ENDS AT A ROW CORNER NEEDS STARTED ELSEIF (LNODES (1, N1) .EQ. 5) THEN AMBIG = .TRUE. @@ -158,7 +158,7 @@ SUBROUTINE ADDROW (MXND, MXCORN, MXLOOP, MLN, MAXPRM, NUID, XN, N3 = LNODES (2, N2) GOTO 110 -C A CIRCLUAR ROW THAT ENDS AT A ROW REVERSAL NEEDS STARTED +C A CIRCULAR ROW THAT ENDS AT A ROW REVERSAL NEEDS STARTED ELSEIF (LNODES (1, N1) .EQ. 7) THEN CALL EXTND5 (MXND, XN, YN, ANGLE (N2), N1, N2, N3, X, Y, @@ -201,7 +201,7 @@ SUBROUTINE ADDROW (MXND, MXCORN, MXLOOP, MLN, MAXPRM, NUID, XN, ENDIF ELSE - CALL MESSAGE('PROBLEMS IN ADDROW - THE CIRCLUAR ROW') + CALL MESSAGE('PROBLEMS IN ADDROW - THE CIRCULAR ROW') CALL MESSAGE('HAS NO END POINT CLASSIFICATION') ERR = .TRUE. GOTO 120 diff --git a/packages/seacas/applications/grepos/gp_comand.F b/packages/seacas/applications/grepos/gp_comand.F index 2da50e3ff5..2dd38ea1e1 100644 --- a/packages/seacas/applications/grepos/gp_comand.F +++ b/packages/seacas/applications/grepos/gp_comand.F @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2022 National Technology & Engineering Solutions +C Copyright(C) 1999-2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -851,7 +851,7 @@ SUBROUTINE COMAND (NDBIN, EXECUT, GO TO 320 END IF ELSE -C ... Field is Attribute index -- first of ndim attributes involed in revolve. 1-based +C ... Field is Attribute index -- first of ndim attributes involved in revolve. 1-based CALL FFINTG (IFLD, INTYP, IFIELD, $ 'attribute index', 0, ATTIND, *420) END IF diff --git a/packages/seacas/applications/mapvar-kd/optkd.c b/packages/seacas/applications/mapvar-kd/optkd.c index 025a320568..6cf801857b 100644 --- a/packages/seacas/applications/mapvar-kd/optkd.c +++ b/packages/seacas/applications/mapvar-kd/optkd.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2021 National Technology & Engineering Solutions + * Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -119,10 +119,12 @@ void rf_select(real *a, int count, int l, int r, int k, int discrim) perm[j] = tmp; i = i + 1; j = j - 1; - while (a[discrim * count + perm[i]] < t) + while (a[discrim * count + perm[i]] < t) { i++; - while (a[discrim * count + perm[j]] > t) + } + while (a[discrim * count + perm[j]] > t) { j--; + } } if (a[discrim * count + perm[l]] == t) { /* exchange(x[l], x[j]); */ @@ -138,10 +140,12 @@ void rf_select(real *a, int count, int l, int r, int k, int discrim) perm[r] = tmp; } /* Now adjust L, R so they surround the subset containing the (k-l+1)-th element */ - if (j <= k) + if (j <= k) { l = j + 1; - if (k <= j) + } + if (k <= j) { r = j - 1; + } } } @@ -201,10 +205,12 @@ int findmaxvariance(int l, int u, int dimension, real *points, int N) /*******************************************************************************/ int check(real *points, int N, int l, int u, int m, int discrim) { - for (int i = l; i < m; i++) + for (int i = l; i < m; i++) { assert(points[discrim * N + perm[i]] <= points[discrim * N + perm[m]]); - for (int i = m; i < u; i++) + } + for (int i = m; i < u; i++) { assert(points[discrim * N + perm[i]] >= points[discrim * N + perm[m]]); + } return 1; } @@ -365,10 +371,12 @@ int optBoundsContainsRegion(real *B, real *xmin, real *xmax, int Dimension) { if (Dimension == 3) { if (xmin[0] <= B[0] && xmax[0] >= B[1] && xmin[1] <= B[2] && xmax[1] >= B[3] && - xmin[2] <= B[4] && xmax[2] >= B[5]) + xmin[2] <= B[4] && xmax[2] >= B[5]) { return 1; - else + } + else { return 0; + } } else { int dc; diff --git a/packages/seacas/applications/mat2exo/mat2exo.C b/packages/seacas/applications/mat2exo/mat2exo.C index cce94861af..399cc92c97 100644 --- a/packages/seacas/applications/mat2exo/mat2exo.C +++ b/packages/seacas/applications/mat2exo/mat2exo.C @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) const std::string ext{".exo"}; std::string line(argv[1]); - line = line.substr(0, line.find(".")); + line = line.substr(0, line.find('.')); line += ext; int exo_file = ex_create(line.c_str(), EX_CLOBBER, &cpu_word_size, &io_word_size); if (exo_file < 0) { @@ -357,7 +357,7 @@ std::vector matGetStr(const std::string &name) { matvar_t *matvar = Mat_VarRead(mat_file, name.c_str()); if (matvar == nullptr) { - return std::vector(); + return {}; } if (matvar->dims[0] != 1) { diff --git a/packages/seacas/applications/nas2exo/N2EExoWriter.C b/packages/seacas/applications/nas2exo/N2EExoWriter.C index a564e1be66..163da40c34 100644 --- a/packages/seacas/applications/nas2exo/N2EExoWriter.C +++ b/packages/seacas/applications/nas2exo/N2EExoWriter.C @@ -97,23 +97,22 @@ namespace ExoModules { bool result{true}; // Now we write the nodes - size_t num_nodes = this->gridList.size(); - double *x = new double[num_nodes]; - double *y = new double[num_nodes]; - double *z = new double[num_nodes]; + size_t num_nodes = this->gridList.size(); + std::vector x; + std::vector y; + std::vector z; + x.reserve(num_nodes); + y.reserve(num_nodes); + z.reserve(num_nodes); for (size_t i = 0; i < num_nodes; i++) { N2EPoint3D crd = std::get<1>(this->gridList[i]); - x[i] = crd.x[0]; - y[i] = crd.x[1]; - z[i] = crd.x[2]; + x.push_back(crd.x[0]); + y.push_back(crd.x[1]); + z.push_back(crd.x[2]); } - int ret = ex_put_coord(this->exoFileID, x, y, z); - - delete[] x; - delete[] y; - delete[] z; + int ret = ex_put_coord(this->exoFileID, x.data(), y.data(), z.data()); if (ret != 0) { std::cerr << "Problem writing node coordinates in N2EExoWriter::writeFile(). punching out.\n"; @@ -192,8 +191,8 @@ namespace ExoModules { numNodesCopied += nodes_per_elem; } - retvalue = - ex_put_conn(this->exoFileID, thisElType.elementType, block, elemCon.data(), NULL, NULL); + retvalue = ex_put_conn(this->exoFileID, thisElType.elementType, block, elemCon.data(), + nullptr, nullptr); switch (thisElType.numNodesPerElem) { diff --git a/packages/seacas/applications/nas2exo/N2ENasReader.C b/packages/seacas/applications/nas2exo/N2ENasReader.C index f5f5aedaff..612a29870d 100644 --- a/packages/seacas/applications/nas2exo/N2ENasReader.C +++ b/packages/seacas/applications/nas2exo/N2ENasReader.C @@ -2,7 +2,7 @@ // Name : testnas2exo.cpp // Author : Ramon J. Moral (STRA LLC), John Niederhaus (Coordinator, SNL) // Version : -// Copyright : (c) Sandia National Labs 2020, 2021, 2022 +// Copyright : (c) Sandia National Labs 2020, 2021, 2022, 2023 // Description : Testing nas2exo Library, C++ 14 //============================================================================ @@ -23,7 +23,7 @@ namespace NasModules { // C++ 14 version // this->inStream = make_unique(this->inFileName); // C++ 11 version - this->inStream.reset(new std::ifstream(this->inFileName)); + this->inStream = std::make_unique(this->inFileName); // Let's set the buffer this->inStream->rdbuf()->pubsetbuf(this->_readBuffer, sizeof(this->_readBuffer)); @@ -58,8 +58,9 @@ namespace NasModules { for (;;) { this->inStream->getline(buff, 511); - if (this->inStream->eof()) + if (this->inStream->eof()) { break; + } ++count; } diff --git a/packages/seacas/applications/nas2exo/nas2exo.C b/packages/seacas/applications/nas2exo/nas2exo.C index 53e67590b8..4e01d573f3 100644 --- a/packages/seacas/applications/nas2exo/nas2exo.C +++ b/packages/seacas/applications/nas2exo/nas2exo.C @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) } // Save some memory - reader.reset(NULL); + reader.reset(nullptr); if (!writer.writeFile()) { diff --git a/packages/seacas/applications/nem_slice/elb.h b/packages/seacas/applications/nem_slice/elb.h index 1416d64fc8..ebc957f935 100644 --- a/packages/seacas/applications/nem_slice/elb.h +++ b/packages/seacas/applications/nem_slice/elb.h @@ -119,7 +119,7 @@ struct Problem_Description int mech_add_procs{-1}; /* adds processors in cases of mechanisms */ int dsd_add_procs{-1}; /* adds processors in cases of disconnected subdomains */ int no_sph{-1}; - int fix_columns{0}; /* detect, fix vertical column partitioning */ + int fix_columns{0}; /* detect, fix vertical column partitioning */ char *groups{nullptr}; std::vector group_no{}; int num_groups{-1}; diff --git a/packages/seacas/applications/nem_slice/elb_exo_util.C b/packages/seacas/applications/nem_slice/elb_exo_util.C index 2410d093df..bf5620901c 100644 --- a/packages/seacas/applications/nem_slice/elb_exo_util.C +++ b/packages/seacas/applications/nem_slice/elb_exo_util.C @@ -19,9 +19,9 @@ #include #include -#include "elb.h" // for Weight_Description, etc -#include "elb_elem.h" // for get_elem_type, E_Type, etc -#include "elb_err.h" // for Gen_Error, MAX_ERR_MSG +#include "elb.h" // for Weight_Description, etc +#include "elb_elem.h" // for get_elem_type, E_Type, etc +#include "elb_err.h" // for Gen_Error, MAX_ERR_MSG #include "elb_exo.h" #include "elb_groups.h" // for parse_groups #include "elb_util.h" // for in_list, roundfloat diff --git a/packages/seacas/applications/nem_slice/elb_groups.C b/packages/seacas/applications/nem_slice/elb_groups.C index eca9fa7d3a..5437f24720 100644 --- a/packages/seacas/applications/nem_slice/elb_groups.C +++ b/packages/seacas/applications/nem_slice/elb_groups.C @@ -20,7 +20,7 @@ #include // for free, malloc #include // for strchr, strlen #include -#include // for vector +#include // for vector /*****************************************************************************/ namespace { diff --git a/packages/seacas/applications/nem_slice/elb_inp.C b/packages/seacas/applications/nem_slice/elb_inp.C index 19de028fc2..cb0a205313 100644 --- a/packages/seacas/applications/nem_slice/elb_inp.C +++ b/packages/seacas/applications/nem_slice/elb_inp.C @@ -1750,37 +1750,42 @@ namespace { token or at the terminating NUL character. */ int my_getsubopt(char **optionp, char *const *tokens, char **valuep) { - if (**optionp == '\0') + if (**optionp == '\0') { return -1; + } /* Find end of next token. */ char *endp = (char *)my_strchrnul(*optionp, ','); /* Find start of value. */ char *vstart = (char *)memchr(*optionp, '=', endp - *optionp); - if (vstart == nullptr) + if (vstart == nullptr) { vstart = endp; + } /* Try to match the characters between *OPTIONP and VSTART against one of the TOKENS. */ - for (int cnt = 0; tokens[cnt] != nullptr; ++cnt) + for (int cnt = 0; tokens[cnt] != nullptr; ++cnt) { if (strncmp(*optionp, tokens[cnt], vstart - *optionp) == 0 && tokens[cnt][vstart - *optionp] == '\0') { /* We found the current option in TOKENS. */ *valuep = vstart != endp ? vstart + 1 : nullptr; - if (*endp != '\0') + if (*endp != '\0') { *endp++ = '\0'; + } *optionp = endp; return cnt; } + } /* The current suboption does not match any option. */ *valuep = *optionp; - if (*endp != '\0') + if (*endp != '\0') { *endp++ = '\0'; + } *optionp = endp; return -1; diff --git a/packages/seacas/applications/nem_slice/elb_loadbal.C b/packages/seacas/applications/nem_slice/elb_loadbal.C index 4fe9c859f9..61124d49a4 100644 --- a/packages/seacas/applications/nem_slice/elb_loadbal.C +++ b/packages/seacas/applications/nem_slice/elb_loadbal.C @@ -30,7 +30,7 @@ #include "elb_graph.h" // for generate_graph #include "elb_groups.h" // for get_group_info #include "elb_loadbal.h" -#include "elb_util.h" // for find_inter, etc +#include "elb_util.h" // for find_inter, etc #include "fix_column_partitions.h" #ifndef M_PI @@ -686,6 +686,11 @@ int generate_loadbal(Machine_Description *machine, Problem_Description *problem, lb->ignore_z, tmp_v2p, argc, argv); BALANCE_STATS(machine, tmp_vwgts, tmp_nv, tmp_v2p); } +#else + else if (lb->type == ZOLTAN_RCB || lb->type == ZOLTAN_RIB || lb->type == ZOLTAN_HSFC) { + Gen_Error(0, "fatal: Invalid load balance types -- Zoltan is not supported in this build"); + goto cleanup; + } #endif else if (lb->type == LINEAR) { fmt::print(stderr, "Using internal linear decomposition\n"); @@ -905,7 +910,7 @@ int generate_loadbal(Machine_Description *machine, Problem_Description *problem, generate_graph(problem, mesh, graph, weight, sphere); /* - * adjacancy graph sent to identify_mechanisms must be 1 based + * adjacency graph sent to identify_mechanisms must be 1 based * */ @@ -1565,7 +1570,7 @@ namespace { if (side_cnt < nnodes) { nnodes = side_cnt; } - nnodes--; /* decrement to find the number of intersections needed */ + nnodes--; /* decrement to find the number of intersections needed */ nelem = 0; /* reset this in case no intersections are needed */ @@ -1870,12 +1875,12 @@ namespace { Gen_Error(0, cmesg); return 0; /* and get out of here */ - } /* End "if sid < 0 && !problem>skip_checks" */ - } /* End "if (sid > 0)" */ - } /* End "if (proc != proc2)" */ - } /* End "for (ncnt = 0; ncnt < nelem; ncnt++)" */ - } /* End "if (nelem > 1)" */ - } /* End "for (nscnt = 0; nscnt < nsides; nscnt++)" */ + } /* End "if sid < 0 && !problem>skip_checks" */ + } /* End "if (sid > 0)" */ + } /* End "if (proc != proc2)" */ + } /* End "for (ncnt = 0; ncnt < nelem; ncnt++)" */ + } /* End "if (nelem > 1)" */ + } /* End "for (nscnt = 0; nscnt < nsides; nscnt++)" */ if (internal) { lb->int_elems[proc].push_back(ecnt); @@ -1993,8 +1998,8 @@ namespace { */ time1 = get_time(); for (INT pcnt = 1; pcnt < machine->num_procs; pcnt++) { - int save_fv1 = 0; - int64_t size = + int save_fv1 = 0; + auto size = static_cast(lb->e_cmap_procs[pcnt].size()); /* Define shortcuts size and procs */ std::vector procs = lb->e_cmap_procs[pcnt]; @@ -2522,9 +2527,9 @@ namespace { nx, ny, nz, nx * ny * nz); float xmin; - float xmax; /* Minimum and maximum x-coordinate values */ + float xmax; /* Minimum and maximum x-coordinate values */ float ymin; - float ymax; /* Minimum and maximum y-coordinate values */ + float ymax; /* Minimum and maximum y-coordinate values */ float zmin; float zmax; /* Minimum and maximum z-coordinate values */ double dx; /* xmax - xmin */ @@ -2749,7 +2754,7 @@ namespace { ZOLTAN_ID_PTR dummy2; /* Empty output from Zoltan_LB_Partition */ int dummy0; int *dummy3; - int *dummy4; /* Empty output from Zoltan_LB_Partition */ + int *dummy4; /* Empty output from Zoltan_LB_Partition */ int zngid_ent; int znlid_ent; /* Useful output from Zoltan_LB_Partition */ int znobj; diff --git a/packages/seacas/applications/nem_slice/elb_util.C b/packages/seacas/applications/nem_slice/elb_util.C index 93d258d8c9..c26f5dbdcc 100644 --- a/packages/seacas/applications/nem_slice/elb_util.C +++ b/packages/seacas/applications/nem_slice/elb_util.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -196,7 +196,7 @@ namespace { /* * The following 'qsort' routine is modified from Sedgewicks * algorithm It selects the pivot based on the median of the left, - * right, and center values to try to avoid degenerate cases ocurring + * right, and center values to try to avoid degenerate cases occurring * when a single value is chosen. It performs a quicksort on * intervals down to the GDS_QSORT_CUTOFF size and then performs a final * insertion sort on the almost sorted final array. Based on data in diff --git a/packages/seacas/applications/nem_slice/fix_column_partitions.C b/packages/seacas/applications/nem_slice/fix_column_partitions.C index 7a7f9d2825..fe202b6fbc 100644 --- a/packages/seacas/applications/nem_slice/fix_column_partitions.C +++ b/packages/seacas/applications/nem_slice/fix_column_partitions.C @@ -108,8 +108,9 @@ int fix_column_partitions(LB_Description *lb, Mesh_Description const * // - if not, fix it for (size_t i = 0; i < nel; i++) { - if (processed_flag[i]) + if (processed_flag[i]) { continue; + } E_Type etype = mesh->elem_type[i]; @@ -167,8 +168,9 @@ int fix_column_partitions(LB_Description *lb, Mesh_Description const * break; } } - if (!found) + if (!found) { Gen_Error(0, "FATAL: side/face node not found in element node list?"); + } } std::array normal{0.0, 0.0, 0.0}; @@ -317,14 +319,14 @@ int fix_column_partitions(LB_Description *lb, Mesh_Description const * std::vector colelems; colelems.reserve(nabove + nbelow + 1); - typename std::vector::reverse_iterator rit = above_list.rbegin(); + auto rit = above_list.rbegin(); while (rit != above_list.rend()) { colelems.push_back(*rit); ++rit; } colelems.push_back(i); - typename std::vector::iterator it = below_list.begin(); + auto it = below_list.begin(); while (it != below_list.end()) { colelems.push_back(*it); ++it; @@ -347,16 +349,16 @@ int fix_column_partitions(LB_Description *lb, Mesh_Description const * std::pair::iterator, bool> status = procid_elcount.insert(std::pair(procid, 1)); if (!status.second) { // procid already in map; could not insert - std::map::iterator itmap = status.first; + auto itmap = status.first; (itmap->second)++; } ++it; } // Which processor has a dominant presence in this column? - int max_procid = -1; - int max_elems = 0; - std::map::iterator itmap = procid_elcount.begin(); + int max_procid = -1; + int max_elems = 0; + auto itmap = procid_elcount.begin(); while (itmap != procid_elcount.end()) { if (itmap->second > max_elems) { max_procid = itmap->first; diff --git a/packages/seacas/applications/nem_spread/el_exoII_io.C b/packages/seacas/applications/nem_spread/el_exoII_io.C index 7398430263..bf2e406746 100644 --- a/packages/seacas/applications/nem_spread/el_exoII_io.C +++ b/packages/seacas/applications/nem_spread/el_exoII_io.C @@ -321,9 +321,9 @@ template void NemSpread::load_mesh() if (globals.Num_Assemblies > 0) { globals.Assemblies.resize(globals.Num_Assemblies); - for (int i = 0; i < globals.Num_Assemblies; i++) { - globals.Assemblies[i].name = nullptr; - globals.Assemblies[i].entity_list = nullptr; + for (auto &assembly : globals.Assemblies) { + assembly.name = nullptr; + assembly.entity_list = nullptr; } ex_get_assemblies(mesh_exoid, globals.Assemblies.data()); @@ -643,6 +643,14 @@ template void NemSpread::load_mesh() safe_free((void **)&globals.Coordinate_Frame_Tags); } + // Clear out allocated memory for assembly entity_list... + for (auto &assembly : globals.Assemblies) { + free(assembly.name); + delete[] assembly.entity_list; + assembly.name = nullptr; + assembly.entity_list = nullptr; + } + /* done with the Coordinate names */ for (int i1 = 0; i1 < globals.Num_Dim; i1++) { safe_free((void **)&(Coord_Name[i1])); diff --git a/packages/seacas/applications/nem_spread/globals.h b/packages/seacas/applications/nem_spread/globals.h index f3ff60a65e..e642837f3c 100644 --- a/packages/seacas/applications/nem_spread/globals.h +++ b/packages/seacas/applications/nem_spread/globals.h @@ -33,7 +33,7 @@ template struct NODE_COMM_MAP }; /*---------------------------------------------------------------------------*/ -/* GLOBAL QUANTITITES THAT ARE THE SAME ON ALL PROCESSORS */ +/* GLOBAL QUANTITIES THAT ARE THE SAME ON ALL PROCESSORS */ /*---------------------------------------------------------------------------*/ template class Globals { diff --git a/packages/seacas/applications/nem_spread/md_timer_getrusage.C b/packages/seacas/applications/nem_spread/md_timer_getrusage.C index 23b69626f7..134b4ca40a 100644 --- a/packages/seacas/applications/nem_spread/md_timer_getrusage.C +++ b/packages/seacas/applications/nem_spread/md_timer_getrusage.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -10,8 +10,8 @@ #include // for ratio double second() { - static auto start = std::chrono::steady_clock::now(); - auto now = std::chrono::steady_clock::now(); - std::chrono::duration diff = now - start; + static auto start = std::chrono::steady_clock::now(); + auto now = std::chrono::steady_clock::now(); + const std::chrono::duration diff = now - start; return diff.count(); } diff --git a/packages/seacas/applications/nem_spread/nem_spread.h b/packages/seacas/applications/nem_spread/nem_spread.h index 1714d6f85d..fd8fc3bba1 100644 --- a/packages/seacas/applications/nem_spread/nem_spread.h +++ b/packages/seacas/applications/nem_spread/nem_spread.h @@ -15,7 +15,7 @@ #include "rf_io_const.h" #define UTIL_NAME "nem_spread" -#define VER_STR "7.02 (2023/02/06)" +#define VER_STR "7.03 (2023/07/28)" extern void check_exodus_error(int, const char *); extern double second(); diff --git a/packages/seacas/applications/nem_spread/pe_load_lb_info.C b/packages/seacas/applications/nem_spread/pe_load_lb_info.C index 9c8525e4e6..3f90da10e2 100644 --- a/packages/seacas/applications/nem_spread/pe_load_lb_info.C +++ b/packages/seacas/applications/nem_spread/pe_load_lb_info.C @@ -88,7 +88,7 @@ template void NemSpread::load_lb_info() int mode = EX_READ | int64api; int iio_ws = 0; // Don't interfere with exodus files; this is the nemesis file. if ((lb_exoid = ex_open(Exo_LB_File.c_str(), mode, &cpu_ws, &iio_ws, &version)) == -1) { - fmt::print(stderr, "[{}] ERROR: Couldn\'t open lb file, {}\n", __func__, Exo_LB_File); + fmt::print(stderr, "[{}] ERROR: Could not open lb file, {}\n", __func__, Exo_LB_File); exit(1); } @@ -149,7 +149,7 @@ template void NemSpread::load_lb_info() } /* End "for (int iproc=0; iproc -void NemSpread::read_cmap_params(int lb_exoid, - std::vector> &E_Comm_Map, +void NemSpread::read_cmap_params(int lb_exoid, std::vector> &E_Comm_Map, std::vector> &N_Comm_Map, INT *cmap_max_size) { diff --git a/packages/seacas/applications/nem_spread/ps_restart.C b/packages/seacas/applications/nem_spread/ps_restart.C index 2d6312f677..0924cd8720 100644 --- a/packages/seacas/applications/nem_spread/ps_restart.C +++ b/packages/seacas/applications/nem_spread/ps_restart.C @@ -632,34 +632,22 @@ int NemSpread::read_vars(int exoid, int index, INT *eb_ids, INT *eb_cnts if (Restart_Info.NVar_Elem > 0) { fmt::print("Reading {} element variables...\n", Restart_Info.NVar_Elem); - if (read_elem_vars(exoid, index, eb_ids, eb_cnts, eb_map_ptr, eb_cnts_local) < 0) { - fmt::print(stderr, "{}: Error distributing elemental variables.\n", __func__); - return -1; - } + read_elem_vars(exoid, index, eb_ids, eb_cnts, eb_map_ptr, eb_cnts_local); } if (Restart_Info.NVar_Node > 0) { fmt::print("Reading {} nodal variables...\n", Restart_Info.NVar_Node); - if (read_nodal_vars(exoid, index) < 0) { - fmt::print(stderr, "{}: Error distributing nodal variables.\n", __func__); - return -1; - } + read_nodal_vars(exoid, index); } if (Restart_Info.NVar_Sset > 0) { fmt::print("Reading {} sideset variables...\n", Restart_Info.NVar_Sset); - if (read_sset_vars(exoid, index, ss_ids, ss_cnts) < 0) { - fmt::print(stderr, "{}: Error distributing sideset variables.\n", __func__); - return -1; - } + read_sset_vars(exoid, index, ss_ids, ss_cnts); } if (Restart_Info.NVar_Nset > 0) { fmt::print("Reading {} nodeset variables...\n", Restart_Info.NVar_Nset); - if (read_nset_vars(exoid, index, ns_ids, ns_cnts) < 0) { - fmt::print(stderr, "{}: Error distributing nodeset variables.\n", __func__); - return -1; - } + read_nset_vars(exoid, index, ns_ids, ns_cnts); } return 0; diff --git a/packages/seacas/applications/nem_spread/sort_utils.C b/packages/seacas/applications/nem_spread/sort_utils.C index 9ccfcf1fed..de06b70305 100644 --- a/packages/seacas/applications/nem_spread/sort_utils.C +++ b/packages/seacas/applications/nem_spread/sort_utils.C @@ -19,7 +19,7 @@ /* * The following 'indexed qsort' routine is modified from Sedgewicks * algorithm It selects the pivot based on the median of the left, - * right, and center values to try to avoid degenerate cases ocurring + * right, and center values to try to avoid degenerate cases occurring * when a single value is chosen. It performs a quicksort on * intervals down to the GDS_QSORT_CUTOFF size and then performs a final * insertion sort on the almost sorted final array. Based on data in diff --git a/packages/seacas/applications/numbers/nu_locrl.f b/packages/seacas/applications/numbers/nu_locrl.f index 7650ebb92d..7003954f58 100644 --- a/packages/seacas/applications/numbers/nu_locrl.f +++ b/packages/seacas/applications/numbers/nu_locrl.f @@ -1,11 +1,11 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C C See packages/seacas/LICENSE for details C======================================================================= - INTEGER FUNCTION LOCRL (VALUE, NVALUS, VALUOK, VALUS) + INTEGER FUNCTION LOCRL (VALUEE, NVALUES, VALUEOK, VALUES) C======================================================================= C --*** LOCRL *** (TIMSEL) Find closest real value of selected values @@ -15,18 +15,18 @@ INTEGER FUNCTION LOCRL (VALUE, NVALUS, VALUOK, VALUS) C --selected real values (which may not be ordered). C -- C --Parameters: -C -- VALUE - the value to be searched for -C -- NVALUS - the number of values in the list -C -- VALUOK - VALUS(i) is selected iff VALUOK(i) -C -- VALUS - the list of values +C -- VALUEE - the value to be searched for +C -- NVALUES - the number of values in the list +C -- VALUEOK - VALUES(i) is selected iff VALUEOK(i) +C -- VALUES - the list of values - LOGICAL VALUOK(*) - REAL VALUS(*) + LOGICAL VALUEOK(*) + REAL VALUES(*) IX = 0 - DO 100 I = 1, NVALUS - IF (VALUOK(I)) THEN - DIFI = ABS (VALUS(I) - VALUE) + DO 100 I = 1, NVALUES + IF (VALUEOK(I)) THEN + DIFI = ABS (VALUES(I) - VALUEE) IF ((IX .EQ. 0) .OR. (DIF .GT. DIFI)) THEN DIF = DIFI IX = I diff --git a/packages/seacas/applications/slice/CMakeLists.txt b/packages/seacas/applications/slice/CMakeLists.txt index 08d4167478..846ef38957 100644 --- a/packages/seacas/applications/slice/CMakeLists.txt +++ b/packages/seacas/applications/slice/CMakeLists.txt @@ -5,6 +5,13 @@ IF (TPL_ENABLE_METIS) ADD_DEFINITIONS(-DUSE_METIS) ENDIF() +ASSERT_DEFINED(${PROJECT_NAME}_ENABLE_Zoltan) +IF (${PROJECT_NAME}_ENABLE_Zoltan) + TRIBITS_INCLUDE_DIRECTORIES(${Zoltan_INCLUDE_DIRS}) + SET(ZOLTAN_DEP zoltan) + ADD_DEFINITIONS(-DUSE_ZOLTAN) +ENDIF() + TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(HEADERS "") diff --git a/packages/seacas/applications/slice/SL_Decompose.C b/packages/seacas/applications/slice/SL_Decompose.C new file mode 100644 index 0000000000..5bddf0a749 --- /dev/null +++ b/packages/seacas/applications/slice/SL_Decompose.C @@ -0,0 +1,943 @@ +// Copyright(C) 1999-2023 National Technology & Engineering Solutions +// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with +// NTESS, the U.S. Government retains certain rights in this software. +// +// See packages/seacas/LICENSE for details + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#if USE_METIS +#include +#else +using idx_t = int; +#endif + +#if USE_ZOLTAN +#include // for Zoltan_Initialize +#include // for Zoltan +#endif + +extern int debug_level; +extern double seacas_timer(); +extern void progress(const std::string &output); + +namespace { + template + void create_adjacency_list(const Ioss::Region ®ion, std::vector &pointer, + std::vector &adjacency, INT) + { + progress(__func__); + // Size of pointer list is element count + 1; + // Size of adjacency list is sum of nodes-per-element for each element. + size_t sum = 0; + size_t count = 0; + const auto &ebs = region.get_element_blocks(); + for (const auto &eb : ebs) { + size_t element_count = eb->entity_count(); + size_t element_nodes = eb->topology()->number_nodes(); + sum += element_count * element_nodes; + count += element_count; + } + + pointer.reserve(count + 1); + adjacency.reserve(sum); + fmt::print(stderr, "\tAdjacency Size = {} for {} elements.\n", fmt::group_digits(sum), + fmt::group_digits(count)); + + // Now, iterate the blocks again, get connectivity and build adjacency structure. + std::vector connectivity; + for (const auto &eb : ebs) { + eb->get_field_data("connectivity_raw", connectivity); + size_t element_count = eb->entity_count(); + size_t element_nodes = eb->topology()->number_nodes(); + + size_t el = 0; + for (size_t j = 0; j < element_count; j++) { + pointer.push_back(adjacency.size()); + for (size_t k = 0; k < element_nodes; k++) { + INT node = connectivity[el++] - 1; + adjacency.push_back(node); + } + } + } + pointer.push_back(adjacency.size()); + assert(pointer.size() == count + 1); + assert(adjacency.size() == sum); + } + + void exodus_error(int lineno) + { + std::ostringstream errmsg; + fmt::print( + errmsg, + "Exodus error ({}) {} at line {} in file Slice.C. Please report to gdsjaar@sandia.gov " + "if you need help.", + exerrval, ex_strerror(exerrval), lineno); + + ex_err(nullptr, nullptr, EX_PRTLASTMSG); + throw std::runtime_error(errmsg.str()); + } + + int case_compare(const char *s1, const char *s2) + { + const char *c1 = s1; + const char *c2 = s2; + for (;;) { + if (::toupper(*c1) != ::toupper(*c2)) { + return (::toupper(*c1) - ::toupper(*c2)); + } + if (*c1 == '\0') { + return 0; + } + c1++; + c2++; + } + } + +#ifdef USE_ZOLTAN + template + std::tuple, std::vector, std::vector> + get_element_centroid(const Ioss::Region ®ion, IOSS_MAYBE_UNUSED INT dummy) + { + size_t element_count = region.get_property("element_count").get_int(); + + // The zoltan methods supported in slice are all geometry based + // and use the element centroid. + std::vector x(element_count); + std::vector y(element_count); + std::vector z(element_count); + + const auto *nb = region.get_node_blocks()[0]; + std::vector coor; + nb->get_field_data("mesh_model_coordinates", coor); + + const auto &blocks = region.get_element_blocks(); + size_t el = 0; + for (auto &eb : blocks) { + std::vector connectivity; + eb->get_field_data("connectivity_raw", connectivity); + size_t blk_element_count = eb->entity_count(); + size_t blk_element_nodes = eb->topology()->number_nodes(); + + for (size_t j = 0; j < blk_element_count; j++) { + for (size_t k = 0; k < blk_element_nodes; k++) { + auto node = connectivity[j * blk_element_nodes + k] - 1; + x[el] += coor[node * 3 + 0]; + y[el] += coor[node * 3 + 1]; + z[el] += coor[node * 3 + 2]; + } + x[el] /= blk_element_nodes; + y[el] /= blk_element_nodes; + z[el] /= blk_element_nodes; + el++; + } + } + return {x, y, z}; + } + /*****************************************************************************/ + /***** Global data structure used by Zoltan callbacks. *****/ + /***** Could implement Zoltan callbacks without global data structure, *****/ + /***** but using the global data structure makes implementation quick. *****/ + struct + { + size_t ndot; /* Length of x, y, z, and part (== # of elements) */ + int *vwgt; /* vertex weights */ + double *x; /* x-coordinates */ + double *y; /* y-coordinates */ + double *z; /* z-coordinates */ + } Zoltan_Data; + + /*****************************************************************************/ + /***** ZOLTAN CALLBACK FUNCTIONS *****/ + int zoltan_num_dim(void * /*data*/, int *ierr) + { + /* Return dimensionality of coordinate data. + * Using global data structure Zoltan_Data, initialized in ZOLTAN_RCB_assign. + */ + *ierr = ZOLTAN_OK; + if (Zoltan_Data.z != nullptr) { + return 3; + } + if (Zoltan_Data.y != nullptr) { + return 2; + } + return 1; + } + + int zoltan_num_obj(void * /*data*/, int *ierr) + { + /* Return number of objects. + * Using global data structure Zoltan_Data, initialized in ZOLTAN_RCB_assign. + */ + *ierr = ZOLTAN_OK; + return Zoltan_Data.ndot; + } + + void zoltan_obj_list(void * /*data*/, int /*ngid_ent*/, int /*nlid_ent*/, ZOLTAN_ID_PTR gids, + ZOLTAN_ID_PTR /*lids*/, int wdim, float *wgts, int *ierr) + { + /* Return list of object IDs. + * Return only global IDs; don't need local IDs since running in serial. + * gids are array indices for coordinate and vwgts arrays. + * Using global data structure Zoltan_Data, initialized in ZOLTAN_RCB_assign. + */ + std::iota(gids, gids + Zoltan_Data.ndot, 0); + if (wdim != 0) { + for (size_t i = 0; i < Zoltan_Data.ndot; i++) { + wgts[i] = static_cast(Zoltan_Data.vwgt[i]); + } + } + + *ierr = ZOLTAN_OK; + } + + void zoltan_geom(void * /*data*/, int /*ngid_ent*/, int /*nlid_ent*/, int nobj, + const ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR /*lids*/, int ndim, double *geom, + int *ierr) + { + /* Return coordinates for objects. + * gids are array indices for coordinate arrays. + * Using global data structure Zoltan_Data, initialized in ZOLTAN_RCB_assign. + */ + + for (size_t i = 0; i < static_cast(nobj); i++) { + size_t j = gids[i]; + geom[i * ndim] = Zoltan_Data.x[j]; + if (ndim > 1) { + geom[i * ndim + 1] = Zoltan_Data.y[j]; + } + if (ndim > 2) { + geom[i * ndim + 2] = Zoltan_Data.z[j]; + } + } + + *ierr = ZOLTAN_OK; + } + + template + void decompose_zoltan(const Ioss::Region ®ion, int ranks, SystemInterface &interFace, + std::vector &elem_to_proc, IOSS_MAYBE_UNUSED INT dummy) + { + if (ranks == 1) { + return; + } + + size_t element_count = region.get_property("element_count").get_int(); + if (element_count != static_cast(static_cast(element_count))) { + fmt::print(stderr, "ERROR: Cannot have a mesh with more than 2.1 Billion elements in a " + "Zoltan decomposition.\n"); + exit(EXIT_FAILURE); + } + + auto [x, y, z] = get_element_centroid(region, dummy); + + // Copy mesh data and pointers into structure accessible from callback fns. + Zoltan_Data.ndot = element_count; + Zoltan_Data.vwgt = nullptr; + if (interFace.ignore_x_ && interFace.ignore_y_) { + Zoltan_Data.x = z.data(); + } + else if (interFace.ignore_x_ && interFace.ignore_z_) { + Zoltan_Data.x = y.data(); + } + else if (interFace.ignore_y_ && interFace.ignore_z_) { + Zoltan_Data.x = x.data(); + } + else if (interFace.ignore_x_) { + Zoltan_Data.x = y.data(); + Zoltan_Data.y = z.data(); + } + else if (interFace.ignore_y_) { + Zoltan_Data.x = x.data(); + Zoltan_Data.y = z.data(); + } + else if (!interFace.ignore_z_) { + Zoltan_Data.x = x.data(); + Zoltan_Data.y = y.data(); + } + else { + Zoltan_Data.x = x.data(); + Zoltan_Data.y = y.data(); + Zoltan_Data.z = z.data(); + } + + // Initialize Zoltan + int argc = 0; + char **argv = nullptr; + + float ver = 0.0; + Zoltan_Initialize(argc, argv, &ver); + fmt::print("Using Zoltan version {:.2}, method {}\n", static_cast(ver), + interFace.decomposition_method()); + + Zoltan zz(Ioss::ParallelUtils::comm_world()); + + // Register Callback functions + // Using global Zoltan_Data; could register it here instead as data field. + zz.Set_Num_Obj_Fn(zoltan_num_obj, nullptr); + zz.Set_Obj_List_Fn(zoltan_obj_list, nullptr); + zz.Set_Num_Geom_Fn(zoltan_num_dim, nullptr); + zz.Set_Geom_Multi_Fn(zoltan_geom, nullptr); + + // Set parameters for Zoltan + zz.Set_Param("DEBUG_LEVEL", "0"); + std::string str = fmt::format("{}", ranks); + zz.Set_Param("NUM_GLOBAL_PARTS", str); + zz.Set_Param("LB_METHOD", interFace.decomposition_method()); + zz.Set_Param("NUM_LID_ENTRIES", "0"); + zz.Set_Param("REMAP", "0"); + zz.Set_Param("RETURN_LISTS", "PARTITION_ASSIGNMENTS"); + zz.Set_Param("RCB_RECTILINEAR_BLOCKS", "1"); + + int num_global = sizeof(INT) / sizeof(ZOLTAN_ID_TYPE); + num_global = num_global < 1 ? 1 : num_global; + + // Call partitioner + int changes = 0; + int num_local = 0; + int num_import = 1; + int num_export = 1; + ZOLTAN_ID_PTR import_global_ids = nullptr; + ZOLTAN_ID_PTR import_local_ids = nullptr; + ZOLTAN_ID_PTR export_global_ids = nullptr; + ZOLTAN_ID_PTR export_local_ids = nullptr; + int *import_procs = nullptr; + int *import_to_part = nullptr; + int *export_procs = nullptr; + int *export_to_part = nullptr; + int rc = zz.LB_Partition(changes, num_global, num_local, num_import, import_global_ids, + import_local_ids, import_procs, import_to_part, num_export, + export_global_ids, export_local_ids, export_procs, export_to_part); + + if (rc != ZOLTAN_OK) { + fmt::print(stderr, "ERROR: Problem during call to Zoltan LB_Partition.\n"); + goto End; + } + + // Sanity check + if (element_count != static_cast(num_export)) { + fmt::print(stderr, "Sanity check failed; ndot {} != num_export {}.\n", element_count, + static_cast(num_export)); + goto End; + } + + elem_to_proc.resize(element_count); + for (size_t i = 0; i < element_count; i++) { + elem_to_proc[i] = export_to_part[i]; + } + + End: + /* Clean up */ + Zoltan::LB_Free_Part(&export_global_ids, &export_local_ids, &export_procs, &export_to_part); + Zoltan::LB_Free_Part(&export_global_ids, &export_local_ids, &export_procs, &export_to_part); + } +#endif + +#if USE_METIS + int get_common_node_count(const Ioss::Region ®ion) + { + progress(__func__); + // Determine number of nodes that elements must share to be + // considered connected. A 8-node hex-only mesh would have 4 + // A 3D shell mesh should have 2. Basically, use the minimum + // number of nodes per side for all element blocks... Omit sphere + // elements; ignore bars(?)... + + int common_nodes = 999; + + const auto &ebs = region.get_element_blocks(); + for (const auto &eb : ebs) { + const Ioss::ElementTopology *topology = eb->topology(); + const Ioss::ElementTopology *boundary = topology->boundary_type(0); + if (boundary != nullptr) { + common_nodes = std::min(common_nodes, boundary->number_boundaries()); + } + else { + // Different topologies on some element faces... + size_t nb = topology->number_boundaries(); + for (size_t bb = 1; bb <= nb; bb++) { + boundary = topology->boundary_type(bb); + if (boundary != nullptr) { + common_nodes = std::min(common_nodes, boundary->number_boundaries()); + } + } + } + } + + common_nodes = std::max(1, common_nodes); + fmt::print(stderr, "Setting common_nodes to {}\n", common_nodes); + return common_nodes; + } + + template + void decompose_metis(const Ioss::Region ®ion, SystemInterface &interFace, + std::vector &elem_to_proc, IOSS_MAYBE_UNUSED INT dummy) + { + size_t element_count = region.get_property("element_count").get_int(); + + std::vector pointer; + std::vector adjacency; + + double start = seacas_timer(); + create_adjacency_list(region, pointer, adjacency, dummy); + double end = seacas_timer(); + fmt::print(stderr, "\tCreate Adjacency List = {:.5}\n", end - start); + + // Call Metis to get the partition... + { + start = seacas_timer(); + idx_t elem_count = element_count; + idx_t common = get_common_node_count(region); + idx_t proc_count = interFace.processor_count(); + idx_t obj_val = 0; + std::vector options((METIS_NOPTIONS)); + METIS_SetDefaultOptions(&options[0]); + if (interFace.decomposition_method() == "kway") { + options[METIS_OPTION_PTYPE] = METIS_PTYPE_KWAY; + } + else { + options[METIS_OPTION_PTYPE] = METIS_PTYPE_RB; + } + + options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; + if (interFace.contiguous_decomposition()) { + options[METIS_OPTION_CONTIG] = 1; + } + options[METIS_OPTION_DBGLVL] = 2; + options[METIS_OPTION_MINCONN] = 1; + + idx_t node_count = region.get_property("node_count").get_int(); + std::vector node_partition(node_count); + std::vector elem_partition(element_count); + + fmt::print(stderr, "\tCalling METIS Decomposition routine.\n"); + + METIS_PartMeshDual(&elem_count, &node_count, &pointer[0], &adjacency[0], nullptr, nullptr, + &common, &proc_count, nullptr, &options[0], &obj_val, &elem_partition[0], + &node_partition[0]); + + Ioss::Utils::clear(node_partition); + elem_to_proc.reserve(element_count); + std::copy(elem_partition.begin(), elem_partition.end(), std::back_inserter(elem_to_proc)); + + end = seacas_timer(); + fmt::print(stderr, "\tMETIS Partition = {:.5}\n", end - start); + fmt::print(stderr, "Objective value = {}\n", obj_val); + + // TODO Check Error... + } + } +#endif + + void output_histogram(const std::vector &proc_work, size_t avg_work, size_t median) + { + fmt::print("Work-per-processor Histogram\n"); + std::array histogram{}; + + auto wmin = *std::min_element(proc_work.begin(), proc_work.end()); + auto wmax = *std::max_element(proc_work.begin(), proc_work.end()); + + size_t hist_size = std::min(size_t(16), (wmax - wmin)); + hist_size = std::min(hist_size, proc_work.size()); + + if (hist_size <= 1) { + fmt::print("\tWork is the same on all processors; no histogram needed.\n\n"); + return; + } + + auto delta = double(wmax + 1 - wmin) / hist_size; + for (const auto &pw : proc_work) { + auto bin = size_t(double(pw - wmin) / delta); + SMART_ASSERT(bin < hist_size)(bin)(hist_size); + histogram[bin]++; + } + + size_t proc_width = Ioss::Utils::number_width(proc_work.size(), true); + size_t work_width = Ioss::Utils::number_width(wmax, true); + + fmt::print("\n\t{:^{}} {:^{}}\n", "Work Range", 2 * work_width + 2, "#", proc_width); + auto hist_max = *std::max_element(histogram.begin(), histogram.end()); + for (size_t i = 0; i < hist_size; i++) { + int max_star = 50; + int star_cnt = ((double)histogram[i] / hist_max * max_star); + std::string stars(star_cnt, '*'); + for (int j = 9; j < star_cnt;) { + stars[j] = '|'; + j += 10; + } + if (histogram[i] > 0 && star_cnt == 0) { + stars = '.'; + } + size_t w1 = wmin + size_t(i * delta); + size_t w2 = wmin + size_t((i + 1) * delta); + std::string postfix; + if (w1 <= avg_work && avg_work < w2) { + postfix += "average"; + } + if (w1 <= median && median < w2) { + if (!postfix.empty()) { + postfix += ", "; + } + postfix += "median"; + } + fmt::print("\t{:{}}..{:{}} ({:{}}):\t{:{}} {}\n", fmt::group_digits(w1), work_width, + fmt::group_digits(w2), work_width, fmt::group_digits(histogram[i]), proc_width, + stars, max_star, postfix); + } + fmt::print("\n"); + } + + void scale_decomp(std::vector &elem_to_proc, int iscale, size_t num_proc) + { + // Do the scaling (integer division...) + if (iscale == 0) { + // Auto scaling was asked for. Determine max entry in `elem_to_proc` and + // set the scale factor. + auto max_proc = *std::max_element(elem_to_proc.begin(), elem_to_proc.end()); + + iscale = (max_proc + 1) / num_proc; + fmt::print(" Element Processor Map automatic scaling factor = {}\n", iscale); + + if (iscale == 0) { + fmt::print(stderr, + "ERROR: Max value in element processor map is {} which is\n" + "\tless than the processor count ({}). Scaling values is not possible.", + max_proc, num_proc); + exit(EXIT_FAILURE); + } + } + std::transform(elem_to_proc.begin(), elem_to_proc.end(), elem_to_proc.begin(), + [iscale](int p) { return p / iscale; }); + } + + std::pair extract_iscale_name(const std::string &var_name, + const std::string &var_type) + { + if (var_name.empty()) { + fmt::print(stderr, "\nERROR: No element decomposition {} specified.\n", var_type); + exit(EXIT_FAILURE); + } + // If the "var_name" string contains a comma, then the value + // following the comma is either an integer "scale" which is + // divided into each entry in `elem_to_proc`, or it is the + // string "auto" which will automatically scale all values by + // the *integer* "max/processorCount" + // + // NOTE: integer division with *no* rounding is used. + int iscale = 1; + auto pos = var_name.find(','); + if (pos != std::string::npos) { + // Extract the string following the comma... + auto scale = var_name.substr(pos + 1); + if (scale == "AUTO" || scale == "auto") { + iscale = 0; + } + else { + iscale = std::stoi(scale); + } + } + return {iscale, var_name.substr(0, pos)}; + } +} // namespace + +template void decompose_elements(const Ioss::Region ®ion, SystemInterface &interFace, + std::vector &elem_to_proc, IOSS_MAYBE_UNUSED int dummy); +template void decompose_elements(const Ioss::Region ®ion, SystemInterface &interFace, + std::vector &elem_to_proc, IOSS_MAYBE_UNUSED int64_t dummy); + +template +void decompose_elements(const Ioss::Region ®ion, SystemInterface &interFace, + std::vector &elem_to_proc, IOSS_MAYBE_UNUSED INT dummy) +{ + progress(__func__); + // Populate the 'elem_to_proc' vector with a mapping from element to processor. + + size_t element_count = region.get_property("element_count").get_int(); + size_t elem_per_proc = element_count / interFace.processor_count(); + size_t extra = element_count % interFace.processor_count(); + + elem_to_proc.reserve(element_count); + + fmt::print(stderr, "\nDecomposing {} elements across {} processors using method '{}'.\n", + fmt::group_digits(element_count), fmt::group_digits(interFace.processor_count()), + interFace.decomposition_method()); + if (interFace.lineDecomp_) { + fmt::print(stderr, "\tDecomposition will be modified to put element lines/chains/columns on " + "same processor rank\n"); + } + + if (interFace.outputDecompMap_) { + fmt::print(stderr, "\tDecomposition will be output to an element map named '{}'.\n", + interFace.decomposition_variable()); + } + if (interFace.outputDecompField_) { + fmt::print(stderr, "\tDecomposition will be output to an element field named '{}'.\n", + interFace.decomposition_variable()); + } + fmt::print(stderr, "\n"); + + if (interFace.decomposition_method() == "linear") { + size_t elem_beg = 0; + for (size_t proc = 0; proc < interFace.processor_count(); proc++) { + size_t add = (proc < extra) ? 1 : 0; + size_t elem_end = elem_beg + elem_per_proc + add; + + for (size_t elem = elem_beg; elem < elem_end; elem++) { + elem_to_proc.push_back(proc); + } + elem_beg = elem_end; + } + } + else if (interFace.decomposition_method() == "scattered" || + interFace.decomposition_method() == "random") { + // Scattered... + size_t proc = 0; + for (size_t elem = 0; elem < element_count; elem++) { + elem_to_proc.push_back(proc++); + if (proc >= interFace.processor_count()) { + proc = 0; + } + } + if (interFace.decomposition_method() == "random") { + // Random... Use scattered method and then random_shuffle() the vector. + // Ensures that each processor has correct number of elements, but + // they are randomly distributed. + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(elem_to_proc.begin(), elem_to_proc.end(), g); + } + } + + else if (interFace.decomposition_method() == "rcb" || interFace.decomposition_method() == "rib" || + interFace.decomposition_method() == "hsfc") { +#if USE_ZOLTAN + decompose_zoltan(region, interFace.processor_count(), interFace, elem_to_proc, dummy); +#else + fmt::print(stderr, "ERROR: Zoltan library not enabled in this version of slice.\n" + " The 'rcb', 'rib', and 'hsfc' methods are not available.\n\n"); + std::exit(1); +#endif + } + + else if (interFace.decomposition_method() == "rb" || interFace.decomposition_method() == "kway") { +#if USE_METIS + decompose_metis(region, interFace, elem_to_proc, dummy); +#else + fmt::print(stderr, "ERROR: Metis library not enabled in this version of slice.\n" + " The 'rb' and 'kway' methods are not available.\n\n"); + std::exit(1); +#endif + } + + else if (interFace.decomposition_method() == "variable") { + auto [iscale, elem_variable] = + extract_iscale_name(interFace.decomposition_variable(), "variable"); + + // Get all element blocks and cycle through each reading the + // values for the processor... + const auto &blocks = region.get_element_blocks(); + auto *c_region = (Ioss::Region *)(®ion); + c_region->begin_state(1); + for (const auto &block : blocks) { + if (!block->field_exists(elem_variable)) { + fmt::print(stderr, "\nERROR: Element variable '{}' does not exist on block {}.\n", + elem_variable, block->name()); + exit(EXIT_FAILURE); + } + std::vector tmp_vals; + block->get_field_data(elem_variable, tmp_vals); + auto block_count = block->entity_count(); + for (int64_t i = 0; i < block_count; i++) { + elem_to_proc.push_back((int)tmp_vals[i]); + } + } + scale_decomp(elem_to_proc, iscale, interFace.processor_count()); + } + else if (interFace.decomposition_method() == "map") { + auto [iscale, map_name] = extract_iscale_name(interFace.decomposition_variable(), "map"); + + Ioss::DatabaseIO *db = region.get_database(); + int exoid = db->get_file_pointer(); + + bool map_read = false; + int map_count = ex_inquire_int(exoid, EX_INQ_ELEM_MAP); + if (map_count > 0) { + int max_name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_USED_NAME_LENGTH); + max_name_length = max_name_length < 32 ? 32 : max_name_length; + char **names = Ioss::Utils::get_name_array(map_count, max_name_length); + int error = ex_get_names(exoid, EX_ELEM_MAP, names); + if (error < 0) { + exodus_error(__LINE__); + } + + for (int i = 0; i < map_count; i++) { + if (case_compare(names[i], map_name.c_str()) == 0) { + elem_to_proc.resize(element_count); + error = ex_get_num_map(exoid, EX_ELEM_MAP, i + 1, elem_to_proc.data()); + if (error < 0) { + exodus_error(__LINE__); + } + map_read = true; + break; + } + } + Ioss::Utils::delete_name_array(names, map_count); + } + + if (!map_read) { + fmt::print(stderr, "\nERROR: Element decomposition map '{}' could not be read from file.\n", + map_name); + exit(EXIT_FAILURE); + } + + scale_decomp(elem_to_proc, iscale, interFace.processor_count()); + } + else if (interFace.decomposition_method() == "file") { + // Read the element decomposition mapping from a file. The + // syntax of the file is an optional element count followed by + // the processor for this range. If the element range is + // omitted, then the processor applies to the next element in + // the sequence. All elements must be specified or an error will + // be raised. + // + // Example: + // 0 + // 100 1 + // 0 + // + // Will assign: + // * element 1 to processor 0; + // * followed by the next 100 elements (2 to 101) to processor 1; + // * followed by the next element (102) to processor 0. + // + // The resulting decomposition will have 2 elements (1, 102) on + // processor 0 and 100 elements (2..101) on processor 1. + + const std::string &filename = interFace.decomposition_file(); + if (filename.empty()) { + fmt::print(stderr, "\nERROR: No element decomposition file specified.\n"); + exit(EXIT_FAILURE); + } + + std::ifstream decomp_file(filename, std::ios::in); + if (!decomp_file.good()) { + fmt::print( + stderr, + "\nERROR: Element decomposition file '{}' does not exist or could not be opened.\n", + filename); + exit(EXIT_FAILURE); + } + + std::string line; + size_t line_num = 0; + while (std::getline(decomp_file, line)) { + line_num++; + // See if 1 or 2 tokens on line... + std::vector tokens; + tokens = SLIB::tokenize(line, ", \t"); + size_t proc = 0; + size_t count = 1; + if (tokens.empty()) { + break; + } + if (tokens.size() == 1) { + // Just a processor specification for the next element... + proc = std::stoi(tokens[0]); + elem_to_proc.push_back(proc); + } + else { + // Count and processor specified. + count = std::stoi(tokens[0]); + proc = std::stoi(tokens[1]); + } + if (proc > interFace.processor_count()) { + fmt::print(stderr, + "\nERROR: Invalid processor {} specified on line {} of decomposition file.\n" + "\tValid range is 0..{}\n", + fmt::group_digits(proc), fmt::group_digits(line_num), + fmt::group_digits(interFace.processor_count() - 1)); + exit(EXIT_FAILURE); + } + + if (elem_to_proc.size() + count > element_count) { + fmt::print(stderr, + "\nERROR: The processor specification on line {}" + " of the decomposition file results in too many elements being specified.\n" + "\tThe total number of elements in the model is {}\n" + "\tPrior to this line, {} elements were specified.\n" + "\tIncluding this line, {} elements will be specified.\n", + fmt::group_digits(line_num), fmt::group_digits(element_count), + fmt::group_digits(elem_to_proc.size()), + fmt::group_digits(elem_to_proc.size() + count)); + exit(EXIT_FAILURE); + } + + for (size_t i = 0; i < count; i++) { + elem_to_proc.push_back(proc); + } + } + } + else { + fmt::print(stderr, "ERROR: Unrecognized decomposition method '{}'\n\n", + interFace.decomposition_method()); + exit(EXIT_FAILURE); + } + + assert(elem_to_proc.size() == element_count); +} + +template void line_decomp_modify(const Ioss::chain_t &element_chains, + std::vector &elem_to_proc, int proc_count); +template void line_decomp_modify(const Ioss::chain_t &element_chains, + std::vector &elem_to_proc, int proc_count); + +template +void line_decomp_modify(const Ioss::chain_t &element_chains, std::vector &elem_to_proc, + int proc_count) +{ + // Get a map of all chains and the elements in the chains. Map key will be root. + std::map> chains; + + for (size_t i = 0; i < element_chains.size(); i++) { + auto &chain_entry = element_chains[i]; + if (chain_entry.link >= 0) { + chains[chain_entry.element].push_back(i + 1); + if ((debug_level & 16) != 0) { + fmt::print("[{}]: element {}, link {}, processor {}\n", i + 1, chain_entry.element, + chain_entry.link, elem_to_proc[i]); + } + } + } + + // Delta: elements added/removed from each processor... + std::vector delta(proc_count); + + // Now, for each chain... + for (auto &chain : chains) { + if ((debug_level & 16) != 0) { + fmt::print("Chain Root: {} contains: {}\n", chain.first, fmt::join(chain.second, ", ")); + } + + std::vector chain_proc_count(proc_count); + const auto &chain_elements = chain.second; + + // * get processors used by elements in the chain... + for (const auto &element : chain_elements) { + auto proc = elem_to_proc[element - 1]; + chain_proc_count[proc]++; + } + + // * Now, subtract the `delta` from each count + for (int i = 0; i < proc_count; i++) { + chain_proc_count[i] -= delta[i]; + } + + // * Find the maximum value in `chain_proc_count` + auto max = std::max_element(chain_proc_count.begin(), chain_proc_count.end()); + auto max_proc = std::distance(chain_proc_count.begin(), max); + + // * Assign all elements in the chain to `max_proc`. + // * Update the deltas for all processors that gain/lose elements... + for (const auto &element : chain_elements) { + if (elem_to_proc[element - 1] != max_proc) { + auto old_proc = elem_to_proc[element - 1]; + elem_to_proc[element - 1] = max_proc; + delta[max_proc]++; + delta[old_proc]--; + } + } + } + + std::vector proc_element_count(proc_count); + for (auto proc : elem_to_proc) { + proc_element_count[proc]++; + } + if ((debug_level & 16) != 0) { + fmt::print("\nElements/Processor: {}\n", fmt::join(proc_element_count, ", ")); + fmt::print("Delta/Processor: {}\n", fmt::join(delta, ", ")); + } +} + +template void output_decomposition_statistics(const std::vector &elem_to_proc, int proc_count, + size_t number_elements); +template void output_decomposition_statistics(const std::vector &elem_to_proc, + int proc_count, size_t number_elements); +template +void output_decomposition_statistics(const std::vector &elem_to_proc, int proc_count, + size_t number_elements) +{ + // Output histogram of elements / rank... + std::vector elem_per_rank(proc_count); + for (INT proc : elem_to_proc) { + elem_per_rank[proc]++; + } + + size_t proc_width = Ioss::Utils::number_width(proc_count, false); + size_t work_width = Ioss::Utils::number_width(number_elements, true); + + auto min_work = *std::min_element(elem_per_rank.begin(), elem_per_rank.end()); + auto max_work = *std::max_element(elem_per_rank.begin(), elem_per_rank.end()); + size_t median = 0; + { + auto pw_copy(elem_per_rank); + std::nth_element(pw_copy.begin(), pw_copy.begin() + pw_copy.size() / 2, pw_copy.end()); + median = pw_copy[pw_copy.size() / 2]; + fmt::print("\nElements per processor:\n\tMinimum = {}, Maximum = {}, Median = {}, Ratio = " + "{:.3}\n\n", + fmt::group_digits(min_work), fmt::group_digits(max_work), fmt::group_digits(median), + (double)(max_work) / min_work); + } + if (min_work == max_work) { + fmt::print("\nWork on all processors is {}\n\n", fmt::group_digits(min_work)); + } + else { + int max_star = 40; + int min_star = max_star * ((double)min_work / (double)(max_work)); + min_star = std::max(1, min_star); + int delta = max_star - min_star; + + double avg_work = (double)number_elements / (double)proc_count; + for (size_t i = 0; i < elem_per_rank.size(); i++) { + int star_cnt = + (double)(elem_per_rank[i] - min_work) / (max_work - min_work) * delta + min_star; + std::string stars(star_cnt, '*'); + std::string format = "\tProcessor {:{}}, work = {:{}} ({:.2f})\t{}\n"; + if (elem_per_rank[i] == max_work) { + fmt::print(fg(fmt::color::red), format, i, proc_width, fmt::group_digits(elem_per_rank[i]), + work_width, (double)elem_per_rank[i] / avg_work, stars); + } + else if (elem_per_rank[i] == min_work) { + fmt::print(fg(fmt::color::green), format, i, proc_width, + fmt::group_digits(elem_per_rank[i]), work_width, elem_per_rank[i] / avg_work, + stars); + } + else { + fmt::print(format, i, proc_width, fmt::group_digits(elem_per_rank[i]), work_width, + elem_per_rank[i] / avg_work, stars); + } + } + + // Output Histogram... + output_histogram(elem_per_rank, (size_t)avg_work, median); + } +} diff --git a/packages/seacas/applications/slice/SL_Decompose.h b/packages/seacas/applications/slice/SL_Decompose.h new file mode 100644 index 0000000000..b426ddf432 --- /dev/null +++ b/packages/seacas/applications/slice/SL_Decompose.h @@ -0,0 +1,23 @@ +// Copyright(C) 1999-2023 National Technology & Engineering Solutions +// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with +// NTESS, the U.S. Government retains certain rights in this software. +// +// See packages/seacas/LICENSE for details + +#include +#include +#include +#include + +#pragma once +template +void decompose_elements(const Ioss::Region ®ion, SystemInterface &interFace, + std::vector &elem_to_proc, IOSS_MAYBE_UNUSED INT dummy); + +template +void line_decomp_modify(const Ioss::chain_t &element_chains, std::vector &elem_to_proc, + int proc_count); + +template +void output_decomposition_statistics(const std::vector &elem_to_proc, int proc_count, + size_t number_elements); diff --git a/packages/seacas/applications/slice/SL_SystemInterface.C b/packages/seacas/applications/slice/SL_SystemInterface.C index e4efa81cf8..11a030574a 100644 --- a/packages/seacas/applications/slice/SL_SystemInterface.C +++ b/packages/seacas/applications/slice/SL_SystemInterface.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -42,7 +42,7 @@ SystemInterface::~SystemInterface() = default; void SystemInterface::enroll_options() { - options_.usage("[options] file_to_split"); + options_.usage("[options] file_to_split [output_file]"); options_.enroll("help", GetLongOption::NoValue, "Print this summary and exit", nullptr); @@ -58,8 +58,15 @@ void SystemInterface::enroll_options() "\t\t'linear' : #elem/#proc to each processor\n" "\t\t'scattered': Shuffle elements to each processor (cyclic)\n" "\t\t'random' : Random distribution of elements, maintains balance\n" +#if USE_METIS "\t\t'rb' : Metis multilevel recursive bisection\n" "\t\t'kway' : Metis multilevel k-way graph partitioning\n" +#endif +#if USE_ZOLTAN + "\t\t'rib' : Zoltan recursive-inertial-bisection\n" + "\t\t'rcb' : Zoltan recursive-coordinate-bisection\n" + "\t\t'hsfc' : Zoltan hilbert-space-filling curve\n" +#endif "\t\t'variable' : Read element-processor assignment from an element variable\n" "\t\t'map' : Read element-processor assignment from an element map [processor_id]\n" "\t\t'file' : Read element-processor assignment from file", @@ -83,6 +90,21 @@ void SystemInterface::enroll_options() "\t\tIf two integers (count proc), they specify that the next\n" "\t\t\t'count' elements are on processor 'proc'", nullptr); + +#if USE_ZOLTAN + options_.enroll( + "ignore_x", GetLongOption::NoValue, + "If using `rcb`, `rib`, or `hsfc`, decompose as if mesh in yz plane. Ignore x dimension.", + nullptr); + options_.enroll( + "ignore_y", GetLongOption::NoValue, + "If using `rcb`, `rib`, or `hsfc`, decompose as if mesh in xz plane. Ignore y dimension.", + nullptr); + options_.enroll( + "ignore_z", GetLongOption::NoValue, + "If using `rcb`, `rib`, or `hsfc`, decompose as if mesh in xy plane. Ignore z dimension.", + nullptr); +#endif options_.enroll("contiguous_decomposition", GetLongOption::NoValue, "If the input mesh is contiguous, create contiguous decompositions", nullptr, nullptr); @@ -94,7 +116,6 @@ void SystemInterface::enroll_options() "\t\tOmit or enter 'ALL' for all surfaces in model\n" "\t\tDo not split a line/column across processors.", nullptr, "ALL", true); - options_.enroll("output_decomp_map", GetLongOption::NoValue, "Do not output the split files; instead write the decomposition information to " "an element map.\n" @@ -160,7 +181,8 @@ void SystemInterface::enroll_options() "\t\t 2 = Communication, NodeSet, Sideset information.\n" "\t\t 4 = Progress information in File/Rank.\n" "\t\t 8 = File/Rank Decomposition information.\n" - "\t\t 16 = Chain/Line generation/decomp information.", + "\t\t 16 = Chain/Line generation/decomp information.\n" + "\t\t 32 = Show decomposition histogram (elements / rank).", "0"); options_.enroll("version", GetLongOption::NoValue, "Print version and exit", nullptr); @@ -218,7 +240,8 @@ bool SystemInterface::parse_options(int argc, char **argv) if (options_.retrieve("help") != nullptr) { options_.usage(); fmt::print(stderr, "\n\t Can also set options via SLICE_OPTIONS environment variable.\n"); - fmt::print(stderr, "\n\tDocumentation: https://sandialabs.github.io/seacas-docs/sphinx/html/index.html#slice\n"); + fmt::print(stderr, "\n\tDocumentation: " + "https://sandialabs.github.io/seacas-docs/sphinx/html/index.html#slice\n"); fmt::print(stderr, "\n\t->->-> Send email to gsjaardema@gmail.com for slice support.<-<-<-\n"); exit(EXIT_SUCCESS); } @@ -256,7 +279,7 @@ bool SystemInterface::parse_options(int argc, char **argv) "\nThe following options were specified via the SLICE_OPTIONS environment variable:\n" "\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, GetLongOption::basename(*argv)); } processorCount_ = options_.get_option_value("processors", processorCount_); @@ -275,7 +298,7 @@ bool SystemInterface::parse_options(int argc, char **argv) } else { fmt::print(stderr, - "\nThe 'file' decompositon method was specified, but no element " + "\nThe 'file' decomposition method was specified, but no element " "to processor mapping file was specified via the -decomposition_file option\n"); return false; } @@ -322,6 +345,11 @@ bool SystemInterface::parse_options(int argc, char **argv) contig_ = options_.retrieve("contiguous_decomposition") != nullptr; outputDecompMap_ = options_.retrieve("output_decomp_map") != nullptr; outputDecompField_ = options_.retrieve("output_decomp_field") != nullptr; +#if USE_ZOLTAN + ignore_x_ = options_.retrieve("ignore_x") != nullptr; + ignore_y_ = options_.retrieve("ignore_y") != nullptr; + ignore_z_ = options_.retrieve("ignore_z") != nullptr; +#endif if (outputDecompMap_ && outputDecompField_) { fmt::print( @@ -398,10 +426,7 @@ void SystemInterface::parse_step_option(const char *tokens) if (strchr(tokens, ':') != nullptr) { // The string contains a separator - int vals[3]; - vals[0] = stepMin_; - vals[1] = stepMax_; - vals[2] = stepInterval_; + std::array vals = {stepMin_, stepMax_, stepInterval_}; int j = 0; for (int &val : vals) { diff --git a/packages/seacas/applications/slice/SL_SystemInterface.h b/packages/seacas/applications/slice/SL_SystemInterface.h index 94c6d949a3..6e18156adc 100644 --- a/packages/seacas/applications/slice/SL_SystemInterface.h +++ b/packages/seacas/applications/slice/SL_SystemInterface.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -100,6 +100,9 @@ class SystemInterface bool zlib_{true}; bool outputDecompMap_{false}; bool outputDecompField_{false}; + bool ignore_x_{false}; + bool ignore_y_{false}; + bool ignore_z_{false}; bool lineDecomp_{false}; std::string lineSurfaceList_{}; diff --git a/packages/seacas/applications/slice/SL_Version.h b/packages/seacas/applications/slice/SL_Version.h index b72c67043b..93e1aebcc1 100644 --- a/packages/seacas/applications/slice/SL_Version.h +++ b/packages/seacas/applications/slice/SL_Version.h @@ -9,6 +9,6 @@ static std::array qainfo{ "slice", - "2022/09/12", - "2.0.00", + "2023/09/14", + "2.1.05", }; diff --git a/packages/seacas/applications/slice/Slice.C b/packages/seacas/applications/slice/Slice.C index fc87509a0c..29274e3c5b 100644 --- a/packages/seacas/applications/slice/Slice.C +++ b/packages/seacas/applications/slice/Slice.C @@ -4,11 +4,10 @@ // // See packages/seacas/LICENSE for details +#include #include #include -#include -#include #include #include #include @@ -20,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -32,19 +32,11 @@ #include #include #include -#include #include #include -#include #include #include -#if USE_METIS -#include -#else -using idx_t = int; -#endif - #include #ifdef SEACAS_HAVE_MPI @@ -65,19 +57,19 @@ int debug_level = 0; // size_t partial_count = 1'00'000; size_t partial_count = 1'000'000'000; -namespace { - void progress(const std::string &output) - { - static auto start = std::chrono::steady_clock::now(); +void progress(const std::string &output) +{ + static auto start = std::chrono::steady_clock::now(); - if ((debug_level & 1) != 0) { - auto now = std::chrono::steady_clock::now(); - std::chrono::duration diff = now - start; - fmt::print(stderr, " [{:.2f} - {}]\t{}\n", diff.count(), - fmt::group_digits(Ioss::MemoryUtils::get_memory_info()), output); - } + if ((debug_level & 1) != 0) { + auto now = std::chrono::steady_clock::now(); + std::chrono::duration diff = now - start; + fmt::print(stderr, " [{:.2f} - {}]\t{}\n", diff.count(), + fmt::group_digits(Ioss::MemoryUtils::get_memory_info()), output); } +} +namespace { void proc_progress(int p, int proc_count) { if (((debug_level & 8) != 0) && ((proc_count <= 20) || ((p + 1) % (proc_count / 20) == 0))) { @@ -85,6 +77,36 @@ namespace { } } + Ioss::PropertyManager set_properties(SystemInterface &interFace) + { + Ioss::PropertyManager properties; + if (interFace.netcdf4_) { + properties.add(Ioss::Property("FILE_TYPE", "netcdf4")); + } + + if (interFace.netcdf5_) { + properties.add(Ioss::Property("FILE_TYPE", "netcdf5")); + } + + if (interFace.compressionLevel_ > 0 || interFace.shuffle_ || interFace.szip_) { + properties.add(Ioss::Property("FILE_TYPE", "netcdf4")); + properties.add(Ioss::Property("COMPRESSION_LEVEL", interFace.compressionLevel_)); + properties.add(Ioss::Property("COMPRESSION_SHUFFLE", static_cast(interFace.shuffle_))); + if (interFace.szip_) { + properties.add(Ioss::Property("COMPRESSION_METHOD", "szip")); + } + else if (interFace.zlib_) { + properties.add(Ioss::Property("COMPRESSION_METHOD", "zlib")); + } + } + + if (interFace.ints64Bit_) { + properties.add(Ioss::Property("INTEGER_SIZE_DB", 8)); + properties.add(Ioss::Property("INTEGER_SIZE_API", 8)); + } + return properties; + } + // Add the chain maps for file-per-rank output... template void output_chain_maps(std::vector &proc_region, const Ioss::chain_t &chains, @@ -92,41 +114,36 @@ namespace { INT /* dummy */) { progress(__func__); - size_t block_count = proc_region[0]->get_property("element_block_count").get_int(); - size_t offset = 0; - for (size_t b = 0; b < block_count; b++) { - if (debug_level & 4) { - progress("\tBlock " + std::to_string(b + 1)); - } + // Build the proc-local chain map and then output it on a block-by-block basis... + size_t proc_count = proc_region.size(); + std::vector> map(proc_count); - size_t proc_count = proc_region.size(); - std::vector> map(proc_count); - for (size_t p = proc_begin; p < proc_begin + proc_size; p++) { - const auto &proc_ebs = proc_region[p]->get_element_blocks(); - size_t proc_element_count = proc_ebs[b]->entity_count(); - map[p].reserve(proc_element_count * 2); + size_t global_element_count = elem_to_proc.size(); + for (size_t j = 0; j < global_element_count; j++) { + size_t p = elem_to_proc[j]; + if (p >= proc_begin && p < proc_begin + proc_size) { + auto &chain_entry = chains[j]; + // TODO: Map this from global to local element number... + size_t loc_elem = + chain_entry.element > 0 + ? proc_region[p]->get_database()->element_global_to_local(chain_entry.element) + : 0; + map[p].push_back(loc_elem); + map[p].push_back(chain_entry.link); } + } - size_t global_element_count = elem_to_proc.size(); - for (size_t j = 0; j < global_element_count; j++) { - size_t p = elem_to_proc[offset + j]; - if (p >= proc_begin && p < proc_begin + proc_size) { - auto &chain_entry = chains[j + offset]; - // TODO: Map this from global to local element number... - size_t loc_elem = - proc_region[p]->get_database()->element_global_to_local(chain_entry.element); - map[p].push_back(loc_elem); - map[p].push_back(chain_entry.link); - } - } - offset += global_element_count; + // Now iterate through the blocks on each rank and output that portion of the map... + size_t block_count = proc_region[0]->get_property("element_block_count").get_int(); - for (size_t p = proc_begin; p < proc_begin + proc_size; p++) { - const auto &proc_ebs = proc_region[p]->get_element_blocks(); - proc_ebs[b]->put_field_data("chain", map[p]); - map[p].clear(); - proc_progress(p, proc_count); + for (size_t p = proc_begin; p < proc_begin + proc_size; p++) { + const auto &proc_ebs = proc_region[p]->get_element_blocks(); + size_t offset = 0; + for (size_t b = 0; b < block_count; b++) { + size_t proc_element_count = proc_ebs[b]->entity_count(); + proc_ebs[b]->put_field_data("chain", &map[p][offset], proc_element_count * 2 * sizeof(INT)); + offset += proc_element_count; } } } @@ -187,9 +204,23 @@ namespace { { const auto &blocks = region.get_element_blocks(); size_t offset = 0; + + // Convert is outputting to 64-bit database... + std::vector elem_to_proc64; + if (sizeof(INT) == 8) { + elem_to_proc64.reserve(elem_to_proc.size()); + for (const auto &etp : elem_to_proc) { + elem_to_proc64.push_back(etp); + } + } for (const auto &block : blocks) { size_t num_elem = block->entity_count(); - block->put_field_data(decomp_variable_name, (void *)&elem_to_proc[offset], -1); + if (sizeof(INT) == 8) { + block->put_field_data(decomp_variable_name, (void *)&elem_to_proc64[offset], -1); + } + else { + block->put_field_data(decomp_variable_name, (void *)&elem_to_proc[offset], -1); + } if (add_chain_info) { std::vector chain; chain.reserve(num_elem * 2); @@ -237,39 +268,6 @@ namespace { region.end_mode(Ioss::STATE_TRANSIENT); } - template - void line_decomp_modify(const Ioss::chain_t &element_chains, - const std::vector &elem_to_proc, int proc_count, INT dummy); - - int case_compare(const char *s1, const char *s2) - { - const char *c1 = s1; - const char *c2 = s2; - for (;;) { - if (::toupper(*c1) != ::toupper(*c2)) { - return (::toupper(*c1) - ::toupper(*c2)); - } - if (*c1 == '\0') { - return 0; - } - c1++; - c2++; - } - } - - void exodus_error(int lineno) - { - std::ostringstream errmsg; - fmt::print( - errmsg, - "Exodus error ({}) {} at line {} in file Slice.C. Please report to gdsjaar@sandia.gov " - "if you need help.", - exerrval, ex_strerror(exerrval), lineno); - - ex_err(nullptr, nullptr, EX_PRTLASTMSG); - throw std::runtime_error(errmsg.str()); - } - template void populate_proc_node(size_t count, size_t offset, size_t element_nodes, const std::vector &elem_to_proc, const std::vector &glob_conn, @@ -310,42 +308,6 @@ namespace { return true; } -#if USE_METIS - int get_common_node_count(const Ioss::Region ®ion) - { - progress(__func__); - // Determine number of nodes that elements must share to be - // considered connected. A 8-node hex-only mesh would have 4 - // A 3D shell mesh should have 2. Basically, use the minimum - // number of nodes per side for all element blocks... Omit sphere - // elements; ignore bars(?)... - - int common_nodes = 999; - - const auto &ebs = region.get_element_blocks(); - for (const auto &eb : ebs) { - const Ioss::ElementTopology *topology = eb->topology(); - const Ioss::ElementTopology *boundary = topology->boundary_type(0); - if (boundary != nullptr) { - common_nodes = std::min(common_nodes, boundary->number_boundaries()); - } - else { - // Different topologies on some element faces... - size_t nb = topology->number_boundaries(); - for (size_t bb = 1; bb <= nb; bb++) { - boundary = topology->boundary_type(bb); - if (boundary != nullptr) { - common_nodes = std::min(common_nodes, boundary->number_boundaries()); - } - } - } - } - - common_nodes = std::max(1, common_nodes); - fmt::print(stderr, "Setting common_nodes to {}\n", common_nodes); - return common_nodes; - } -#endif } // namespace // ======================================================================== @@ -457,460 +419,6 @@ int main(int argc, char *argv[]) namespace { - template - void create_adjacency_list(const Ioss::Region ®ion, std::vector &pointer, - std::vector &adjacency, INT) - { - progress(__func__); - // Size of pointer list is element count + 1; - // Size of adjacency list is sum of nodes-per-element for each element. - size_t sum = 0; - size_t count = 0; - const auto &ebs = region.get_element_blocks(); - for (const auto &eb : ebs) { - size_t element_count = eb->entity_count(); - size_t element_nodes = eb->topology()->number_nodes(); - sum += element_count * element_nodes; - count += element_count; - } - - pointer.reserve(count + 1); - adjacency.reserve(sum); - fmt::print(stderr, "\tAdjacency Size = {} for {} elements.\n", fmt::group_digits(sum), - fmt::group_digits(count)); - - // Now, iterate the blocks again, get connectivity and build adjacency structure. - std::vector connectivity; - for (const auto &eb : ebs) { - eb->get_field_data("connectivity_raw", connectivity); - size_t element_count = eb->entity_count(); - size_t element_nodes = eb->topology()->number_nodes(); - - size_t el = 0; - for (size_t j = 0; j < element_count; j++) { - pointer.push_back(adjacency.size()); - for (size_t k = 0; k < element_nodes; k++) { - INT node = connectivity[el++] - 1; - adjacency.push_back(node); - } - } - } - pointer.push_back(adjacency.size()); - assert(pointer.size() == count + 1); - assert(adjacency.size() == sum); - } - - template - void decompose_elements(const Ioss::Region ®ion, SystemInterface &interFace, - std::vector &elem_to_proc, IOSS_MAYBE_UNUSED INT dummy) - { - progress(__func__); - // Populate the 'elem_to_proc' vector with a mapping from element to processor. - - size_t element_count = region.get_property("element_count").get_int(); - size_t elem_per_proc = element_count / interFace.processor_count(); - size_t extra = element_count % interFace.processor_count(); - - elem_to_proc.reserve(element_count); - - fmt::print(stderr, "\nDecomposing {} elements across {} processors using method '{}'.\n", - fmt::group_digits(element_count), fmt::group_digits(interFace.processor_count()), - interFace.decomposition_method()); - if (interFace.lineDecomp_) { - fmt::print(stderr, "\tDecomposition will be modified to put element lines/chains/columns on " - "same processor rank\n"); - } - - if (interFace.outputDecompMap_) { - fmt::print(stderr, "\tDecomposition will be output to an element map named '{}'.\n", - interFace.decomposition_variable()); - } - if (interFace.outputDecompField_) { - fmt::print(stderr, "\tDecomposition will be output to an element field named '{}'.\n", - interFace.decomposition_variable()); - } - fmt::print(stderr, "\n"); - - if (interFace.decomposition_method() == "linear") { - size_t elem_beg = 0; - for (size_t proc = 0; proc < interFace.processor_count(); proc++) { - size_t add = (proc < extra) ? 1 : 0; - size_t elem_end = elem_beg + elem_per_proc + add; - - for (size_t elem = elem_beg; elem < elem_end; elem++) { - elem_to_proc.push_back(proc); - } - elem_beg = elem_end; - } - } - else if (interFace.decomposition_method() == "scattered") { - // Scattered... - size_t proc = 0; - for (size_t elem = 0; elem < element_count; elem++) { - elem_to_proc.push_back(proc++); - if (proc >= interFace.processor_count()) { - proc = 0; - } - } - } - - else if (interFace.decomposition_method() == "rb" || - interFace.decomposition_method() == "kway") { -#if USE_METIS - std::vector pointer; - std::vector adjacency; - - double start = seacas_timer(); - create_adjacency_list(region, pointer, adjacency, dummy); - double end = seacas_timer(); - fmt::print(stderr, "\tCreate Adjacency List = {:.5}\n", end - start); - - // Call Metis to get the partition... - { - start = seacas_timer(); - idx_t elem_count = element_count; - idx_t common = get_common_node_count(region); - idx_t proc_count = interFace.processor_count(); - idx_t obj_val = 0; - std::vector options((METIS_NOPTIONS)); - METIS_SetDefaultOptions(&options[0]); - if (interFace.decomposition_method() == "kway") { - options[METIS_OPTION_PTYPE] = METIS_PTYPE_KWAY; - } - else { - options[METIS_OPTION_PTYPE] = METIS_PTYPE_RB; - } - - options[METIS_OPTION_OBJTYPE] = METIS_OBJTYPE_CUT; - if (interFace.contiguous_decomposition()) { - options[METIS_OPTION_CONTIG] = 1; - } - options[METIS_OPTION_DBGLVL] = 2; - options[METIS_OPTION_MINCONN] = 1; - - idx_t node_count = region.get_property("node_count").get_int(); - std::vector node_partition(node_count); - std::vector elem_partition(element_count); - - fmt::print(stderr, "\tCalling METIS Decomposition routine.\n"); - - METIS_PartMeshDual(&elem_count, &node_count, &pointer[0], &adjacency[0], nullptr, nullptr, - &common, &proc_count, nullptr, &options[0], &obj_val, &elem_partition[0], - &node_partition[0]); - - Ioss::Utils::clear(node_partition); - elem_to_proc.reserve(element_count); - std::copy(elem_partition.begin(), elem_partition.end(), std::back_inserter(elem_to_proc)); - - end = seacas_timer(); - fmt::print(stderr, "\tMETIS Partition = {:.5}\n", end - start); - fmt::print(stderr, "Objective value = {}\n", obj_val); - - // TODO Check Error... - } -#else - fmt::print(stderr, "ERROR: Metis library not enabled in this version of slice.\n" - " The 'rb' and 'kway' methods are not available.\n\n"); - std::exit(1); -#endif - } - - else if (interFace.decomposition_method() == "random") { - // Random... Use scattered method and then random_shuffle() the vector. - // Ensures that each processor has correct number of elements, but - // they are randomly distributed. - size_t proc = 0; - for (size_t elem = 0; elem < element_count; elem++) { - elem_to_proc.push_back(proc++); - if (proc >= interFace.processor_count()) { - proc = 0; - } - } - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(elem_to_proc.begin(), elem_to_proc.end(), g); - } - - else if (interFace.decomposition_method() == "variable") { - const std::string &elem_variable = interFace.decomposition_variable(); - if (elem_variable.empty()) { - fmt::print(stderr, "\nERROR: No element decomposition variable specified.\n"); - exit(EXIT_FAILURE); - } - // Get all element blocks and cycle through each reading the - // values for the processor... - const auto &blocks = region.get_element_blocks(); - auto *c_region = (Ioss::Region *)(®ion); - c_region->begin_state(1); - for (const auto &block : blocks) { - if (!block->field_exists(elem_variable)) { - fmt::print(stderr, "\nERROR: Element variable '{}' does not exist on block {}.\n", - elem_variable, block->name()); - exit(EXIT_FAILURE); - } - std::vector tmp_vals; - block->get_field_data(elem_variable, tmp_vals); - auto block_count = block->entity_count(); - for (int64_t i = 0; i < block_count; i++) { - elem_to_proc.push_back((int)tmp_vals[i]); - } - } - } - else if (interFace.decomposition_method() == "map") { - std::string map_name = interFace.decomposition_variable(); - if (map_name.empty()) { - fmt::print(stderr, "\nERROR: No element decomposition map specified.\n"); - exit(EXIT_FAILURE); - } - - // If the "map_name" string contains a comma, then the value - // following the comma is either an integer "scale" which is - // divided into each entry in `elem_to_proc`, or it is the - // string "auto" which will automatically scale all values by - // the *integer* "max/processorCount" - // - // NOTE: integer division with *no* rounding is used. - - int iscale = 1; - auto pos = map_name.find(","); - if (pos != std::string::npos) { - // Extract the string following the comma... - auto scale = map_name.substr(pos + 1); - if (scale == "AUTO" || scale == "auto") { - iscale = 0; - } - else { - iscale = std::stoi(scale); - } - } - map_name = map_name.substr(0, pos); - - Ioss::DatabaseIO *db = region.get_database(); - int exoid = db->get_file_pointer(); - - bool map_read = false; - int map_count = ex_inquire_int(exoid, EX_INQ_ELEM_MAP); - if (map_count > 0) { - int max_name_length = ex_inquire_int(exoid, EX_INQ_DB_MAX_USED_NAME_LENGTH); - max_name_length = max_name_length < 32 ? 32 : max_name_length; - char **names = Ioss::Utils::get_name_array(map_count, max_name_length); - int error = ex_get_names(exoid, EX_ELEM_MAP, names); - if (error < 0) { - exodus_error(__LINE__); - } - - for (int i = 0; i < map_count; i++) { - if (case_compare(names[i], map_name.c_str()) == 0) { - elem_to_proc.resize(element_count); - error = ex_get_num_map(exoid, EX_ELEM_MAP, i + 1, elem_to_proc.data()); - if (error < 0) { - exodus_error(__LINE__); - } - map_read = true; - break; - } - } - Ioss::Utils::delete_name_array(names, map_count); - } - - if (!map_read) { - fmt::print(stderr, "\nERROR: Element decomposition map '{}' could not be read from file.\n", - map_name); - exit(EXIT_FAILURE); - } - - // Do the scaling (integer division...) - if (iscale == 0) { - // Auto scaling was asked for. Determine max entry in `elem_to_proc` and - // set the scale factor. - auto max_proc = *std::max_element(elem_to_proc.begin(), elem_to_proc.end()); - - iscale = (max_proc + 1) / interFace.processor_count(); - fmt::print(" Element Processor Map automatic scaling factor = {}\n", iscale); - - if (iscale == 0) { - fmt::print(stderr, - "ERROR: Max value in element processor map is {} which is\n" - "\tless than the processor count ({}). Scaling values is not possible.", - max_proc, interFace.processor_count()); - exit(EXIT_FAILURE); - } - } - std::transform(elem_to_proc.begin(), elem_to_proc.end(), elem_to_proc.begin(), - [iscale](int p) { return p / iscale; }); - } - else if (interFace.decomposition_method() == "file") { - // Read the element decomposition mapping from a file. The - // syntax of the file is an optional element count followed by - // the processor for this range. If the element range is - // omitted, then the processor applies to the next element in - // the sequence. All elements must be specified or an error will - // be raised. - // - // Example: - // 0 - // 100 1 - // 0 - // - // Will assign: - // * element 1 to processor 0; - // * followed by the next 100 elements (2 to 101) to processor 1; - // * followed by the next element (102) to processor 0. - // - // The resulting decomposition will have 2 elements (1, 102) on - // processor 0 and 100 elements (2..101) on processor 1. - - const std::string &filename = interFace.decomposition_file(); - if (filename.empty()) { - fmt::print(stderr, "\nERROR: No element decomposition file specified.\n"); - exit(EXIT_FAILURE); - } - - std::ifstream decomp_file(filename, std::ios::in); - if (!decomp_file.good()) { - fmt::print( - stderr, - "\nERROR: Element decomposition file '{}' does not exist or could not be opened.\n", - filename); - exit(EXIT_FAILURE); - } - - std::string line; - size_t line_num = 0; - while (std::getline(decomp_file, line)) { - line_num++; - // See if 1 or 2 tokens on line... - std::vector tokens; - tokens = SLIB::tokenize(line, ", \t"); - size_t proc = 0; - size_t count = 1; - if (tokens.empty()) { - break; - } - if (tokens.size() == 1) { - // Just a processor specification for the next element... - proc = std::stoi(tokens[0]); - elem_to_proc.push_back(proc); - } - else { - // Count and processor specified. - count = std::stoi(tokens[0]); - proc = std::stoi(tokens[1]); - } - if (proc > interFace.processor_count()) { - fmt::print(stderr, - "\nERROR: Invalid processor {} specified on line {} of decomposition file.\n" - "\tValid range is 0..{}\n", - fmt::group_digits(proc), fmt::group_digits(line_num), - fmt::group_digits(interFace.processor_count() - 1)); - exit(EXIT_FAILURE); - } - - if (elem_to_proc.size() + count > element_count) { - fmt::print(stderr, - "\nERROR: The processor specification on line {}" - " of the decomposition file results in too many elements being specified.\n" - "\tThe total number of elements in the model is {}\n" - "\tPrior to this line, {} elements were specified.\n" - "\tIncluding this line, {} elements will be specified.\n", - fmt::group_digits(line_num), fmt::group_digits(element_count), - fmt::group_digits(elem_to_proc.size()), - fmt::group_digits(elem_to_proc.size() + count)); - exit(EXIT_FAILURE); - } - - for (size_t i = 0; i < count; i++) { - elem_to_proc.push_back(proc); - } - } - } - assert(elem_to_proc.size() == element_count); - } - - template - void line_decomp_modify(const Ioss::chain_t &element_chains, std::vector &elem_to_proc, - int proc_count, INT /* dummy */) - { - // Get a map of all chains and the elements in the chains. Map key will be root. - std::map> chains; - - for (size_t i = 0; i < element_chains.size(); i++) { - auto &chain_entry = element_chains[i]; - chains[chain_entry.element].push_back(i + 1); - if ((debug_level & 16) != 0) { - fmt::print("[{}]: element {}, link {}, processor {}\n", i + 1, chain_entry.element, - chain_entry.link, elem_to_proc[i]); - } - } - - // Delta: elements added/removed from each processor... - std::vector delta(proc_count); - - // Now, for each chain... - for (auto &chain : chains) { - if ((debug_level & 16) != 0) { - fmt::print("Chain Root: {} contains: {}\n", chain.first, fmt::join(chain.second, ", ")); - } - - std::vector chain_proc_count(proc_count); - const auto &chain_elements = chain.second; - - // * get processors used by elements in the chain... - for (const auto &element : chain_elements) { - auto proc = elem_to_proc[element - 1]; - chain_proc_count[proc]++; - } - - // * Now, subtract the `delta` from each count - for (int i = 0; i < proc_count; i++) { - chain_proc_count[i] -= delta[i]; - } - - // * Find the maximum value in `chain_proc_count` - auto max = std::max_element(chain_proc_count.begin(), chain_proc_count.end()); - auto max_proc = std::distance(chain_proc_count.begin(), max); - - // * Assign all elements in the chain to `max_proc`. - // * Update the deltas for all processors that gain/lose elements... - for (const auto &element : chain_elements) { - if (elem_to_proc[element - 1] != max_proc) { - auto old_proc = elem_to_proc[element - 1]; - elem_to_proc[element - 1] = max_proc; - delta[max_proc]++; - delta[old_proc]--; - } - } - } - - std::vector proc_element_count(proc_count); - for (auto proc : elem_to_proc) { - proc_element_count[proc]++; - } - if ((debug_level & 16) != 0) { - fmt::print("\nElements/Processor: {}\n", fmt::join(proc_element_count, ", ")); - fmt::print("Delta/Processor: {}\n", fmt::join(delta, ", ")); - } - } - - template - void free_connectivity_storage(std::vector>> &connectivity, - size_t proc_begin, size_t proc_size) - { - progress(__func__); - for (size_t p = proc_begin; p < proc_begin + proc_size; p++) { - size_t block_count = connectivity[p].size(); - for (size_t b = 0; b < block_count; b++) { - Ioss::Utils::clear(connectivity[p][b]); - } - Ioss::Utils::clear(connectivity[p]); - } - - size_t processor_count = connectivity.size(); - if (proc_begin + proc_size == processor_count) { - Ioss::Utils::clear(connectivity); - } - } - template void get_sidesets(const Ioss::Region ®ion, std::vector &proc_region, const std::vector &elem_to_proc, INT /*dummy*/) @@ -1779,7 +1287,7 @@ namespace { } } for (size_t p = 0; p < proc_count; p++) { - Ioss::NodeBlock *nb = + auto *nb = new Ioss::NodeBlock(proc_region[p]->get_database(), "node_block1", on_proc_count[p], 3); proc_region[p]->add(nb); if (debug_level & 2) { @@ -1857,43 +1365,27 @@ namespace { } bool ints64 = (sizeof(INT) == 8); - Ioss::PropertyManager properties; - if (interFace.netcdf4_) { - properties.add(Ioss::Property("FILE_TYPE", "netcdf4")); - } - - if (interFace.netcdf5_) { - properties.add(Ioss::Property("FILE_TYPE", "netcdf5")); - } - - if (interFace.compressionLevel_ > 0 || interFace.shuffle_ || interFace.szip_) { - properties.add(Ioss::Property("FILE_TYPE", "netcdf4")); - properties.add(Ioss::Property("COMPRESSION_LEVEL", interFace.compressionLevel_)); - properties.add(Ioss::Property("COMPRESSION_SHUFFLE", static_cast(interFace.shuffle_))); - if (interFace.szip_) { - properties.add(Ioss::Property("COMPRESSION_METHOD", "szip")); - } - else if (interFace.zlib_) { - properties.add(Ioss::Property("COMPRESSION_METHOD", "zlib")); - } - } - - if (interFace.ints64Bit_) { - properties.add(Ioss::Property("INTEGER_SIZE_DB", 8)); - properties.add(Ioss::Property("INTEGER_SIZE_API", 8)); - } + Ioss::PropertyManager properties = set_properties(interFace); double start = seacas_timer(); std::vector elem_to_proc; decompose_elements(region, interFace, elem_to_proc, dummy); double end = seacas_timer(); fmt::print(stderr, "Decompose elements = {:.5}\n", end - start); + progress("exit decompose_elements"); Ioss::chain_t element_chains; if (interFace.lineDecomp_) { element_chains = Ioss::generate_element_chains(region, interFace.lineSurfaceList_, debug_level, dummy); - line_decomp_modify(element_chains, elem_to_proc, interFace.processor_count(), dummy); + progress("Ioss::generate_element_chains"); + line_decomp_modify(element_chains, elem_to_proc, interFace.processor_count()); + progress("line_decomp_modify"); + } + + if (debug_level & 32) { + output_decomposition_statistics(elem_to_proc, interFace.processor_count(), + elem_to_proc.size()); } if (!create_split_files) { @@ -1902,6 +1394,9 @@ namespace { if (dbo == nullptr || !dbo->ok(true)) { std::exit(EXIT_FAILURE); } + if (ints64) { + dbo->set_int_byte_size_api(Ioss::USE_INT64_API); + } // NOTE: 'output_region' owns 'dbo' pointer at this time Ioss::Region output_region(dbo, "region_2"); @@ -1928,6 +1423,7 @@ namespace { add_decomp_map(output_region, interFace.decomposition_variable(), line_decomp); output_decomp_map(output_region, elem_to_proc, element_chains, interFace.decomposition_variable(), line_decomp); + progress("output_decomp_map"); } if (interFace.outputDecompField_) { @@ -1935,6 +1431,7 @@ namespace { add_decomp_field(output_region, interFace.decomposition_variable(), line_decomp); output_decomp_field(output_region, elem_to_proc, element_chains, interFace.decomposition_variable(), line_decomp); + progress("output_decomp_field"); } return; @@ -2072,10 +1569,10 @@ namespace { end = seacas_timer(); fmt::print(stderr, "\tCommunication map Output = {:.5}\n", end - start); + start = seacas_timer(); output_connectivity(region, proc_region, elem_to_proc, proc_begin, proc_size, (INT)1); end = seacas_timer(); - - fmt::print(stderr, "Connectivity Output = {:.5}\n", end - start); + fmt::print(stderr, "\tConnectivity Output = {:.5}\n", end - start); start = seacas_timer(); #if 0 @@ -2100,7 +1597,10 @@ namespace { fmt::print(stderr, "\tSideset Output = {:.5}\n", end - start); if (interFace.lineDecomp_) { + start = seacas_timer(); output_chain_maps(proc_region, element_chains, elem_to_proc, proc_begin, proc_size, (INT)0); + end = seacas_timer(); + fmt::print(stderr, "\tChain Map Output = {:.5}\n", end - start); } // Close all files... @@ -2144,4 +1644,5 @@ namespace { filename = tmp; } } + } // namespace diff --git a/packages/seacas/applications/slice/cmake/Dependencies.cmake b/packages/seacas/applications/slice/cmake/Dependencies.cmake index 253b734110..c38922d3f5 100644 --- a/packages/seacas/applications/slice/cmake/Dependencies.cmake +++ b/packages/seacas/applications/slice/cmake/Dependencies.cmake @@ -1,4 +1,5 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( LIB_REQUIRED_PACKAGES SEACASExodus SEACASIoss SEACASSuplibC SEACASSuplibCpp + LIB_OPTIONAL_PACKAGES Zoltan LIB_OPTIONAL_TPLS METIS ) diff --git a/packages/seacas/applications/zellij/Cell.C b/packages/seacas/applications/zellij/Cell.C index 3d67a38282..20841364e8 100644 --- a/packages/seacas/applications/zellij/Cell.C +++ b/packages/seacas/applications/zellij/Cell.C @@ -260,8 +260,7 @@ size_t Cell::processor_boundary_node_count() const // Iterate `ranks` and for each rank, "color" the `bnd_nodes` that that rank touches... // Skip center. size_t b_count = 0; - for (int i = 0; i < (int)ranks.size(); i++) { - auto the_rank = ranks[i]; + for (auto the_rank : ranks) { if (the_rank == rank(Loc::C)) { continue; } diff --git a/packages/seacas/applications/zellij/CustomDoxygen.css b/packages/seacas/applications/zellij/CustomDoxygen.css new file mode 100644 index 0000000000..0d96812b42 --- /dev/null +++ b/packages/seacas/applications/zellij/CustomDoxygen.css @@ -0,0 +1,619 @@ + +/* function descriptions */ +.memtitle { + padding: 8px; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url(); + background-repeat: repeat-x; + background-color: #fff; + line-height: 1.25; + font-weight: 600; + float: left; +} + +dt { + font-weight: 600; +} + +p.reference, p.definition { + font: 400 14px/22px -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;; + margin-top: 0px; + margin-bottom: 5px; + padding-top: 8px; + border-top: 1px solid #eee; +} + +/* parameter names */ +.params .paramname, .retval .paramname, .tparams .paramname { + font-weight: 600; + vertical-align: top; +} + +/* parameter data types */ +.paramtype { + white-space: nowrap; + color: #008141; +} + +/* headers */ +h1, h2, h3, h4, h5, h6 { + font-weight: 600; +} + +/* parameter names */ +.paramname { + color: #db0303; + white-space: nowrap; +} + +/* overall style */ +body, table, div, p, dl { + font-style: normal; + font-variant-ligatures: normal; + font-variant-caps: normal; + font-variant-numeric: normal; + font-variant-east-asian: normal; + font-weight: 500; + font-stretch: normal; + font-size: 14px; + line-height: 22px; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} + +/* project name */ +#projectname { + /* markdown font */ + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + margin: 0; + padding: 2px 0; +} +/* title area */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} + +h2.groupheader { + border-bottom: 1px solid #eee; + color: #000; + font-size: 150%; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + margin-top: 1em; + padding-top: 12px; + padding-bottom: 4px; + width: 100%; +} + +/* function description text box */ +.memdoc, dl.reflist dd { + + border-bottom: none; + border-left: none; + border-right: none; + padding: 0px 10px 0px 10px; + background-color: #FFF; + border-top-width: 0; + background-image: none; + background-repeat: repeat-x; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0) 5px 5px 5px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); +} + +/* function prototype text box */ +.memproto, dl.reflist dt { + border-bottom: 1px solid #999; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 0px 0 0px 0; + color: #000; + font-weight: bold; + text-shadow: none; + background-color: #f9f9f9; + box-shadow: none; + border-top-right-radius: 4px; + -moz-box-shadow: none; + -moz-border-radius-topright: 4px; + -webkit-box-shadow: none; + -webkit-border-top-right-radius: 4px; +} + +/* function prototype */ +.memname td { + + vertical-align: bottom; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + +} + + +/* icon for each data type */ +.icon { + background-color: #026ea1; +} +/* arrows for treenav */ + +.arrow { + color: #09A716; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} +/* colors and fonts for description pages */ + +table, div, p, dl { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: black; +} + +.sm li, .sm a { + position: relative; + color: black; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: #FFF; + min-height: 100%; + overflow-x: hidden; + background: #fff; +} + +/* file member function descriptions */ +.memberdecls td, .fieldtable tr { + + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 501; +} + +/* function descriptor */ +td.mdescLeft, td.mdescRight { + padding: 0 8px 4px 8px; + color: #000; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 400; +} + +/* headers for #include descriptions */ +tt, code, kbd, samp { + display: inline-block; + direction: ltr; + background-color: #f8f8f8; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* list for file members */ +div.contents { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* links to a class or struct on the class list page */ +a.el { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* header dividers */ +hr { + height: 0; + border: none; + border-top: 1px solid #eee; +} + +#side-nav { + padding: 0 0 0 0; + margin: 0; + display: block; + position: absolute; + left: 0; + width: 250; +} +/* nav tree arrow symbol */ + +#nav-sync img { + opacity: 0; +} +#nav-sync img:hover { + opacity: 0.9; +} +/* The main page button */ + +.sm-dox>li:first-child>a, .sm-dox>li:first-child> :not(ul) a { + padding-right: 12px; +} +/* content of for all class members list */ + +#doc-content { + overflow: auto; + display: block; + padding: 0; + margin: 0; + margin-left: 0; + -webkit-overflow-scrolling: touch; + background-color: #FFF; +} +/* label for which tree menu you are on (displays in the doc menu */ + +.title { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + font-size: 150%; + margin: -2px 0 0 2px; + background-color: white; +} +/* title for each section (class List, Class index) */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} +/* title for each section (class List, Class index) */ + +div.headertitle { + padding: none; + background-color: white; +} +/* actual header for each section */ + +div.header { + background-image: none; + background-repeat: repeat-x; + background-color: #FFF; + margin: 0; + border-bottom: 1px solid #eee; +} +/* for class and function lists */ + +table.directory { + font-style: normal; + font-variant-caps: normal; + font-weight: normal; + font-stretch: normal; + line-height: normal; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-size-adjust: none; + font-kerning: auto; + font-optical-sizing: auto; + font-variant-alternates: normal; + font-variant-east-asian: normal; + font-variant-ligatures: normal; + font-variant-numeric: normal; + font-variant-position: normal; + font-language-override: normal; + font-feature-settings: normal; + font-variation-settings: normal; +} +/* main page, classes, files banner */ + +.sm-dox { + padding: 0 0; + background-image: none; + line-height: 36px; + background-color: #7fbdff; +} +/* item list on botton left */ + +.navpath li.navelem a { + height: 32px; + display: block; + text-decoration: none; + outline: none; + color: #FFF; + font-family: 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; + text-shadow: none; + text-decoration: none; +} +.navpath li { + list-style-type: none; + float: left; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #364D7C; +} +/* top menu, Classes button */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:active, .sm-dox a.highlighted, .sm-dox a.highlighted { + padding-right: 12px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + background-color: #7fbdff; + color: #b8b8b8; + padding-left: 12px; +} + +.sm-dox a.has-submenu { + padding-right: 24px; +} + +.sm a { + display: block; +} +/* top menu, main buttons label */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:visited, .sm-dox a:visited { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + color: #000; + text-shadow: none; +} +/* hover over class/main page, files buttons */ + +.sm-dox a:hover { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + text-decoration: none; + text-decoration-line: none; + text-decoration-style: solid; + text-decoration-color: currentcolor; + text-shadow: none; + color: #FFF; + outline: 0; + outline-color: currentcolor; + outline-style: none; + outline-width: 0; + background-color: #156ac9; + background-image: none; +} + +.sm-dox ul a:hover { + background-image: none; + background-repeat: repeat-x; + color: white; + background-color: #000; + text-shadow: none; +} + +/* top list items */ + +.sm-dox ul { + color: #FFF; + border-top-color: rgb(187, 187, 187); + border-top-style: solid; + border-top-width: 1px; + border-right-color: rgb(187, 187, 187); + border-right-style: solid; + border-right-width: 1px; + border-bottom-color: rgb(187, 187, 187); + border-bottom-style: solid; + border-bottom-width: 1px; + border-left-color: rgb(187, 187, 187); + border-left-style: solid; + border-left-width: 1px; + border-image-outset: 0; + border-image-repeat: stretch; + border-image-slice: 100%; + border-image-source: none; + border-image-width: 1; + padding: 5px 0; + background: #fff; + background-color: rgb(255, 255, 255); + background-position-x: 0%; + background-position-y: 0%; + background-repeat: repeat; + background-attachment: scroll; + background-image: none; + background-size: auto; + background-origin: padding-box; + background-clip: border-box; + -moz-border-radius: 5px !important; + -webkit-border-radius: 5px; + border-radius: 5px !important; + -moz-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); +} +.sm-dox ul a:hover { + background-image: none; +} +/* dividers for class/function lists */ + +div.directory { + margin: 10px 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + width: 100%; +} +/* for navigation tree links */ + +#nav-tree .label a { + padding-top: 1px; + padding-right: 1px; + padding-bottom: 1px; + margin-left: 12px; + color: #FFF; + font-weight: 700; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} +/* hovering over tree view items */ + +#nav-tree .label a:hover { + padding-top: 2px; + padding-right: 2px; + padding-bottom: -3px; + margin-left: 12px; + color: #000; + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; + background-color: #FFF +} +/* nav tree labels */ + +#nav-tree .label { + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; +} +/* still for the navtree, but not labels */ + +#nav-tree { + padding: 0 0; + background-color: #404040; + font-size: normal; + overflow: auto; + background-image: none; + margin-right: 16px; +} + +span.lineno { + background-color: #f7f7f7; +} + +a { + color: #4d95c4; +} + +span.lineno a { + background-color: #e6e5e5; +} + +div.fragment { + padding: 0 0 1px 0; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #eee; +} + +.permalink { + color: #476092; + font-size: 85%; +} + +/* selected nav tree */ +#nav-tree .selected { + background-image: none; + background-repeat: repeat-x; + color: #fff; + background-color: #000; +} +/* selected nav tree link */ + +#nav-tree .selected a { + background-image: none; + background-repeat: repeat-x; + color: #fff; +} +/* visited nav tree link */ + +#nav-tree .visited a { + background-image: none; + background-repeat: repeat-x; + color: #127FCF; +} +/* bar separator for tree view */ + +.ui-resizable-e { + background-image: none; + background-size: 100%; + background-repeat: repeat-y; + background-attachment: scroll; + cursor: ew-resize; + height: 100%; + right: 0; + top: 0; + width: 0; + background-color: black; +} +/* visited links in general */ + +a:visited { + color: #4d95c4; +} +/* bottom bar */ + +a.code, a.code:visited, a.line, a.line:visited { + color: #4d95c4; +} + +.contents a:visited { + color: #4d95c4; +} + +.navpath ul { + font-size: 11px; + background-image: none; + background-repeat: repeat-x; + background-position: 0 -5px; + height: 30px; + line-height: 30px; + color: #fff; + border: none; + overflow: hidden; + margin: 0; + padding: 0; + background-color: #181818; +} +/* text 'Generated by doxygen' */ + +.navpath li.footer { + list-style-type: none; + float: right; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #FFF; + font-size: 8pt; +} + +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 400; + src: url("../fonts/RobotoSlab/roboto-slab.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype") +} +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 700; + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype") +} diff --git a/packages/seacas/applications/zellij/Doxyfile b/packages/seacas/applications/zellij/Doxyfile index 082e1685d0..e2cf609b5a 100644 --- a/packages/seacas/applications/zellij/Doxyfile +++ b/packages/seacas/applications/zellij/Doxyfile @@ -1353,7 +1353,7 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = CustomDoxygen.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note diff --git a/packages/seacas/applications/zellij/UnitCell.C b/packages/seacas/applications/zellij/UnitCell.C index a1a2f96dbf..0f69d03275 100644 --- a/packages/seacas/applications/zellij/UnitCell.C +++ b/packages/seacas/applications/zellij/UnitCell.C @@ -48,8 +48,9 @@ namespace { // Check if the numbers are really close -- needed // when comparing numbers near zero. double diff = std::abs(A - B); - if (diff <= maxDiff) + if (diff <= maxDiff) { return true; + } A = std::abs(A); B = std::abs(B); diff --git a/packages/seacas/applications/zellij/ZE_SystemInterface.C b/packages/seacas/applications/zellij/ZE_SystemInterface.C index 8f8ffb2aaa..5fd3bdb319 100644 --- a/packages/seacas/applications/zellij/ZE_SystemInterface.C +++ b/packages/seacas/applications/zellij/ZE_SystemInterface.C @@ -293,7 +293,7 @@ bool SystemInterface::parse_options(int argc, char **argv) "\t{}\n\n", options); } - options_.parse(options, options_.basename(*argv)); + options_.parse(options, Ioss::GetLongOption::basename(*argv)); } outputName_ = options_.get_option_value("output", outputName_); diff --git a/packages/seacas/cmake/Dependencies.cmake b/packages/seacas/cmake/Dependencies.cmake index 34a816c0e2..3b1b3d6598 100644 --- a/packages/seacas/cmake/Dependencies.cmake +++ b/packages/seacas/cmake/Dependencies.cmake @@ -42,7 +42,7 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( Nemslice applications/nem_slice PT OPTIONAL Nemspread applications/nem_spread PT OPTIONAL Numbers applications/numbers PT OPTIONAL - Slice applications/slice ST OPTIONAL + Slice applications/slice PT OPTIONAL Txtexo applications/txtexo PT OPTIONAL Ex2ex1v2 applications/ex2ex1v2 PT OPTIONAL ) diff --git a/packages/seacas/cmake/tpls/FindTPLADIOS2.cmake b/packages/seacas/cmake/tpls/FindTPLADIOS2.cmake index f8a9497be7..bddbe96e9c 100644 --- a/packages/seacas/cmake/tpls/FindTPLADIOS2.cmake +++ b/packages/seacas/cmake/tpls/FindTPLADIOS2.cmake @@ -80,7 +80,7 @@ ENDIF() # TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( ADIOS2 REQUIRED_HEADERS adios2.h - REQUIRED_LIBS_NAMES adios2 + REQUIRED_LIBS_NAMES adios2_cxx11_mpi,adios2_cxx11,adios2_core_mpi,adios2_core ) # NOTE: If FIND_PACKAGE(ADIOS2 ...) was called and successfully found ADIOS2, then diff --git a/packages/seacas/doc-source/aprepro/Aprepro.tex b/packages/seacas/doc-source/aprepro/Aprepro.tex index 87dd169357..b84bf46088 100644 --- a/packages/seacas/doc-source/aprepro/Aprepro.tex +++ b/packages/seacas/doc-source/aprepro/Aprepro.tex @@ -119,5 +119,4 @@ \include{examples} \include{library} \include{references} -\include{endmatter} \end{document} diff --git a/packages/seacas/doc-source/aprepro/examples.tex b/packages/seacas/doc-source/aprepro/examples.tex index 18c31122db..b45640c53f 100644 --- a/packages/seacas/doc-source/aprepro/examples.tex +++ b/packages/seacas/doc-source/aprepro/examples.tex @@ -109,21 +109,23 @@ \section{Command Line Variable Assignment}\label{example:varval} \section{Loop Example} -This example illustrates the use of the loop construct to print a table of sines -and cosines from 0 to 90 degrees in 5 degree increments. +This example illustrates the use of the loop construct to print a +table of sines and cosines from 0 to 90 degrees in 5 degree +increments. + +Note the use of the double braces at the end of the first line to +suppress the output of the initialization of the \var{angle} variable. Input: \begin{apinp} \$ Test looping - print sin, cos from 0 to 90 by 5 -\{angle = -5\} -\{Loop(19)\} -\{angle += 5\} \{sind(angle)\} \{cosd(angle)\} +\{Loop(19, angle, 0, 5)\} +\{angle\} \{sind(angle)\} \{cosd(angle)\} \{EndLoop\} \end{apinp} Output: \begin{apout} \$ Test looping - print sin, cos from 0 to 90 by 5 --5 0 0 1 5 0.08715574275 0.9961946981 10 0.1736481777 0.984807753 @@ -209,48 +211,48 @@ \section{Aprepro Exodus Example} The input below illustrates the use of the \cmd{exodus\_meta} and \cmd{exodus\_info} functions. \begin{apinp} -\{exodus_meta("exodus.g")\} +\{exodus\_meta("exodus.g")\} - Title = \{ex_title\} - Dimension = \{ex_dimension\} - Node Count = \{ex_node_count\} -Element Count = \{ex_element_count\} + Title = \{ex\_title\} + Dimension = \{ex\_dimension\} + Node Count = \{ex\_node\_count\} +Element Count = \{ex\_element\_count\} Element Block Info: - Count = \{ex_block_count\} - Names = \{ex_block_names\} - Topology = \{ex_block_topology\} - Ids = \{print_array(transpose(ex_block_ids))\} -\{print_array(ex_block_info)\} + Count = \{ex\_block\_count\} + Names = \{ex\_block\_names\} + Topology = \{ex\_block\_topology\} + Ids = \{print\_array(transpose(ex\_block\_ids))\} +\{print\_array(ex\_block\_info)\} Nodeset Info: - Count = \{ex_nodeset_count\} - Names = \{ex_nodeset_names\} - Ids = \{print_array(transpose(ex_nodeset_ids))\} -\{print_array(ex_nodeset_info)\} + Count = \{ex\_nodeset\_count\} + Names = \{ex\_nodeset\_names\} + Ids = \{print\_array(transpose(ex\_nodeset\_ids))\} +\{print\_array(ex\_nodeset\_info)\} Sideset Info: - Count = \{ex_sideset_count\} - Names = \{ex_sideset_names\} - Ids = \{print_array(transpose(ex_sideset_ids))\} -\{print_array(ex_sideset_info)\} + Count = \{ex\_sideset\_count\} + Names = \{ex\_sideset\_names\} + Ids = \{print\_array(transpose(ex\_sideset\_ids))\} +\{print\_array(ex\_sideset\_info)\} Timestep Info: - Count = \{ex_timestep_count\} - Times = \{print_array(transpose(ex_timestep_times))\} + Count = \{ex\_timestep\_count\} + Times = \{print\_array(transpose(ex\_timestep\_times))\} -NOTE: Array index are 0-based by default; get_word is 1-based... \{i_=0\} -\{loop(ex_block_count)\} -Element block \{ex_block_ids[i_]\} named '\{get_word(++i_,ex_block_names,",")\}' has topology '\{get_word(i_,ex_block_topology,",")\}' +NOTE: Array index are 0-based by default; get\_word is 1-based... \{i\_=0\} +\{loop(ex\_block\_count)\} +Element block \{ex\_block\_ids[i\_]\} named '\{get\_word(++i\_,ex\_block\_names,",")\}' has topology '\{get\_word(i\_,ex\_block\_topology,",")\}' \{endloop\} Extract Information Records using begin \ldots end -\{info1 = exodus_info("exodus.g", "start extract", "end extract")\} +\{info1 = exodus\_info("exodus.g", "start extract", "end extract")\} Rescan String: \{rescan(info1)\} Extract Information Records using prefix and then rescan: -\{info2 = exodus_info("exodus.g", "PRE: ")\} +\{info2 = exodus\_info("exodus.g", "PRE: ")\} \{rescan(info2)\} \end{apinp} @@ -263,7 +265,7 @@ \section{Aprepro Exodus Example} Element Block Info: Count = 4 - Names = inner_core,Shell-MinX,Shell-MaxY,Shell-MinZ + Names = inner\_core,Shell-MinX,Shell-MaxY,Shell-MinZ Topology = hex8,shell4,shell4,shell4 Ids = 1 2 3 4 1 24 8 0 @@ -273,7 +275,7 @@ \section{Aprepro Exodus Example} Nodeset Info: Count = 3 - Names = nodelist_1,nodelist_2,nodelist_3 + Names = nodelist\_1,nodelist\_2,nodelist\_3 Ids = 1 2 3 1 20 20 2 15 15 @@ -281,7 +283,7 @@ \section{Aprepro Exodus Example} Sideset Info: Count = 6 - Names = surface_1,surface_2,surface_3,surface_4,surface_5,surface_6 + Names = surface\_1,surface\_2,surface\_3,surface\_4,surface\_5,surface\_6 Ids = 1 2 3 4 5 6 1 12 48 2 8 32 @@ -294,18 +296,20 @@ \section{Aprepro Exodus Example} Count = 7 Times = 0 1 2 3 4 5 6 -NOTE: Array index are 0-based by default; get_word is 1-based... 0 -Element block 1 named 'inner_core' has topology 'hex8' +NOTE: Array index are 0-based by default; get\_word is 1-based... 0 +Element block 1 named 'inner\_core' has topology 'hex8' Element block 2 named 'Shell-MinX' has topology 'shell4' Element block 3 named 'Shell-MaxY' has topology 'shell4' Element block 4 named 'Shell-MinZ' has topology 'shell4' Extract Information Records using begin \ldots end +\ldots(The next three lines are the "raw" info records) {loop(6)} -{a_++^2} +{a\_++^2} {endloop} Rescan String: +\ldots(This shows the "rescanned" info records) 0 1 4 @@ -314,9 +318,8 @@ \section{Aprepro Exodus Example} 25 Extract Information Records using prefix and then rescan: -{ECHO(OFF)} -{Units("si")} -{ECHO(ON)} +\ldots(The next seven lines are the "raw" info records) +{{Units("si")}} 1 foot = {1~foot} {lout} 12 inch = {12~inch} {lout} 1728 in^3 = {1728~in^3} {Vout} @@ -324,6 +327,7 @@ \section{Aprepro Exodus Example} 60 mph = {60~mph} {vout} 88 fps = {88~fps} {vout} +\ldots (this is the output from the "rescanned" info records) 1 foot = 0.3048 meter 12 inch = 0.3048 meter 1728 in^3 = 0.02831684659 meter^3 @@ -344,19 +348,19 @@ \section{Aprepro Test File Example} \{1\} \{10E-1\} \{10.E-1\} \{.1E+1\} \{.1E1\} Test assign statements: -\{_a = 5\} \{b=_a\} $ Should print 5 5 -\{_a +=b\} \{_a\} $ Should print 10 10 -\{_a -=b\} \{_a\} $ Should print 5 5 -\{_a *=b\} \{_a\} $ Should print 25 25 -\{_a /=b\} \{_a\} $ Should print 5 5 -\{_a ^=b\} \{_a\} $ Should print 3125 3125 -\{_a = b\} \{_a**=b\} \{_a\} $ Should print 5 3125 3125 +\{\_a = 5\} \{b=\_a\} $ Should print 5 5 +\{\_a +=b\} \{\_a\} $ Should print 10 10 +\{\_a -=b\} \{\_a\} $ Should print 5 5 +\{\_a *=b\} \{\_a\} $ Should print 25 25 +\{\_a /=b\} \{\_a\} $ Should print 5 5 +\{\_a ^=b\} \{\_a\} $ Should print 3125 3125 +\{\_a = b\} \{\_a**=b\} \{\_a\} $ Should print 5 3125 3125 Test trigonometric functions (radians) \{pi = d2r(180)\} \{atan2(0,-1)\} \{4*atan(1.0)\} $ Three values of pi -\{_a = sin(pi/4)\} \{pi-4*asin(_a)\} $ sin(pi/4) -\{_b = cos(pi/4)\} \{pi-4*acos(_b)\} $ cos(pi/4) -\{_c = tan(pi/4)\} \{pi-4*atan(_c)\} $ tan(pi/4) +\{\_a = sin(pi/4)\} \{pi-4*asin(\_a)\} $ sin(pi/4) +\{\_b = cos(pi/4)\} \{pi-4*acos(\_b)\} $ cos(pi/4) +\{\_c = tan(pi/4)\} \{pi-4*atan(\_c)\} $ tan(pi/4) Test trigonometric functions (degrees) \{r2d(pi)\} \{pid = atan2d(0,-1)\} \{4 * atand(1.0)\} @@ -419,17 +423,15 @@ \section{Aprepro Test File Example} \{[5.01]\} \{[-5.01]\} $ Test looping - print sin, cos from 0 to 90 by 5 -\{_angle = -5\} -\{Loop(19)\} -\{_angle += 5\} \{_sa=sind(_angle)\} \{_ca=cosd(_angle)\} \{hypot(_sa, _ca)\} +\{Loop(19, angle, 0, 5)\} +\{\_angle\} \{\_sa=sind(\_angle)\} \{\_ca=cosd(\_angle)\} \{hypot(\_sa, \_ca)\} \{EndLoop\} -$$$$ Test formatting and string concatenation -\{_i = 0\} \{_SAVE = _FORMAT\} -\{loop(20)\} -\{IO(++_i)\} Using the format \{_FORMAT = "%." // tostring(_i) // "g"\}, PI = \{PI\} +$$$$ Test formatting and string concatenation \{\{\_SAVE = \_FORMAT\}\} +\{loop(20, \_i, 1)\} +\{IO(\_i)\} Using the format \{\_FORMAT = "%." // tostring(\_i) // "g"\}, PI = \{PI\} \{endloop\} -Reset format to default: \{_FORMAT = _SAVE\} +Reset format to default: \{\_FORMAT = \_SAVE\} $$$$ Test string rescanning and executing \{ECHO(OFF)\} @@ -452,36 +454,38 @@ \section{Aprepro Test File Example} Original String: \{t1 = "atan2(0,-1)"\} Executed String: \{execute(t1)\} -string = \{_string = " one two, three"\} -delimiter "\{_delm = " ,"\}" -word count = \{word_count(_string,_delm)\} -second word = "\{get_word(2,_string,_delm)\}" +string = \{\_string = " one two, three"\} +delimiter "\{\_delm = " ,"\}" +word count = \{word\_count(\_string,\_delm)\} +second word = "\{get\_word(2,\_string,\_delm)\}" -string = \{_string = " (one two, three * four - five"\} -delimiter "\{_delm = " ,(*-"\}" -word count = \{word_count(_string,_delm)\} -second word = "\{get_word(2,_string,_delm)\}" +string = \{\_string = " (one two, three * four - five"\} +delimiter "\{\_delm = " ,(*-"\}" +word count = \{word\_count(\_string,\_delm)\} +second word = "\{get\_word(2,\_string,\_delm)\}" -string = \{_string = " one two, three"\} -delimiter "\{_delm = " ,"\}" -word count = \{ iwords = word_count(_string,_delm)\} +string = \{\_string = " one two, three"\} +delimiter "\{\_delm = " ,"\}" +word count = \{ iwords = word\_count(\_string,\_delm)\} -\{_n = 0\} - \{loop(iwords)\} -word \{++_n\} = "\{get_word(_n,_string,_delm)\}" + \{loop(iwords, \_n, 1)\} +word \{\_n\} = "\{get\_word(\_n,\_string,\_delm)\}" \{endloop\} $ Check parsing of escaped braces... \verb+\+\{ int a = b + \{PI/2\} \verb+\+\} \verb+\+\{ \verb+\+\} \end{apinp} -When processec by \aprepro{}, there will be two warning messages and -one error message: +When processec by \aprepro{}, there will be four warning messages and +two error messages: \begin{apout} -Aprepro: WARN: Undefined variable 'Parse' (test.inp_app, line 74) -Aprepro: ERROR: syntax error (test.inp_app, line 74) -Aprepro: WARN: Undefined variable 'T' (test.inp_app, line 106) +Aprepro: ERROR: syntax error, unexpected UNDVAR (test.inp_app, line 78) +Aprepro: WARNING: Undefined variable 'This' (test.inp_app, line 79) +Aprepro: ERROR: syntax error, unexpected UNDVAR (test.inp_app, line 79) +Aprepro: WARNING: User-defined Variable 'a' redefined (_string_, line 0) +Aprepro: WARNING: Undefined variable 'T' (test.inp_app, line 203) +Aprepro: WARNING: Undefined variable 'new_var' (test.inp_app, line 238) \end{apout} The processed output from this example is: \begin{apout} @@ -542,7 +546,6 @@ \section{Aprepro Test File Example} 5 -5 $ Test looping - print sin, cos from 0 to 90 by 5 --5 0 0 1 1 5 0.08715574275 0.9961946981 1 10 0.1736481777 0.984807753 1 @@ -564,7 +567,6 @@ \section{Aprepro Test File Example} 90 1 6.123233996e-17 1 $$$$ Test formatting and string concatenation -0 %.10g 1 Using the format %.1g, PI = 3 2 Using the format %.2g, PI = 3.1 3 Using the format %.3g, PI = 3.14 @@ -622,7 +624,6 @@ \section{Aprepro Test File Example} delimiter " ," word count = 3 -0 word 1 = "one" word 2 = "two" word 3 = "three" diff --git a/packages/seacas/doc-source/aprepro/functions.tex b/packages/seacas/doc-source/aprepro/functions.tex index ca65d003f2..72d5bf8769 100644 --- a/packages/seacas/doc-source/aprepro/functions.tex +++ b/packages/seacas/doc-source/aprepro/functions.tex @@ -25,7 +25,7 @@ \section{Mathematical Functions} acos(x) & Inverse cosine of $x$, returns radians.\\ acosd(x) & Inverse cosine of $x$, returns degrees.\\ acosh(x) & Inverse hyperbolic cosine of $x$.\\ -asin(x) & Inverse sine of $x$, returns degrees.\\ +asind(x) & Inverse sine of $x$, returns degrees.\\ asin(x) & Inverse sine of $x$, returns radians.\\ asinh(x) & Inverse hyperbolic sine of $x$.\\ atan(x) & Inverse tangent of $x$, returns radians.\\ @@ -45,7 +45,8 @@ \section{Mathematical Functions} erf(x) & Error Function $\mathrm{erf}(x)=\frac{2}{\sqrt{\pi}}\int_{0}^{x}e^{-t^{2}}\, dt$ \\ erfc(x) & Complementary Error Function $1-\mathrm{erf}(x)$ \\ exp(x) & Exponential $e^x$ \\ -find\_word(word,svar,del)& Find 1-based index of \var{word} in \var{svar}. Words are separated by one or more of the characters in the string variable del. Returns 0 if \var{word} is not found.\\ +expm1(x) & Exponential. Accurate version of $e^x - 1.0$ for small $x$. \\ +find\_word(word,svar,del) & Find 1-based index of \var{word} in \var{svar}. Words are separated by one or more of the characters in the string variable del. Returns 0 if \var{word} is not found.\\ floor(x) & Largest integer not greater than $x$.\\ fmod(x,y) & Floating-point remainder of $x/y$.\\ FtoC(x) & Convert from degrees Fahrenheit to degrees Celsius. \\ @@ -69,6 +70,7 @@ \section{Mathematical Functions} rand\_lognormal(m,s)& Random value with lognormal distribution with mean $m$ and stddev $s$.\\ rand\_normal(m,s) & Random value normally distributed with mean $m$ and stddev $s$.\\ rand\_weibull(a, b) & Random value with weibull distribution with $\alpha=a$ and $\beta=b$. \\ +seconds() & Returns the number of seconds since the epoch. The value is useful as the \var{seed} value in the function \cmd{srand}.\\ sign(x,y) & $x * \text{sgn}(y)$\\ sin(x) & Sine of $x$, with $x$ in radians. \\ sind(x) & Sine of $x$, with $x$ in degrees. \\ @@ -93,6 +95,7 @@ \section{Mathematical Functions} \hline \endhead DUMP() & Output a list of all defined variables and their value. \\ +DUMP\_JSON() & Output a list of all defined variables and their value in JSON format. \\ DUMP\_FUNC() & Output a list of all double and string functions recognized by \aprepro{}. \\ DUMP\_PREVAR() & Output a list of all predefined variables and their value. \\ IO(x) & Convert x to an integer and then to a string. Can be used to output integer values if your output format (\cmd{\_FORMAT}) is set to something that doesn't output integers correctly. \\ @@ -115,10 +118,11 @@ \section{Mathematical Functions} getenv(svar) & Returns a string containing the value of the environment variable \var{svar}. If the environment variable is not defined, an empty string is returned. \\ help() & Tell how to get help on variables, functions, \ldots \\ include\_path(path) & Specify an optional path to be prepended to a filename when opening a file. Can also be specified via the \cmd{-I} command line option when executing aprepro. \\ +import(svar) & include contents of the file specified by the value of \var{svar}. See Section~\ref{sec:inclusion} for details. \\ include(file) & include contents of the file. See Section~\ref{sec:inclusion} for details. \\ cinclude(file) & conditionally include contents of the file. See Section~\ref{sec:inclusion} for details. \\ import(svar) & include contents of the file pointed to by \var{svar}. See Section~\ref{sec:inclusion} for details. \\ -output(filename) & Creates the file specified by filename and +output(filename) & Creates the file specified by \var{filename} and sends all subsequent output from aprepro to that file. Calling \cmd{output(\"stdout\")} will close the current output file and return output to the terminal (standard output).\\ output\_append(fn) & If file with name \var{fn} exists, append output to it; otherwise create the file and send all subsequent output from aprepro to that file. \\ rescan(svar) & The difference between \cmd{execute(sv1)} and \cmd{rescan(sv2)} is that \var{sv1} must be a valid expression, but \var{sv2} can contain zero or more expressions. \\ @@ -128,6 +132,33 @@ \section{Mathematical Functions} tostring(x) & Returns a string representation of the numerical variable \var{x}. The variable \var{x} is unchanged. \\ to\_upper(svar) & Translates all lowercase character in \var{svar} to uppercase. It modifies \var{svar} and returns the resulting string. \\ toupper(svar) & Translates all lowercase character in \var{svar} to uppercase. It modifies \var{svar} and returns the resulting string. \\ +version() & Return the version string. (See also the \var{\_VERSION} variable). \\ +\hline +\end{longtable} + +\begin{longtable}{lp{4.0in}} +\caption{Array Functions}\label{t:arrayfunctions}\\ +Syntax & Description \\ +\hline +\endhead +csv\_array(filename, [skip]) & Create a 2D array from the data in a CSV (Comma-Separated-Value) file optionally skipping rows. If \var{skip} is an integer, then skip that many rows; if \var{skip} is a character, then skip lines beginning with that character.\\ +array\_from\_string(string, delim) & Create a 1D array from the data in a delimited \var{string}. The array double values are separated by one or more of the characters in the string variable \var{delim}. \\ +identity(size) & Create a 2D identity array with \var{size} rows and columns. The elements along the diagonal are equal to 1.0 \\ +linear\_array(init, final, count) & Create a 1D array of \var{count} rows. Values are linearly spaced from \var{init} to \var{final}. \\ +make\_array(rows, cols, init=0) & Create a 2D array of size \var{rows} by \var{cols} initialized to \var{init}. The array is initialized to 0 if \var{init} is not specified. \\ +transpose(array) & Return the transpose of input array \\ +\hline +\end{longtable} + +\begin{longtable}{lp{4.0in}} +\caption{Functions with Array variables as parameters}\label{t:arrayparameters}\\ +Syntax & Description \\ +\hline +\endhead +cols(array) & Returns the number of columns in the array \var{array}. \\ +rows(array) & Returns the number of rows in the array \var{array}. \\ +print\_array(array) & Prints the data in the array \var{array}. \\ + \hline \end{longtable} @@ -294,18 +325,71 @@ \subsection{Switch Statements} \subsection{Loops} Repeated processing of a group of lines can be controlled with the \cmd{loop(control)}, and \cmd{endloop} commands. The syntax is: \begin{apinp} -\{loop(variable)\} -\ldots Process these lines \var{variable} times +\{loop(variable, index\_variable, initial\_value, increment)\} +\ldots Process these lines \var{variable} times. \{endloop\} \end{apinp} -Loops can be nested. A numerical variable or constant must be specified as the -loop control specifier. You cannot use an algebraic expression such as +The number of iterations of the loop is specified by \var{variable} which can be an explicit integer value, or an existing variable. If it is a variable, then the truncated integer value of the variable will be used. For example, if the variable contains the value 3.14, then the loop will be iterated 3 times. + +The optional \var{index\_variable} will be automatically initialized +to the optional \var{initial\_value} (0 if not specified) at the +beginning of the loop and incremented by the optional \var{increment} +(1 if not specified) value each time through the loop. Loops can be +nested. + +If the \var{index\_variable} is not specified in the \cmd{loop} +command, then the variable \var{\_\_loop\_\#} will be used where ``\#'' +represents the one-based nesting level of the current loop. -\cmd{\{loop(3+5)\}}. +A numerical variable or constant must be specified as the loop control +specifier. You cannot use an algebraic expression such as + +\begin{apinp} +\{loop(3+5)\} \ldots INVALID +\end{apinp} The \cmd{endloop} command must be on a line by itself with no other text except optional whitespace (spaces or tabs). +These are all valid loop invocations: +\begin{apinp} +\{loop(variable, index\_variable, initial\_value, increment)\} +\end{apinp} + +\begin{apinp} +\{loop(variable, index\_variable, initial\_value)\} +\ldots same as \{loop(variable, index\_variable, initial\_value, 1)\} +\end{apinp} + +\begin{apinp} +\{loop(variable, index\_variable)\} +\ldots same as \{loop(variable, index\_variable, 0, 1)\} +\end{apinp} + +\begin{apinp} +\{loop(variable)\} +\ldots same as \{loop(variable, \_\_loop\_1, 0, 1\} +\end{apinp} + +A couple examples of using loops are shown here: +\begin{apinp} +\{loop(10, \_i, 1, 2)\} +\ldots These lines will be executed 10 times. +\ldots The variable \var{\_i} will have the values 1, 3, 5, \ldots, 19. +\{endloop\} +\end{apinp} + +\begin{apinp} +\{outer=10\} \{inner=4\} +\{loop(outer, \_i)\} +\{loop(inner)\} +\ldots These lines will be executed $10 * 4$ times. +\ldots The variable \var{\_i} will have the values 0 through 9. +\ldots The variable \var{\_\_loop\_2} will have the values 0, 1, 2, 3 and incremented in each iteration of the inner loop. +\{endloop\} +\{endloop\} +\end{apinp} + \subsection{ECHO}\label{echo} The printing of lines to the output file can be controlled through the use of the \cmd{ECHO(OFF)} and \cmd{ECHO(ON)} commands. The syntax is: @@ -320,6 +404,17 @@ \subsection{ECHO}\label{echo} The printing of lines to the output file can be co \cmd{ECHO} will automatically be turned on at the end of an included file. The commands \cmd{ECHO} and \cmd{NOECHO} are synonyms for \cmd{ECHO(ON)} and \cmd{ECHO(OFF)}. +\subsection{Suppress individual expression output} +In addition to the \cmd{ECHO} option shown in the previous section, it +is possible to suppress the echoing of the results of an expression by +surrounding the expression with double braces instead of the normal +single braces. For example: +\begin{apinp} +\{\{\_i = 0\}\} +\end{apinp} +Will disable the echoing of that expression (although the newline will +still be echoed). + \subsection{VERBATIM} The printing of all lines to the output file without processing can be controlled through the use of the \cmd{VERBATIM(ON)} and \cmd{VERBATIM(OFF)} commands. The syntax is: @@ -367,7 +462,7 @@ \subsection{Output File Specification} The \cmd{output} function can be used the standard output which is where output is written by default. \subsection{\exo{} Metadata Extraction} \aprepro{} can parse the -metadata from a binary \exo{}~\cite{exodus} file and create several +metadata from a binary \exo{}~\cite{bib:exodus} file and create several variables which can then be used for calculations or decisions. The function syntax is \cmd{exodus\_meta(filename)}. The argument to the function is a string containing the filename of the diff --git a/packages/seacas/doc-source/aprepro/library.tex b/packages/seacas/doc-source/aprepro/library.tex index cf17e14098..8d1b295de0 100644 --- a/packages/seacas/doc-source/aprepro/library.tex +++ b/packages/seacas/doc-source/aprepro/library.tex @@ -170,43 +170,52 @@ \section{Aprepro Library Test/Example Program} \lstset{language=C++, basicstyle=\small, numbers=left, stepnumber=1, numbersep=5pt, numberstyle=\tiny, morekeywords={[2]aprepro},keywordstyle={[2]\color{blue}}} \begin{lstlisting} -#include #include +#include #include "aprepro.h" // This function is used below in the example showing how an // application can add its own functions to an aprepro instance. -double succ(double i) { - return ++i; -} +double succ(double i) { return ++i; } int main(int argc, char *argv[]) { bool readfile = false; + std::string output_file; + SEAMS::Aprepro aprepro; // EXAMPLE: Add a function to aprepro... - SEAMS::symrec *ptr = aprepro.putsym("succ", SEAMS::Aprepro::FUNCTION, 0); + SEAMS::symrec *ptr = aprepro.putsym("succ", SEAMS::Aprepro::SYMBOL_TYPE::FUNCTION, false); ptr->value.fnctptr_d = succ; - ptr->info = "Return the successor to d"; - ptr->syntax = "succ(d)"; + ptr->info = "Return the successor to d"; + ptr->syntax = "succ(d)"; // EXAMPLE: Add a couple variables... - aprepro.add_variable("Greg", "Is the author of this code", true); // Make it immutable + aprepro.add_variable("Greg", "Is the author of this code", true); // Make it immutable aprepro.add_variable("BirthYear", 1958); - for(int ai = 1; ai < argc; ++ai) { + for (int ai = 1; ai < argc; ++ai) { std::string arg = argv[ai]; - if (arg == "-i") { + if (arg == "-o") { + output_file = argv[++ai]; + } + else if (arg == "-i") { // Read from cin and echo each line to cout All results will // also be stored in Aprepro::parsing_results() stream if needed // at end of file. aprepro.ap_options.interactive = true; - bool result = aprepro.parse_stream(std::cin, "standard input"); + bool result = aprepro.parse_stream(std::cin, "standard input"); if (result) { - std::cout << "PARSING RESULTS: " << aprepro.parsing_results().str(); + if (!output_file.empty()) { + std::ofstream ofile(output_file); + ofile << aprepro.parsing_results().str(); + } + else { + std::cout << aprepro.parsing_results().str(); + } } } else if (arg[0] == '-') { @@ -218,37 +227,75 @@ \section{Aprepro Library Test/Example Program} // Aprepro::parsing_results() std::fstream infile(argv[ai]); if (!infile.good()) { - std::cerr << "APREPRO: Could not open file: " << argv[ai] << '\n'; - return 0; + if (!aprepro.ap_options.include_path.empty() && argv[ai][0] != '/') { + std::string filename = aprepro.ap_options.include_path + "/" + argv[ai]; + infile.open(filename, std::fstream::in); + } + } + if (!infile.good()) { + std::cerr << "APREPRO: Could not open file: " << argv[ai] << '\n'; + return 0; } bool result = aprepro.parse_stream(infile, argv[ai]); if (result) { - std::cout << "PARSING RESULTS: " << aprepro.parsing_results().str(); + if (!output_file.empty()) { + std::ofstream ofile(output_file); + ofile << aprepro.parsing_results().str(); + } + else { + std::cout << aprepro.parsing_results().str(); + } } readfile = true; } } - - if (readfile) return 0; + if (readfile) { + std::cerr << "Aprepro: There were " << aprepro.get_error_count() + << " errors detected during parsing.\n"; + return aprepro.get_error_count() == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + } // Read and parse a string's worth of data at a time. // Cannot use looping/ifs/... with this method. - std::string line; - while( std::cout << "\nexpession: " && - std::getline(std::cin, line) && - !line.empty() ) { - if (line[0] != '{') - line = "{" + line + "}\n"; - else - line += "\n"; - - bool result = aprepro.parse_string(line, "input"); + std::string line, tmp; + while (std::cout << "\nexpression: " && std::getline(std::cin, tmp) && !tmp.empty()) { + + line += tmp; + + if (*tmp.rbegin() == '\\') { + line.erase(line.length() - 1); + continue; + } + + line += "\n"; + + bool result = aprepro.parse_string_interactive(line); + if (result) { - std::cout << " : " << aprepro.parsing_results().str(); - aprepro.clear_results(); + std::string res_str = aprepro.parsing_results().str(); + std::cout << " : " << res_str; + + // Example showing how to get the substitution history for the current line. + if (aprepro.ap_options.keep_history) { + std::vector hist = aprepro.get_history(); + for (const auto &curr_history : hist) { + + std::cout << curr_history.original << " was substituted with " + << curr_history.substitution << " at index " << curr_history.index << '\n'; + } + + aprepro.clear_history(); + } } + + aprepro.clear_results(); + + line.clear(); } + std::cerr << "Aprepro: There were " << aprepro.get_error_count() + << " errors detected during parsing.\n"; + return aprepro.get_error_count() == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } \end{lstlisting} diff --git a/packages/seacas/doc-source/aprepro/predefined_variables.tex b/packages/seacas/doc-source/aprepro/predefined_variables.tex index 562ab541ed..748708459c 100644 --- a/packages/seacas/doc-source/aprepro/predefined_variables.tex +++ b/packages/seacas/doc-source/aprepro/predefined_variables.tex @@ -23,18 +23,25 @@ \chapter{Predefined Variables}\label{ch:predefined} E & 2.71828182845904523536 & base of natural logarithm \\ GAMMA & 0.57721566490153286060 & $\gamma$, euler-mascheroni constant \\ PHI & 1.61803398874989484820 & golden ratio $(\sqrt{5}+1)/2$ \\ - VERSION & Varies, string value & current version of \aprepro \\ + TRUE & 1 & \\ + FALSE & 0 & \\ + \_VERSION\_ & Varies, string value & current version of \aprepro \\ \_FORMAT& \texttt{"}\%.10g\texttt{"} & default output format \\ \_C\_ & \texttt{"}\$\texttt{"} & default comment character \\ \end{longtable} -Note that the output format is used to output both integers and floating point -numbers. Therefore, it should use the \%g format descriptor which will use either -the decimal (\%d), exponential (\%e), or float (\%f) format, whichever is shorter, -with insignificant zeros suppressed. The table below illustrates the effect of -different format specifications on the output of the variable \textbf{PI} and the -value 1.0 . See the documentation of your C compiler for more information. For -most cases, the default value is sufficient. +Note that the output format is used to output both integers and +floating point numbers. Therefore, it should use the \%g format +descriptor which will use either the decimal (\%d), exponential (\%e), +or float (\%f) format, whichever is shorter, with insignificant zeros +suppressed. If the output format is set to the empty string, the the +output will use as many variables as needed to fully represent the +double precision value. + +The table below illustrates the effect of different format +specifications on the output of the variable \textbf{PI} and the value +1.0 . See the documentation of your C compiler for more +information. For most cases, the default value is sufficient. \begin{longtable}{lll} \caption{Effect of various output format specifications}\\ @@ -44,6 +51,7 @@ \chapter{Predefined Variables}\label{ch:predefined} \%.10e & 3.1415926536e+00 & 1.0000000000e+00 \\ \%.10f & 3.1415926536 & 1.0000000000 \\ \%.10d & 1413754136 & 0000000000 \\ +"" & 3.141592653589793 & 1 \\ \end{longtable} The comment character should be set to the character that the program diff --git a/packages/seacas/doc-source/aprepro/title.tex b/packages/seacas/doc-source/aprepro/title.tex index 34fc7ddecf..6e1665fddc 100644 --- a/packages/seacas/doc-source/aprepro/title.tex +++ b/packages/seacas/doc-source/aprepro/title.tex @@ -9,7 +9,6 @@ \title{\theTitle} \ifsand \pdfbookmark[1]{Cover}{cover} -\doCover \newpage \else \SANDmarks{cover} @@ -20,8 +19,6 @@ %\begin{titlepage} \begin{center} -\SANDnumVar\\ -\SANDreleaseTypeVar\\ \ifdraft Draft Date: \SANDprintDateVar\\ \else @@ -34,7 +31,6 @@ \vspace{0.75in} \CoverFont{m}{12}{14pt} \SANDauthorVar\\ -Simulation Modeling Sciences Department\\ Sandia National Laboratories\\ Albuquerque, NM 87185-0380\\ \vspace*{.5in} diff --git a/packages/seacas/doc-source/aprepro/units.tex b/packages/seacas/doc-source/aprepro/units.tex index b940abcd19..d0d396e9bc 100644 --- a/packages/seacas/doc-source/aprepro/units.tex +++ b/packages/seacas/doc-source/aprepro/units.tex @@ -230,14 +230,86 @@ \section{Defined Units Variables} The conversion expressions were obtained from References~\cite{bib:isotopes}, \cite{bib:jaeger}, \cite{bib:lambe}, and~\cite{bib:simpson}. +\section{Physical Constants} +The units system also defines several physical constants which are +listed in the following table. The values for these were obtained from +\url{https://en.wikipedia.org/wiki/List_of_physical_constants}. +Although the \aprepro{} units system should adjust the values +correctly for different systems, it is recommended that the ``si'' +system be used to avoid any possible conversion errors. + +\begin{longtable}{l|l} +\caption{Physical Constants} \\ +\hline +Quantity & Value \\ +\hline +Avogadro\_constant & $ 6.02214076x10^{23}\ / mol $ \\ +Bohr\_magneton & $ 9.2740100783x10^{-24}\ J/T $ \\ +Bohr\_radius & $ 5.29177210903x10^{-11}\ m $ \\ +Boltzmann\_constant & $ 1.380649x10^{-23}\ J/{}^{\circ}K $ \\ +Coulomb\_constant & $ 8.9875517923x10^9\ N m^2\cdot C^{-2} $ \\ +Faraday\_constant & $ 96485.3321233100184\ C/mol $ \\ +Fermi\_coupling\_constant & $ 1.166378710x10^{-5}\ GeV^{-2} $ \\ +Hartree\_energy & $ 4.3597447222071x10^{-18}\ J $ \\ +Josephson\_constant & $ 483597.8484x10^9\ Hz/V $ \\ +Newtonian\_constant\_of\_gravitation & $ 6.67430x10^{-11}\ m^3/kg\cdot s^{-2} $ \\ +Gravitational\_constant & $ 6.67430x10^{-11}\ m^3/kg\cdot s^{-2} $ \\ +Planck\_constant & $ 6.62607015x10^{-34}\ J/Hz $ \\ +Rydberg\_constant & $ 10973731.568160\ m $ \\ +Rydberg\_unit\_of\_energy & $ 2.1798723611035x10^-{18}\ J $ \\ +Stefan\_Boltzmann\_constant & $ 5.670374419x10^{-8}\ W\cdot m^{-2}\cdot {}^{\circ}K^{-4} $ \\ +Thomson\_cross\_section & $ 6.6524587321x10^{-29}\ m^2 $ \\ +W\_to\_Z\_mass\_ratio & $ 0.88153 $ \\ +Wien\_entropy\_displacement\_law\_constant & $ 3.002916077x10^{-3}\ m\cdot {}^{\circ}K $ \\ +Wien\_frequency\_displacement\_law\_constant & $ 5.878925757x10^{10}\ Hz/{}^{\circ}K $ \\ +Wien\_wavelength\_displacement\_law\_constant & $ 2.897771955x10^{-3}\ m\cdot {}^{\circ}K $ \\ +atomic\_mass\_constant & $ 1.66053906660x10^{-27}\ kg $ \\ +atomic\_mass\_of\_carbon\_12 & $ 1.99264687992x10^{-26}\ kg $ \\ +characteristic\_impedance\_of\_vacuum & $ 376.730313668\ \Omega $ \\ +classical\_electron\_radius & $ 2.8179403262x10^{-15}\ m $ \\ +conductance\_quantum & $ 7.748091729x10^{-5}\ S $ \\ +cosmological\_constant & $ 1.089x10^{-52}\ m^{-2} $ \\ +electron\_g\_factor & $ -2.00231930436256 $ \\ +electron\_mass & $ 9.1093837015x10^{-31}\ kg $ \\ +elementary\_charge & $ 1.602176634x10^{-19}\ C $ \\ +fine\_structure\_constant & $ 7.2973525693x10^{-3} $ \\ +first\_radiation\_constant & $ 3.741771852x10^{-16}\ W\cdot m^2 $ \\ +hyperfine\_transition\_frequency\_of\_133Cs & $ 139192631770\ Hz $ \\ +inverse\_conductance\_quantum & $ 12906.40372\ \Omega $ \\ +inverse\_fine\_structure\_constant & $ 137.035999084 $ \\ +magnetic\_flux\_quantum & $ 2.067833848x10^{-15}\ V\cdot s $ \\ +molar\_Planck\_constant & $ 3.9903127128934314x10^{-10}\ J\cdot s / mol $ \\ +molar\_gas\_constant & $ 8.31446261815324\ J/mol/{}^{\circ}K $ \\ +molar\_mass\_constant & $ 0.99999999965x10^{-3}\ kg/mol $ \\ +molar\_mass\_of\_carbon\_12 & $ 11.9999999958x10^{-3}\ kg/mol $ \\ +muon\_g\_factor & $ -2.0023318418 $ \\ +muon\_mass & $ 1.883531627x10^{-28}\ kg $ \\ +neutron\_mass & $ 1.67492749804x10^{-27}\ kg $ \\ +nuclear\_magneton & $ 5.0507837461x10^{-27}\ J/T $ \\ +proton\_g\_factor & $ 5.5856946893 $ \\ +proton\_mass & $ 1.67262192369x10^{-27}\ kg $ \\ +proton\_to\_electron\_mass\_ratio & $ 1836.15267343 $ \\ +quantum\_of\_circulation & $ 3.6369475516x10^{-4}\ m^2/s $ \\ +reduced\_Planck\_constant & $ 1.054571817x10^{-34}\ J\cdot s $ \\ +sec\_radiation\_constant & $ 1.438776877x10^{-2}\ m\cdot {}^{\circ}K $ \\ +speed\_of\_light\_in\_vacuum & $ 299792458\ m/s $ \\ +tau\_mass & $ 3.16754x10^{-27}\ kg $ \\ +top\_quark\_mass & $ 3.0784x10^{-25}\ kg $ \\ +vacuum\_electric\_permittivity & $ 8.8541878128x10^{-12}\ F/m $ \\ +vacuum\_magnetic\_permeability & $ 1.25663706212x10^{-6}\ N\cdot A^{-2} $ \\ +von\_Klitzing\_constant & $ 25812.80745\ \Omega $ \\ +weak\_mixing\_angle & $ 0.22290 $ \\ +\end{longtable} + + + \section{Usage} The following example illustrates the basic usage of the \aprepro{} units conversion utility. \begin{apinp} \$ Aprepro Units Utility Example -\$ \{ECHO(OFF)\} \textit{\ldots{}Turn off echoing of the conversion factors} -\$ \{Units(``shock'')\} \textit{\ldots{}Select the shock units system} +\$ \{\{Units(``shock'')\}\} \textit{\ldots{}Select the shock units system, use double brace to suppress echoing} \$ NOTE: Dimensions - \{lout\}, \{mout\}, \{dout\}, \{pout\} \textit{\ldots{}This will document what quantities are used in the file after it is run through Aprepro} \{len1 = 10.0 * inch\} \textit{\ldots{}Define a length in an english unit (inches)} @@ -301,7 +373,7 @@ \section{Additional Comments} A few additional comments and warnings on the use of the units system are detailed below. -Omitting the \{ECHO(OFF)\} line prior to the \{Units(``unit\_system'')\} +Using only single braces for the \{Units(``unit\_system'')\} function will print out the contents of the units header and conversion files. Each line in the output will be preceded by the current comment character which is \$ by default. @@ -331,3 +403,7 @@ \section{Additional Comments} redefined from the value set by the units system. You can enter the command \cmd{DUMP()} to see a list of all defined variables and their current value. + +The \aprepro{} variable \cmd{\_UNITS\_SYSTEM} is defined to the name +of the current units system that is loaded or ``none'' if no units +system has been loaded. diff --git a/packages/seacas/doc-source/exo_utils/epu.tex b/packages/seacas/doc-source/exo_utils/epu.tex index 701eeb100f..b176edf17f 100644 --- a/packages/seacas/doc-source/exo_utils/epu.tex +++ b/packages/seacas/doc-source/exo_utils/epu.tex @@ -201,7 +201,7 @@ \subsubsection{Additional Options} \param{-steps } & Specify a subset of timesteps to transfer to output file.\par Format is begin:end:step. For example, -steps 1:10:2 would result in steps 1,3,5,7,9 being transferred to the output - databaes. Enter LAST to just transfer last step, for example, ``-steps LAST'' \\ + database. Enter LAST to just transfer last step, for example, ``-steps LAST'' \\ \param{-Part\_count } & How many pieces (files) of the model should be joined. This option is typically used with either the \param{-start\_part} or the \param{-subcycle} options in diff --git a/packages/seacas/format.sh b/packages/seacas/format.sh index adf5c7cb6b..c995a6aa97 100755 --- a/packages/seacas/format.sh +++ b/packages/seacas/format.sh @@ -1,6 +1,6 @@ #!/bin/sh for i in $(ls ./*.[cCh]); do echo $i - /usr/local/bin/clang-format -i -style=file $i + /opt/homebrew/bin/clang-format -i -style=file $i done diff --git a/packages/seacas/libraries/aprepro_lib/CMakeLists.txt b/packages/seacas/libraries/aprepro_lib/CMakeLists.txt index b34a01963a..5d7a208104 100644 --- a/packages/seacas/libraries/aprepro_lib/CMakeLists.txt +++ b/packages/seacas/libraries/aprepro_lib/CMakeLists.txt @@ -34,6 +34,7 @@ endif() SET(HEADERS aprepro.h + apr_symrec.h apr_tokenize.h ) @@ -111,11 +112,12 @@ endif() if (${PACKAGE_NAME}_ENABLE_TESTS) TRIBITS_ADD_EXECUTABLE(aprepro_lib_test NOEXEPREFIX NOEXESUFFIX INSTALLABLE SOURCES apr_test.cc LINKER_LANGUAGE CXX) + TRIBITS_ADD_EXECUTABLE(aprepro_strings_test NOEXEPREFIX NOEXESUFFIX INSTALLABLE SOURCES strings.cc LINKER_LANGUAGE CXX) TRIBITS_ADD_ADVANCED_TEST( aprepro_lib_unit_test TEST_0 EXEC aprepro_lib_test - ARGS -o test.output ${CMAKE_CURRENT_SOURCE_DIR}/test.inp_app + ARGS -o test.output ${CMAKE_CURRENT_SOURCE_DIR}/test.inp_app NOEXEPREFIX NOEXESUFFIX PASS_ANY TEST_1 CMND diff ARGS -w @@ -130,8 +132,7 @@ TRIBITS_ADD_ADVANCED_TEST( TRIBITS_ADD_ADVANCED_TEST( aprepro_lib_array_test TEST_0 EXEC aprepro_lib_test - ARGS --info=test-array.dump --include=${CMAKE_CURRENT_SOURCE_DIR} -o test-array.out - ${CMAKE_CURRENT_SOURCE_DIR}/test-array.i + ARGS --info=test-array.dump --include=${CMAKE_CURRENT_SOURCE_DIR} -o test-array.out test-array.i NOEXEPREFIX NOEXESUFFIX PASS_ANY TEST_1 CMND diff ARGS -w @@ -145,6 +146,42 @@ TRIBITS_ADD_ADVANCED_TEST( FINAL_PASS_REGULAR_EXPRESSION XHOSTTYPE Windows ) + +TRIBITS_ADD_ADVANCED_TEST( + aprepro_lib_array_test_short_opt + TEST_0 EXEC aprepro_lib_test + ARGS --info=test-short-array.dump -I=${CMAKE_CURRENT_SOURCE_DIR} -o test-short-array.out + test-array.i + NOEXEPREFIX NOEXESUFFIX + PASS_ANY + TEST_1 CMND diff ARGS -w + ${CMAKE_CURRENT_SOURCE_DIR}/test-array.gold + ${CMAKE_CURRENT_BINARY_DIR}/test-short-array.out + TEST_2 CMND diff ARGS -w + ${CMAKE_CURRENT_SOURCE_DIR}/test-array.stderr.gold + ${CMAKE_CURRENT_BINARY_DIR}/test-short-array.dump + COMM mpi serial + OVERALL_NUM_MPI_PROCS 1 + FINAL_PASS_REGULAR_EXPRESSION + XHOSTTYPE Windows +) + +TRIBITS_ADD_ADVANCED_TEST( + aprepro_lib_unit_test_strings + TEST_0 EXEC aprepro_strings_test + OUTPUT_FILE test-strings.output + NOEXEPREFIX NOEXESUFFIX + PASS_ANY + TEST_1 CMND grep ARGS -v ^Aprepro test-strings.output OUTPUT_FILE grepped-strings.out + TEST_2 CMND diff ARGS -w + ${CMAKE_CURRENT_SOURCE_DIR}/test_standard.out + ${CMAKE_CURRENT_BINARY_DIR}/grepped-strings.out + COMM mpi serial + OVERALL_NUM_MPI_PROCS 1 + FINAL_PASS_REGULAR_EXPRESSION + XHOSTTYPE Windows +) + endif() TRIBITS_SUBPACKAGE_POSTPROCESS() diff --git a/packages/seacas/libraries/aprepro_lib/CustomDoxygen.css b/packages/seacas/libraries/aprepro_lib/CustomDoxygen.css new file mode 100644 index 0000000000..0d96812b42 --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/CustomDoxygen.css @@ -0,0 +1,619 @@ + +/* function descriptions */ +.memtitle { + padding: 8px; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url(); + background-repeat: repeat-x; + background-color: #fff; + line-height: 1.25; + font-weight: 600; + float: left; +} + +dt { + font-weight: 600; +} + +p.reference, p.definition { + font: 400 14px/22px -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;; + margin-top: 0px; + margin-bottom: 5px; + padding-top: 8px; + border-top: 1px solid #eee; +} + +/* parameter names */ +.params .paramname, .retval .paramname, .tparams .paramname { + font-weight: 600; + vertical-align: top; +} + +/* parameter data types */ +.paramtype { + white-space: nowrap; + color: #008141; +} + +/* headers */ +h1, h2, h3, h4, h5, h6 { + font-weight: 600; +} + +/* parameter names */ +.paramname { + color: #db0303; + white-space: nowrap; +} + +/* overall style */ +body, table, div, p, dl { + font-style: normal; + font-variant-ligatures: normal; + font-variant-caps: normal; + font-variant-numeric: normal; + font-variant-east-asian: normal; + font-weight: 500; + font-stretch: normal; + font-size: 14px; + line-height: 22px; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} + +/* project name */ +#projectname { + /* markdown font */ + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + margin: 0; + padding: 2px 0; +} +/* title area */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} + +h2.groupheader { + border-bottom: 1px solid #eee; + color: #000; + font-size: 150%; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + margin-top: 1em; + padding-top: 12px; + padding-bottom: 4px; + width: 100%; +} + +/* function description text box */ +.memdoc, dl.reflist dd { + + border-bottom: none; + border-left: none; + border-right: none; + padding: 0px 10px 0px 10px; + background-color: #FFF; + border-top-width: 0; + background-image: none; + background-repeat: repeat-x; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0) 5px 5px 5px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); +} + +/* function prototype text box */ +.memproto, dl.reflist dt { + border-bottom: 1px solid #999; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 0px 0 0px 0; + color: #000; + font-weight: bold; + text-shadow: none; + background-color: #f9f9f9; + box-shadow: none; + border-top-right-radius: 4px; + -moz-box-shadow: none; + -moz-border-radius-topright: 4px; + -webkit-box-shadow: none; + -webkit-border-top-right-radius: 4px; +} + +/* function prototype */ +.memname td { + + vertical-align: bottom; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + +} + + +/* icon for each data type */ +.icon { + background-color: #026ea1; +} +/* arrows for treenav */ + +.arrow { + color: #09A716; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} +/* colors and fonts for description pages */ + +table, div, p, dl { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: black; +} + +.sm li, .sm a { + position: relative; + color: black; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: #FFF; + min-height: 100%; + overflow-x: hidden; + background: #fff; +} + +/* file member function descriptions */ +.memberdecls td, .fieldtable tr { + + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 501; +} + +/* function descriptor */ +td.mdescLeft, td.mdescRight { + padding: 0 8px 4px 8px; + color: #000; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 400; +} + +/* headers for #include descriptions */ +tt, code, kbd, samp { + display: inline-block; + direction: ltr; + background-color: #f8f8f8; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* list for file members */ +div.contents { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* links to a class or struct on the class list page */ +a.el { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* header dividers */ +hr { + height: 0; + border: none; + border-top: 1px solid #eee; +} + +#side-nav { + padding: 0 0 0 0; + margin: 0; + display: block; + position: absolute; + left: 0; + width: 250; +} +/* nav tree arrow symbol */ + +#nav-sync img { + opacity: 0; +} +#nav-sync img:hover { + opacity: 0.9; +} +/* The main page button */ + +.sm-dox>li:first-child>a, .sm-dox>li:first-child> :not(ul) a { + padding-right: 12px; +} +/* content of for all class members list */ + +#doc-content { + overflow: auto; + display: block; + padding: 0; + margin: 0; + margin-left: 0; + -webkit-overflow-scrolling: touch; + background-color: #FFF; +} +/* label for which tree menu you are on (displays in the doc menu */ + +.title { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + font-size: 150%; + margin: -2px 0 0 2px; + background-color: white; +} +/* title for each section (class List, Class index) */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} +/* title for each section (class List, Class index) */ + +div.headertitle { + padding: none; + background-color: white; +} +/* actual header for each section */ + +div.header { + background-image: none; + background-repeat: repeat-x; + background-color: #FFF; + margin: 0; + border-bottom: 1px solid #eee; +} +/* for class and function lists */ + +table.directory { + font-style: normal; + font-variant-caps: normal; + font-weight: normal; + font-stretch: normal; + line-height: normal; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-size-adjust: none; + font-kerning: auto; + font-optical-sizing: auto; + font-variant-alternates: normal; + font-variant-east-asian: normal; + font-variant-ligatures: normal; + font-variant-numeric: normal; + font-variant-position: normal; + font-language-override: normal; + font-feature-settings: normal; + font-variation-settings: normal; +} +/* main page, classes, files banner */ + +.sm-dox { + padding: 0 0; + background-image: none; + line-height: 36px; + background-color: #7fbdff; +} +/* item list on botton left */ + +.navpath li.navelem a { + height: 32px; + display: block; + text-decoration: none; + outline: none; + color: #FFF; + font-family: 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; + text-shadow: none; + text-decoration: none; +} +.navpath li { + list-style-type: none; + float: left; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #364D7C; +} +/* top menu, Classes button */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:active, .sm-dox a.highlighted, .sm-dox a.highlighted { + padding-right: 12px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + background-color: #7fbdff; + color: #b8b8b8; + padding-left: 12px; +} + +.sm-dox a.has-submenu { + padding-right: 24px; +} + +.sm a { + display: block; +} +/* top menu, main buttons label */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:visited, .sm-dox a:visited { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + color: #000; + text-shadow: none; +} +/* hover over class/main page, files buttons */ + +.sm-dox a:hover { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + text-decoration: none; + text-decoration-line: none; + text-decoration-style: solid; + text-decoration-color: currentcolor; + text-shadow: none; + color: #FFF; + outline: 0; + outline-color: currentcolor; + outline-style: none; + outline-width: 0; + background-color: #156ac9; + background-image: none; +} + +.sm-dox ul a:hover { + background-image: none; + background-repeat: repeat-x; + color: white; + background-color: #000; + text-shadow: none; +} + +/* top list items */ + +.sm-dox ul { + color: #FFF; + border-top-color: rgb(187, 187, 187); + border-top-style: solid; + border-top-width: 1px; + border-right-color: rgb(187, 187, 187); + border-right-style: solid; + border-right-width: 1px; + border-bottom-color: rgb(187, 187, 187); + border-bottom-style: solid; + border-bottom-width: 1px; + border-left-color: rgb(187, 187, 187); + border-left-style: solid; + border-left-width: 1px; + border-image-outset: 0; + border-image-repeat: stretch; + border-image-slice: 100%; + border-image-source: none; + border-image-width: 1; + padding: 5px 0; + background: #fff; + background-color: rgb(255, 255, 255); + background-position-x: 0%; + background-position-y: 0%; + background-repeat: repeat; + background-attachment: scroll; + background-image: none; + background-size: auto; + background-origin: padding-box; + background-clip: border-box; + -moz-border-radius: 5px !important; + -webkit-border-radius: 5px; + border-radius: 5px !important; + -moz-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); +} +.sm-dox ul a:hover { + background-image: none; +} +/* dividers for class/function lists */ + +div.directory { + margin: 10px 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + width: 100%; +} +/* for navigation tree links */ + +#nav-tree .label a { + padding-top: 1px; + padding-right: 1px; + padding-bottom: 1px; + margin-left: 12px; + color: #FFF; + font-weight: 700; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} +/* hovering over tree view items */ + +#nav-tree .label a:hover { + padding-top: 2px; + padding-right: 2px; + padding-bottom: -3px; + margin-left: 12px; + color: #000; + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; + background-color: #FFF +} +/* nav tree labels */ + +#nav-tree .label { + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; +} +/* still for the navtree, but not labels */ + +#nav-tree { + padding: 0 0; + background-color: #404040; + font-size: normal; + overflow: auto; + background-image: none; + margin-right: 16px; +} + +span.lineno { + background-color: #f7f7f7; +} + +a { + color: #4d95c4; +} + +span.lineno a { + background-color: #e6e5e5; +} + +div.fragment { + padding: 0 0 1px 0; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #eee; +} + +.permalink { + color: #476092; + font-size: 85%; +} + +/* selected nav tree */ +#nav-tree .selected { + background-image: none; + background-repeat: repeat-x; + color: #fff; + background-color: #000; +} +/* selected nav tree link */ + +#nav-tree .selected a { + background-image: none; + background-repeat: repeat-x; + color: #fff; +} +/* visited nav tree link */ + +#nav-tree .visited a { + background-image: none; + background-repeat: repeat-x; + color: #127FCF; +} +/* bar separator for tree view */ + +.ui-resizable-e { + background-image: none; + background-size: 100%; + background-repeat: repeat-y; + background-attachment: scroll; + cursor: ew-resize; + height: 100%; + right: 0; + top: 0; + width: 0; + background-color: black; +} +/* visited links in general */ + +a:visited { + color: #4d95c4; +} +/* bottom bar */ + +a.code, a.code:visited, a.line, a.line:visited { + color: #4d95c4; +} + +.contents a:visited { + color: #4d95c4; +} + +.navpath ul { + font-size: 11px; + background-image: none; + background-repeat: repeat-x; + background-position: 0 -5px; + height: 30px; + line-height: 30px; + color: #fff; + border: none; + overflow: hidden; + margin: 0; + padding: 0; + background-color: #181818; +} +/* text 'Generated by doxygen' */ + +.navpath li.footer { + list-style-type: none; + float: right; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #FFF; + font-size: 8pt; +} + +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 400; + src: url("../fonts/RobotoSlab/roboto-slab.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype") +} +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 700; + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype") +} diff --git a/packages/seacas/libraries/aprepro_lib/Doxyfile b/packages/seacas/libraries/aprepro_lib/Doxyfile index efe171533e..b280cf54a3 100644 --- a/packages/seacas/libraries/aprepro_lib/Doxyfile +++ b/packages/seacas/libraries/aprepro_lib/Doxyfile @@ -1304,7 +1304,7 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = CustomDoxygen.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note diff --git a/packages/seacas/libraries/aprepro_lib/FlexLexer.h b/packages/seacas/libraries/aprepro_lib/FlexLexer.h index 863c8d4137..b3b37d033a 100644 --- a/packages/seacas/libraries/aprepro_lib/FlexLexer.h +++ b/packages/seacas/libraries/aprepro_lib/FlexLexer.h @@ -2,7 +2,7 @@ // FlexLexer.h -- define interfaces for lexical analyzer classes generated // by flex -// Copyright (c) 1993 The Regents of the University of California. +// Copyright (c) 1993, 2023 The Regents of the University of California. // All rights reserved. // // This code is derived from software contributed to Berkeley by @@ -51,7 +51,7 @@ #include "aprepro_parser.h" extern "C++" { - +// NOLINTBEGIN struct yy_buffer_state; typedef int yy_state_type; @@ -194,6 +194,7 @@ class yyFlexLexer : public FlexLexer int yy_more_offset; int yy_prev_more_offset; }; +// NOLINTEND } #endif // yyFlexLexer || ! yyFlexLexerOnce diff --git a/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc b/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc index c5c51f27a6..255159ff80 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc @@ -5,7 +5,6 @@ // See packages/seacas/LICENSE for details #include "apr_scanner.h" // for Scanner -#include "apr_symrec.h" #include "apr_util.h" #include "aprepro.h" // for Aprepro, symrec, file_rec, etc #include "aprepro_parser.h" // for Parser, Parser::token, etc @@ -35,7 +34,9 @@ #endif namespace { - const std::string version_string{"6.15 (2023/07/12)"}; + const std::string version_short{"6.22"}; + const std::string version_date{"(2023/09/28)"}; + const std::string version_string = version_short + " " + version_date; void output_copyright(); @@ -94,12 +95,19 @@ namespace SEAMS { ap_file_list.emplace(file_rec()); init_table("$"); aprepro = this; + + add_variable("__loop_level__", 0, false, true); } Aprepro::~Aprepro() { if (!outputStream.empty()) { outputStream.top()->flush(); + while (outputStream.size() > 1) { + std::ostream *output = outputStream.top(); + outputStream.pop(); + delete output; + } } // May need to delete this if set via --info=filename command. @@ -125,7 +133,8 @@ namespace SEAMS { cleanup_memory(); } - std::string Aprepro::version() { return version_string; } + const std::string &Aprepro::version() { return version_string; } + const std::string &Aprepro::short_version() { return version_short; } std::string Aprepro::long_version() const { @@ -220,7 +229,7 @@ namespace SEAMS { if (colorize) { (*errorStream) << trmclr::red; } - (*errorStream) << "Aprepro: ERROR: "; + (*errorStream) << "Aprepro-" << short_version() << ": ERROR: "; } ss << msg; @@ -411,7 +420,7 @@ namespace SEAMS { // it returns the same type which means that the "parser_type" is // the same. If we have a function, see if it has already been // defined and if so, check that the parser_type matches and then - // retrn that pointer instead of creating a new symrec. + // return that pointer instead of creating a new symrec. if (is_function) { symrec *ptr = getsym(sym_name); @@ -454,6 +463,9 @@ namespace SEAMS { if (equals == std::string::npos) { equals = option.size(); } + else { + equals = equals - number_dash; + } // NOTE: `option` contains two leading `--` or `-` and a single character... if (!short_opt.empty() && number_dash == 1 && option.substr(1, equals) == short_opt) { diff --git a/packages/seacas/libraries/aprepro_lib/apr_array.cc b/packages/seacas/libraries/aprepro_lib/apr_array.cc index 4a61465bed..b161a3360c 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_array.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_array.cc @@ -1,10 +1,9 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions +// Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // // See packages/seacas/LICENSE for details -#include "apr_symrec.h" #include "aprepro.h" // for array, Aprepro, etc #include // for vector diff --git a/packages/seacas/libraries/aprepro_lib/apr_builtin.cc b/packages/seacas/libraries/aprepro_lib/apr_builtin.cc index 1aaa819e01..f02ea1523c 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_builtin.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_builtin.cc @@ -6,6 +6,7 @@ #include "apr_builtin.h" #include "apr_symrec.h" +#include "enumerate.h" #include #include @@ -22,6 +23,11 @@ #include #include +#if defined FMT_SUPPORT +#include +#include +#endif + #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include @@ -79,8 +85,8 @@ namespace SEAMS { extern SEAMS::Aprepro *aprepro; -#define d2r(x) ((x)*PI / 180.) -#define r2d(x) ((x)*180. / PI) +#define d2r(x) ((x) * PI / 180.) +#define r2d(x) ((x) * 180. / PI) #ifndef max #define max(x, y) (x) > (y) ? (x) : (y) @@ -465,9 +471,9 @@ namespace SEAMS { { double seconds = h * 3600.0 + mi * 60 + se; - long m = static_cast(mon); - long d = static_cast(day); - long y = static_cast(year); + int64_t m = static_cast(mon); + int64_t d = static_cast(day); + int64_t y = static_cast(year); if (m > 2) { m -= 3; @@ -476,9 +482,9 @@ namespace SEAMS { m += 9; --y; } - long c = y / 100L; - long ya = y - (100L * c); - long j = (146097L * c) / 4L + (1461L * ya) / 4L + (153L * m + 2L) / 5L + d + 1721119L; + int64_t c = y / 100L; + int64_t ya = y - (100L * c); + int64_t j = (146097L * c) / 4L + (1461L * ya) / 4L + (153L * m + 2L) / 5L + d + 1721119L; if (seconds < 12 * 3600.0) { j--; seconds += 12.0 * 3600.0; @@ -651,8 +657,8 @@ namespace SEAMS { { const auto &tokens = get_tokenized_strings(string, delm); std::string sword{word}; - for (size_t i = 0; i < tokens.size(); i++) { - if (tokens[i] == sword) { + for (auto [i, token] : enumerate(tokens)) { + if (token == sword) { return i + 1; } } @@ -947,7 +953,18 @@ namespace SEAMS { } lines << "\t"; for (int ic = 0; ic < cols; ic++) { +#if defined FMT_SUPPORT + SEAMS::symrec *format = aprepro->getsym("_FORMAT"); + if (format->value.svar.empty()) { + fmt::print(lines, "{}", my_array_data->data[idx++]); + } + else { + auto tmpstr = fmt::sprintf(format->value.svar, my_array_data->data[idx++]); + lines << tmpstr; + } +#else lines << my_array_data->data[idx++]; +#endif if (ic < cols - 1) { lines << "\t"; } @@ -1021,6 +1038,76 @@ namespace SEAMS { return array_data; } + array *do_principal(const array *a) + { + // Good calculator and a version of malvern's method at: + // https://www.continuummechanics.org/principalstress.html + + auto array_data = aprepro->make_array(3, 1); + + if (a->rows != 3 || a->cols != 3) { + aprepro->error("Invalid array size. Must be 3x3 for principal values calculation.\n", false); + return array_data; + } + if (a->data[1] != a->data[3] || a->data[2] != a->data[6] || a->data[5] != a->data[7]) { + aprepro->error("Array is not symmetric in principal values calculation.\n", false); + return array_data; + } + + const double third = 1.0 / 3.0; + const double sqrt3 = sqrt(3.0); + + // Find principal trial stresses and directions - + // [ 0 1 2 ] [ sk1 sk4 sk6 ] + // [ 3 4 5 ] [ sk4 sk2 sk5 ] + // [ 6 7 8 ] [ sk6 sk5 sk3 ] + + const double sk1 = a->data[0]; + const double sk2 = a->data[4]; + const double sk3 = a->data[8]; + const double sk4 = a->data[1]; + const double sk5 = a->data[5]; + const double sk6 = a->data[2]; + + double dsk12 = sk1 - sk2; + double dsk13 = sk1 - sk3; + double dsk23 = sk2 - sk3; + + double i1 = (sk1 + sk2 + sk3); + double i2 = + (dsk12 * dsk12 + dsk13 * dsk13 + dsk23 * dsk23) / 6.0 + sk4 * sk4 + sk5 * sk5 + sk6 * sk6; + + double s1 = (dsk12 + dsk13) * third; + double s2 = (-dsk12 + dsk23) * third; + double s3 = (-dsk13 - dsk23) * third; + + double i3 = s1 * s2 * s3 + (2. * sk4 * sk5 * sk6) - (s1 * sk5 * sk5) - (s2 * sk6 * sk6) - + (s3 * sk4 * sk4); + + // calculate constants for malvern method (p92) + double fi2 = (i2 == 0.0) ? 1.0 : i2; + + double cos3al = sqrt3 * 1.5 * i3 / fi2 / sqrt(fi2); + // cos3al = sign( min( 1.0, abs(cos3al) ),cos3al ); + + double calpha = cos(acos(cos3al) / 3.0); + double salpha = sqrt(1.0 - calpha * calpha); + + double t = sqrt3 * sqrt(i2); + double p1 = (i1 + t * 2. * calpha) * third; + double p2 = (i1 - t * (calpha + salpha * sqrt3)) * third; + double p3 = (i1 - t * (calpha - salpha * sqrt3)) * third; + + array_data->data[0] = p1; + array_data->data[1] = p2; + array_data->data[2] = p3; + + // ... Sort Into Correct Position (p1 > p2 > p3) + std::sort(array_data->data.begin(), array_data->data.end(), std::greater()); + + return array_data; + } + array *do_csv_array1(const char *filename) { return do_csv_array(filename, 0.0); } array *do_csv_array(const char *filename, double skip) @@ -1131,4 +1218,28 @@ namespace SEAMS { assert(idx == array_data->rows); return array_data; } + + array *do_sym_tensor_from_string(const char *string, const char *delm) + { + auto array_data = aprepro->make_array(3, 3); + auto tokens = SEAMS::tokenize(string, delm); + if (tokens.size() != 6) { + aprepro->error("Incorrect number of values found in sym_tensor_from_string function. Must " + "be 6: xx, yy, zz, xy, yz, xz.\n", + false); + return array_data; + } + + array_data->data[0] = std::stod(tokens[0]); + array_data->data[4] = std::stod(tokens[1]); + array_data->data[8] = std::stod(tokens[2]); + array_data->data[1] = std::stod(tokens[3]); + array_data->data[5] = std::stod(tokens[4]); + array_data->data[2] = std::stod(tokens[5]); + array_data->data[3] = array_data->data[1]; + array_data->data[7] = array_data->data[5]; + array_data->data[6] = array_data->data[2]; + + return array_data; + } } // namespace SEAMS diff --git a/packages/seacas/libraries/aprepro_lib/apr_builtin.h b/packages/seacas/libraries/aprepro_lib/apr_builtin.h index d896cf29fb..bf8ee7340b 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_builtin.h +++ b/packages/seacas/libraries/aprepro_lib/apr_builtin.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -92,8 +92,6 @@ namespace SEAMS { const char *do_dumpsym1(char *pre); const char *do_dumpfunc1(char *pre); const char *do_dumpvar1(char *pre); - const char *do_tolower(char *string); - const char *do_toupper(char *string); const char *do_Units(char *type); const char *do_file_to_string(char *filename); const char *do_error(char *error_string); @@ -101,7 +99,6 @@ namespace SEAMS { const char *do_getenv(char *env); const char *do_output(char *filename); const char *do_append(char *filename); - const char *do_execute(char *string); const char *do_rescan(char *string); const char *do_if(double x); @@ -109,29 +106,16 @@ namespace SEAMS { const char *do_elseif(double x); const char *do_switch(double x); const char *do_case(double x); - const char *do_intout(double intval); - const char *do_tostring(double x); const char *do_get_word(double n, char *string, char *delm); - const char *do_extract(char *string, char *begin, char *end); const char *do_print_array(const array *my_array_data); const char *do_import(char *string); const char *do_execute(char *string); - const char *do_getenv(char *env); const char *do_tolower(char *string); const char *do_toupper(char *string); const char *do_tostring(double x); - const char *do_output(char *filename); - const char *do_append(char *filename); - const char *do_error(char *error_string); - const char *do_get_date(); - const char *do_get_iso_date(); - const char *do_get_time(); - const char *do_get_word(double n, char *string, char *delm); - const char *do_file_to_string(char *filename); const char *do_extract(char *string, char *begin, char *end); - const char *do_include_path(char *new_path); const char *do_intout(double intval); const char *do_print_array(array *my_array_data); const char *do_str_if(char *string); @@ -153,5 +137,7 @@ namespace SEAMS { array *do_linear_array(double init, double final, double count); array *do_identity(double size); array *do_transpose(const array *a); + array *do_principal(const array *a); array *do_array_from_string(const char *string, const char *delm); + array *do_sym_tensor_from_string(const char *string, const char *delm); } // namespace SEAMS diff --git a/packages/seacas/libraries/aprepro_lib/apr_init.cc b/packages/seacas/libraries/aprepro_lib/apr_init.cc index fd7661ca2c..ce8c16b2c7 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_init.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_init.cc @@ -11,11 +11,11 @@ Initialize variables and functions Aprepro ***/ #include "apr_builtin.h" -#include "apr_symrec.h" #include "apr_tokenize.h" #include "aprepro.h" // for symrec, Aprepro, etc #include "init_structs.h" // for array_a_init, array_c_init, etc -#include // for string +#include +#include // for string namespace SEAMS { init arith_0_fncts[] = { @@ -28,7 +28,7 @@ namespace SEAMS { {"acosd", do_acosd, "acosd(x)", "Inverse cosine of x, returns degrees."}, {"acosh", do_acosh, "acosh(x)", "Inverse hyperbolic cosine of x."}, {"asin", do_asin, "asin(x)", "Inverse sine of x, returns radians."}, - {"asind", do_asind, "asin(x)", "Inverse sine of x, returns degrees."}, + {"asind", do_asind, "asind(x)", "Inverse sine of x, returns degrees."}, {"asinh", do_asinh, "asinh(x)", "Inverse hyperbolic sine of x."}, {"atan", do_atan, "atan(x)", "Inverse tangent of x, returns radians."}, {"atand", do_atand, "atand(x)", "Inverse tangent of x, returns degrees."}, @@ -317,6 +317,10 @@ namespace SEAMS { " The array double values are\n\t\t\tseparated by one or more of the characters in the " "string " "variable delim."}, + {"sym_tensor_from_string", do_sym_tensor_from_string, "sym_tensor_from_string(string, delim)", + "Create a 3x3 symmetric array from the data in a delimited string." + " The six array values are\n\t\t\tseparated by one or more of the characters in the " + "string variable delim. Order is xx, yy, zz, xy, yz, xz."}, {nullptr, nullptr, nullptr, nullptr}}; array_ddd_init array_ddd_fncts[] = { @@ -338,6 +342,8 @@ namespace SEAMS { array_a_init array_a_fncts[] = { {"transpose", do_transpose, "transpose(array)", "Return the transpose of input array"}, + {"principal_stress", do_principal, "principal_stress(array)", + "Calculate principal stresses of symmetric 3x3 stress tensor (array)."}, {nullptr, nullptr, nullptr, nullptr}}; // clang-format off @@ -358,6 +364,7 @@ namespace SEAMS { // clang-format on svar_init svariables[] = {{"_FORMAT", "%.10g"}, /* Default output format */ + {"_UNITS_SYSTEM", "none"}, {nullptr, nullptr}}; /* NOTE: The current comment is stored in "_C_" * Since it can be changed by user on command line, we diff --git a/packages/seacas/libraries/aprepro_lib/apr_parser.cc b/packages/seacas/libraries/aprepro_lib/apr_parser.cc index 9e547e2e0b..2e9defa48e 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_parser.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_parser.cc @@ -46,6 +46,7 @@ #if defined FMT_SUPPORT #include +#include #endif #include #include @@ -388,7 +389,6 @@ namespace SEAMS { int yylen = 0; // Error handling. - int yynerrs_ = 0; int yyerrstatus_ = 0; /// The lookahead symbol. @@ -543,10 +543,8 @@ namespace SEAMS { #endif } else { - static char tmpstr[512]; - int len = - snprintf(tmpstr, 512, format->value.svar.c_str(), (yystack_[1].value.val)); - aprepro.lexer->LexerOutput(tmpstr, len); + auto tmpstr = fmt::sprintf(format->value.svar, (yystack_[1].value.val)); + aprepro.lexer->LexerOutput(tmpstr.c_str(), tmpstr.size()); } } } @@ -556,7 +554,7 @@ namespace SEAMS { case 6: // line: LBRACE sexp RBRACE #line 137 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { - if (echo && (yystack_[1].value.string) != NULL) { + if (echo && (yystack_[1].value.string) != nullptr) { aprepro.lexer->LexerOutput((yystack_[1].value.string), strlen((yystack_[1].value.string))); } @@ -780,7 +778,7 @@ namespace SEAMS { #line 172 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.arrfnct_c == NULL)) + (yystack_[3].value.tptr)->value.arrfnct_c == nullptr)) (yylhs.value.arrval) = (*((yystack_[3].value.tptr)->value.arrfnct_c))((yystack_[1].value.string)); else @@ -793,7 +791,7 @@ namespace SEAMS { #line 178 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.arrfnct_cd == NULL)) + (yystack_[5].value.tptr)->value.arrfnct_cd == nullptr)) (yylhs.value.arrval) = (*((yystack_[5].value.tptr)->value.arrfnct_cd))( (yystack_[3].value.string), (yystack_[1].value.val)); else @@ -806,7 +804,7 @@ namespace SEAMS { #line 184 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.arrfnct_cc == NULL)) + (yystack_[5].value.tptr)->value.arrfnct_cc == nullptr)) (yylhs.value.arrval) = (*((yystack_[5].value.tptr)->value.arrfnct_cc))( (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -819,7 +817,7 @@ namespace SEAMS { #line 190 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.arrfnct_ddd == NULL)) + (yystack_[7].value.tptr)->value.arrfnct_ddd == nullptr)) (yylhs.value.arrval) = (*((yystack_[7].value.tptr)->value.arrfnct_ddd))( (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -832,7 +830,7 @@ namespace SEAMS { #line 196 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.arrfnct_dd == NULL)) + (yystack_[5].value.tptr)->value.arrfnct_dd == nullptr)) (yylhs.value.arrval) = (*((yystack_[5].value.tptr)->value.arrfnct_dd))( (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -845,7 +843,7 @@ namespace SEAMS { #line 202 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.arrfnct_d == NULL)) + (yystack_[3].value.tptr)->value.arrfnct_d == nullptr)) (yylhs.value.arrval) = (*((yystack_[3].value.tptr)->value.arrfnct_d))((yystack_[1].value.val)); else @@ -858,7 +856,7 @@ namespace SEAMS { #line 208 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.arrfnct_a == NULL)) + (yystack_[3].value.tptr)->value.arrfnct_a == nullptr)) (yylhs.value.arrval) = (*((yystack_[3].value.tptr)->value.arrfnct_a))((yystack_[1].value.arrval)); else @@ -1081,7 +1079,7 @@ namespace SEAMS { #line 276 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.strfnct_c == NULL)) + (yystack_[3].value.tptr)->value.strfnct_c == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[3].value.tptr)->value.strfnct_c))( (yystack_[1].value.string)); else @@ -1094,7 +1092,7 @@ namespace SEAMS { #line 282 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[2].value.tptr), - (yystack_[2].value.tptr)->value.strfnct == NULL)) + (yystack_[2].value.tptr)->value.strfnct == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[2].value.tptr)->value.strfnct))(); else (yylhs.value.string) = (char *)""; @@ -1106,7 +1104,7 @@ namespace SEAMS { #line 288 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.strfnct_d == NULL)) + (yystack_[3].value.tptr)->value.strfnct_d == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[3].value.tptr)->value.strfnct_d))((yystack_[1].value.val)); else @@ -1119,7 +1117,7 @@ namespace SEAMS { #line 294 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.strfnct_a == NULL)) + (yystack_[3].value.tptr)->value.strfnct_a == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[3].value.tptr)->value.strfnct_a))( (yystack_[1].value.arrval)); else @@ -1141,7 +1139,7 @@ namespace SEAMS { #line 301 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.strfnct_dd == NULL)) + (yystack_[5].value.tptr)->value.strfnct_dd == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[5].value.tptr)->value.strfnct_dd))( (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -1154,7 +1152,7 @@ namespace SEAMS { #line 307 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[11].value.tptr), - (yystack_[11].value.tptr)->value.strfnct_dcccc == NULL)) + (yystack_[11].value.tptr)->value.strfnct_dcccc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[11].value.tptr)->value.strfnct_dcccc))( (yystack_[9].value.val), (yystack_[7].value.string), (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.string)); @@ -1168,7 +1166,7 @@ namespace SEAMS { #line 313 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.strfnct_dcc == NULL)) + (yystack_[7].value.tptr)->value.strfnct_dcc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[7].value.tptr)->value.strfnct_dcc))( (yystack_[5].value.val), (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -1181,7 +1179,7 @@ namespace SEAMS { #line 319 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.strfnct_ccc == NULL)) + (yystack_[7].value.tptr)->value.strfnct_ccc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[7].value.tptr)->value.strfnct_ccc))( (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.string)); @@ -1195,7 +1193,7 @@ namespace SEAMS { #line 325 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.strfnct_cc == NULL)) + (yystack_[5].value.tptr)->value.strfnct_cc == nullptr)) (yylhs.value.string) = (char *)(*((yystack_[5].value.tptr)->value.strfnct_cc))( (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -1586,7 +1584,7 @@ namespace SEAMS { #line 408 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[2].value.tptr), - (yystack_[2].value.tptr)->value.fnctptr == NULL)) + (yystack_[2].value.tptr)->value.fnctptr == nullptr)) (yylhs.value.val) = (*((yystack_[2].value.tptr)->value.fnctptr))(); else (yylhs.value.val) = 0.0; @@ -1598,7 +1596,7 @@ namespace SEAMS { #line 415 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.fnctptr_d == NULL)) + (yystack_[3].value.tptr)->value.fnctptr_d == nullptr)) (yylhs.value.val) = (*((yystack_[3].value.tptr)->value.fnctptr_d))((yystack_[1].value.val)); else @@ -1611,7 +1609,7 @@ namespace SEAMS { #line 422 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.fnctptr_c == NULL)) + (yystack_[3].value.tptr)->value.fnctptr_c == nullptr)) (yylhs.value.val) = (*((yystack_[3].value.tptr)->value.fnctptr_c))((yystack_[1].value.string)); else @@ -1624,7 +1622,7 @@ namespace SEAMS { #line 429 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[3].value.tptr), - (yystack_[3].value.tptr)->value.fnctptr_a == NULL)) + (yystack_[3].value.tptr)->value.fnctptr_a == nullptr)) (yylhs.value.val) = (*((yystack_[3].value.tptr)->value.fnctptr_a))((yystack_[1].value.arrval)); else @@ -1637,7 +1635,7 @@ namespace SEAMS { #line 436 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_cd == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_cd == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_cd))( (yystack_[3].value.string), (yystack_[1].value.val)); else @@ -1650,7 +1648,7 @@ namespace SEAMS { #line 443 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_dc == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_dc == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_dc))( (yystack_[3].value.val), (yystack_[1].value.string)); else @@ -1663,7 +1661,7 @@ namespace SEAMS { #line 450 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_cc == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_cc == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_cc))( (yystack_[3].value.string), (yystack_[1].value.string)); else @@ -1676,7 +1674,7 @@ namespace SEAMS { #line 457 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.fnctptr_ccc == NULL)) + (yystack_[7].value.tptr)->value.fnctptr_ccc == nullptr)) (yylhs.value.val) = (*((yystack_[7].value.tptr)->value.fnctptr_ccc))( (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.string)); @@ -1690,7 +1688,7 @@ namespace SEAMS { #line 464 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[5].value.tptr), - (yystack_[5].value.tptr)->value.fnctptr_dd == NULL)) + (yystack_[5].value.tptr)->value.fnctptr_dd == nullptr)) (yylhs.value.val) = (*((yystack_[5].value.tptr)->value.fnctptr_dd))( (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -1703,7 +1701,7 @@ namespace SEAMS { #line 470 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.fnctptr_ddd == NULL)) + (yystack_[7].value.tptr)->value.fnctptr_ddd == nullptr)) (yylhs.value.val) = (*((yystack_[7].value.tptr)->value.fnctptr_ddd))( (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); else @@ -1716,7 +1714,7 @@ namespace SEAMS { #line 476 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[7].value.tptr), - (yystack_[7].value.tptr)->value.fnctptr_ccd == NULL)) + (yystack_[7].value.tptr)->value.fnctptr_ccd == nullptr)) (yylhs.value.val) = (*((yystack_[7].value.tptr)->value.fnctptr_ccd))( (yystack_[5].value.string), (yystack_[3].value.string), (yystack_[1].value.val)); else @@ -1729,7 +1727,7 @@ namespace SEAMS { #line 482 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[9].value.tptr), - (yystack_[9].value.tptr)->value.fnctptr_dddd == NULL)) + (yystack_[9].value.tptr)->value.fnctptr_dddd == nullptr)) (yylhs.value.val) = (*((yystack_[9].value.tptr)->value.fnctptr_dddd))( (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); @@ -1743,7 +1741,7 @@ namespace SEAMS { #line 488 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[9].value.tptr), - (yystack_[9].value.tptr)->value.fnctptr_dddd == NULL)) + (yystack_[9].value.tptr)->value.fnctptr_dddd == nullptr)) (yylhs.value.val) = (*((yystack_[9].value.tptr)->value.fnctptr_dddd))( (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); @@ -1757,7 +1755,7 @@ namespace SEAMS { #line 494 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[11].value.tptr), - (yystack_[11].value.tptr)->value.fnctptr_ddddc == NULL)) + (yystack_[11].value.tptr)->value.fnctptr_ddddc == nullptr)) (yylhs.value.val) = (*((yystack_[11].value.tptr)->value.fnctptr_ddddc))( (yystack_[9].value.val), (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.string)); @@ -1771,7 +1769,7 @@ namespace SEAMS { #line 500 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (arg_check((yystack_[13].value.tptr), - (yystack_[13].value.tptr)->value.fnctptr_dddddd == NULL)) + (yystack_[13].value.tptr)->value.fnctptr_dddddd == nullptr)) (yylhs.value.val) = (*((yystack_[13].value.tptr)->value.fnctptr_dddddd))( (yystack_[11].value.val), (yystack_[9].value.val), (yystack_[7].value.val), (yystack_[5].value.val), (yystack_[3].value.val), (yystack_[1].value.val)); @@ -1991,7 +1989,6 @@ namespace SEAMS { yyerrlab: // If not already recovering from an error, report this error. if (!yyerrstatus_) { - ++yynerrs_; context yyctx(*this, yyla); std::string msg = yysyntax_error_(yyctx); error(YY_MOVE(msg)); diff --git a/packages/seacas/libraries/aprepro_lib/apr_scanner.cc b/packages/seacas/libraries/aprepro_lib/apr_scanner.cc index c00575dee7..8a644a03af 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_scanner.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_scanner.cc @@ -209,7 +209,7 @@ typedef size_t yy_size_t; #endif /* %if-not-reentrant */ -extern yy_size_t yyleng; +extern int yyleng; /* %endif */ /* %if-c-only */ @@ -386,7 +386,7 @@ typedef unsigned char YY_CHAR; #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */ \ - yyleng = (size_t)(yy_cp - yy_bp); \ + yyleng = (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */ \ @@ -402,57 +402,49 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[703] = { - 0, 0, 0, 52, 52, 0, 0, 41, 41, 0, 0, 2, 2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 103, 100, 100, 101, 98, 99, 99, 99, 100, 95, 52, - 72, 87, 100, 69, 100, 100, 73, 74, 65, 63, 75, 64, 51, 68, 50, 77, 76, - 79, 54, 80, 78, 53, 53, 53, 88, 89, 70, 95, 100, 92, 66, 100, 100, 98, - 99, 99, 99, 100, 95, 44, 44, 45, 41, 44, 41, 41, 41, 41, 44, 44, 100, - 3, 3, 4, 2, 3, 2, 2, 2, 2, 3, 3, 100, 100, 35, 98, 99, - - 99, 99, 100, 95, 100, 100, 98, 100, 100, 99, 99, 99, 100, 95, 100, 100, 19, - 98, 99, 99, 99, 100, 95, 100, 100, 23, 98, 99, 99, 99, 100, 95, 100, 100, - 27, 98, 99, 99, 99, 100, 95, 0, 0, 99, 99, 99, 93, 94, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 52, 0, 84, 0, 90, 85, 0, 91, 71, 57, - 61, 55, 62, 56, 51, 0, 67, 58, 51, 50, 0, 81, 83, 82, 53, 53, 53, - 59, 0, 86, 0, 0, 0, 0, 99, 99, 99, 93, 94, 0, 0, 0, - - 41, 41, 41, 41, 41, 42, 43, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, - 0, 35, 0, 0, 99, 99, 99, 93, 94, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 99, 99, 99, 93, 94, 0, 0, 19, 0, 0, 99, 99, - 99, 93, 94, 0, 0, 0, 0, 23, 0, 0, 99, 99, 99, 93, 94, 0, 0, - 0, 0, 27, 0, 0, 99, 99, 99, 93, 94, 0, 0, 0, 0, 0, 99, 99, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, - - 51, 0, 50, 53, 53, 0, 49, 99, 99, 0, 0, 41, 41, 0, 0, 0, 2, - 2, 0, 99, 99, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, - 99, 99, 0, 0, 99, 99, 0, 0, 0, 0, 99, 99, 0, 0, 0, 0, 99, - 99, 0, 0, 0, 0, 0, 0, 96, 97, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 53, 53, 49, 96, 97, 0, 0, 41, 41, 0, 0, - 0, 37, 0, 0, 2, 2, 0, 96, 97, 0, 0, 0, 0, 0, 0, - - 0, 15, 0, 0, 13, 0, 0, 14, 0, 96, 97, 0, 0, 96, 97, 0, 0, - 0, 0, 96, 97, 0, 0, 0, 0, 96, 97, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, - 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 39, 0, 0, 0, - 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 35, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 17, 0, 0, 23, - 0, 0, 0, 21, 0, 27, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 30, - 0, 8, 0, 0, 0, 0, 49, 0, 0, 0, 40, 0, 38, 0, 0, - - 31, 0, 32, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 23, 0, 0, - 27, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 39, 0, 49, 0, - 0, 34, 0, 15, 0, 0, 0, 0, 16, 0, 0, 20, 0, 0, 0, 0, 48, - 0, 7, 0, 0, 0, 25, 0, 46, 0, 0, 0, 15, 0, 0, 0, 0, 25, - 0, 9, 0, 0, 0, 0, 0, 0, 0, 18, 0, 22, 0, 0, 0, 0, 0, - 28, 0, 0, 26, 0, 0, 0, 0, 0, 0, 5, 0, 0, 10, 1, - - 11, 0}; +static yyconst flex_int16_t yy_accept[685] = { + 0, 0, 0, 50, 50, 0, 0, 39, 39, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 103, 100, 100, 101, 98, 99, 99, 99, 100, 95, 50, 70, 85, 100, 67, 100, 100, + 71, 72, 63, 61, 73, 62, 49, 66, 48, 75, 74, 77, 52, 78, 76, 51, 51, 51, 86, 87, + 68, 95, 100, 90, 64, 100, 100, 98, 99, 99, 99, 100, 95, 42, 42, 43, 39, 42, 39, 39, + 39, 39, 42, 42, 100, 3, 3, 4, 2, 3, 2, 2, 2, 2, 3, 3, 100, 100, 33, 98, + 99, + + 99, 99, 100, 95, 100, 100, 98, 99, 99, 99, 100, 95, 100, 100, 17, 98, 99, 99, 99, 100, + 95, 100, 100, 21, 98, 99, 99, 99, 100, 95, 100, 100, 25, 98, 99, 99, 99, 100, 95, 0, + 0, 99, 99, 99, 92, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 50, 0, 82, + 0, 88, 83, 0, 89, 69, 55, 59, 53, 60, 54, 49, 0, 65, 56, 49, 48, 0, 79, 81, + 80, 51, 51, 51, 57, 0, 84, 91, 0, 0, 0, 0, 99, 99, 99, 92, 93, 0, 94, 0, + + 0, 39, 39, 39, 39, 39, 40, 41, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 33, + 0, 0, 99, 99, 99, 92, 93, 0, 0, 94, 0, 0, 0, 0, 99, 99, 99, 92, 93, 0, + 94, 0, 17, 0, 0, 99, 99, 99, 92, 93, 0, 0, 0, 94, 0, 21, 0, 0, 99, 99, + 99, 92, 93, 0, 0, 0, 94, 0, 25, 0, 0, 99, 99, 99, 92, 93, 0, 0, 0, 0, + 0, 94, 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 49, + + 0, 48, 51, 51, 0, 47, 99, 99, 0, 0, 39, 39, 0, 0, 0, 2, 2, 0, 99, 99, + 0, 0, 0, 0, 99, 99, 0, 0, 99, 99, 0, 0, 0, 0, 99, 99, 0, 0, 0, 0, + 99, 99, 0, 0, 0, 0, 0, 0, 96, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 51, 47, 96, 97, 0, 0, 39, 39, 0, 0, 0, 35, 0, 0, 2, + 2, 0, 96, 97, 0, 0, 0, 0, 0, 0, 0, 13, 0, 96, 97, 0, 0, 96, 97, 0, + + 0, 0, 0, 96, 97, 0, 0, 0, 0, 96, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 37, 0, 0, 0, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17, 0, 0, 0, 15, 0, 0, 21, 0, 0, 0, 19, 0, 25, 0, 0, 0, 0, + 0, 0, 0, 44, 0, 0, 28, 0, 8, 0, 0, 0, 0, 47, 0, 0, 0, 38, 0, 36, + 0, 0, 29, 0, 30, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 21, 0, 0, 25, + + 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 37, 0, 47, 0, 0, 32, 0, 13, + 0, 0, 0, 0, 14, 0, 0, 18, 0, 0, 0, 0, 46, 0, 7, 0, 0, 0, 23, 0, + 44, 0, 0, 0, 13, 0, 0, 0, 0, 23, 0, 9, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 20, 0, 0, 0, 0, 0, 26, 0, 0, 24, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 10, 1, 11, 0}; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, @@ -476,123 +468,120 @@ static yyconst flex_int32_t yy_meta[69] = {0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 1, 1, 1}; -static yyconst flex_int16_t yy_base[752] = { +static yyconst flex_int16_t yy_base[731] = { 0, 0, 0, 68, 0, 136, 0, 204, 0, 271, 272, 337, 0, 405, 0, - 473, 0, 541, 0, 609, 0, 677, 0, 2511, 2512, 744, 2512, 2512, 0, 2467, - 236, 213, 808, 748, 2512, 2486, 276, 2512, 2499, 2497, 2512, 2512, 268, 269, 2512, - 270, 265, 267, 270, 2512, 2512, 2483, 2482, 2481, 2512, 0, 2460, 247, 2512, 2512, - 2479, 264, 2435, 2512, 2512, 2488, 749, 2487, 864, 2455, 255, 735, 737, 2512, 752, - 2512, 753, 2512, 756, 293, 755, 756, 236, 775, 760, 2512, 761, 2512, 764, 2512, - 767, 294, 768, 774, 237, 277, 2494, 778, 2512, 2493, 932, - - 2452, 264, 768, 801, 2482, 781, 2481, 989, 990, 1042, 2449, 265, 780, 810, 2488, - 1109, 2512, 2487, 1174, 2446, 267, 784, 1111, 2485, 1241, 2512, 2484, 1306, 2443, 268, - 787, 1112, 2482, 1373, 2512, 2481, 1438, 2440, 270, 1504, 1119, 1507, 2440, 0, 279, - 740, 2512, 2512, 1114, 2426, 975, 771, 2422, 2442, 2448, 2425, 264, 717, 1508, 771, - 2512, 320, 2512, 2512, 2466, 2512, 2452, 2512, 2512, 2512, 2512, 2512, 985, 997, 2512, - 2512, 987, 993, 1008, 2512, 2512, 2512, 0, 806, 981, 2512, 268, 2512, 2462, 1511, - 1512, 1105, 0, 985, 1092, 2461, 2460, 1116, 1515, 1244, - - 1516, 1519, 787, 1243, 1245, 2512, 2512, 1249, 969, 2418, 1523, 1524, 1520, 1001, 1248, - 1250, 2440, 2466, 2512, 1527, 1375, 0, 1093, 1096, 2465, 2464, 1376, 1378, 2454, 1368, - 1530, 1243, 1532, 1245, 1120, 1370, 1250, 1371, 1142, 0, 1097, 1098, 2453, 2452, 1372, - 2460, 2512, 1535, 1549, 0, 1100, 1107, 2459, 2458, 1255, 1505, 1533, 2457, 2512, 1543, - 1564, 0, 1217, 1227, 2456, 2455, 1537, 1546, 1538, 2454, 2512, 1552, 1607, 0, 1233, - 1234, 2453, 2452, 1611, 1550, 800, 1382, 1562, 1231, 1347, 2397, 2396, 2420, 2390, 2399, - 2414, 977, 2398, 2389, 2416, 2406, 2391, 2392, 2512, 2423, - - 2422, 2421, 2420, 1349, 1351, 1556, 1026, 1352, 1353, 1521, 804, 1620, 1624, 2382, 2376, - 1623, 1625, 1626, 2397, 1354, 1355, 796, 1571, 1639, 1282, 1394, 2512, 1554, 1395, 1108, - 1131, 1400, 1272, 1406, 1359, 1360, 1575, 1581, 1362, 1364, 1573, 1623, 1601, 1635, 1508, - 1593, 1636, 1644, 1632, 1645, 1609, 1611, 1650, 1651, 1653, 1664, 1383, 1665, 0, 0, - 2384, 2384, 2396, 2380, 1636, 2390, 2378, 2378, 2372, 2368, 2398, 2398, 2376, 1637, 0, - 0, 2420, 0, 0, 1663, 1664, 1539, 1675, 2361, 2369, 1697, 2512, 2368, 2368, 1698, - 1702, 2391, 0, 0, 1669, 1678, 1724, 2414, 1682, 1686, - - 1407, 2512, 1697, 1711, 2512, 1717, 1727, 2512, 1728, 0, 0, 1665, 1712, 0, 0, - 1710, 1707, 1735, 1729, 0, 0, 1733, 1740, 1741, 1739, 0, 0, 1738, 1747, 1745, - 1749, 1746, 1748, 2355, 2359, 1735, 2347, 2360, 2372, 2358, 2358, 2346, 1751, 2376, 2381, - 2343, 2341, 1744, 1751, 2352, 1750, 2350, 2350, 2375, 1751, 1754, 2397, 2512, 1755, 1758, - 1768, 1770, 1773, 1748, 1753, 1763, 1769, 1774, 1776, 1810, 1783, 1784, 1813, 1816, 1820, - 1817, 1823, 1826, 2396, 1825, 1827, 2335, 2360, 2512, 2393, 2328, 2368, 1831, 2340, 2341, - 1835, 2512, 2354, 2350, 2102, 2089, 1829, 1826, 1807, 2084, - - 1845, 2079, 2072, 2108, 1840, 1850, 1841, 1845, 1838, 1852, 2107, 1855, 1856, 1861, 2106, - 1864, 2104, 1857, 1865, 1873, 2103, 2102, 1866, 2100, 2512, 1870, 1877, 2051, 999, 2098, - 2512, 2097, 2072, 1881, 2512, 1885, 2046, 2029, 2062, 2032, 2031, 1892, 1897, 1894, 2089, - 1908, 2512, 1914, 2058, 2087, 2512, 2086, 1925, 2085, 1935, 1899, 1918, 1928, 1900, 2084, - 2512, 2083, 1910, 2081, 2512, 1912, 2080, 2512, 2079, 1914, 2078, 2512, 2077, 2512, 2076, - 1879, 1931, 2025, 2045, 2063, 2070, 2512, 2038, 1940, 2512, 1941, 2512, 2036, 1945, 2020, - 1951, 1945, 1947, 1963, 2066, 2512, 1970, 2512, 2033, 2062, - - 2512, 2061, 2512, 1975, 2060, 1959, 1977, 1979, 1932, 2059, 2512, 2058, 1953, 2057, 2512, - 2055, 2054, 2512, 1992, 817, 1995, 2044, 1988, 2024, 1996, 2512, 2042, 1999, 2049, 1997, - 2031, 2011, 1980, 2015, 2006, 2512, 2005, 2512, 2007, 2013, 1965, 2002, 2512, 1973, 1985, - 2512, 2018, 1984, 1981, 2025, 2512, 1894, 2512, 1949, 1844, 1868, 2512, 2000, 1867, 1710, - 2025, 2028, 2512, 2030, 1675, 1561, 1560, 2512, 2041, 2512, 1514, 1514, 2037, 1417, 1365, - 2035, 1289, 2512, 1287, 2512, 2046, 1284, 1088, 1274, 1258, 2512, 1228, 1253, 2512, 1113, - 1021, 729, 774, 772, 268, 2512, 265, 248, 2512, 2512, - - 2512, 2512, 2109, 2115, 2121, 2123, 2129, 2134, 2136, 2141, 2143, 2149, 2155, 2161, 2167, - 2173, 2179, 2185, 2191, 2197, 2203, 2209, 2215, 2221, 2227, 2233, 2239, 2245, 2251, 2257, - 2263, 2269, 2275, 2281, 2287, 2293, 2299, 2305, 2311, 2317, 2323, 2329, 2335, 2341, 2347, - 2353, 2359, 2365, 2371, 2377, 2383}; - -static yyconst flex_int16_t yy_def[752] = { - 0, 702, 1, 702, 3, 702, 5, 702, 7, 1, 1, 702, 11, 702, 13, 702, 15, - 702, 17, 702, 19, 702, 21, 702, 702, 702, 702, 702, 703, 703, 703, 702, 702, 702, - 702, 702, 704, 702, 702, 705, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 706, 706, 706, 702, 702, 702, 702, 702, 702, 702, 707, 707, 707, - 702, 68, 68, 707, 707, 702, 702, 702, 708, 702, 708, 709, 709, 709, 702, 702, 702, - 702, 702, 702, 710, 702, 710, 711, 711, 711, 702, 702, 712, 712, 702, 712, 702, - - 100, 100, 712, 712, 713, 713, 713, 713, 713, 702, 110, 110, 713, 713, 714, 714, 702, - 714, 702, 119, 119, 714, 714, 715, 715, 702, 715, 702, 128, 128, 715, 715, 716, 716, - 702, 716, 702, 137, 137, 716, 716, 702, 32, 703, 703, 703, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 704, 702, 702, 705, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 706, 706, 706, - 702, 702, 702, 707, 707, 707, 707, 68, 68, 68, 707, 707, 707, 702, 702, - - 708, 708, 709, 709, 709, 702, 702, 702, 702, 702, 702, 710, 710, 711, 711, 711, 702, - 712, 702, 712, 712, 100, 100, 100, 712, 712, 712, 712, 713, 713, 713, 713, 717, 713, - 713, 713, 713, 713, 713, 110, 110, 110, 713, 713, 713, 714, 702, 714, 714, 119, 119, - 119, 714, 714, 714, 714, 714, 715, 702, 715, 715, 128, 128, 128, 715, 715, 715, 715, - 715, 716, 702, 716, 716, 137, 137, 137, 716, 716, 716, 716, 716, 716, 716, 703, 703, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - - 702, 702, 702, 706, 706, 707, 707, 68, 68, 707, 707, 709, 709, 702, 702, 702, 711, - 711, 702, 100, 100, 712, 712, 712, 718, 717, 702, 717, 719, 713, 713, 720, 713, 713, - 110, 110, 713, 713, 119, 119, 714, 714, 714, 714, 128, 128, 715, 715, 715, 715, 137, - 137, 716, 716, 716, 716, 716, 716, 703, 703, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 706, 706, 702, 68, 68, 707, 707, 709, 709, 702, 702, - 702, 702, 702, 702, 711, 711, 702, 100, 100, 712, 712, 712, 721, 712, 712, - - 718, 702, 718, 719, 702, 719, 720, 702, 720, 110, 110, 713, 713, 119, 119, 714, 714, - 714, 714, 128, 128, 715, 715, 715, 715, 137, 137, 716, 716, 716, 716, 716, 716, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 707, 707, 702, 702, - 702, 702, 702, 712, 712, 721, 702, 712, 712, 718, 719, 720, 713, 713, 714, 714, 714, - 714, 714, 715, 715, 715, 715, 715, 716, 716, 716, 722, 716, 716, 702, 702, 702, 723, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 724, 707, 702, 702, - - 702, 702, 702, 725, 712, 712, 712, 726, 713, 714, 727, 714, 714, 714, 728, 715, 729, - 715, 715, 715, 730, 731, 716, 722, 702, 716, 716, 702, 702, 723, 702, 732, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 724, 724, 733, 734, 702, 702, 702, 702, 725, 702, - 735, 712, 736, 712, 726, 726, 737, 714, 727, 702, 738, 714, 728, 702, 715, 729, 702, - 739, 715, 730, 702, 731, 702, 740, 716, 716, 702, 702, 702, 732, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 724, 724, 733, 733, 734, 702, 702, 702, 702, 735, - - 702, 736, 702, 712, 741, 742, 737, 737, 714, 738, 702, 743, 715, 739, 702, 744, 740, - 702, 716, 716, 702, 702, 702, 702, 702, 702, 702, 702, 745, 702, 702, 733, 733, 702, - 741, 702, 742, 702, 742, 746, 714, 743, 702, 715, 744, 702, 716, 747, 716, 702, 702, - 702, 702, 702, 702, 745, 702, 702, 702, 702, 742, 746, 702, 746, 748, 749, 747, 702, - 716, 702, 702, 702, 702, 750, 702, 746, 748, 702, 749, 702, 716, 751, 702, 702, 750, - 702, 702, 751, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - - 702, 0, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702}; - -static yyconst flex_int16_t yy_nxt[2581] = { + 473, 0, 541, 0, 609, 0, 677, 0, 2445, 2446, 744, 2446, 2446, 0, 2401, + 236, 213, 808, 748, 2446, 2420, 276, 2446, 2433, 2431, 2446, 2446, 268, 269, 2446, + 270, 265, 267, 270, 2446, 2446, 2417, 2416, 2415, 2446, 0, 2394, 247, 2446, 2446, + 2413, 264, 2369, 2367, 2446, 2421, 749, 2420, 873, 2388, 255, 735, 742, 2446, 753, + 2446, 754, 2446, 757, 293, 745, 758, 236, 765, 762, 2446, 766, 2446, 769, 2446, + 758, 294, 772, 770, 237, 751, 2427, 780, 2446, 2426, 941, + + 2385, 264, 772, 802, 2415, 775, 2414, 1009, 2382, 265, 784, 796, 2421, 1076, 2446, + 2420, 1141, 2379, 267, 788, 1207, 2418, 1209, 2446, 2417, 1274, 2376, 268, 801, 1340, + 2415, 1342, 2446, 2414, 1407, 2373, 270, 1473, 1476, 1479, 270, 0, 730, 773, 2446, + 2446, 1079, 2360, 815, 812, 2356, 2376, 2382, 2359, 263, 268, 2446, 1480, 794, 2446, + 320, 2446, 2446, 2400, 2446, 2386, 2446, 2446, 2446, 2446, 2446, 1063, 1070, 2446, 2446, + 1066, 1071, 1078, 2446, 2446, 2446, 0, 1054, 1058, 2446, 1042, 2446, 2446, 2396, 1483, + 1484, 1202, 0, 1062, 1067, 2395, 2394, 1204, 2393, 1487, + + 1213, 1488, 787, 1099, 1214, 1215, 2446, 2446, 1219, 1048, 2351, 1495, 1496, 1491, 1104, + 1218, 1343, 2373, 2399, 2446, 1499, 1345, 0, 1073, 1074, 2398, 2397, 1346, 1348, 2396, + 2386, 789, 1503, 1212, 0, 1077, 1078, 2385, 2384, 1338, 2383, 2391, 2446, 1506, 1491, + 0, 1079, 1081, 2390, 2389, 1217, 1474, 1501, 2388, 2387, 2446, 1509, 1532, 0, 1083, + 1195, 2386, 2385, 1350, 1513, 1515, 2384, 2383, 2446, 1520, 1573, 0, 1197, 1198, 2382, + 2381, 1579, 1530, 777, 1352, 1533, 2380, 1196, 1200, 2325, 2324, 2348, 2318, 2327, 2342, + 819, 2326, 2317, 2344, 2334, 2319, 2320, 2446, 2351, 2350, + + 2349, 2348, 1205, 1317, 1530, 312, 1318, 1319, 1502, 1340, 1574, 1575, 2310, 2304, 1589, + 1588, 1592, 2325, 1320, 1321, 1543, 1516, 1607, 1123, 1322, 1324, 1545, 1342, 1325, 1327, + 1562, 1552, 1548, 1569, 1328, 1576, 1595, 1598, 1551, 1602, 1577, 1579, 1604, 1618, 1619, + 1623, 1353, 1630, 0, 0, 2312, 2312, 2324, 2308, 1601, 2318, 2306, 2306, 2300, 2296, + 2326, 2326, 2304, 1602, 0, 0, 2348, 0, 0, 1630, 1632, 1117, 1365, 2289, 2297, + 1641, 2446, 2296, 2296, 1647, 1651, 2319, 0, 0, 1644, 1645, 1672, 2342, 1646, 1659, + 1517, 2446, 1665, 0, 0, 1654, 1657, 0, 0, 1669, + + 1670, 1682, 1677, 0, 0, 1683, 1688, 1686, 1685, 0, 0, 1694, 1696, 1691, 1698, + 1699, 1700, 2283, 2287, 1682, 2275, 2288, 2300, 2286, 2286, 2274, 1703, 2304, 2309, 2271, + 2269, 1692, 1699, 2280, 1684, 2278, 2278, 2303, 1689, 1705, 2325, 2446, 1710, 1715, 1718, + 1697, 1713, 1692, 1720, 1723, 1724, 1766, 1728, 1725, 1731, 1750, 1769, 1732, 1754, 1757, + 2324, 1759, 1762, 2263, 2288, 2446, 2321, 2256, 2296, 1777, 2268, 2269, 1787, 2446, 2282, + 2278, 2261, 2261, 1771, 1763, 1745, 2262, 1792, 2261, 2060, 2083, 1782, 1802, 1783, 1799, + 1783, 1798, 2076, 1794, 1804, 1812, 2071, 1809, 2051, 1796, + + 1806, 1816, 2050, 2049, 1814, 2048, 2446, 1821, 1825, 1999, 1089, 2045, 2446, 2044, 2019, + 1827, 2446, 1831, 1993, 1977, 2010, 1980, 1979, 1822, 1843, 1836, 2037, 1849, 2446, 1855, + 2005, 2034, 2446, 2033, 1865, 2032, 1868, 1870, 1871, 1872, 1834, 2031, 2446, 2029, 1837, + 2028, 2446, 1841, 2027, 2446, 2026, 1838, 2025, 2446, 2023, 2446, 2022, 1849, 1853, 1971, + 1991, 2009, 2017, 2446, 1985, 1883, 2446, 1884, 2446, 1983, 1887, 1967, 1900, 1895, 1897, + 1914, 2013, 2446, 1917, 2446, 1980, 2011, 2446, 2010, 2446, 1920, 2008, 1902, 1917, 1922, + 1855, 2006, 2446, 2003, 1875, 2002, 2446, 2001, 2000, 2446, + + 1933, 1890, 1928, 1990, 1934, 1969, 1939, 2446, 1987, 1904, 1994, 1942, 1992, 1943, 1939, + 1983, 1990, 2446, 1941, 2446, 1945, 1946, 1924, 1985, 2446, 1949, 1984, 2446, 1957, 1979, + 1953, 1961, 2446, 1913, 2446, 1962, 1864, 1887, 2446, 1960, 1545, 1500, 1963, 1965, 2446, + 1966, 1374, 1370, 1369, 2446, 1982, 2446, 1334, 1221, 1972, 1253, 1198, 1967, 1224, 2446, + 1223, 2446, 1988, 1222, 1208, 1128, 1136, 2446, 1096, 1099, 2446, 981, 850, 762, 785, + 774, 267, 2446, 265, 240, 2446, 2446, 2446, 2446, 2051, 2057, 2063, 2065, 2071, 2076, + 2078, 2083, 2085, 2091, 2097, 2103, 2109, 2115, 2121, 2127, + + 2133, 2139, 2145, 2151, 2157, 2163, 2169, 2175, 2181, 2187, 2193, 2199, 2205, 2211, 2217, + 2223, 2229, 2235, 2241, 2247, 2253, 2259, 2265, 2271, 2277, 2283, 2289, 2295, 2301, 2307}; + +static yyconst flex_int16_t yy_def[731] = { + 0, 684, 1, 684, 3, 684, 5, 684, 7, 1, 1, 684, 11, 684, 13, 684, 15, + 684, 17, 684, 19, 684, 21, 684, 684, 684, 684, 684, 685, 685, 685, 684, 684, 684, + 684, 684, 686, 684, 684, 687, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 688, 688, 688, 684, 684, 684, 684, 684, 684, 684, 689, 689, 689, + 684, 68, 68, 689, 689, 684, 684, 684, 690, 684, 690, 691, 691, 691, 684, 684, 684, + 684, 684, 684, 692, 684, 692, 693, 693, 693, 684, 684, 694, 694, 684, 694, 684, + + 100, 100, 694, 694, 695, 695, 695, 684, 108, 108, 695, 695, 696, 696, 684, 696, 684, + 117, 117, 696, 696, 697, 697, 684, 697, 684, 126, 126, 697, 697, 698, 698, 684, 698, + 684, 135, 135, 698, 698, 684, 32, 685, 685, 685, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 686, 684, 684, 687, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 688, 688, 688, 684, + 684, 684, 684, 689, 689, 689, 689, 68, 68, 68, 689, 689, 689, 689, 684, + + 684, 690, 690, 691, 691, 691, 684, 684, 684, 684, 684, 684, 692, 692, 693, 693, 693, + 684, 694, 684, 694, 694, 100, 100, 100, 694, 694, 694, 694, 694, 695, 695, 695, 695, + 108, 108, 108, 695, 695, 695, 695, 696, 684, 696, 696, 117, 117, 117, 696, 696, 696, + 696, 696, 696, 697, 684, 697, 697, 126, 126, 126, 697, 697, 697, 697, 697, 697, 698, + 684, 698, 698, 135, 135, 135, 698, 698, 698, 698, 698, 698, 698, 698, 685, 685, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + + 684, 684, 688, 688, 689, 689, 68, 68, 689, 689, 691, 691, 684, 684, 684, 693, 693, + 684, 100, 100, 694, 694, 694, 699, 108, 108, 695, 695, 117, 117, 696, 696, 696, 696, + 126, 126, 697, 697, 697, 697, 135, 135, 698, 698, 698, 698, 698, 698, 685, 685, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 688, 688, 684, 68, + 68, 689, 689, 691, 691, 684, 684, 684, 684, 684, 684, 693, 693, 684, 100, 100, 694, + 694, 694, 700, 694, 694, 699, 684, 699, 108, 108, 695, 695, 117, 117, 696, + + 696, 696, 696, 126, 126, 697, 697, 697, 697, 135, 135, 698, 698, 698, 698, 698, 698, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 689, 689, 684, + 684, 684, 684, 684, 694, 694, 700, 684, 694, 694, 699, 695, 695, 696, 696, 696, 696, + 696, 697, 697, 697, 697, 697, 698, 698, 698, 701, 698, 698, 684, 684, 684, 702, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 703, 689, 684, 684, 684, 684, 684, + 704, 694, 694, 694, 705, 695, 696, 706, 696, 696, 696, 707, 697, 708, 697, + + 697, 697, 709, 710, 698, 701, 684, 698, 698, 684, 684, 702, 684, 711, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 703, 703, 712, 713, 684, 684, 684, 684, 704, 684, 714, + 694, 715, 694, 705, 705, 716, 696, 706, 684, 717, 696, 707, 684, 697, 708, 684, 718, + 697, 709, 684, 710, 684, 719, 698, 698, 684, 684, 684, 711, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 703, 703, 712, 712, 713, 684, 684, 684, 684, 714, 684, 715, 684, + 694, 720, 721, 716, 716, 696, 717, 684, 722, 697, 718, 684, 723, 719, 684, + + 698, 698, 684, 684, 684, 684, 684, 684, 684, 684, 724, 684, 684, 712, 712, 684, 720, + 684, 721, 684, 721, 725, 696, 722, 684, 697, 723, 684, 698, 726, 698, 684, 684, 684, + 684, 684, 684, 724, 684, 684, 684, 684, 721, 725, 684, 725, 727, 728, 726, 684, 698, + 684, 684, 684, 684, 729, 684, 725, 727, 684, 728, 684, 698, 730, 684, 684, 729, 684, + 684, 730, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 0, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684}; + +static yyconst flex_int16_t yy_nxt[2515] = { 0, 24, 25, 26, 25, 24, 24, 27, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 28, 28, 28, 28, 29, 28, 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 24, 31, 24, 24, 28, 28, 28, @@ -611,12 +600,12 @@ static yyconst flex_int16_t yy_nxt[2581] = { 73, 73, 73, 73, 73, 78, 73, 73, 73, 73, 73, 73, 79, 79, 79, 79, 80, 79, 79, 79, 79, 79, 79, 79, 81, 79, 79, 79, 79, 79, 73, 82, 73, 73, 79, 79, 79, 79, 80, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 83, 73, 73, 73, 84, 84, 84, 84, 146, 147, 163, 148, 167, 163, 169, 173, 175, - 171, 177, 185, 178, 176, 168, 170, 172, 187, 174, 195, 202, 213, 146, 179, + 83, 73, 73, 73, 84, 84, 84, 84, 144, 145, 162, 146, 166, 162, 168, 172, 174, + 170, 176, 184, 177, 175, 167, 169, 171, 186, 173, 195, 203, 214, 144, 178, - 206, 147, 207, 148, 224, 242, 187, 252, 264, 185, 276, 284, 144, 144, 701, 187, 174, - 195, 217, 289, 298, 179, 163, 289, 290, 163, 224, 242, 187, 252, 264, 700, 276, 284, - 699, 61, 61, 85, 86, 87, 88, 85, 85, 89, 85, 85, 85, 85, 85, 85, 85, + 207, 145, 208, 146, 225, 237, 683, 248, 261, 184, 274, 684, 142, 142, 367, 186, 173, + 195, 288, 297, 291, 178, 162, 190, 292, 162, 225, 237, 157, 248, 261, 682, 274, 681, + 684, 61, 61, 85, 86, 87, 88, 85, 85, 89, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 90, 85, 85, 85, 85, 85, 85, 91, 91, 91, 91, 92, 91, 91, 91, 91, 91, 91, 91, 93, 91, 91, 91, 91, 91, 85, 94, 85, 85, 91, 91, 91, 91, 92, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, @@ -626,155 +615,151 @@ static yyconst flex_int16_t yy_nxt[2581] = { 101, 100, 100, 100, 100, 100, 100, 100, 102, 100, 100, 100, 100, 100, 96, 103, 96, 96, 100, 100, 100, 100, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 104, 96, 96, 96, 105, 106, 26, 106, 105, 105, 107, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 108, 105, 109, 105, 105, 105, 105, 105, 105, 110, 110, - - 110, 110, 111, 110, 110, 110, 110, 110, 110, 110, 112, 110, 110, 110, 110, 110, 105, - 113, 105, 105, 110, 110, 110, 110, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 114, 105, 105, 105, 115, 116, 117, 116, 115, 115, 118, 115, 115, 115, - 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 119, 119, - 119, 119, 120, 119, 119, 119, 119, 119, 119, 119, 121, 119, 119, 119, 119, 119, 115, - 122, 115, 115, 119, 119, 119, 119, 120, 119, 119, 119, 119, 119, 119, 119, - - 119, 119, 119, 119, 119, 123, 115, 115, 115, 124, 125, 126, 125, 124, 124, 127, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 128, 128, 128, 128, 129, 128, 128, 128, 128, 128, 128, 128, 130, 128, 128, 128, 128, - 128, 124, 131, 124, 124, 128, 128, 128, 128, 129, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 132, 124, 124, 124, 133, 134, 135, 134, 133, 133, 136, 133, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - - 133, 133, 137, 137, 137, 137, 138, 137, 137, 137, 137, 137, 137, 137, 139, 137, 137, - 137, 137, 137, 133, 140, 133, 133, 137, 137, 137, 137, 138, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 141, 133, 133, 133, 142, 190, 142, 190, 159, 191, - 159, 191, 199, 199, 199, 201, 702, 202, 202, 190, 211, 211, 211, 211, 211, 198, 212, - 702, 292, 219, 213, 285, 293, 144, 144, 208, 213, 208, 220, 219, 220, 231, 698, 231, - 697, 247, 144, 198, 259, 202, 230, 230, 144, 285, 696, 205, 204, 219, 196, - - 187, 197, 271, 219, 209, 291, 144, 210, 143, 149, 215, 149, 160, 192, 216, 190, 200, - 200, 205, 271, 702, 230, 187, 292, 160, 160, 209, 293, 160, 210, 227, 702, 225, 228, - 226, 150, 216, 151, 304, 245, 152, 153, 221, 154, 243, 232, 244, 356, 253, 155, 254, - 265, 227, 266, 381, 228, 395, 150, 156, 157, 304, 245, 158, 153, 189, 189, 649, 189, - 189, 189, 189, 189, 189, 189, 189, 190, 189, 189, 189, 189, 189, 189, 193, 193, 189, - 189, 189, 189, 189, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, - - 193, 193, 193, 193, 193, 193, 193, 189, 189, 189, 189, 193, 193, 193, 193, 193, 193, - 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 189, 189, 189, 189, 218, 218, - 219, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, 222, - 222, 218, 218, 218, 218, 218, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, - 222, 222, 222, 222, 222, 222, 222, 218, 218, 218, 218, 222, 222, 222, 222, 222, 222, - 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 218, 218, 218, 218, - - 233, 236, 288, 173, 213, 173, 237, 234, 238, 177, 300, 178, 300, 305, 174, 301, 174, - 308, 235, 239, 144, 302, 179, 302, 315, 290, 303, 367, 377, 579, 289, 290, 695, 368, - 580, 305, 174, 190, 174, 308, 235, 239, 229, 229, 179, 229, 229, 229, 229, 229, 229, - 229, 229, 230, 229, 229, 229, 229, 229, 229, 240, 240, 229, 229, 229, 229, 229, 240, - 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, - 229, 229, 229, 229, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, - - 240, 240, 240, 240, 240, 240, 229, 229, 229, 229, 248, 247, 248, 247, 259, 149, 190, - 149, 690, 230, 279, 271, 279, 691, 309, 320, 331, 190, 321, 335, 336, 230, 339, 330, - 198, 330, 255, 267, 331, 340, 256, 268, 233, 694, 257, 269, 309, 320, 280, 331, 321, - 335, 336, 230, 339, 333, 198, 333, 255, 267, 334, 340, 256, 268, 156, 286, 257, 269, - 281, 282, 283, 310, 311, 249, 246, 246, 247, 246, 246, 246, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 246, 250, 250, 246, 246, 246, 246, 246, 250, - - 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, - 246, 246, 246, 246, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 250, 250, 246, 246, 246, 246, 260, 259, 260, 208, 202, 208, 202, 345, 208, - 213, 208, 213, 230, 689, 233, 247, 693, 346, 686, 233, 144, 234, 144, 351, 352, 144, - 234, 144, 359, 345, 245, 209, 235, 312, 210, 313, 314, 235, 317, 346, 318, 230, 402, - 692, 689, 351, 352, 680, 334, 678, 359, 403, 245, 209, 235, 312, 210, 313, - - 314, 235, 317, 341, 318, 261, 258, 258, 259, 258, 258, 258, 258, 258, 258, 258, 258, - 258, 258, 258, 258, 258, 258, 258, 262, 262, 258, 258, 258, 258, 258, 262, 262, 262, - 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 258, 258, - 258, 258, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, - 262, 262, 258, 258, 258, 258, 272, 271, 272, 219, 219, 230, 219, 230, 236, 230, 271, - 271, 360, 237, 375, 238, 376, 378, 379, 393, 394, 687, 327, 405, 410, 411, - - 239, 414, 408, 415, 227, 328, 406, 228, 360, 402, 375, 409, 376, 378, 379, 393, 394, - 236, 403, 686, 410, 411, 239, 414, 334, 415, 227, 337, 338, 228, 324, 322, 323, 357, - 325, 432, 332, 273, 270, 270, 271, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 274, 274, 270, 270, 270, 270, 270, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 270, 270, 270, 270, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - - 274, 274, 270, 270, 270, 270, 271, 247, 142, 159, 142, 159, 306, 191, 306, 191, 199, - 199, 199, 201, 702, 702, 190, 190, 211, 211, 211, 212, 220, 219, 220, 231, 190, 231, - 327, 247, 248, 247, 248, 259, 259, 230, 202, 328, 260, 259, 260, 420, 259, 684, 683, - 247, 271, 272, 271, 272, 327, 306, 144, 306, 342, 343, 668, 680, 271, 328, 259, 190, - 277, 420, 278, 143, 160, 219, 255, 247, 192, 307, 256, 200, 200, 380, 257, 702, 702, - 347, 230, 160, 160, 267, 344, 221, 230, 268, 232, 350, 255, 269, 329, 249, - - 256, 348, 349, 247, 257, 354, 355, 261, 279, 271, 279, 267, 279, 271, 279, 268, 273, - 354, 358, 269, 329, 396, 307, 202, 386, 247, 386, 202, 213, 213, 416, 413, 421, 387, - 259, 412, 280, 247, 259, 144, 397, 219, 397, 144, 144, 144, 259, 259, 426, 398, 427, - 418, 271, 271, 421, 271, 281, 282, 283, 382, 281, 282, 353, 383, 390, 391, 271, 271, - 438, 438, 426, 219, 427, 388, 190, 190, 230, 678, 202, 389, 219, 382, 424, 417, 219, - 383, 390, 391, 219, 399, 438, 438, 419, 422, 144, 400, 449, 447, 386, 402, - - 386, 213, 425, 430, 423, 213, 428, 387, 403, 247, 456, 429, 247, 405, 448, 433, 464, - 144, 449, 405, 455, 144, 406, 230, 431, 397, 219, 397, 406, 408, 408, 247, 456, 459, - 398, 259, 460, 247, 409, 409, 271, 259, 259, 259, 465, 483, 675, 271, 271, 271, 271, - 271, 491, 219, 491, 190, 219, 219, 467, 230, 219, 492, 190, 461, 230, 247, 465, 468, - 469, 466, 402, 247, 405, 473, 474, 408, 247, 478, 247, 403, 478, 406, 500, 462, 409, - 259, 259, 470, 476, 468, 469, 472, 471, 480, 463, 473, 474, 475, 477, 478, - - 479, 484, 478, 498, 500, 509, 505, 506, 481, 507, 497, 514, 247, 514, 508, 259, 485, - 504, 259, 271, 515, 520, 259, 520, 510, 271, 512, 271, 271, 271, 521, 531, 534, 513, - 534, 511, 491, 190, 491, 500, 543, 535, 219, 219, 516, 492, 546, 531, 546, 230, 517, - 553, 219, 553, 247, 547, 557, 247, 247, 259, 554, 500, 514, 247, 514, 518, 259, 259, - 271, 377, 657, 515, 271, 519, 520, 259, 520, 481, 523, 271, 672, 271, 534, 521, 534, - 559, 584, 526, 584, 522, 527, 535, 544, 555, 531, 585, 582, 566, 591, 531, - - 591, 531, 247, 543, 558, 594, 552, 559, 543, 546, 557, 546, 247, 563, 259, 597, 259, - 597, 547, 566, 531, 562, 570, 569, 598, 576, 553, 219, 553, 557, 582, 577, 575, 271, - 247, 554, 604, 219, 604, 608, 619, 584, 625, 584, 625, 605, 628, 631, 628, 582, 585, - 626, 591, 531, 591, 259, 543, 609, 594, 671, 670, 638, 543, 592, 632, 582, 632, 247, - 612, 613, 639, 597, 616, 597, 594, 259, 604, 219, 604, 582, 598, 582, 659, 271, 606, - 605, 668, 646, 608, 641, 608, 594, 620, 647, 271, 647, 650, 625, 650, 625, - - 628, 673, 628, 673, 643, 651, 626, 638, 636, 638, 644, 629, 632, 582, 632, 663, 639, - 592, 639, 647, 271, 647, 594, 665, 664, 660, 650, 638, 650, 633, 663, 666, 663, 377, - 669, 651, 639, 663, 673, 664, 673, 664, 681, 271, 681, 640, 664, 681, 271, 681, 658, - 657, 655, 654, 653, 652, 618, 646, 648, 615, 643, 611, 636, 603, 601, 629, 674, 634, - 596, 630, 627, 624, 582, 661, 623, 622, 621, 633, 618, 574, 572, 615, 568, 565, 648, - 611, 561, 603, 601, 551, 599, 596, 590, 589, 588, 587, 676, 586, 583, 582, - - 531, 578, 525, 674, 574, 572, 568, 682, 565, 561, 551, 549, 682, 144, 144, 162, 162, - 162, 162, 162, 162, 165, 165, 165, 165, 165, 165, 183, 183, 189, 189, 548, 189, 189, - 189, 202, 545, 202, 202, 203, 203, 203, 213, 541, 213, 213, 214, 214, 214, 218, 218, - 218, 218, 218, 218, 229, 229, 540, 229, 229, 229, 246, 246, 246, 246, 246, 246, 258, - 258, 258, 258, 258, 258, 270, 270, 270, 270, 270, 270, 326, 326, 326, 326, 326, 326, - 401, 401, 401, 401, 401, 401, 404, 404, 404, 404, 404, 404, 407, 407, 407, - - 407, 407, 407, 457, 457, 457, 457, 457, 457, 524, 524, 524, 524, 524, 524, 530, 530, - 530, 530, 530, 530, 542, 542, 542, 542, 542, 542, 550, 550, 550, 550, 550, 550, 556, - 556, 556, 556, 556, 556, 560, 560, 560, 560, 560, 560, 564, 564, 564, 564, 564, 564, - 567, 567, 567, 567, 567, 567, 571, 571, 571, 571, 571, 571, 573, 573, 573, 573, 573, - 573, 581, 581, 581, 581, 581, 581, 593, 593, 593, 593, 593, 593, 595, 595, 595, 595, - 595, 595, 600, 600, 600, 600, 600, 600, 602, 602, 602, 602, 602, 602, 607, - - 607, 607, 607, 607, 607, 610, 610, 610, 610, 610, 610, 614, 614, 614, 614, 614, 614, - 617, 617, 617, 617, 617, 617, 635, 635, 635, 635, 635, 635, 637, 637, 637, 637, 637, - 637, 642, 642, 642, 642, 642, 642, 645, 645, 645, 645, 645, 645, 656, 656, 656, 656, - 656, 656, 662, 662, 662, 662, 662, 662, 667, 667, 667, 667, 667, 667, 677, 677, 677, - 677, 677, 677, 679, 679, 679, 679, 679, 679, 685, 685, 685, 685, 685, 685, 688, 688, - 688, 688, 688, 688, 539, 538, 537, 536, 533, 532, 531, 529, 528, 525, 458, - - 503, 502, 501, 499, 496, 495, 494, 493, 490, 489, 488, 487, 486, 485, 482, 447, 458, - 454, 453, 452, 451, 450, 377, 446, 445, 444, 443, 442, 441, 440, 439, 437, 436, 435, - 434, 392, 385, 384, 303, 303, 301, 301, 374, 373, 372, 371, 370, 369, 366, 365, 364, - 363, 362, 361, 271, 271, 271, 259, 259, 259, 247, 247, 247, 230, 230, 230, 219, 219, - 219, 319, 316, 190, 190, 190, 299, 166, 297, 296, 295, 294, 287, 702, 275, 271, 271, - 263, 259, 259, 251, 247, 247, 241, 230, 230, 223, 219, 219, 194, 190, 190, - - 188, 186, 184, 182, 181, 180, 166, 164, 161, 145, 702, 23, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702}; - -static yyconst flex_int16_t yy_chk[2581] = { + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 108, 108, + + 108, 108, 109, 108, 108, 108, 108, 108, 108, 108, 110, 108, 108, 108, 108, 108, 105, + 111, 105, 105, 108, 108, 108, 108, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 112, 105, 105, 105, 113, 114, 115, 114, 113, 113, 116, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 117, 117, + 117, 117, 118, 117, 117, 117, 117, 117, 117, 117, 119, 117, 117, 117, 117, 117, 113, + 120, 113, 113, 117, 117, 117, 117, 118, 117, 117, 117, 117, 117, 117, 117, + + 117, 117, 117, 117, 117, 121, 113, 113, 113, 122, 123, 124, 123, 122, 122, 125, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 126, 126, 126, 126, 127, 126, 126, 126, 126, 126, 126, 126, 128, 126, 126, 126, 126, + 126, 122, 129, 122, 122, 126, 126, 126, 126, 127, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 130, 122, 122, 122, 131, 132, 133, 132, 131, 131, 134, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, + + 131, 131, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 135, 135, 137, 135, 135, + 135, 135, 135, 131, 138, 131, 131, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 139, 131, 131, 131, 140, 190, 140, 203, 158, 191, + 158, 191, 190, 200, 200, 200, 202, 684, 684, 190, 203, 283, 212, 142, 212, 209, 212, + 209, 212, 212, 198, 213, 214, 220, 214, 233, 142, 233, 269, 186, 221, 220, 221, 283, + 680, 232, 205, 684, 142, 243, 142, 218, 198, 210, 232, 679, 211, 206, 196, + + 232, 197, 186, 256, 220, 284, 199, 232, 141, 147, 217, 147, 159, 192, 216, 157, 210, + 201, 201, 211, 206, 684, 684, 186, 346, 240, 159, 284, 678, 157, 159, 228, 217, 159, + 229, 148, 226, 149, 227, 234, 150, 151, 287, 152, 222, 186, 290, 240, 238, 153, 239, + 684, 249, 228, 250, 324, 229, 148, 154, 155, 241, 677, 156, 151, 291, 262, 230, 263, + 292, 357, 288, 289, 157, 189, 189, 358, 189, 189, 189, 189, 189, 189, 189, 189, 190, + 189, 189, 189, 189, 189, 189, 193, 193, 189, 189, 189, 189, 189, 193, 193, + + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 189, + 189, 189, 189, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 189, 189, 189, 189, 219, 219, 220, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 223, 223, 219, 219, 219, 219, 219, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 219, + 219, 219, 219, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + + 223, 223, 223, 223, 223, 219, 219, 219, 219, 231, 231, 676, 231, 231, 231, 231, 231, + 231, 231, 231, 232, 231, 231, 231, 231, 231, 231, 235, 235, 231, 231, 231, 231, 231, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 231, 231, 231, 231, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 231, 231, 231, 231, 244, 243, 244, 147, 172, 147, 299, 172, + 299, 303, 176, 300, 177, 304, 301, 173, 301, 307, 173, 302, 288, 289, 308, + + 178, 671, 203, 314, 289, 319, 320, 214, 303, 325, 326, 329, 304, 330, 173, 335, 307, + 173, 142, 561, 203, 308, 178, 142, 562, 392, 675, 319, 320, 154, 285, 325, 326, 329, + 393, 330, 142, 335, 668, 674, 245, 242, 242, 243, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 246, 246, 242, 242, 242, 242, 242, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 242, + 242, 242, 242, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + + 246, 246, 246, 246, 246, 242, 242, 242, 242, 243, 257, 256, 257, 190, 209, 190, 209, + 203, 203, 243, 209, 214, 209, 232, 671, 662, 660, 336, 669, 341, 342, 198, 251, 142, + 142, 349, 252, 142, 672, 350, 253, 240, 210, 673, 365, 211, 311, 312, 313, 336, 316, + 341, 342, 198, 251, 668, 666, 349, 252, 309, 310, 350, 253, 240, 210, 331, 365, 211, + 311, 312, 313, 254, 316, 258, 255, 255, 256, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 259, 259, 255, 255, 255, 255, 255, 259, + + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 255, 255, 255, 255, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 255, 255, 255, 255, 256, 270, 269, 270, 214, 220, 220, 232, 220, + 190, 256, 232, 269, 269, 366, 368, 369, 383, 384, 394, 142, 395, 398, 264, 399, 404, + 203, 265, 665, 650, 662, 266, 228, 317, 660, 229, 366, 368, 369, 383, 384, 394, 142, + 395, 398, 264, 399, 404, 371, 265, 397, 327, 328, 266, 228, 317, 337, 229, + + 323, 321, 322, 347, 267, 416, 271, 268, 268, 269, 268, 268, 268, 268, 268, 268, 268, + 268, 268, 268, 268, 268, 268, 268, 268, 272, 272, 268, 268, 268, 268, 268, 272, 272, + 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 268, + 268, 268, 268, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, 272, + 272, 272, 272, 268, 268, 268, 268, 269, 243, 277, 269, 277, 140, 158, 140, 158, 305, + 191, 305, 191, 200, 200, 200, 202, 684, 243, 190, 190, 212, 212, 212, 213, + + 221, 220, 221, 243, 233, 278, 233, 244, 243, 244, 257, 256, 257, 190, 232, 256, 251, + 256, 220, 392, 252, 270, 269, 270, 253, 279, 280, 281, 393, 332, 333, 305, 269, 305, + 256, 269, 657, 275, 251, 276, 282, 190, 252, 141, 159, 220, 253, 367, 192, 306, 243, + 201, 201, 256, 243, 684, 232, 264, 334, 159, 159, 265, 370, 222, 243, 266, 386, 234, + 338, 339, 245, 243, 340, 258, 277, 269, 277, 203, 203, 264, 277, 269, 277, 265, 271, + 344, 345, 266, 344, 348, 376, 214, 376, 142, 142, 214, 306, 256, 402, 377, + + 256, 408, 278, 385, 256, 396, 269, 142, 387, 220, 387, 142, 401, 372, 373, 405, 410, + 388, 411, 400, 269, 269, 279, 280, 281, 269, 403, 380, 279, 280, 343, 381, 269, 422, + 422, 372, 373, 405, 410, 378, 411, 190, 376, 190, 376, 379, 220, 220, 220, 380, 214, + 377, 406, 381, 214, 422, 422, 389, 407, 409, 412, 220, 431, 390, 433, 232, 142, 392, + 232, 414, 142, 243, 243, 387, 220, 387, 393, 440, 413, 243, 417, 432, 388, 415, 243, + 256, 433, 256, 256, 447, 256, 220, 465, 269, 243, 439, 269, 443, 269, 440, + + 269, 269, 269, 190, 473, 446, 473, 220, 232, 444, 190, 447, 220, 474, 450, 451, 482, + 220, 455, 456, 392, 449, 243, 460, 232, 243, 243, 256, 448, 393, 256, 445, 460, 256, + 269, 452, 450, 451, 482, 454, 455, 456, 453, 457, 458, 460, 462, 459, 466, 461, 467, + 480, 256, 492, 460, 486, 269, 487, 479, 269, 463, 269, 488, 490, 269, 491, 489, 496, + 243, 496, 502, 256, 502, 513, 190, 494, 497, 482, 516, 503, 516, 495, 525, 500, 220, + 220, 493, 517, 473, 498, 473, 499, 463, 528, 232, 528, 243, 474, 256, 482, + + 243, 513, 529, 535, 220, 535, 243, 501, 256, 505, 539, 256, 536, 496, 243, 496, 269, + 502, 256, 502, 504, 508, 497, 269, 513, 509, 503, 269, 516, 526, 516, 541, 566, 525, + 566, 537, 243, 517, 564, 243, 256, 567, 548, 256, 573, 513, 573, 576, 534, 540, 528, + 269, 528, 541, 525, 269, 579, 243, 579, 529, 544, 545, 551, 552, 548, 580, 535, 220, + 535, 586, 220, 586, 513, 513, 564, 536, 558, 256, 587, 559, 557, 539, 539, 590, 566, + 607, 566, 607, 610, 639, 610, 591, 269, 567, 608, 594, 598, 613, 595, 564, + + 654, 573, 513, 573, 620, 610, 525, 610, 576, 574, 601, 525, 623, 621, 602, 614, 564, + 614, 579, 564, 579, 586, 220, 586, 564, 576, 243, 580, 590, 632, 587, 632, 626, 590, + 629, 269, 629, 588, 633, 631, 607, 641, 607, 620, 614, 564, 614, 620, 645, 608, 576, + 256, 621, 611, 576, 269, 621, 646, 629, 269, 629, 655, 632, 655, 632, 620, 574, 645, + 645, 645, 611, 633, 653, 655, 621, 655, 646, 646, 646, 652, 615, 650, 647, 663, 269, + 663, 628, 625, 622, 663, 269, 663, 618, 642, 367, 640, 639, 637, 636, 630, + + 635, 634, 600, 628, 597, 625, 651, 648, 593, 615, 618, 643, 585, 583, 616, 578, 612, + 609, 606, 564, 605, 604, 603, 630, 600, 556, 656, 554, 597, 550, 547, 593, 658, 543, + 585, 583, 533, 581, 656, 578, 572, 571, 570, 569, 568, 565, 564, 513, 664, 560, 507, + 556, 554, 550, 664, 142, 142, 161, 161, 161, 161, 161, 161, 164, 164, 164, 164, 164, + 164, 182, 182, 189, 189, 547, 189, 189, 189, 203, 543, 203, 203, 204, 204, 204, 214, + 533, 214, 214, 215, 215, 215, 219, 219, 219, 219, 219, 219, 231, 231, 531, + + 231, 231, 231, 242, 242, 242, 242, 242, 242, 255, 255, 255, 255, 255, 255, 268, 268, + 268, 268, 268, 268, 391, 391, 391, 391, 391, 391, 441, 441, 441, 441, 441, 441, 506, + 506, 506, 506, 506, 506, 512, 512, 512, 512, 512, 512, 524, 524, 524, 524, 524, 524, + 532, 532, 532, 532, 532, 532, 538, 538, 538, 538, 538, 538, 542, 542, 542, 542, 542, + 542, 546, 546, 546, 546, 546, 546, 549, 549, 549, 549, 549, 549, 553, 553, 553, 553, + 553, 553, 555, 555, 555, 555, 555, 555, 563, 563, 563, 563, 563, 563, 575, + + 575, 575, 575, 575, 575, 577, 577, 577, 577, 577, 577, 582, 582, 582, 582, 582, 582, + 584, 584, 584, 584, 584, 584, 589, 589, 589, 589, 589, 589, 592, 592, 592, 592, 592, + 592, 596, 596, 596, 596, 596, 596, 599, 599, 599, 599, 599, 599, 617, 617, 617, 617, + 617, 617, 619, 619, 619, 619, 619, 619, 624, 624, 624, 624, 624, 624, 627, 627, 627, + 627, 627, 627, 638, 638, 638, 638, 638, 638, 644, 644, 644, 644, 644, 644, 649, 649, + 649, 649, 649, 649, 659, 659, 659, 659, 659, 659, 661, 661, 661, 661, 661, + + 661, 667, 667, 667, 667, 667, 667, 670, 670, 670, 670, 670, 670, 530, 527, 523, 522, + 521, 520, 519, 518, 515, 514, 513, 511, 510, 507, 442, 485, 484, 483, 481, 478, 477, + 476, 475, 472, 471, 470, 469, 468, 467, 464, 431, 442, 438, 437, 436, 435, 434, 367, + 430, 429, 428, 427, 426, 425, 424, 423, 421, 420, 419, 418, 382, 375, 374, 302, 302, + 300, 300, 364, 363, 362, 361, 360, 359, 356, 355, 354, 353, 352, 351, 269, 269, 269, + 269, 256, 256, 256, 256, 243, 243, 243, 243, 232, 232, 232, 232, 220, 220, + + 220, 220, 318, 315, 190, 190, 190, 190, 298, 165, 296, 295, 294, 293, 286, 273, 269, + 269, 260, 256, 256, 247, 243, 243, 236, 232, 232, 224, 220, 220, 194, 190, 190, 188, + 187, 185, 183, 181, 180, 179, 165, 163, 160, 143, 684, 23, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684}; + +static yyconst flex_int16_t yy_chk[2515] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -796,9 +781,9 @@ static yyconst flex_int16_t yy_chk[2581] = { 7, 7, 7, 7, 9, 10, 9, 10, 30, 31, 36, 31, 42, 36, 43, 46, 47, 45, 48, 57, 48, 47, 42, 43, 45, 61, 46, 70, 79, 91, 30, 48, - 82, 94, 82, 94, 102, 112, 95, 121, 130, 57, 139, 145, 79, 91, 698, 61, 46, - 70, 95, 157, 157, 48, 162, 187, 187, 162, 102, 112, 95, 121, 130, 697, 139, 145, - 695, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 82, 94, 82, 94, 102, 110, 680, 119, 128, 57, 137, 141, 79, 91, 306, 61, 46, + 70, 155, 155, 156, 48, 161, 306, 156, 161, 102, 110, 61, 119, 128, 679, 137, 677, + 141, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, @@ -826,145 +811,141 @@ static yyconst flex_int16_t yy_chk[2581] = { 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 25, 71, 25, 72, 33, 66, - 33, 66, 74, 76, 74, 76, 78, 80, 81, 66, 84, 86, 84, 86, 88, 72, 88, - 90, 158, 103, 92, 146, 158, 80, 81, 83, 93, 83, 97, 97, 97, 106, 694, 106, - 693, 122, 92, 72, 131, 203, 113, 106, 93, 146, 692, 81, 80, 322, 71, - - 160, 71, 281, 104, 83, 152, 203, 83, 25, 32, 92, 32, 33, 66, 93, 311, 74, - 76, 81, 620, 78, 114, 160, 152, 84, 86, 83, 152, 88, 83, 104, 90, 103, 104, - 103, 32, 93, 32, 184, 114, 32, 32, 97, 32, 113, 106, 113, 281, 122, 32, 122, - 131, 104, 131, 311, 104, 322, 32, 32, 32, 184, 114, 32, 32, 68, 68, 620, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 25, 71, 25, 80, 33, 66, + 33, 66, 72, 74, 76, 74, 76, 78, 90, 66, 81, 143, 84, 80, 84, 83, 86, + 83, 86, 88, 72, 88, 93, 103, 92, 106, 81, 106, 279, 95, 97, 97, 97, 143, + 676, 106, 80, 203, 93, 120, 92, 95, 72, 83, 111, 675, 83, 81, 71, + + 232, 71, 95, 129, 104, 144, 72, 112, 25, 32, 93, 32, 33, 66, 92, 95, 83, + 74, 76, 83, 81, 78, 90, 159, 279, 112, 84, 144, 674, 83, 86, 104, 93, 88, + 104, 32, 103, 32, 103, 106, 32, 32, 149, 32, 97, 159, 150, 112, 111, 32, 111, + 203, 120, 104, 120, 232, 104, 32, 32, 32, 112, 673, 32, 32, 150, 129, 104, 129, + 150, 291, 149, 149, 32, 68, 68, 291, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 100, 100, - 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 108, 109, 151, 173, 214, 177, 109, 108, 109, 178, 174, 178, 174, 185, 173, 174, 177, - 194, 108, 109, 214, 179, 178, 179, 209, 209, 179, 292, 307, 529, 151, 151, 691, 292, - 529, 185, 173, 307, 177, 194, 108, 109, 110, 110, 178, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 116, 116, 116, 123, 132, 149, 192, - 149, 683, 330, 141, 141, 141, 683, 195, 223, 330, 198, 224, 241, 242, 235, 251, 235, - 192, 235, 123, 132, 235, 252, 123, 132, 331, 690, 123, 132, 195, 223, 141, 331, 224, - 241, 242, 239, 251, 239, 192, 239, 123, 132, 239, 252, 123, 132, 149, 149, 123, 132, - 141, 141, 141, 198, 198, 116, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, - 119, 119, 119, 119, 119, 119, 119, 119, 125, 125, 125, 200, 204, 200, 205, 263, 208, - 215, 208, 216, 232, 688, 234, 255, 687, 264, 685, 237, 204, 234, 205, 275, 276, 215, - 237, 216, 284, 263, 232, 200, 234, 204, 200, 205, 208, 237, 215, 264, 216, 333, 325, - 684, 682, 275, 276, 679, 333, 677, 284, 325, 232, 200, 234, 204, 200, 205, - - 208, 237, 215, 255, 216, 125, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 134, 134, 134, 221, 227, 230, 228, 236, 238, 245, 282, - 357, 285, 238, 304, 238, 305, 308, 309, 320, 321, 675, 326, 329, 335, 336, - - 238, 339, 332, 340, 221, 326, 329, 221, 285, 401, 304, 332, 305, 308, 309, 320, 321, - 334, 401, 674, 335, 336, 238, 339, 334, 340, 221, 245, 245, 221, 228, 227, 227, 282, - 230, 357, 236, 134, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, - - 137, 137, 137, 137, 137, 137, 140, 256, 142, 159, 142, 159, 190, 191, 190, 191, 199, - 201, 199, 201, 202, 213, 190, 191, 211, 212, 211, 212, 220, 220, 220, 231, 310, 231, - 233, 257, 248, 248, 248, 267, 269, 231, 382, 233, 260, 260, 260, 345, 268, 672, 671, - 249, 280, 272, 272, 272, 328, 306, 382, 306, 256, 256, 667, 666, 283, 328, 261, 306, - 140, 345, 140, 142, 159, 323, 249, 341, 191, 190, 249, 199, 201, 310, 249, 202, 213, - 267, 337, 211, 212, 261, 257, 220, 338, 261, 231, 269, 249, 261, 233, 248, - - 249, 268, 268, 343, 249, 280, 280, 260, 273, 273, 273, 261, 279, 279, 279, 261, 272, - 283, 283, 261, 328, 323, 306, 312, 316, 342, 316, 313, 317, 318, 341, 338, 346, 316, - 349, 337, 273, 344, 347, 312, 324, 324, 324, 313, 317, 318, 348, 350, 351, 324, 352, - 343, 353, 354, 346, 355, 273, 273, 273, 312, 279, 279, 279, 313, 317, 318, 356, 358, - 365, 374, 351, 395, 352, 316, 380, 381, 412, 665, 383, 316, 396, 312, 349, 342, 399, - 313, 317, 318, 400, 324, 365, 374, 344, 347, 383, 324, 381, 374, 386, 403, - - 386, 390, 350, 355, 348, 391, 353, 386, 403, 417, 396, 354, 416, 404, 380, 358, 412, - 390, 381, 406, 395, 391, 404, 413, 356, 397, 397, 397, 406, 407, 409, 419, 396, 399, - 397, 422, 400, 418, 407, 409, 428, 425, 423, 424, 413, 436, 660, 430, 432, 429, 433, - 431, 443, 455, 443, 448, 456, 459, 417, 464, 460, 443, 449, 403, 465, 466, 413, 418, - 418, 416, 461, 467, 462, 424, 424, 463, 468, 430, 469, 461, 433, 462, 451, 406, 463, - 471, 472, 419, 428, 418, 418, 423, 422, 432, 409, 424, 424, 425, 429, 430, - - 431, 436, 433, 449, 451, 465, 456, 459, 433, 460, 448, 470, 470, 470, 464, 473, 451, - 455, 474, 476, 470, 475, 475, 475, 466, 477, 468, 480, 478, 481, 475, 497, 488, 469, - 488, 467, 491, 498, 491, 499, 497, 488, 505, 507, 471, 491, 501, 508, 501, 509, 472, - 506, 506, 506, 510, 501, 508, 512, 513, 518, 506, 499, 514, 514, 514, 473, 516, 519, - 523, 659, 656, 514, 526, 474, 520, 520, 520, 476, 478, 527, 655, 576, 534, 520, 534, - 510, 536, 480, 536, 477, 481, 534, 498, 507, 542, 536, 544, 516, 543, 543, - - 543, 556, 559, 542, 509, 544, 505, 510, 543, 546, 556, 546, 563, 513, 566, 548, 570, - 548, 546, 516, 557, 512, 519, 518, 548, 526, 553, 553, 553, 557, 558, 527, 523, 577, - 609, 553, 555, 555, 555, 558, 576, 584, 586, 584, 586, 555, 589, 592, 589, 593, 584, - 586, 591, 591, 591, 613, 592, 559, 593, 654, 652, 606, 591, 543, 594, 594, 594, 641, - 563, 566, 606, 597, 570, 597, 594, 644, 604, 604, 604, 607, 597, 608, 633, 649, 557, - 604, 648, 645, 607, 609, 608, 633, 577, 619, 619, 619, 621, 625, 621, 625, - - 628, 658, 628, 658, 642, 621, 625, 637, 635, 639, 613, 589, 632, 632, 632, 640, 637, - 591, 639, 647, 647, 647, 632, 641, 640, 634, 650, 661, 650, 594, 662, 644, 664, 631, - 649, 650, 661, 676, 673, 662, 673, 664, 669, 669, 669, 608, 676, 681, 681, 681, 630, - 629, 627, 624, 623, 622, 617, 616, 619, 614, 612, 610, 605, 602, 600, 628, 658, 599, - 595, 590, 588, 583, 581, 639, 580, 579, 578, 632, 575, 573, 571, 569, 567, 564, 647, - 562, 560, 554, 552, 550, 549, 545, 541, 540, 539, 538, 664, 537, 533, 532, - - 530, 528, 524, 673, 522, 521, 517, 669, 515, 511, 504, 503, 681, 703, 703, 704, 704, - 704, 704, 704, 704, 705, 705, 705, 705, 705, 705, 706, 706, 707, 707, 502, 707, 707, - 707, 708, 500, 708, 708, 709, 709, 709, 710, 496, 710, 710, 711, 711, 711, 712, 712, - 712, 712, 712, 712, 713, 713, 495, 713, 713, 713, 714, 714, 714, 714, 714, 714, 715, - 715, 715, 715, 715, 715, 716, 716, 716, 716, 716, 716, 717, 717, 717, 717, 717, 717, - 718, 718, 718, 718, 718, 718, 719, 719, 719, 719, 719, 719, 720, 720, 720, - - 720, 720, 720, 721, 721, 721, 721, 721, 721, 722, 722, 722, 722, 722, 722, 723, 723, - 723, 723, 723, 723, 724, 724, 724, 724, 724, 724, 725, 725, 725, 725, 725, 725, 726, - 726, 726, 726, 726, 726, 727, 727, 727, 727, 727, 727, 728, 728, 728, 728, 728, 728, - 729, 729, 729, 729, 729, 729, 730, 730, 730, 730, 730, 730, 731, 731, 731, 731, 731, - 731, 732, 732, 732, 732, 732, 732, 733, 733, 733, 733, 733, 733, 734, 734, 734, 734, - 734, 734, 735, 735, 735, 735, 735, 735, 736, 736, 736, 736, 736, 736, 737, - - 737, 737, 737, 737, 737, 738, 738, 738, 738, 738, 738, 739, 739, 739, 739, 739, 739, - 740, 740, 740, 740, 740, 740, 741, 741, 741, 741, 741, 741, 742, 742, 742, 742, 742, - 742, 743, 743, 743, 743, 743, 743, 744, 744, 744, 744, 744, 744, 745, 745, 745, 745, - 745, 745, 746, 746, 746, 746, 746, 746, 747, 747, 747, 747, 747, 747, 748, 748, 748, - 748, 748, 748, 749, 749, 749, 749, 749, 749, 750, 750, 750, 750, 750, 750, 751, 751, - 751, 751, 751, 751, 494, 493, 490, 489, 487, 486, 485, 483, 482, 479, 457, - - 454, 453, 452, 450, 447, 446, 445, 444, 442, 441, 440, 439, 438, 437, 435, 434, 398, - 392, 389, 388, 385, 384, 377, 373, 372, 371, 370, 369, 368, 367, 366, 364, 363, 362, - 361, 319, 315, 314, 303, 302, 301, 300, 298, 297, 296, 295, 294, 293, 291, 290, 289, - 288, 287, 286, 278, 277, 270, 266, 265, 258, 254, 253, 246, 244, 243, 229, 226, 225, - 218, 217, 210, 197, 196, 189, 167, 165, 156, 155, 154, 153, 150, 143, 138, 136, 133, - 129, 127, 124, 120, 118, 115, 111, 107, 105, 101, 99, 96, 69, 67, 65, - - 62, 60, 56, 53, 52, 51, 39, 38, 35, 29, 23, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, - 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702, 702}; + 100, 100, 100, 100, 100, 100, 100, 100, 100, 108, 108, 672, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 114, 114, 114, 147, 172, 147, 173, 176, + 173, 183, 177, 173, 177, 184, 178, 172, 178, 194, 176, 178, 186, 186, 195, + + 177, 670, 204, 210, 210, 224, 225, 215, 183, 236, 237, 247, 184, 248, 172, 260, 194, + 176, 204, 511, 372, 195, 177, 215, 511, 324, 669, 224, 225, 147, 147, 236, 237, 247, + 324, 248, 372, 260, 667, 666, 114, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + + 117, 117, 117, 117, 117, 117, 117, 117, 117, 121, 123, 123, 123, 192, 201, 198, 201, + 205, 206, 251, 209, 216, 209, 234, 664, 661, 659, 261, 657, 273, 274, 192, 121, 205, + 206, 283, 121, 216, 665, 284, 121, 234, 201, 665, 303, 201, 205, 206, 209, 261, 216, + 273, 274, 192, 121, 656, 654, 283, 121, 198, 198, 284, 121, 234, 201, 251, 303, 201, + 205, 206, 209, 121, 216, 123, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 130, 132, 132, 132, 217, 222, 228, 240, 229, + 310, 264, 328, 280, 347, 304, 307, 308, 319, 320, 325, 217, 326, 329, 130, 330, 335, + 373, 130, 653, 649, 648, 130, 222, 217, 647, 222, 304, 307, 308, 319, 320, 325, 373, + 326, 329, 130, 330, 335, 310, 130, 328, 240, 240, 130, 222, 217, 264, 222, + + 229, 228, 228, 280, 130, 347, 132, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 138, 252, 139, 139, 139, 140, 158, 140, 158, 190, + 191, 190, 191, 200, 202, 200, 202, 214, 245, 190, 191, 212, 213, 212, 213, + + 221, 221, 221, 253, 233, 139, 233, 244, 244, 244, 257, 257, 257, 309, 233, 265, 245, + 266, 322, 391, 245, 270, 270, 270, 245, 139, 139, 139, 391, 252, 252, 305, 278, 305, + 258, 281, 642, 138, 245, 138, 139, 305, 245, 140, 158, 321, 245, 641, 191, 190, 333, + 200, 202, 339, 332, 214, 327, 258, 253, 212, 213, 258, 309, 221, 331, 258, 322, 233, + 265, 265, 244, 334, 266, 257, 271, 271, 271, 311, 312, 258, 277, 277, 277, 258, 270, + 278, 278, 258, 281, 281, 315, 316, 315, 311, 312, 317, 305, 337, 333, 315, + + 338, 339, 271, 321, 340, 327, 343, 316, 323, 323, 323, 317, 332, 311, 312, 336, 341, + 323, 342, 331, 344, 345, 271, 271, 271, 346, 334, 316, 277, 277, 277, 317, 348, 355, + 364, 311, 312, 336, 341, 315, 342, 370, 376, 371, 376, 315, 385, 386, 389, 316, 380, + 376, 337, 317, 381, 355, 364, 323, 338, 340, 343, 390, 364, 323, 371, 396, 380, 393, + 397, 345, 381, 400, 401, 387, 387, 387, 393, 386, 344, 403, 348, 370, 387, 346, 402, + 406, 371, 409, 408, 397, 407, 439, 420, 414, 448, 385, 412, 389, 413, 386, + + 415, 416, 417, 432, 427, 396, 427, 440, 446, 390, 433, 397, 443, 427, 402, 402, 435, + 444, 408, 408, 445, 401, 449, 414, 447, 450, 451, 454, 400, 445, 453, 393, 417, 455, + 458, 403, 402, 402, 435, 407, 408, 408, 406, 409, 412, 414, 416, 413, 420, 415, 435, + 433, 456, 448, 417, 439, 459, 440, 432, 460, 417, 462, 443, 446, 463, 447, 444, 452, + 452, 452, 457, 457, 457, 479, 480, 450, 452, 481, 470, 457, 470, 451, 479, 455, 487, + 489, 449, 470, 473, 453, 473, 454, 458, 483, 491, 483, 494, 473, 500, 481, + + 492, 490, 483, 488, 488, 488, 495, 456, 501, 460, 490, 498, 488, 496, 496, 496, 505, + 502, 502, 502, 459, 462, 496, 508, 524, 463, 502, 509, 516, 480, 516, 492, 518, 524, + 518, 489, 541, 516, 526, 545, 552, 518, 498, 548, 525, 525, 525, 526, 487, 491, 528, + 558, 528, 492, 525, 559, 530, 591, 530, 528, 494, 495, 500, 501, 498, 530, 535, 535, + 535, 537, 537, 537, 538, 539, 540, 535, 508, 595, 537, 509, 505, 538, 539, 540, 566, + 568, 566, 568, 571, 638, 571, 541, 602, 566, 568, 545, 552, 574, 548, 575, + + 637, 573, 573, 573, 588, 610, 574, 610, 575, 525, 558, 573, 591, 588, 559, 576, 576, + 576, 579, 589, 579, 586, 586, 586, 590, 576, 623, 579, 589, 603, 586, 603, 595, 590, + 601, 601, 601, 539, 603, 602, 607, 615, 607, 619, 614, 614, 614, 621, 622, 607, 615, + 626, 619, 571, 614, 631, 621, 622, 629, 629, 629, 640, 632, 640, 632, 643, 573, 644, + 646, 658, 610, 632, 636, 655, 643, 655, 644, 646, 658, 634, 576, 630, 623, 651, 651, + 651, 627, 624, 590, 663, 663, 663, 617, 616, 613, 612, 611, 609, 606, 601, + + 605, 604, 599, 598, 596, 594, 631, 626, 592, 614, 587, 621, 584, 582, 581, 577, 572, + 570, 565, 563, 562, 561, 560, 629, 557, 555, 640, 553, 551, 549, 546, 544, 646, 542, + 536, 534, 532, 531, 655, 527, 523, 522, 521, 520, 519, 515, 514, 512, 651, 510, 506, + 504, 503, 499, 663, 685, 685, 686, 686, 686, 686, 686, 686, 687, 687, 687, 687, 687, + 687, 688, 688, 689, 689, 497, 689, 689, 689, 690, 493, 690, 690, 691, 691, 691, 692, + 486, 692, 692, 693, 693, 693, 694, 694, 694, 694, 694, 694, 695, 695, 485, + + 695, 695, 695, 696, 696, 696, 696, 696, 696, 697, 697, 697, 697, 697, 697, 698, 698, + 698, 698, 698, 698, 699, 699, 699, 699, 699, 699, 700, 700, 700, 700, 700, 700, 701, + 701, 701, 701, 701, 701, 702, 702, 702, 702, 702, 702, 703, 703, 703, 703, 703, 703, + 704, 704, 704, 704, 704, 704, 705, 705, 705, 705, 705, 705, 706, 706, 706, 706, 706, + 706, 707, 707, 707, 707, 707, 707, 708, 708, 708, 708, 708, 708, 709, 709, 709, 709, + 709, 709, 710, 710, 710, 710, 710, 710, 711, 711, 711, 711, 711, 711, 712, + + 712, 712, 712, 712, 712, 713, 713, 713, 713, 713, 713, 714, 714, 714, 714, 714, 714, + 715, 715, 715, 715, 715, 715, 716, 716, 716, 716, 716, 716, 717, 717, 717, 717, 717, + 717, 718, 718, 718, 718, 718, 718, 719, 719, 719, 719, 719, 719, 720, 720, 720, 720, + 720, 720, 721, 721, 721, 721, 721, 721, 722, 722, 722, 722, 722, 722, 723, 723, 723, + 723, 723, 723, 724, 724, 724, 724, 724, 724, 725, 725, 725, 725, 725, 725, 726, 726, + 726, 726, 726, 726, 727, 727, 727, 727, 727, 727, 728, 728, 728, 728, 728, + + 728, 729, 729, 729, 729, 729, 729, 730, 730, 730, 730, 730, 730, 484, 482, 478, 477, + 476, 475, 472, 471, 469, 468, 467, 465, 464, 461, 441, 438, 437, 436, 434, 431, 430, + 429, 428, 426, 425, 424, 423, 422, 421, 419, 418, 388, 382, 379, 378, 375, 374, 367, + 363, 362, 361, 360, 359, 358, 357, 356, 354, 353, 352, 351, 318, 314, 313, 302, 301, + 300, 299, 297, 296, 295, 294, 293, 292, 290, 289, 288, 287, 286, 285, 282, 276, 275, + 268, 267, 263, 262, 255, 254, 250, 249, 242, 241, 239, 238, 231, 230, 227, + + 226, 219, 218, 211, 199, 197, 196, 189, 166, 164, 154, 153, 152, 151, 148, 136, 134, + 131, 127, 125, 122, 118, 116, 113, 109, 107, 105, 101, 99, 96, 69, 67, 65, 63, + 62, 60, 56, 53, 52, 51, 39, 38, 35, 29, 23, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, + + 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684, 684}; static yyconst flex_int16_t yy_rule_linenum[102] = { - 0, 105, 106, 107, 108, 112, 113, 114, 115, 116, 118, 119, 121, 130, 131, 159, 195, - 219, 225, 246, 253, 264, 269, 283, 288, 295, 318, 329, 331, 345, 358, 383, 389, 394, - 399, 404, 414, 422, 430, 439, 467, 488, 489, 490, 491, 493, 498, 523, 525, 527, 566, - 567, 570, 572, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, - 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, - 611, 612, 613, 614, 615, 616, 622, 628, 640, 642, 644, 660, 661, 671, 674, 675, + 0, 124, 125, 126, 127, 131, 132, 133, 134, 135, 137, 138, 140, 146, 227, 251, 257, + 278, 285, 296, 301, 315, 320, 327, 350, 361, 363, 377, 390, 415, 421, 426, 431, 436, + 446, 454, 462, 471, 499, 520, 521, 522, 523, 525, 530, 555, 557, 559, 598, 599, 602, + 604, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, + 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, + 645, 646, 647, 648, 654, 660, 672, 692, 694, 696, 713, 729, 730, 740, 743, 744, - 677}; + 746}; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -982,20 +963,23 @@ static yyconst flex_int16_t yy_rule_linenum[102] = { * See packages/seacas/LICENSE for details */ +#include #include #include #include #include #include -#include #include #include #include #include "apr_getline.h" #include "apr_scanner.h" +#include "apr_tokenize.h" #include "apr_util.h" #include "aprepro.h" +#include "fmt/format.h" +#include "fmt/ostream.h" #define YY_NO_UNISTD_H /* import the parser's token type into a local typedef */ @@ -1013,6 +997,8 @@ namespace SEAMS { } // namespace SEAMS namespace { + bool begin_double_brace = false; + bool end_double_brace = false; bool string_is_ascii(const char *line, size_t len) { for (size_t i = 0; i < len; i++) { @@ -1049,7 +1035,7 @@ bool switch_skip_to_endcase = false; double switch_condition = 0.0; // Value specified in "switch(condition)" // For substitution history -size_t curr_index = 0; +int curr_index = 0; std::string history_string; size_t hist_start = 0; @@ -1284,12 +1270,12 @@ YY_DECL } while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) { yy_current_state = (int)yy_def[yy_current_state]; - if (yy_current_state >= 703) + if (yy_current_state >= 685) yy_c = yy_meta[(unsigned int)yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c]; ++yy_cp; - } while (yy_base[yy_current_state] != 2512); + } while (yy_base[yy_current_state] != 2446); yy_find_action: /* %% [10.0] code to find the action number goes here */ @@ -1369,91 +1355,98 @@ YY_DECL YY_RULE_SETUP { aprepro.stateImmutable = aprepro.ap_options.immutable; } YY_BREAK case 12: - YY_RULE_SETUP - { - BEGIN(GET_LOOP_VAR); - if (aprepro.ap_options.debugging) - std::cerr << "DEBUG LOOP - Found loop begin test " << yytext << " in file " - << aprepro.ap_file_list.top().name << " at line " - << aprepro.ap_file_list.top().lineno << "\n"; - } + YY_RULE_SETUP { BEGIN(GET_LOOP_VAR); } YY_BREAK case 13: - /* rule 13 can match eol */ - case 14: - /* rule 14 can match eol */ + /* rule 13 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; - /* Loop control defined by integer */ - char *pt = strchr(yytext, ')'); - *pt = '\0'; - sscanf(yytext, "%lf", &yylval->val); - - if (yylval->val <= 0) { - BEGIN(LOOP_SKIP); + /* `yytext` includes closing `)}` and newline... Strip these */ + char *pt = strchr(yytext, ')'); + *pt = '\0'; + auto tokens = tokenize(yytext, " ,\t"); + if (aprepro.ap_options.debugging) { + fmt::print(stderr, "DEBUG LOOP: tokens = {}\n", fmt::join(tokens, ", ")); } - else { /* Value defined and != 0. */ - temp_f = get_temp_filename(); - SEAMS::file_rec new_file(temp_f, 0, true, (int)yylval->val); - if (aprepro.ap_options.debugging) - std::cerr << "DEBUG LOOP VAR = " << aprepro.ap_file_list.top().loop_count - << " in file " << aprepro.ap_file_list.top().name << " at line " - << aprepro.ap_file_list.top().lineno - 1 << "\n"; - outer_file = &aprepro.ap_file_list.top(); - aprepro.ap_file_list.push(new_file); - - tmp_file = new std::fstream(temp_f, std::ios::out); - loop_lvl++; - BEGIN(LOOP); - } - aprepro.isCollectingLoop = true; - } - YY_BREAK - case 15: - /* rule 15 can match eol */ - YY_RULE_SETUP - { - aprepro.ap_file_list.top().lineno++; - /* Loop control defined by variable */ - symrec *s; - char *pt = strchr(yytext, ')'); - *pt = '\0'; - if (!check_valid_var(yytext)) { - aprepro.warning("Invalid variable name syntax '" + std::string(yytext) + "'"); - BEGIN(LOOP_SKIP); + /* Determine if the first token is a symbol or an explicit number... */ + auto count = tokens[0]; + bool all_dig = count.find_first_not_of("0123456789") == std::string::npos; + int loop_iterations = 0; + if (all_dig) { + loop_iterations = std::stoi(count); } else { - s = aprepro.getsym(yytext); - - if (s == nullptr || - (s->type != token::SVAR && s->type != token::IMMSVAR && s->value.var == 0.)) { + symrec *s; + if (!check_valid_var(tokens[0].c_str())) { + aprepro.warning("Invalid variable name syntax '" + tokens[0] + "'"); BEGIN(LOOP_SKIP); } - else { /* Value defined and != 0. */ - if (aprepro.ap_options.debugging) - std::cerr << "DEBUG LOOP VAR = " << aprepro.ap_file_list.top().loop_count - << " in file " << aprepro.ap_file_list.top().name << " at line " - << aprepro.ap_file_list.top().lineno - 1 << "\n"; - - temp_f = get_temp_filename(); - SEAMS::file_rec new_file(temp_f, 0, true, (int)s->value.var); - outer_file = &aprepro.ap_file_list.top(); - aprepro.ap_file_list.push(new_file); - - tmp_file = new std::fstream(temp_f, std::ios::out); - loop_lvl++; - BEGIN(LOOP); + else { + s = aprepro.getsym(tokens[0]); + if (s == nullptr || + (s->type != token::SVAR && s->type != token::IMMSVAR && s->value.var == 0.)) { + BEGIN(LOOP_SKIP); + } + else { + loop_iterations = (int)s->value.var; + } } } + + temp_f = get_temp_filename(); + SEAMS::file_rec new_file(temp_f, 0, true, loop_iterations); + outer_file = &aprepro.ap_file_list.top(); + new_file.loop_level = outer_file->loop_level + 1; + + // Get optional loop index... + std::string sym_name; + if (tokens.size() == 1) { + // Default loop index variable name if not specified in loop command. + sym_name = fmt::format("__loop_{}", new_file.loop_level); + } + else { + sym_name = tokens[1]; + } + SEAMS::symrec *li = aprepro.getsym(sym_name); + if (li == nullptr) { + li = aprepro.putsym(sym_name, SEAMS::Aprepro::SYMBOL_TYPE::VARIABLE, true); + } + + // Get optional loop index initial value. Default to 0 if not specified. + double init = 0.0; + if (tokens.size() >= 3) { + init = std::stod(tokens[2]); + } + li->value.var = init; + + // Get optional loop index increment value. Default to 1 if not specified. + if (tokens.size() >= 4) { + double increment = std::stod(tokens[3]); + new_file.loop_increment = increment; + } + + new_file.loop_index = li; + aprepro.ap_file_list.push(new_file); + + tmp_file = new std::fstream(temp_f, std::ios::out); + loop_lvl++; + BEGIN(LOOP); aprepro.isCollectingLoop = true; + if (aprepro.ap_options.debugging) { + fmt::print( + stderr, + "DEBUG LOOP: iteration count = {}, loop_index variable = {}, initial value = " + "{}, increment = {}\n", + loop_iterations, sym_name, init, new_file.loop_increment); + } } YY_BREAK - case 16: - /* rule 16 can match eol */ + case 14: + /* rule 14 can match eol */ YY_RULE_SETUP { outer_file->lineno++; @@ -1479,8 +1472,8 @@ YY_DECL } } YY_BREAK - case 17: - /* rule 17 can match eol */ + case 15: + /* rule 15 can match eol */ YY_RULE_SETUP { loop_lvl++; /* Nested Loop */ @@ -1488,8 +1481,8 @@ YY_DECL outer_file->lineno++; } YY_BREAK - case 18: - /* rule 18 can match eol */ + case 16: + /* rule 16 can match eol */ YY_RULE_SETUP { if (aprepro.ap_options.interactive || aprepro.string_interactive()) { @@ -1510,8 +1503,8 @@ YY_DECL } } YY_BREAK - case 19: - /* rule 19 can match eol */ + case 17: + /* rule 17 can match eol */ YY_RULE_SETUP { (*tmp_file) << yytext; @@ -1519,8 +1512,8 @@ YY_DECL } YY_BREAK - case 20: - /* rule 20 can match eol */ + case 18: + /* rule 18 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; @@ -1533,16 +1526,16 @@ YY_DECL } } YY_BREAK - case 21: - /* rule 21 can match eol */ + case 19: + /* rule 19 can match eol */ YY_RULE_SETUP { loop_lvl++; /* Nested Loop */ aprepro.ap_file_list.top().lineno++; } YY_BREAK - case 22: - /* rule 22 can match eol */ + case 20: + /* rule 20 can match eol */ YY_RULE_SETUP { if (aprepro.ap_options.interactive || aprepro.string_interactive()) { @@ -1556,16 +1549,16 @@ YY_DECL } } YY_BREAK - case 23: - /* rule 23 can match eol */ + case 21: + /* rule 21 can match eol */ YY_RULE_SETUP { /* Do not increment line count */ ; } YY_BREAK - case 24: - /* rule 24 can match eol */ + case 22: + /* rule 22 can match eol */ YY_RULE_SETUP { yyless(0); @@ -1574,8 +1567,8 @@ YY_DECL switch_skip_to_endcase = false; } YY_BREAK - case 25: - /* rule 25 can match eol */ + case 23: + /* rule 23 can match eol */ YY_RULE_SETUP { if (!switch_active) { @@ -1602,8 +1595,8 @@ YY_DECL } } YY_BREAK - case 26: - /* rule 26 can match eol */ + case 24: + /* rule 24 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; @@ -1616,12 +1609,12 @@ YY_DECL aprepro.ap_file_list.top().lineno); } YY_BREAK - case 27: - /* rule 27 can match eol */ + case 25: + /* rule 25 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; } YY_BREAK - case 28: - /* rule 28 can match eol */ + case 26: + /* rule 26 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; @@ -1637,7 +1630,7 @@ YY_DECL * where they would eat up any leading whitespace on * a line. */ - case 29: + case 27: YY_RULE_SETUP { // Used to avoid undefined variable warnings in old ifdef/ifndef construct @@ -1652,7 +1645,7 @@ YY_DECL unput('{'); } YY_BREAK - case 30: + case 28: YY_RULE_SETUP { // Used to avoid undefined variable warnings in old ifdef/ifndef construct @@ -1678,8 +1671,8 @@ YY_DECL * NOTE: if_lvl was not incremented, so don't need to decrement when * endif found. */ - case 31: - /* rule 31 can match eol */ + case 29: + /* rule 29 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; @@ -1687,32 +1680,32 @@ YY_DECL BEGIN(IF_SKIP); } YY_BREAK - case 32: - /* rule 32 can match eol */ + case 30: + /* rule 30 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; if_skip_level++; } YY_BREAK - case 33: - /* rule 33 can match eol */ + case 31: + /* rule 31 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; if_skip_level++; } YY_BREAK - case 34: - /* rule 34 can match eol */ + case 32: + /* rule 32 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; if_skip_level++; } YY_BREAK - case 35: - /* rule 35 can match eol */ + case 33: + /* rule 33 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; } YY_BREAK @@ -1720,7 +1713,7 @@ YY_DECL * skip the entire block up and including the endif. * The (IF_WHILE_SKIP) start condition handles this skipping. */ - case 36: + case 34: YY_RULE_SETUP { if (aprepro.ap_options.debugging) @@ -1730,7 +1723,7 @@ YY_DECL BEGIN(IF_WHILE_SKIP); } YY_BREAK - case 37: + case 35: YY_RULE_SETUP { if (aprepro.ap_options.debugging) @@ -1740,7 +1733,7 @@ YY_DECL BEGIN(IF_WHILE_SKIP); } YY_BREAK - case 38: + case 36: YY_RULE_SETUP { if (aprepro.ap_options.debugging) @@ -1751,8 +1744,8 @@ YY_DECL } YY_BREAK - case 39: - /* rule 39 can match eol */ + case 37: + /* rule 37 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; @@ -1784,8 +1777,8 @@ YY_DECL } YY_BREAK - case 40: - /* rule 40 can match eol */ + case 38: + /* rule 38 can match eol */ YY_RULE_SETUP { /* If any previous 'block' of this if has executed, then @@ -1809,19 +1802,19 @@ YY_DECL } } YY_BREAK + case 39: + case 40: case 41: case 42: - case 43: - case 44: YY_RULE_SETUP { ; } YY_BREAK - case 45: - /* rule 45 can match eol */ + case 43: + /* rule 43 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; } YY_BREAK - case 46: - /* rule 46 can match eol */ + case 44: + /* rule 44 can match eol */ YY_RULE_SETUP { @@ -1848,22 +1841,22 @@ YY_DECL aprepro.ap_file_list.top().lineno++; } YY_BREAK - case 47: + case 45: YY_RULE_SETUP { BEGIN(GET_FILENAME); file_must_exist = true; } YY_BREAK - case 48: + case 46: YY_RULE_SETUP { BEGIN(GET_FILENAME); file_must_exist = false; } YY_BREAK - case 49: - /* rule 49 can match eol */ + case 47: + /* rule 47 can match eol */ YY_RULE_SETUP { aprepro.ap_file_list.top().lineno++; @@ -1906,18 +1899,18 @@ YY_DECL } } YY_BREAK - case 50: - case 51: + case 48: + case 49: YY_RULE_SETUP { sscanf(yytext, "%lf", &yylval->val); return (token::NUM); } YY_BREAK - case 52: + case 50: YY_RULE_SETUP; // Empty rule YY_BREAK - case 53: + case 51: YY_RULE_SETUP { symrec *s; @@ -1928,153 +1921,153 @@ YY_DECL return ((token::yytokentype)s->type); } YY_BREAK - case 54: + case 52: YY_RULE_SETUP return (token::EQUAL); YY_BREAK - case 55: + case 53: YY_RULE_SETUP return (token::EQ_PLUS); YY_BREAK - case 56: + case 54: YY_RULE_SETUP return (token::EQ_MINUS); YY_BREAK - case 57: + case 55: YY_RULE_SETUP return (token::EQ_TIME); YY_BREAK - case 58: + case 56: YY_RULE_SETUP return (token::EQ_DIV); YY_BREAK - case 59: + case 57: YY_RULE_SETUP return (token::EQ_POW); YY_BREAK - case 60: + case 58: YY_RULE_SETUP return (token::EQ_POW); YY_BREAK - case 61: + case 59: YY_RULE_SETUP return (token::INC); YY_BREAK - case 62: + case 60: YY_RULE_SETUP return (token::DEC); YY_BREAK - case 63: + case 61: YY_RULE_SETUP return (token::PLU); YY_BREAK - case 64: + case 62: YY_RULE_SETUP return (token::SUB); YY_BREAK - case 65: + case 63: YY_RULE_SETUP return (token::TIM); YY_BREAK - case 66: + case 64: YY_RULE_SETUP return (token::TIM); /* ~ is same as multiply */ YY_BREAK - case 67: + case 65: YY_RULE_SETUP return (token::CONCAT); /* String concatenation */ YY_BREAK - case 68: + case 66: YY_RULE_SETUP return (token::DIV); YY_BREAK - case 69: + case 67: YY_RULE_SETUP return (token::MOD); YY_BREAK - case 70: + case 68: YY_RULE_SETUP return (token::POW); YY_BREAK - case 71: + case 69: YY_RULE_SETUP return (token::POW); YY_BREAK - case 72: - /* rule 72 can match eol */ + case 70: + /* rule 70 can match eol */ YY_RULE_SETUP aprepro.ap_file_list.top().lineno++; YY_BREAK - case 73: + case 71: YY_RULE_SETUP return (token::LPAR); YY_BREAK - case 74: + case 72: YY_RULE_SETUP return (token::RPAR); YY_BREAK - case 75: + case 73: YY_RULE_SETUP return (token::COMMA); YY_BREAK - case 76: + case 74: YY_RULE_SETUP return (token::SEMI); YY_BREAK - case 77: + case 75: YY_RULE_SETUP return (token::COLON); YY_BREAK - case 78: + case 76: YY_RULE_SETUP return (token::QUEST); YY_BREAK - case 79: + case 77: YY_RULE_SETUP return (token::LT); YY_BREAK - case 80: + case 78: YY_RULE_SETUP return (token::GT); YY_BREAK - case 81: + case 79: YY_RULE_SETUP return (token::LE); YY_BREAK - case 82: + case 80: YY_RULE_SETUP return (token::GE); YY_BREAK - case 83: + case 81: YY_RULE_SETUP return (token::EQ); YY_BREAK - case 84: + case 82: YY_RULE_SETUP return (token::NE); YY_BREAK - case 85: + case 83: YY_RULE_SETUP return (token::LAND); YY_BREAK - case 86: + case 84: YY_RULE_SETUP return (token::LOR); YY_BREAK - case 87: + case 85: YY_RULE_SETUP return (token::NOT); YY_BREAK - case 88: + case 86: YY_RULE_SETUP return (token::LBRACK); YY_BREAK - case 89: + case 87: YY_RULE_SETUP return (token::RBRACK); YY_BREAK - case 90: - /* rule 90 can match eol */ + case 88: + /* rule 88 can match eol */ YY_RULE_SETUP { char *pt = strrchr(yytext, '"'); @@ -2083,8 +2076,8 @@ YY_DECL return token::QSTRING; } YY_BREAK - case 91: - /* rule 91 can match eol */ + case 89: + /* rule 89 can match eol */ YY_RULE_SETUP { char *pt = strrchr(yytext, '\''); @@ -2093,7 +2086,7 @@ YY_DECL return token::QSTRING; } YY_BREAK - case 92: + case 90: YY_RULE_SETUP { // Add to the history string @@ -2106,26 +2099,65 @@ YY_DECL return (token::RBRACE); } YY_BREAK - case 93: + case 91: + YY_RULE_SETUP + { + if (begin_double_brace) { + end_double_brace = true; + } + else { + yyerror("Found an unexpected double end brace ('}}').\n\t" + "It can only end an expression started with a double brace ('{{').\n\tCheck " + "syntax."); + } + + // Add to the history string + save_history_string(); + + if (switch_skip_to_endcase) + BEGIN(END_CASE_SKIP); + else + BEGIN(if_state[if_lvl]); + return (token::RBRACE); + } + YY_BREAK + case 92: YY_RULE_SETUP { if (echo) LexerOutput("{", 1); } YY_BREAK - case 94: + case 93: YY_RULE_SETUP { if (echo) LexerOutput("}", 1); } YY_BREAK + case 94: + YY_RULE_SETUP + { + // Check if we need to save the substitution history first. + if (aprepro.ap_options.keep_history && (aprepro.ap_file_list.top().name != "_string_")) { + if (curr_index > yyleng) + hist_start = curr_index - yyleng; + else + hist_start = 0; + } + + BEGIN(PARSING); + echo = false; + begin_double_brace = true; + return (token::LBRACE); + } + YY_BREAK case 95: YY_RULE_SETUP { // Check if we need to save the substitution history first. if (aprepro.ap_options.keep_history && (aprepro.ap_file_list.top().name != "_string_")) { - if (curr_index > (size_t)yyleng) + if (curr_index > yyleng) hist_start = curr_index - yyleng; else hist_start = 0; @@ -2171,6 +2203,11 @@ YY_DECL if (echo && !suppress_nl) ECHO; suppress_nl = false; + if (end_double_brace) { + echo = true; + begin_double_brace = false; + end_double_brace = false; + } aprepro.ap_file_list.top().lineno++; } YY_BREAK @@ -2554,7 +2591,7 @@ yy_state_type yyFlexLexer::yy_get_previous_state() } while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) { yy_current_state = (int)yy_def[yy_current_state]; - if (yy_current_state >= 703) + if (yy_current_state >= 685) yy_c = yy_meta[(unsigned int)yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c]; @@ -2585,11 +2622,11 @@ yy_state_type yyFlexLexer::yy_try_NUL_trans(yy_state_type yy_current_state) } while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) { yy_current_state = (int)yy_def[yy_current_state]; - if (yy_current_state >= 703) + if (yy_current_state >= 685) yy_c = yy_meta[(unsigned int)yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int)yy_c]; - yy_is_jam = (yy_current_state == 702); + yy_is_jam = (yy_current_state == 684); return yy_is_jam ? 0 : yy_current_state; } @@ -2608,7 +2645,7 @@ void yyFlexLexer::yyunput(int c, char *yy_bp) *yy_cp = (yy_hold_char); if (yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2) { /* need to shift things up to make room */ - /* +2 for EOB chars. */ + /* +2 for EOB chars. */ yy_size_t number_to_move = (yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; @@ -3063,7 +3100,10 @@ void yyFlexLexer::yy_pop_state() /* %endif */ /* %if-c++-only */ int yyFlexLexer::yy_top_state() -/* %endif */ { return (yy_start_stack)[(yy_start_stack_ptr)-1]; } +/* %endif */ +{ + return (yy_start_stack)[(yy_start_stack_ptr)-1]; +} #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 @@ -3342,6 +3382,11 @@ namespace SEAMS { yyin = aprepro.open_file(aprepro.ap_file_list.top().name, "r"); yyFlexLexer::yypush_buffer_state(yyFlexLexer::yy_create_buffer(yyin, YY_BUF_SIZE)); aprepro.ap_file_list.top().lineno = 0; + + if (aprepro.ap_file_list.top().loop_index != nullptr) { + aprepro.ap_file_list.top().loop_index->value.var += + aprepro.ap_file_list.top().loop_increment; + } } } else { diff --git a/packages/seacas/libraries/aprepro_lib/apr_test.cc b/packages/seacas/libraries/aprepro_lib/apr_test.cc index cdb3c4fbe1..bbf801cf9d 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_test.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_test.cc @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions +// Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -7,7 +7,6 @@ #include #include -#include "apr_symrec.h" #include "aprepro.h" // This function is used below in the example showing how an @@ -37,7 +36,7 @@ int main(int argc, char *argv[]) if (arg == "-o") { output_file = argv[++ai]; } - if (arg == "-i") { + else if (arg == "-i") { // Read from cin and echo each line to cout All results will // also be stored in Aprepro::parsing_results() stream if needed // at end of file. @@ -61,6 +60,12 @@ int main(int argc, char *argv[]) // then the output can be obtained in an std::ostringstream via // Aprepro::parsing_results() std::fstream infile(argv[ai]); + if (!infile.good()) { + if (!aprepro.ap_options.include_path.empty() && argv[ai][0] != '/') { + std::string filename = aprepro.ap_options.include_path + "/" + argv[ai]; + infile.open(filename, std::fstream::in); + } + } if (!infile.good()) { std::cerr << "APREPRO: Could not open file: " << argv[ai] << '\n'; return 0; @@ -83,7 +88,7 @@ int main(int argc, char *argv[]) if (readfile) { std::cerr << "Aprepro: There were " << aprepro.get_error_count() << " errors detected during parsing.\n"; - return 0; + return aprepro.get_error_count() == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } // Read and parse a string's worth of data at a time. @@ -125,4 +130,5 @@ int main(int argc, char *argv[]) } std::cerr << "Aprepro: There were " << aprepro.get_error_count() << " errors detected during parsing.\n"; + return aprepro.get_error_count() == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/packages/seacas/libraries/aprepro_lib/apr_units.cc b/packages/seacas/libraries/aprepro_lib/apr_units.cc index abac313f2b..bd324d7b0f 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_units.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_units.cc @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -37,6 +37,7 @@ namespace { } void load_conversion(var_init *base, svar_init *label); + void load_constants(var_init *base); constexpr double LBF_TO_N = 4.4482216152605; constexpr double PI = 3.141592653589793238462643; @@ -322,7 +323,11 @@ unit_systems systems[] = aprepro->add_variable(systems[i].base[j].vname, systems[i].base[j].value, true); } + symrec *var = aprepro->getsym("_UNITS_SYSTEM"); + var->value.svar = type; + load_conversion(systems[i].base, systems[i].label); + load_constants(systems[i].base); return (" "); } @@ -331,36 +336,134 @@ unit_systems systems[] = } namespace { -void load_conversion(var_init *base, svar_init *label) -{ - const char *tout = label[ 0].value; - const char *lout = label[ 1].value; - const char *aout = label[ 2].value; - const char *mout = label[ 3].value; - const char *fout = label[ 4].value; - const char *vout = label[ 5].value; - const char *Vout = label[ 6].value; - const char *dout = label[ 7].value; - const char *eout = label[ 8].value; - const char *Pout = label[ 9].value; - const char *pout = label[10].value; - const char *Tout = label[11].value; - const char *Aout = label[12].value; - - double m = base[0].value; - double sec = base[1].value; - double kg = base[2].value; - double degK = base[3].value; - double rad = base[4].value; - - double foot = m * 0.3048; - double inch = foot / 12.0; - - std::string title_prefix = "\n"; - for(size_t i = 0; i < 3; i++) { - title_prefix += comment(); -} - title_prefix += " "; + void load_constants(var_init *base) + { + double Ohm = 1; + double Hz = 1; + double A = 1; + double C = 1; + double F = 1; + double V = 1; + double T = 1; + double mol = 1; + double S = 1; + double GeV = 1; + + double m = base[0].value; + double sec = base[1].value; + double kg = base[2].value; + double degK = base[3].value; + + double N = kg * m / (sec * sec); + double J = N * m; + double W = J / sec; + + double sec2 = sec * sec; + double degK4 = degK * degK * degK * degK; + double m2 = m * m; + double m3 = m * m * m; + double C2 = C * C; + double A2 = A * A; + + if (echo != 0) { + std::string title_prefix = "\n"; + for (size_t i = 0; i < 3; i++) { + title_prefix += comment(); + } + title_prefix += " "; + *(aprepro->infoStream) + << title_prefix + << "Physical Constants (https://en.wikipedia.org/wiki/List_of_physical_constants)" + << '\n'; + } + define_var("Avogadro_constant", 6.02214076E23 / mol, "# 6.02214076E23 / mol"); + define_var("Bohr_magneton", 9.2740100783E-24 * J / T, "# 9.2740100783E-24 J/T"); + define_var("Bohr_radius", 5.29177210903E-11 * m, "# 5.29177210903E-11 m"); + define_var("Boltzmann_constant", 1.380649E-23 * J / degK, "# 1.380649E-23 J/degK"); + define_var("Coulomb_constant", 8.9875517923E9 * N * m2 / C2, "# 8.9875517923E9 N m^2 C^-2"); + define_var("Faraday_constant", 96485.3321233100184 * C / mol, "# 96485.3321233100184 C/mol"); + define_var("Fermi_coupling_constant", 1.166378710E-5 / (GeV * GeV), "# 1.166378710E-5 GeV^-2"); + define_var("Hartree_energy", 4.3597447222071E-18 * J, "# 4.3597447222071E-18 J"); + define_var("Josephson_constant", 483597.8484E9 * Hz / V, "# 483597.8484E9 Hz/V"); + define_var("Newtonian_constant_of_gravitation", 6.67430E-11 * m3 / kg / sec2, "# 6.67430E-11 m^3/kg s^-2"); + define_var("Gravitational_constant", 6.67430E-11 * m3 / kg / sec2, "# 6.67430E-11 m^3/kg s^-2"); + define_var("Planck_constant", 6.62607015E-34 * J / Hz, "# 6.62607015E-34 J/Hz"); + define_var("Rydberg_constant", 10973731.568160 / m, "# 10973731.568160 m"); + define_var("Rydberg_unit_of_energy", 2.1798723611035E-18 * J, "# 2.1798723611035E-18 J"); + define_var("Stefan_Boltzmann_constant", 5.670374419E-8 * W / m2 / degK4, "# 5.670374419E-8 W m^-2 degK^-4"); + define_var("Thomson_cross_section", 6.6524587321E-29 * m2, "# 6.6524587321E-29 m^2"); + define_var("W_to_Z_mass_ratio", 0.88153, ""); + define_var("Wien_entropy_displacement_law_constant", 3.002916077E-3 * m * degK, "# 3.002916077E-3 m degK"); + define_var("Wien_frequency_displacement_law_constant", 5.878925757E10 * Hz / degK,"# 5.878925757E10 Hz/degK"); + define_var("Wien_wavelength_displacement_law_constant", 2.897771955E-3 * m * degK, "# 2.897771955E-3 m degK"); + define_var("atomic_mass_constant", 1.66053906660E-27 * kg, "# 1.66053906660E-27 kg"); + define_var("atomic_mass_of_carbon_12", 1.99264687992E-26 * kg, "# 1.99264687992E-26 kg"); + define_var("characteristic_impedance_of_vacuum", 376.730313668 * Ohm, "# 376.730313668 Ohm"); + define_var("classical_electron_radius", 2.8179403262E-15 * m, "# 2.8179403262E-15 m"); + define_var("conductance_quantum", 7.748091729E-5 * S, "# 7.748091729E-5 S"); + define_var("cosmological_constant", 1.089E-52 / m2, "# 1.089E-52 m^-2"); + define_var("electron_g_factor", -2.00231930436256, ""); + define_var("electron_mass", 9.1093837015E-31 * kg, "# 9.1093837015E-31 kg"); + define_var("elementary_charge", 1.602176634E-19 * C, "# 1.602176634E-19 C"); + define_var("fine_structure_constant", 7.2973525693E-3, ""); + define_var("first_radiation_constant", 3.741771852E-16 * W * m2, "# 3.741771852E-16 W m^2"); + define_var("hyperfine_transition_frequency_of_133Cs", 9192631770 * Hz, "# 9192631770 Hz"); + define_var("inverse_conductance_quantum", 12906.40372 * Ohm, "# 12906.40372 Ohm"); + define_var("inverse_fine_structure_constant", 137.035999084, ""); + define_var("magnetic_flux_quantum", 2.067833848E-15 * V * sec, "# 2.067833848E-15 V s"); + define_var("molar_Planck_constant", 3.9903127128934314E-10 * J * sec / mol, "# 3.9903127128934314E-10 J s / mol"); + define_var("molar_gas_constant", 8.31446261815324 * J / mol / degK, "# 8.31446261815324 J/mol/degK"); + define_var("molar_mass_constant", 0.99999999965E-3 * kg / mol, "# 0.99999999965E-3 kg/mol"); + define_var("molar_mass_of_carbon_12", 11.9999999958E-3 * kg / mol, "# 11.9999999958E-3 kg/mol"); + define_var("muon_g_factor", -2.0023318418, ""); + define_var("muon_mass", 1.883531627E-28 * kg, "# 1.883531627E-28 kg"); + define_var("neutron_mass", 1.67492749804E-27 * kg, "# 1.67492749804E-27 kg"); + define_var("nuclear_magneton", 5.0507837461E-27 * J / T, "# 5.0507837461E-27 J/T"); + define_var("proton_g_factor", 5.5856946893, ""); + define_var("proton_mass", 1.67262192369E-27 * kg, "# 1.67262192369E-27 kg"); + define_var("proton_to_electron_mass_ratio", 1836.15267343, ""); + define_var("quantum_of_circulation", 3.6369475516E-4 * m2 / sec, "# 3.6369475516E-4 m^2/s"); + define_var("reduced_Planck_constant", 1.054571817E-34 * J * sec, "# 1.054571817E-34 J s"); + define_var("sec_radiation_constant", 1.438776877E-2 * m * degK, "# 1.438776877E-2 m degK"); + define_var("speed_of_light_in_vacuum", 299792458 * m / sec, "# 299792458 m/s"); + define_var("tau_mass", 3.16754E-27 * kg, "# 3.16754E-27 kg"); + define_var("top_quark_mass", 3.0784E-25 * kg, "# 3.0784E-25 kg"); + define_var("vacuum_electric_permittivity", 8.8541878128E-12 * F / m, "# 8.8541878128E-12 F/m"); + define_var("vacuum_magnetic_permeability", 1.25663706212E-6 * N / A2, "# 1.25663706212E-6 N A^-2"); + define_var("von_Klitzing_constant", 25812.80745 * Ohm, "# 25812.80745 Ohm"); + define_var("weak_mixing_angle", 0.22290, ""); + } + + void load_conversion(var_init *base, svar_init *label) + { + const char *tout = label[ 0].value; + const char *lout = label[ 1].value; + const char *aout = label[ 2].value; + const char *mout = label[ 3].value; + const char *fout = label[ 4].value; + const char *vout = label[ 5].value; + const char *Vout = label[ 6].value; + const char *dout = label[ 7].value; + const char *eout = label[ 8].value; + const char *Pout = label[ 9].value; + const char *pout = label[10].value; + const char *Tout = label[11].value; + const char *Aout = label[12].value; + + double m = base[0].value; + double sec = base[1].value; + double kg = base[2].value; + double degK = base[3].value; + double rad = base[4].value; + + double foot = m * 0.3048; + double inch = foot / 12.0; + + std::string title_prefix = "\n"; + for(size_t i = 0; i < 3; i++) { + title_prefix += comment(); + } + title_prefix += " "; if (echo != 0) { *(aprepro->infoStream) diff --git a/packages/seacas/libraries/aprepro_lib/apr_util.cc b/packages/seacas/libraries/aprepro_lib/apr_util.cc index 5e38b5f02d..b934b9395e 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_util.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_util.cc @@ -1,10 +1,9 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions +// Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // // See packages/seacas/LICENSE for details -#include "apr_symrec.h" #include "aprepro.h" // for symrec, Aprepro, etc #include "aprepro_parser.h" // for Parser, Parser::token, etc @@ -31,7 +30,7 @@ #include #if !defined(S_ISDIR) -#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #else @@ -140,8 +139,8 @@ namespace SEAMS { void immutable_modify(const SEAMS::Aprepro &apr, const SEAMS::symrec *var) { - apr.error("(IMMUTABLE) Variable " + var->name + " is immutable and cannot be modified", true, - false); + apr.warning("(IMMUTABLE) Variable " + var->name + " is immutable and cannot be modified", true, + false); } void undefined_error(const SEAMS::Aprepro &apr, const std::string &var) diff --git a/packages/seacas/libraries/aprepro_lib/apr_util.h b/packages/seacas/libraries/aprepro_lib/apr_util.h index 09187fea65..8ce676e7f6 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_util.h +++ b/packages/seacas/libraries/aprepro_lib/apr_util.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -7,11 +7,12 @@ */ #pragma once -#include "apr_symrec.h" -#include "aprepro.h" #include namespace SEAMS { + struct symrec; + class Aprepro; + bool arg_check(SEAMS::symrec *symbol, bool is_null); void conv_string(char *string); void new_string(const std::string &from, char **to); diff --git a/packages/seacas/libraries/aprepro_lib/aprepro.h b/packages/seacas/libraries/aprepro_lib/aprepro.h index a01a916269..feea00f7ae 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro.h +++ b/packages/seacas/libraries/aprepro_lib/aprepro.h @@ -18,6 +18,8 @@ #include #include +#include "apr_symrec.h" + #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include @@ -29,8 +31,6 @@ namespace SEAMS { struct Symtable; - struct symrec; - struct array; /* Global options */ struct aprepro_options @@ -58,8 +58,11 @@ namespace SEAMS { struct file_rec { std::string name{"STDIN"}; + symrec *loop_index{nullptr}; + double loop_increment{1}; int lineno{1}; int loop_count{0}; + int loop_level{0}; bool tmp_file{false}; file_rec(const char *my_name, int line_num, bool is_temp, int loop_cnt) @@ -112,10 +115,13 @@ namespace SEAMS { const std::ostringstream &parsing_results() const { return parsingResults; } void clear_results(); + /** Return string representation of current version of aprepro + commit date. */ + static const std::string &version(); + /** Return string representation of current version of aprepro. */ - static std::string version(); + static const std::string &short_version(); - /** Return long version: `# Algebraic Preprocessor (Aprepro) version X.X.X` */ + /** Return long version: `# Algebraic Preprocessor (Aprepro) version X.X (date)` */ std::string long_version() const; /** Invoke the scanner and parser for a stream. @@ -258,7 +264,7 @@ namespace SEAMS { // needs to be sent through Aprepro again later. bool doIncludeSubstitution{true}; - // Flag to inidicate whether Aprepro is in the middle of collecting lines for a + // Flag to indicate whether Aprepro is in the middle of collecting lines for a // loop. bool isCollectingLoop{false}; diff --git a/packages/seacas/libraries/aprepro_lib/aprepro.ll b/packages/seacas/libraries/aprepro_lib/aprepro.ll index 58684750a9..31c8aabda3 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro.ll +++ b/packages/seacas/libraries/aprepro_lib/aprepro.ll @@ -1,7 +1,7 @@ /* -*- Mode: c++ -*- */ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -11,6 +11,7 @@ %{ +#include #include #include #include @@ -23,7 +24,11 @@ #include "apr_scanner.h" #include "aprepro.h" #include "apr_util.h" -#include "apr_getline_int.h" +#include "apr_getline.h" +#include "apr_tokenize.h" +#include "fmt/format.h" +#include "fmt/ostream.h" + #define YY_NO_UNISTD_H /* import the parser's token type into a local typedef */ @@ -41,11 +46,13 @@ typedef SEAMS::Parser::token_type token_type; } namespace { + bool begin_double_brace = false; + bool end_double_brace = false; bool string_is_ascii(const char *line, size_t len) { for (size_t i = 0; i < len; i++) { if (!(std::isspace(line[i]) || std::isprint(line[i]))) { - return false; + return false; } } return true; @@ -117,7 +124,7 @@ integer {D}+({E})? "{VERBATIM(OFF)}" { BEGIN(INITIAL); } [A-Za-z0-9_ ]* | . { if (echo) ECHO; } - "\n" { if (echo) ECHO; aprepro.ap_file_list.top().lineno++; } + "\n" { if (echo) ECHO; aprepro.ap_file_list.top().lineno++; } } { @@ -132,74 +139,87 @@ integer {D}+({E})? {WS}"{"[Ll]"oop"{WS}"(" { BEGIN(GET_LOOP_VAR); - if (aprepro.ap_options.debugging) - std::cerr << "DEBUG LOOP - Found loop begin test " << yytext << " in file " - << aprepro.ap_file_list.top().name << " at line " << aprepro.ap_file_list.top().lineno << "\n"; } } { - {number}")".*"\n" | - {integer}")}".*"\n" { + .+")}".*"\n" { aprepro.ap_file_list.top().lineno++; - /* Loop control defined by integer */ + /* `yytext` includes closing `)}` and newline... Strip these */ char *pt = strchr(yytext, ')'); *pt = '\0'; - sscanf (yytext, "%lf", &yylval->val); + auto tokens = tokenize(yytext, " ,\t"); + if (aprepro.ap_options.debugging) { + fmt::print(stderr, "DEBUG LOOP: tokens = {}\n", + fmt::join(tokens, ", ")); + } - if (yylval->val <= 0) { - BEGIN(LOOP_SKIP); + /* Determine if the first token is a symbol or an explicit number... */ + auto count = tokens[0]; + bool all_dig = count.find_first_not_of("0123456789") == std::string::npos; + int loop_iterations = 0; + if (all_dig) { + loop_iterations = std::stoi(count); + } + else { + symrec *s; + if (!check_valid_var(tokens[0].c_str())) { + aprepro.warning("Invalid variable name syntax '" + tokens[0] + "'"); + BEGIN(LOOP_SKIP); + } else { + s = aprepro.getsym(tokens[0]); + if (s == nullptr || (s->type != token::SVAR && s->type != token::IMMSVAR && s->value.var == 0.)) { + BEGIN(LOOP_SKIP); + } + else { + loop_iterations = (int)s->value.var; + } + } } - else {/* Value defined and != 0. */ - temp_f = get_temp_filename(); - SEAMS::file_rec new_file(temp_f, 0, true, (int)yylval->val); - if (aprepro.ap_options.debugging) - std::cerr << "DEBUG LOOP VAR = " << aprepro.ap_file_list.top().loop_count - << " in file " << aprepro.ap_file_list.top().name - << " at line " << aprepro.ap_file_list.top().lineno-1 << "\n"; - outer_file = &aprepro.ap_file_list.top(); - aprepro.ap_file_list.push(new_file); + temp_f = get_temp_filename(); + SEAMS::file_rec new_file(temp_f, 0, true, loop_iterations); + outer_file = &aprepro.ap_file_list.top(); + new_file.loop_level = outer_file->loop_level + 1; - tmp_file = new std::fstream(temp_f, std::ios::out); - loop_lvl++; - BEGIN(LOOP); + // Get optional loop index... + std::string sym_name; + if (tokens.size() == 1) { + // Default loop index variable name if not specified in loop command. + sym_name = fmt::format("__loop_{}", new_file.loop_level); + } + else { + sym_name = tokens[1]; + } + SEAMS::symrec *li = aprepro.getsym(sym_name); + if (li == nullptr) { + li = aprepro.putsym(sym_name, SEAMS::Aprepro::SYMBOL_TYPE::VARIABLE, true); } - aprepro.isCollectingLoop = true; - } - .+")}".*"\n" { - aprepro.ap_file_list.top().lineno++; - /* Loop control defined by variable */ - symrec *s; - char *pt = strchr(yytext, ')'); - *pt = '\0'; - if (!check_valid_var(yytext)) { - aprepro.warning("Invalid variable name syntax '" + std::string(yytext) + "'"); - BEGIN(LOOP_SKIP); - } else { - s = aprepro.getsym(yytext); + // Get optional loop index initial value. Default to 0 if not specified. + double init = 0.0; + if (tokens.size() >= 3) { + init = std::stod(tokens[2]); + } + li->value.var = init; - if (s == nullptr || (s->type != token::SVAR && s->type != token::IMMSVAR && s->value.var == 0.)) { - BEGIN(LOOP_SKIP); - } - else { /* Value defined and != 0. */ - if (aprepro.ap_options.debugging) - std::cerr << "DEBUG LOOP VAR = " << aprepro.ap_file_list.top().loop_count - << " in file " << aprepro.ap_file_list.top().name - << " at line " << aprepro.ap_file_list.top().lineno-1 << "\n"; - - temp_f = get_temp_filename(); - SEAMS::file_rec new_file(temp_f, 0, true, (int)s->value.var); - outer_file = &aprepro.ap_file_list.top(); - aprepro.ap_file_list.push(new_file); - - tmp_file = new std::fstream(temp_f, std::ios::out); - loop_lvl++; - BEGIN(LOOP); - } + // Get optional loop index increment value. Default to 1 if not specified. + if (tokens.size() >= 4) { + double increment = std::stod(tokens[3]); + new_file.loop_increment = increment; } + + new_file.loop_index = li; + aprepro.ap_file_list.push(new_file); + + tmp_file = new std::fstream(temp_f, std::ios::out); + loop_lvl++; + BEGIN(LOOP); aprepro.isCollectingLoop = true; + if (aprepro.ap_options.debugging) { + fmt::print(stderr, "DEBUG LOOP: iteration count = {}, loop_index variable = {}, initial value = {}, increment = {}\n", + loop_iterations, sym_name, init, new_file.loop_increment); + } } } @@ -335,7 +355,7 @@ integer {D}+({E})? suppress_nl = false; if (aprepro.ap_options.debugging) fprintf (stderr, "DEBUG SWITCH: 'endswitch' at line %d\n", - aprepro.ap_file_list.top().lineno); + aprepro.ap_file_list.top().lineno); } .*"\n" { aprepro.ap_file_list.top().lineno++; } @@ -516,7 +536,7 @@ integer {D}+({E})? if (if_state[if_lvl] == IF_SKIP || if_state[if_lvl] == INITIAL) { BEGIN(INITIAL); - suppress_nl = false; + suppress_nl = false; } /* If neither is true, this is a nested if that should be skipped */ @@ -649,16 +669,53 @@ integer {D}+({E})? } +"}}" { + if (begin_double_brace) { + end_double_brace = true; + } + else { + yyerror("Found an unexpected double end brace ('}}').\n\t" + "It can only end an expression started with a double brace ('{{').\n\tCheck syntax."); + } + + // Add to the history string + save_history_string(); + + if (switch_skip_to_endcase) + BEGIN(END_CASE_SKIP); + else + BEGIN(if_state[if_lvl]); + return(token::RBRACE); +} + + \\\{ { if (echo) LexerOutput("{", 1); } \\\} { if (echo) LexerOutput("}", 1); } +"{{" { + // Check if we need to save the substitution history first. + if(aprepro.ap_options.keep_history && + (aprepro.ap_file_list.top().name != "_string_")) + { + if (curr_index > yyleng) + hist_start = curr_index - yyleng; + else + hist_start = 0; + } + + BEGIN(PARSING); + echo = false; + begin_double_brace = true; + return(token::LBRACE); + } + "{" { // Check if we need to save the substitution history first. if(aprepro.ap_options.keep_history && (aprepro.ap_file_list.top().name != "_string_")) { - if (curr_index > (size_t)yyleng) + if (curr_index > yyleng) hist_start = curr_index - yyleng; else hist_start = 0; @@ -687,7 +744,13 @@ integer {D}+({E})? . { if (echo && if_state[if_lvl] != IF_SKIP) ECHO; } "\n" { if (echo && !suppress_nl) ECHO; suppress_nl = false; - aprepro.ap_file_list.top().lineno++;} + if (end_double_brace) { + echo = true; + begin_double_brace = false; + end_double_brace = false; + } + aprepro.ap_file_list.top().lineno++; + } %% @@ -710,9 +773,9 @@ integer {D}+({E})? while (aprepro.ap_file_list.size() > 1) { auto kk = aprepro.ap_file_list.top(); if (kk.name != "STDIN") { - yyFlexLexer::yy_load_buffer_state(); - delete yyin; - yyin = nullptr; + yyFlexLexer::yy_load_buffer_state(); + delete yyin; + yyin = nullptr; } aprepro.ap_file_list.pop(); yyFlexLexer::yypop_buffer_state(); @@ -769,7 +832,7 @@ integer {D}+({E})? } if (aprepro.ap_options.interactive && yyin == &std::cin && isatty(0) != 0 && isatty(1) != 0) { - char *line = ap_getline_int(nullptr); + char *line = SEAMS::getline_int(nullptr); if (strlen(line) == 0) { return 0; @@ -780,7 +843,7 @@ integer {D}+({E})? "be parsed incorrectly."); } - ap_gl_histadd(line); + SEAMS::gl_histadd(line); if (strlen(line) > (size_t)max_size - 2) { yyerror("input line is too long"); @@ -799,10 +862,10 @@ integer {D}+({E})? return -1; } else { - if (!string_is_ascii(buf, yyin->gcount())) { - yyerror("input file contains non-ASCII (probably UTF-8) characters which will most likely " - "be parsed incorrectly."); - } + if (!string_is_ascii(buf, yyin->gcount())) { + yyerror("input file contains non-ASCII (probably UTF-8) characters which will most likely " + "be parsed incorrectly."); + } return yyin->gcount(); } } @@ -869,6 +932,10 @@ integer {D}+({E})? yyin = aprepro.open_file(aprepro.ap_file_list.top().name, "r"); yyFlexLexer::yypush_buffer_state(yyFlexLexer::yy_create_buffer(yyin, YY_BUF_SIZE)); aprepro.ap_file_list.top().lineno = 0; + + if (aprepro.ap_file_list.top().loop_index != nullptr) { + aprepro.ap_file_list.top().loop_index->value.var += aprepro.ap_file_list.top().loop_increment; + } } } else { @@ -1114,7 +1181,7 @@ integer {D}+({E})? // Don't do it if the file is the one used by execute and rescan. if (aprepro.ap_file_list.top().name == "_string_" || - aprepro.ap_file_list.top().name == "standard input") { + aprepro.ap_file_list.top().name == "standard input") { return; } diff --git a/packages/seacas/libraries/aprepro_lib/aprepro_parser.h b/packages/seacas/libraries/aprepro_lib/aprepro_parser.h index 9b953518b1..3c99dfe7d8 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro_parser.h +++ b/packages/seacas/libraries/aprepro_lib/aprepro_parser.h @@ -2,7 +2,7 @@ // Skeleton interface for Bison LALR(1) parsers in C++ -// Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. +// Copyright (C) 2002-2015, 2018-2021, 2023 Free Software Foundation, Inc. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -30,7 +30,6 @@ // This special exception was added by the Free Software Foundation in // version 2.2 of Bison. - /** ** \file aprepro_parser.h ** Define the SEAMS::parser class. @@ -43,251 +42,233 @@ // private implementation details that can be changed or removed. #ifndef YY_SEAMS_APREPRO_PARSER_H_INCLUDED -# define YY_SEAMS_APREPRO_PARSER_H_INCLUDED - +#define YY_SEAMS_APREPRO_PARSER_H_INCLUDED -# include // std::abort -# include -# include -# include -# include +// NOLINTBEGIN +#include // std::abort +#include +#include +#include +#include #if defined __cplusplus -# define YY_CPLUSPLUS __cplusplus +#define YY_CPLUSPLUS __cplusplus #else -# define YY_CPLUSPLUS 199711L +#define YY_CPLUSPLUS 199711L #endif // Support move semantics when possible. #if 201103L <= YY_CPLUSPLUS -# define YY_MOVE std::move -# define YY_MOVE_OR_COPY move -# define YY_MOVE_REF(Type) Type&& -# define YY_RVREF(Type) Type&& -# define YY_COPY(Type) Type +#define YY_MOVE std::move +#define YY_MOVE_OR_COPY move +#define YY_MOVE_REF(Type) Type && +#define YY_RVREF(Type) Type && +#define YY_COPY(Type) Type #else -# define YY_MOVE -# define YY_MOVE_OR_COPY copy -# define YY_MOVE_REF(Type) Type& -# define YY_RVREF(Type) const Type& -# define YY_COPY(Type) const Type& +#define YY_MOVE +#define YY_MOVE_OR_COPY copy +#define YY_MOVE_REF(Type) Type & +#define YY_RVREF(Type) const Type & +#define YY_COPY(Type) const Type & #endif // Support noexcept when possible. #if 201103L <= YY_CPLUSPLUS -# define YY_NOEXCEPT noexcept -# define YY_NOTHROW +#define YY_NOEXCEPT noexcept +#define YY_NOTHROW #else -# define YY_NOEXCEPT -# define YY_NOTHROW throw () +#define YY_NOEXCEPT +#define YY_NOTHROW throw() #endif // Support constexpr when possible. #if 201703 <= YY_CPLUSPLUS -# define YY_CONSTEXPR constexpr +#define YY_CONSTEXPR constexpr #else -# define YY_CONSTEXPR +#define YY_CONSTEXPR #endif - - #ifndef YY_ATTRIBUTE_PURE -# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define YY_ATTRIBUTE_PURE -# endif +#if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +#define YY_ATTRIBUTE_PURE __attribute__((__pure__)) +#else +#define YY_ATTRIBUTE_PURE +#endif #endif #ifndef YY_ATTRIBUTE_UNUSED -# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# else -# define YY_ATTRIBUTE_UNUSED -# endif +#if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +#define YY_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define YY_ATTRIBUTE_UNUSED +#endif #endif /* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YY_USE(E) ((void) (E)) +#if !defined lint || defined __GNUC__ +#define YY_USE(E) ((void)(E)) #else -# define YY_USE(E) /* empty */ +#define YY_USE(E) /* empty */ #endif /* Suppress an incorrect diagnostic about yylval being uninitialized. */ -#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ -# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") -# else -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# endif -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") +#if defined __GNUC__ && !defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if __GNUC__ * 100 + __GNUC_MINOR__ < 407 +#define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") +#else +#define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +#endif +#define YY_IGNORE_MAYBE_UNINITIALIZED_END _Pragma("GCC diagnostic pop") #else -# define YY_INITIAL_VALUE(Value) Value +#define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +#define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif -#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ -# define YY_IGNORE_USELESS_CAST_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") -# define YY_IGNORE_USELESS_CAST_END \ - _Pragma ("GCC diagnostic pop") +#if defined __cplusplus && defined __GNUC__ && !defined __ICC && 6 <= __GNUC__ +#define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wuseless-cast\"") +#define YY_IGNORE_USELESS_CAST_END _Pragma("GCC diagnostic pop") #endif #ifndef YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_END -#endif - -# ifndef YY_CAST -# ifdef __cplusplus -# define YY_CAST(Type, Val) static_cast (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) -# else -# define YY_CAST(Type, Val) ((Type) (Val)) -# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) -# endif -# endif -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif +#define YY_IGNORE_USELESS_CAST_BEGIN +#define YY_IGNORE_USELESS_CAST_END +#endif + +#ifndef YY_CAST +#ifdef __cplusplus +#define YY_CAST(Type, Val) static_cast(Val) +#define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast(Val) +#else +#define YY_CAST(Type, Val) ((Type)(Val)) +#define YY_REINTERPRET_CAST(Type, Val) ((Type)(Val)) +#endif +#endif +#ifndef YY_NULLPTR +#if defined __cplusplus +#if 201103L <= __cplusplus +#define YY_NULLPTR nullptr +#else +#define YY_NULLPTR 0 +#endif +#else +#define YY_NULLPTR ((void *)0) +#endif +#endif /* Debug traces. */ #ifndef SEAMSDEBUG -# if defined YYDEBUG +#if defined YYDEBUG #if YYDEBUG -# define SEAMSDEBUG 1 -# else -# define SEAMSDEBUG 0 -# endif -# else /* ! defined YYDEBUG */ -# define SEAMSDEBUG 1 -# endif /* ! defined YYDEBUG */ -#endif /* ! defined SEAMSDEBUG */ +#define SEAMSDEBUG 1 +#else +#define SEAMSDEBUG 0 +#endif +#else /* ! defined YYDEBUG */ +#define SEAMSDEBUG 1 +#endif /* ! defined YYDEBUG */ +#endif /* ! defined SEAMSDEBUG */ namespace SEAMS { #line 190 "aprepro_parser.h" - - - /// A Bison parser. class Parser { public: #ifdef SEAMSSTYPE -# ifdef __GNUC__ -# pragma GCC message "bison: do not #define SEAMSSTYPE in C++, use %define api.value.type" -# endif +#ifdef __GNUC__ +#pragma GCC message "bison: do not #define SEAMSSTYPE in C++, use %define api.value.type" +#endif typedef SEAMSSTYPE value_type; #else /// Symbol semantic values. - union value_type - { + union value_type { #line 69 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" - double val; /* For returning numbers. */ - struct symrec *tptr; /* For returning symbol-table pointers */ - char *string; /* For returning quoted strings */ - struct array *arrval; /* For returning arrays */ + double val; /* For returning numbers. */ + struct symrec *tptr; /* For returning symbol-table pointers */ + char *string; /* For returning quoted strings */ + struct array *arrval; /* For returning arrays */ #line 215 "aprepro_parser.h" - }; #endif /// Backward compatibility (Bison 3.8). typedef value_type semantic_type; - /// Syntax errors thrown from user actions. struct syntax_error : std::runtime_error { - syntax_error (const std::string& m) - : std::runtime_error (m) - {} + syntax_error(const std::string &m) : std::runtime_error(m) {} - syntax_error (const syntax_error& s) - : std::runtime_error (s.what ()) - {} + syntax_error(const syntax_error &s) : std::runtime_error(s.what()) {} - ~syntax_error () YY_NOEXCEPT YY_NOTHROW; + ~syntax_error() YY_NOEXCEPT YY_NOTHROW; }; /// Token kinds. struct token { - enum token_kind_type - { + enum token_kind_type { SEAMSEMPTY = -2, - END = 0, // "end of file" - SEAMSerror = 256, // error - SEAMSUNDEF = 257, // "invalid token" - NUM = 258, // NUM - QSTRING = 259, // QSTRING - UNDVAR = 260, // UNDVAR - VAR = 261, // VAR - SVAR = 262, // SVAR - IMMVAR = 263, // IMMVAR - IMMSVAR = 264, // IMMSVAR - AVAR = 265, // AVAR - FNCT = 266, // FNCT - SFNCT = 267, // SFNCT - AFNCT = 268, // AFNCT - COMMA = 269, // COMMA - LPAR = 270, // LPAR - RPAR = 271, // RPAR - LBRACK = 272, // LBRACK - RBRACK = 273, // RBRACK - LBRACE = 274, // LBRACE - RBRACE = 275, // RBRACE - SEMI = 276, // SEMI - EQUAL = 277, // EQUAL - EQ_PLUS = 278, // EQ_PLUS - EQ_MINUS = 279, // EQ_MINUS - EQ_TIME = 280, // EQ_TIME - EQ_DIV = 281, // EQ_DIV - EQ_POW = 282, // EQ_POW - QUEST = 283, // QUEST - COLON = 284, // COLON - LOR = 285, // LOR - LAND = 286, // LAND - LT = 287, // LT - GT = 288, // GT - LE = 289, // LE - GE = 290, // GE - EQ = 291, // EQ - NE = 292, // NE - PLU = 293, // PLU - SUB = 294, // SUB - DIV = 295, // DIV - TIM = 296, // TIM - MOD = 297, // MOD - UNARY = 298, // UNARY - NOT = 299, // NOT - POW = 300, // POW - INC = 301, // INC - DEC = 302, // DEC - CONCAT = 303 // CONCAT + END = 0, // "end of file" + SEAMSerror = 256, // error + SEAMSUNDEF = 257, // "invalid token" + NUM = 258, // NUM + QSTRING = 259, // QSTRING + UNDVAR = 260, // UNDVAR + VAR = 261, // VAR + SVAR = 262, // SVAR + IMMVAR = 263, // IMMVAR + IMMSVAR = 264, // IMMSVAR + AVAR = 265, // AVAR + FNCT = 266, // FNCT + SFNCT = 267, // SFNCT + AFNCT = 268, // AFNCT + COMMA = 269, // COMMA + LPAR = 270, // LPAR + RPAR = 271, // RPAR + LBRACK = 272, // LBRACK + RBRACK = 273, // RBRACK + LBRACE = 274, // LBRACE + RBRACE = 275, // RBRACE + SEMI = 276, // SEMI + EQUAL = 277, // EQUAL + EQ_PLUS = 278, // EQ_PLUS + EQ_MINUS = 279, // EQ_MINUS + EQ_TIME = 280, // EQ_TIME + EQ_DIV = 281, // EQ_DIV + EQ_POW = 282, // EQ_POW + QUEST = 283, // QUEST + COLON = 284, // COLON + LOR = 285, // LOR + LAND = 286, // LAND + LT = 287, // LT + GT = 288, // GT + LE = 289, // LE + GE = 290, // GE + EQ = 291, // EQ + NE = 292, // NE + PLU = 293, // PLU + SUB = 294, // SUB + DIV = 295, // DIV + TIM = 296, // TIM + MOD = 297, // MOD + UNARY = 298, // UNARY + NOT = 299, // NOT + POW = 300, // POW + INC = 301, // INC + DEC = 302, // DEC + CONCAT = 303 // CONCAT }; /// Backward compatibility alias (Bison 3.6). typedef token_kind_type yytokentype; @@ -302,67 +283,66 @@ namespace SEAMS { /// Symbol kinds. struct symbol_kind { - enum symbol_kind_type - { - YYNTOKENS = 50, ///< Number of tokens. - S_YYEMPTY = -2, - S_YYEOF = 0, // "end of file" - S_YYerror = 1, // error - S_YYUNDEF = 2, // "invalid token" - S_NUM = 3, // NUM - S_QSTRING = 4, // QSTRING - S_UNDVAR = 5, // UNDVAR - S_VAR = 6, // VAR - S_SVAR = 7, // SVAR - S_IMMVAR = 8, // IMMVAR - S_IMMSVAR = 9, // IMMSVAR - S_AVAR = 10, // AVAR - S_FNCT = 11, // FNCT - S_SFNCT = 12, // SFNCT - S_AFNCT = 13, // AFNCT - S_COMMA = 14, // COMMA - S_LPAR = 15, // LPAR - S_RPAR = 16, // RPAR - S_LBRACK = 17, // LBRACK - S_RBRACK = 18, // RBRACK - S_LBRACE = 19, // LBRACE - S_RBRACE = 20, // RBRACE - S_SEMI = 21, // SEMI - S_EQUAL = 22, // EQUAL - S_EQ_PLUS = 23, // EQ_PLUS - S_EQ_MINUS = 24, // EQ_MINUS - S_EQ_TIME = 25, // EQ_TIME - S_EQ_DIV = 26, // EQ_DIV - S_EQ_POW = 27, // EQ_POW - S_QUEST = 28, // QUEST - S_COLON = 29, // COLON - S_LOR = 30, // LOR - S_LAND = 31, // LAND - S_LT = 32, // LT - S_GT = 33, // GT - S_LE = 34, // LE - S_GE = 35, // GE - S_EQ = 36, // EQ - S_NE = 37, // NE - S_PLU = 38, // PLU - S_SUB = 39, // SUB - S_DIV = 40, // DIV - S_TIM = 41, // TIM - S_MOD = 42, // MOD - S_UNARY = 43, // UNARY - S_NOT = 44, // NOT - S_POW = 45, // POW - S_INC = 46, // INC - S_DEC = 47, // DEC - S_CONCAT = 48, // CONCAT - S_49_n_ = 49, // '\n' - S_YYACCEPT = 50, // $accept - S_input = 51, // input - S_line = 52, // line - S_bool = 53, // bool - S_aexp = 54, // aexp - S_sexp = 55, // sexp - S_exp = 56 // exp + enum symbol_kind_type { + YYNTOKENS = 50, ///< Number of tokens. + S_YYEMPTY = -2, + S_YYEOF = 0, // "end of file" + S_YYerror = 1, // error + S_YYUNDEF = 2, // "invalid token" + S_NUM = 3, // NUM + S_QSTRING = 4, // QSTRING + S_UNDVAR = 5, // UNDVAR + S_VAR = 6, // VAR + S_SVAR = 7, // SVAR + S_IMMVAR = 8, // IMMVAR + S_IMMSVAR = 9, // IMMSVAR + S_AVAR = 10, // AVAR + S_FNCT = 11, // FNCT + S_SFNCT = 12, // SFNCT + S_AFNCT = 13, // AFNCT + S_COMMA = 14, // COMMA + S_LPAR = 15, // LPAR + S_RPAR = 16, // RPAR + S_LBRACK = 17, // LBRACK + S_RBRACK = 18, // RBRACK + S_LBRACE = 19, // LBRACE + S_RBRACE = 20, // RBRACE + S_SEMI = 21, // SEMI + S_EQUAL = 22, // EQUAL + S_EQ_PLUS = 23, // EQ_PLUS + S_EQ_MINUS = 24, // EQ_MINUS + S_EQ_TIME = 25, // EQ_TIME + S_EQ_DIV = 26, // EQ_DIV + S_EQ_POW = 27, // EQ_POW + S_QUEST = 28, // QUEST + S_COLON = 29, // COLON + S_LOR = 30, // LOR + S_LAND = 31, // LAND + S_LT = 32, // LT + S_GT = 33, // GT + S_LE = 34, // LE + S_GE = 35, // GE + S_EQ = 36, // EQ + S_NE = 37, // NE + S_PLU = 38, // PLU + S_SUB = 39, // SUB + S_DIV = 40, // DIV + S_TIM = 41, // TIM + S_MOD = 42, // MOD + S_UNARY = 43, // UNARY + S_NOT = 44, // NOT + S_POW = 45, // POW + S_INC = 46, // INC + S_DEC = 47, // DEC + S_CONCAT = 48, // CONCAT + S_49_n_ = 49, // '\n' + S_YYACCEPT = 50, // $accept + S_input = 51, // input + S_line = 52, // line + S_bool = 53, // bool + S_aexp = 54, // aexp + S_sexp = 55, // sexp + S_exp = 56 // exp }; }; @@ -378,62 +358,44 @@ namespace SEAMS { /// via kind (). /// /// Provide access to semantic value. - template - struct basic_symbol : Base + template struct basic_symbol : Base { /// Alias to Base. typedef Base super_type; /// Default constructor. - basic_symbol () YY_NOEXCEPT - : value () - {} + basic_symbol() YY_NOEXCEPT : value() {} #if 201103L <= YY_CPLUSPLUS /// Move constructor. - basic_symbol (basic_symbol&& that) - : Base (std::move (that)) - , value (std::move (that.value)) - {} + basic_symbol(basic_symbol &&that) : Base(std::move(that)), value(std::move(that.value)) {} #endif /// Copy constructor. - basic_symbol (const basic_symbol& that); + basic_symbol(const basic_symbol &that); /// Constructor for valueless symbols. - basic_symbol (typename Base::kind_type t); + basic_symbol(typename Base::kind_type t); /// Constructor for symbols with semantic value. - basic_symbol (typename Base::kind_type t, - YY_RVREF (value_type) v); + basic_symbol(typename Base::kind_type t, YY_RVREF(value_type) v); /// Destroy the symbol. - ~basic_symbol () - { - clear (); - } - - + ~basic_symbol() { clear(); } /// Destroy contents, and record that is empty. - void clear () YY_NOEXCEPT - { - Base::clear (); - } + void clear() YY_NOEXCEPT { Base::clear(); } /// The user-facing name of this symbol. - std::string name () const YY_NOEXCEPT - { - return Parser::symbol_name (this->kind ()); - } + std::string name() const YY_NOEXCEPT { return Parser::symbol_name(this->kind()); } /// Backward compatibility (Bison 3.6). - symbol_kind_type type_get () const YY_NOEXCEPT; + symbol_kind_type type_get() const YY_NOEXCEPT; /// Whether empty. - bool empty () const YY_NOEXCEPT; + bool empty() const YY_NOEXCEPT; /// Destructive move, \a s is emptied into this. - void move (basic_symbol& s); + void move(basic_symbol &s); /// The semantic value. value_type value; @@ -441,7 +403,7 @@ namespace SEAMS { private: #if YY_CPLUSPLUS < 201103L /// Assignment operator. - basic_symbol& operator= (const basic_symbol& that); + basic_symbol &operator=(const basic_symbol &that); #endif }; @@ -452,33 +414,31 @@ namespace SEAMS { typedef token_kind_type kind_type; /// Default constructor. - by_kind () YY_NOEXCEPT; + by_kind() YY_NOEXCEPT; #if 201103L <= YY_CPLUSPLUS /// Move constructor. - by_kind (by_kind&& that) YY_NOEXCEPT; + by_kind(by_kind &&that) YY_NOEXCEPT; #endif /// Copy constructor. - by_kind (const by_kind& that) YY_NOEXCEPT; + by_kind(const by_kind &that) YY_NOEXCEPT; /// Constructor from (external) token numbers. - by_kind (kind_type t) YY_NOEXCEPT; - - + by_kind(kind_type t) YY_NOEXCEPT; /// Record that this symbol is empty. - void clear () YY_NOEXCEPT; + void clear() YY_NOEXCEPT; /// Steal the symbol kind from \a that. - void move (by_kind& that); + void move(by_kind &that); /// The (internal) type number (corresponding to \a type). /// \a empty when empty. - symbol_kind_type kind () const YY_NOEXCEPT; + symbol_kind_type kind() const YY_NOEXCEPT; /// Backward compatibility (Bison 3.6). - symbol_kind_type type_get () const YY_NOEXCEPT; + symbol_kind_type type_get() const YY_NOEXCEPT; /// The symbol kind. /// \a S_YYEMPTY when empty. @@ -490,101 +450,99 @@ namespace SEAMS { /// "External" symbols: returned by the scanner. struct symbol_type : basic_symbol - {}; + { + }; /// Build a parser object. - Parser (class Aprepro& aprepro_yyarg); - virtual ~Parser (); + Parser(class Aprepro &aprepro_yyarg); + virtual ~Parser(); #if 201103L <= YY_CPLUSPLUS /// Non copyable. - Parser (const Parser&) = delete; + Parser(const Parser &) = delete; /// Non copyable. - Parser& operator= (const Parser&) = delete; + Parser &operator=(const Parser &) = delete; #endif /// Parse. An alias for parse (). /// \returns 0 iff parsing succeeded. - int operator() (); + int operator()(); /// Parse. /// \returns 0 iff parsing succeeded. - virtual int parse (); + virtual int parse(); #if SEAMSDEBUG /// The current debugging stream. - std::ostream& debug_stream () const YY_ATTRIBUTE_PURE; + std::ostream &debug_stream() const YY_ATTRIBUTE_PURE; /// Set the current debugging stream. - void set_debug_stream (std::ostream &); + void set_debug_stream(std::ostream &); /// Type for debugging levels. typedef int debug_level_type; /// The current debugging level. - debug_level_type debug_level () const YY_ATTRIBUTE_PURE; + debug_level_type debug_level() const YY_ATTRIBUTE_PURE; /// Set the current debugging level. - void set_debug_level (debug_level_type l); + void set_debug_level(debug_level_type l); #endif /// Report a syntax error. /// \param msg a description of the syntax error. - virtual void error (const std::string& msg); + virtual void error(const std::string &msg); /// Report a syntax error. - void error (const syntax_error& err); + void error(const syntax_error &err); /// The user-facing name of the symbol whose (internal) number is /// YYSYMBOL. No bounds checking. - static std::string symbol_name (symbol_kind_type yysymbol); - - + static std::string symbol_name(symbol_kind_type yysymbol); class context { public: - context (const Parser& yyparser, const symbol_type& yyla); - const symbol_type& lookahead () const YY_NOEXCEPT { return yyla_; } - symbol_kind_type token () const YY_NOEXCEPT { return yyla_.kind (); } + context(const Parser &yyparser, const symbol_type &yyla); + const symbol_type &lookahead() const YY_NOEXCEPT { return yyla_; } + symbol_kind_type token() const YY_NOEXCEPT { return yyla_.kind(); } /// Put in YYARG at most YYARGN of the expected tokens, and return the /// number of tokens stored in YYARG. If YYARG is null, return the /// number of expected tokens (guaranteed to be less than YYNTOKENS). - int expected_tokens (symbol_kind_type yyarg[], int yyargn) const; + int expected_tokens(symbol_kind_type yyarg[], int yyargn) const; private: - const Parser& yyparser_; - const symbol_type& yyla_; + const Parser &yyparser_; + const symbol_type &yyla_; }; private: #if YY_CPLUSPLUS < 201103L /// Non copyable. - Parser (const Parser&); + Parser(const Parser &); /// Non copyable. - Parser& operator= (const Parser&); + Parser &operator=(const Parser &); #endif - /// Stored state numbers (used for stacks). typedef short state_type; /// The arguments of the error message. - int yy_syntax_error_arguments_ (const context& yyctx, - symbol_kind_type yyarg[], int yyargn) const; + int yy_syntax_error_arguments_(const context &yyctx, symbol_kind_type yyarg[], + int yyargn) const; /// Generate an error message. /// \param yyctx the context in which the error occurred. - virtual std::string yysyntax_error_ (const context& yyctx) const; + virtual std::string yysyntax_error_(const context &yyctx) const; /// Compute post-reduction state. /// \param yystate the current state /// \param yysym the nonterminal to push on the stack - static state_type yy_lr_goto_state_ (state_type yystate, int yysym); + static state_type yy_lr_goto_state_(state_type yystate, int yysym); /// Whether the given \c yypact_ value indicates a defaulted state. /// \param yyvalue the value to check - static bool yy_pact_value_is_default_ (int yyvalue) YY_NOEXCEPT; + static bool yy_pact_value_is_default_(int yyvalue) YY_NOEXCEPT; /// Whether the given \c yytable_ value indicates a syntax error. /// \param yyvalue the value to check - static bool yy_table_value_is_error_ (int yyvalue) YY_NOEXCEPT; + static bool yy_table_value_is_error_(int yyvalue) YY_NOEXCEPT; static const signed char yypact_ninf_; static const signed char yytable_ninf_; @@ -592,14 +550,13 @@ namespace SEAMS { /// Convert a scanner token kind \a t to a symbol kind. /// In theory \a t should be a token_kind_type, but character literals /// are valid, yet not members of the token_kind_type enum. - static symbol_kind_type yytranslate_ (int t) YY_NOEXCEPT; + static symbol_kind_type yytranslate_(int t) YY_NOEXCEPT; /// Convert the symbol name \a n to a form suitable for a diagnostic. - static std::string yytnamerr_ (const char *yystr); + static std::string yytnamerr_(const char *yystr); /// For a symbol, its name in clear. - static const char* const yytname_[]; - + static const char *const yytname_[]; // Tables. // YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing @@ -634,59 +591,57 @@ namespace SEAMS { // YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. static const signed char yyr2_[]; - #if SEAMSDEBUG // YYRLINE[YYN] -- Source line where rule number YYN was defined. static const short yyrline_[]; /// Report on the debug stream that the rule \a r is going to be reduced. - virtual void yy_reduce_print_ (int r) const; + virtual void yy_reduce_print_(int r) const; /// Print the state stack on the debug stream. - virtual void yy_stack_print_ () const; + virtual void yy_stack_print_() const; /// Debugging level. int yydebug_; /// Debug stream. - std::ostream* yycdebug_; + std::ostream *yycdebug_; /// \brief Display a symbol kind, value and location. /// \param yyo The output stream. /// \param yysym The symbol. template - void yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const; + void yy_print_(std::ostream &yyo, const basic_symbol &yysym) const; #endif /// \brief Reclaim the memory associated to a symbol. /// \param yymsg Why this token is reclaimed. /// If null, print nothing. /// \param yysym The symbol. - template - void yy_destroy_ (const char* yymsg, basic_symbol& yysym) const; + template void yy_destroy_(const char *yymsg, basic_symbol &yysym) const; private: /// Type access provider for state based symbols. struct by_state { /// Default constructor. - by_state () YY_NOEXCEPT; + by_state() YY_NOEXCEPT; /// The symbol kind as needed by the constructor. typedef state_type kind_type; /// Constructor. - by_state (kind_type s) YY_NOEXCEPT; + by_state(kind_type s) YY_NOEXCEPT; /// Copy constructor. - by_state (const by_state& that) YY_NOEXCEPT; + by_state(const by_state &that) YY_NOEXCEPT; /// Record that this symbol is empty. - void clear () YY_NOEXCEPT; + void clear() YY_NOEXCEPT; /// Steal the symbol kind from \a that. - void move (by_state& that); + void move(by_state &that); /// The symbol kind (corresponding to \a state). /// \a symbol_kind::S_YYEMPTY when empty. - symbol_kind_type kind () const YY_NOEXCEPT; + symbol_kind_type kind() const YY_NOEXCEPT; /// The state number used to denote an empty symbol. /// We use the initial state, as it does not have a value. @@ -703,140 +658,103 @@ namespace SEAMS { /// Superclass. typedef basic_symbol super_type; /// Construct an empty symbol. - stack_symbol_type (); + stack_symbol_type(); /// Move or copy construction. - stack_symbol_type (YY_RVREF (stack_symbol_type) that); + stack_symbol_type(YY_RVREF(stack_symbol_type) that); /// Steal the contents from \a sym to build this. - stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) sym); + stack_symbol_type(state_type s, YY_MOVE_REF(symbol_type) sym); #if YY_CPLUSPLUS < 201103L /// Assignment, needed by push_back by some old implementations. /// Moves the contents of that. - stack_symbol_type& operator= (stack_symbol_type& that); + stack_symbol_type &operator=(stack_symbol_type &that); /// Assignment, needed by push_back by other implementations. /// Needed by some other old implementations. - stack_symbol_type& operator= (const stack_symbol_type& that); + stack_symbol_type &operator=(const stack_symbol_type &that); #endif }; /// A stack with random access from its top. - template > - class stack + template > class stack { public: // Hide our reversed order. - typedef typename S::iterator iterator; + typedef typename S::iterator iterator; typedef typename S::const_iterator const_iterator; - typedef typename S::size_type size_type; - typedef typename std::ptrdiff_t index_type; + typedef typename S::size_type size_type; + typedef typename std::ptrdiff_t index_type; - stack (size_type n = 200) YY_NOEXCEPT - : seq_ (n) - {} + stack(size_type n = 200) YY_NOEXCEPT : seq_(n) {} #if 201103L <= YY_CPLUSPLUS /// Non copyable. - stack (const stack&) = delete; + stack(const stack &) = delete; /// Non copyable. - stack& operator= (const stack&) = delete; + stack &operator=(const stack &) = delete; #endif /// Random access. /// /// Index 0 returns the topmost element. - const T& - operator[] (index_type i) const - { - return seq_[size_type (size () - 1 - i)]; - } + const T &operator[](index_type i) const { return seq_[size_type(size() - 1 - i)]; } /// Random access. /// /// Index 0 returns the topmost element. - T& - operator[] (index_type i) - { - return seq_[size_type (size () - 1 - i)]; - } + T &operator[](index_type i) { return seq_[size_type(size() - 1 - i)]; } /// Steal the contents of \a t. /// /// Close to move-semantics. - void - push (YY_MOVE_REF (T) t) + void push(YY_MOVE_REF(T) t) { - seq_.push_back (T ()); - operator[] (0).move (t); + seq_.push_back(T()); + operator[](0).move(t); } /// Pop elements from the stack. - void - pop (std::ptrdiff_t n = 1) YY_NOEXCEPT + void pop(std::ptrdiff_t n = 1) YY_NOEXCEPT { for (; 0 < n; --n) - seq_.pop_back (); + seq_.pop_back(); } /// Pop all elements from the stack. - void - clear () YY_NOEXCEPT - { - seq_.clear (); - } + void clear() YY_NOEXCEPT { seq_.clear(); } /// Number of elements on the stack. - index_type - size () const YY_NOEXCEPT - { - return index_type (seq_.size ()); - } + index_type size() const YY_NOEXCEPT { return index_type(seq_.size()); } /// Iterator on top of the stack (going downwards). - const_iterator - begin () const YY_NOEXCEPT - { - return seq_.begin (); - } + const_iterator begin() const YY_NOEXCEPT { return seq_.begin(); } /// Bottom of the stack. - const_iterator - end () const YY_NOEXCEPT - { - return seq_.end (); - } + const_iterator end() const YY_NOEXCEPT { return seq_.end(); } /// Present a slice of the top of a stack. class slice { public: - slice (const stack& stack, index_type range) YY_NOEXCEPT - : stack_ (stack) - , range_ (range) - {} + slice(const stack &stack, index_type range) YY_NOEXCEPT : stack_(stack), range_(range) {} - const T& - operator[] (index_type i) const - { - return stack_[range_ - i]; - } + const T &operator[](index_type i) const { return stack_[range_ - i]; } private: - const stack& stack_; - index_type range_; + const stack &stack_; + index_type range_; }; private: #if YY_CPLUSPLUS < 201103L /// Non copyable. - stack (const stack&); + stack(const stack &); /// Non copyable. - stack& operator= (const stack&); + stack &operator=(const stack &); #endif /// The wrapped container. S seq_; }; - /// Stack type. typedef stack stack_type; @@ -848,7 +766,7 @@ namespace SEAMS { /// if null, no trace is output. /// \param sym the symbol /// \warning the contents of \a s.value is stolen. - void yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym); + void yypush_(const char *m, YY_MOVE_REF(stack_symbol_type) sym); /// Push a new look ahead token on the state on the stack. /// \param m a debug message to display @@ -856,30 +774,24 @@ namespace SEAMS { /// \param s the state /// \param sym the symbol (for its value and location). /// \warning the contents of \a sym.value is stolen. - void yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym); + void yypush_(const char *m, state_type s, YY_MOVE_REF(symbol_type) sym); /// Pop \a n symbols from the stack. - void yypop_ (int n = 1) YY_NOEXCEPT; + void yypop_(int n = 1) YY_NOEXCEPT; /// Constants. - enum - { - yylast_ = 1324, ///< Last index in yytable_. - yynnts_ = 7, ///< Number of nonterminal symbols. - yyfinal_ = 2 ///< Termination state number. + enum { + yylast_ = 1324, ///< Last index in yytable_. + yynnts_ = 7, ///< Number of nonterminal symbols. + yyfinal_ = 2 ///< Termination state number. }; - // User arguments. - class Aprepro& aprepro; - + class Aprepro &aprepro; }; - -} // SEAMS +} // namespace SEAMS #line 881 "aprepro_parser.h" - - - +// NOLINTEND #endif // !YY_SEAMS_APREPRO_PARSER_H_INCLUDED diff --git a/packages/seacas/libraries/aprepro_lib/enumerate.h b/packages/seacas/libraries/aprepro_lib/enumerate.h new file mode 100644 index 0000000000..c523adea8f --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/enumerate.h @@ -0,0 +1,34 @@ +// https://www.reedbeta.com/blog/python-like-enumerate-in-cpp17/ +// std::vector things; +// ... +// for (auto [i, thing] : enumerate(things)) +// { +// .. `i` gets the index and `thing` gets the Thing in each iteration +// } + +#include + +template ())), + typename = decltype(std::end(std::declval()))> +constexpr auto enumerate(T &&iterable) +{ + struct iterator + { + size_t i; + TIter iter; + bool operator!=(const iterator &other) const { return iter != other.iter; } + void operator++() + { + ++i; + ++iter; + } + auto operator*() const { return std::tie(i, *iter); } + }; + struct iterable_wrapper + { + T iterable; + auto begin() { return iterator{0, std::begin(iterable)}; } + auto end() { return iterator{0, std::end(iterable)}; } + }; + return iterable_wrapper{std::forward(iterable)}; +} diff --git a/packages/seacas/libraries/aprepro_lib/robin_hash.h b/packages/seacas/libraries/aprepro_lib/robin_hash.h index 348c48666c..af33636d0f 100644 --- a/packages/seacas/libraries/aprepro_lib/robin_hash.h +++ b/packages/seacas/libraries/aprepro_lib/robin_hash.h @@ -561,7 +561,7 @@ namespace tsl { #else /** * C++11 doesn't support the creation of a std::vector with a custom allocator - * and 'count' default-inserted elements. The needed contructor `explicit + * and 'count' default-inserted elements. The needed constructor `explicit * vector(size_type count, const Allocator& alloc = Allocator());` is only * available in C++14 and later. We thus must resize after using the * `vector(const Allocator& alloc)` constructor. @@ -605,9 +605,10 @@ namespace tsl { } robin_hash(robin_hash &&other) noexcept( - std::is_nothrow_move_constructible::value &&std::is_nothrow_move_constructible< - KeyEqual>::value &&std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_constructible::value) + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value) : Hash(std::move(static_cast(other))), KeyEqual(std::move(static_cast(other))), GrowthPolicy(std::move(static_cast(other))), @@ -625,8 +626,8 @@ namespace tsl { robin_hash &operator=(const robin_hash &other) { if (&other != this) { - Hash:: operator=(other); - KeyEqual:: operator=(other); + Hash::operator=(other); + KeyEqual::operator=(other); GrowthPolicy::operator=(other); m_buckets_data = other.m_buckets_data; @@ -1527,7 +1528,7 @@ namespace tsl { private: /** - * Protocol version currenlty used for serialization. + * Protocol version currently used for serialization. */ static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; diff --git a/packages/seacas/libraries/aprepro_lib/strings.cc b/packages/seacas/libraries/aprepro_lib/strings.cc index db7aff7b7a..5beb8f1b81 100644 --- a/packages/seacas/libraries/aprepro_lib/strings.cc +++ b/packages/seacas/libraries/aprepro_lib/strings.cc @@ -9,254 +9,279 @@ #include // for string, operator<< #include // for vector -// This function is used below in the example showing how an -// application can add its own functions to an aprepro instance. -double succ(double i) { return ++i; } +std::vector build_strings(); -int main(int argc, char *argv[]) +int main(int, char **) { SEAMS::Aprepro aprepro; - // Read and parse a string's worth of data at a time. - // Cannot use looping/ifs/... with this method. - std::vector strings; - strings.emplace_back("$ Test program for Aprepro"); - strings.emplace_back("$"); - strings.emplace_back("Test number representations"); - strings.emplace_back("{1} {10e-1} {10.e-1} {.1e+1} {.1e1}"); - strings.emplace_back("{1} {10E-1} {10.E-1} {.1E+1} {.1E1}"); - strings.emplace_back(" "); - strings.emplace_back("Test assign statements:"); - strings.emplace_back("{_a = 5} {b=_a} $ Should print 5 5"); - strings.emplace_back("{_a +=b} {_a} $ Should print 10 10"); - strings.emplace_back("{_a -=b} {_a} $ Should print 5 5"); - strings.emplace_back("{_a *=b} {_a} $ Should print 25 25"); - strings.emplace_back("{_a /=b} {_a} $ Should print 5 5"); - strings.emplace_back("{_a ^=b} {_a} $ Should print 3125 3125"); - strings.emplace_back("{_a = b} {_a**=b} {_a} $ Should print 5 3125 3125"); - strings.emplace_back(""); - strings.emplace_back("Test trigonometric functions (radians)"); - strings.emplace_back("{pi = d2r(180)} {atan2(0,-1)} {4*atan(1.0)} $ Three values of pi"); - strings.emplace_back("{_a = sin(pi/4)} {pi-4*asin(_a)} $ sin(pi/4)"); - strings.emplace_back("{_b = cos(pi/4)} {pi-4*acos(_b)} $ cos(pi/4)"); - strings.emplace_back("{_c = tan(pi/4)} {pi-4*atan(_c)} $ tan(pi/4)"); - strings.emplace_back(""); - strings.emplace_back("Test trigonometric functions (degrees)"); - strings.emplace_back("{r2d(pi)} {pid = atan2d(0,-1)} {4 * atand(1.0)}"); - strings.emplace_back("{ad = sind(180/4)} {180-4*asind(ad)} $ sin(180/4)"); - strings.emplace_back("{bd = cosd(180/4)} {180-4*acosd(bd)} $ cos(180/4)"); - strings.emplace_back("{cd = tand(180/4)} {180-4*atand(cd)} $ tan(180/4)"); - strings.emplace_back(""); - strings.emplace_back("Test max, min, sign, dim, abs"); - strings.emplace_back("{pmin = min(0.5, 1.0)} {nmin = min(-0.5, -1.0)} $ Should be 0.5, -1"); - strings.emplace_back("{pmax = max(0.5, 1.0)} {nmax = max(-0.5, -1.0)} $ Should be 1.0, -0.5"); - strings.emplace_back("{zero = 0} {sign(0.5, zero) + sign(0.5, -zero)} $ Should be 0 1"); - strings.emplace_back("{nonzero = 1} {sign(0.5, nonzero) + sign(0.5, -nonzero)} $ Should be 1 0"); - strings.emplace_back("{dim(5.5, 4.5)} {dim(4.5, 5.5)} $ Should be 1 0"); - strings.emplace_back(""); - strings.emplace_back("{ifyes = 1} {ifno = 0}"); - strings.emplace_back("$ Test ternary..."); - strings.emplace_back(R("{ifyes == 1 ? " correct " : " incorrect "}")); - strings.emplace_back(R("{ifno == 1 ? " incorrect " : " correct "}")); - strings.emplace_back(""); - strings.emplace_back("$ Test ifdef lines"); - strings.emplace_back(" {Ifdef(ifyes)}"); - strings.emplace_back("This line should be echoed. (a)"); - strings.emplace_back(" {Endif}"); - strings.emplace_back("This line should be echoed. (b)"); - strings.emplace_back(" {Ifdef(ifno)}"); - strings.emplace_back("This line should not be echoed"); - strings.emplace_back(" {Endif}"); - strings.emplace_back("This line should be echoed. (c)"); - strings.emplace_back(" {Ifdef(ifundefined)}"); - strings.emplace_back("This line should not be echoed"); - strings.emplace_back(" {Endif}"); - strings.emplace_back("This line should be echoed. (d)"); - strings.emplace_back(""); - strings.emplace_back("$ Test ifdef - else lines"); - strings.emplace_back(" {Ifdef(ifyes)}"); - strings.emplace_back("This line should be echoed. (1)"); - strings.emplace_back(" {Else}"); - strings.emplace_back("This line should not be echoed (2)"); - strings.emplace_back(" {Endif}"); - strings.emplace_back(" {Ifdef(ifno)}"); - strings.emplace_back("This line should not be echoed. (3)"); - strings.emplace_back(" {Else}"); - strings.emplace_back("This line should be echoed (4)"); - strings.emplace_back(" {Endif}"); - strings.emplace_back(""); - strings.emplace_back("$ Test ifndef - else lines"); - strings.emplace_back(" {Ifndef(ifyes)}"); - strings.emplace_back("This line should not be echoed. (5)"); - strings.emplace_back(" {Else}"); - strings.emplace_back("This line should be echoed (6)"); - strings.emplace_back(" {Endif}"); - strings.emplace_back(" {Ifndef(ifno)}"); - strings.emplace_back("This line should be echoed. (7)"); - strings.emplace_back(" {Else}"); - strings.emplace_back("This line should not be echoed (8)"); - strings.emplace_back(" {Endif}"); - strings.emplace_back("$ Lines a, b, c, d, 1, 4, 6, 7 should be echoed"); - strings.emplace_back("$ Check line counting -- should be on line 78: {Parse Error}"); - strings.emplace_back("{ifdef(ifyes)} {This should be an error}"); - strings.emplace_back("{endif}"); - strings.emplace_back(""); - strings.emplace_back( - "$ ========================================================================"); - strings.emplace_back("$ Test if lines"); - strings.emplace_back("{if(sqrt(4) == 2)}"); - strings.emplace_back(" This line should be echoed. (a)"); - strings.emplace_back("{endif}"); - strings.emplace_back(" This line should be echoed. (b)"); - strings.emplace_back("{if(sqrt(2) == 2 || sqrt(3) == 2)}"); - strings.emplace_back("This line should not be echoed"); - strings.emplace_back("{endif}"); - strings.emplace_back("This line should be echoed. (c)"); - strings.emplace_back(""); - strings.emplace_back("{diff = sqrt(3)*sqrt(3) - 3}"); - strings.emplace_back("$ Test if - else lines"); - strings.emplace_back("{if(sqrt(3)*sqrt(3) - 3 == diff)}"); - strings.emplace_back(" complex if works"); - strings.emplace_back("{else}"); - strings.emplace_back(" complex if does not work"); - strings.emplace_back("{endif}"); - strings.emplace_back(""); - strings.emplace_back("{if (sqrt(4) == 2)}"); - strings.emplace_back(" {if (sqrt(9) == 3)}"); - strings.emplace_back(" {if (sqrt(16) == 4)}"); - strings.emplace_back(" square roots work"); - strings.emplace_back(" {else}"); - strings.emplace_back(" sqrt(16) does not work"); - strings.emplace_back(" {endif}"); - strings.emplace_back(" {else}"); - strings.emplace_back(" sqrt(9) does not work"); - strings.emplace_back(" {endif}"); - strings.emplace_back("{else}"); - strings.emplace_back(" sqrt(4) does not work"); - strings.emplace_back("{endif}"); - strings.emplace_back(""); - strings.emplace_back("{v1 = 1} {v2 = 2}"); - strings.emplace_back("{if (v1 == v2)}"); - strings.emplace_back(" Bad if"); - strings.emplace_back(" {if (v1 != v2)}"); - strings.emplace_back(" should not see (1)"); - strings.emplace_back(" {else}"); - strings.emplace_back(" should not see (2)"); - strings.emplace_back(" {endif}"); - strings.emplace_back(" should not see (3)"); - strings.emplace_back("{else}"); - strings.emplace_back(" {if (v1 != v2)}"); - strings.emplace_back(" good nested if"); - strings.emplace_back(" {else}"); - strings.emplace_back(" bad nested if"); - strings.emplace_back(" {endif}"); - strings.emplace_back(" good"); - strings.emplace_back(" make sure it is still good"); - strings.emplace_back("{endif}"); - strings.emplace_back( - "$ ========================================================================"); - strings.emplace_back("$ Test switch"); - strings.emplace_back("{switch(PI)}"); - strings.emplace_back("This is in a switch, but prior to any case, it should not run"); - strings.emplace_back("{a = 0.5} Should not execute"); - strings.emplace_back(""); - strings.emplace_back("{case (1)}"); - strings.emplace_back("This should not echo"); - strings.emplace_back("{a = 1}"); - strings.emplace_back(""); - strings.emplace_back("{case (2)}"); - strings.emplace_back("This should not echo"); - strings.emplace_back("{a = 2}"); - strings.emplace_back(""); - strings.emplace_back("{case (PI)}"); - strings.emplace_back("This should echo"); - strings.emplace_back("{a = PI}"); - strings.emplace_back(""); - strings.emplace_back("{case (PI)}"); - strings.emplace_back("This should not echo since a previous case matched."); - strings.emplace_back("{a = 2}"); - strings.emplace_back(""); - strings.emplace_back("{default}"); - strings.emplace_back("{a=4}"); - strings.emplace_back(""); - strings.emplace_back("{endswitch}"); - strings.emplace_back(""); - strings.emplace_back("This should be equal to PI -- {PI}"); - strings.emplace_back("$ Test int and [] (shortcut for int)"); - strings.emplace_back("{int(5.01)} {int(-5.01)}"); - strings.emplace_back("{[5.01]} {[-5.01]}"); - strings.emplace_back(""); - strings.emplace_back("$ Test looping - print sin, cos from 0 to 90 by 5"); - strings.emplace_back("{_angle = -5}"); - strings.emplace_back("{Loop(19)}"); - strings.emplace_back( - "{_angle += 5} {_sa=sind(_angle)} {_ca=cosd(_angle)} {hypot(_sa, _ca)} "); - strings.emplace_back("{EndLoop}"); - strings.emplace_back(""); - strings.emplace_back("$$$$ Test formatting and string concatenation"); - strings.emplace_back("{_i = 0} {_SAVE = _FORMAT}"); - strings.emplace_back("{loop(20)}"); - strings.emplace_back( - R("{IO(++_i)} Using the format {_FORMAT = " %." // tostring(_i) // " g "}, PI = {PI}")); - strings.emplace_back("{endloop}"); - strings.emplace_back("Reset format to default: {_FORMAT = _SAVE}"); - strings.emplace_back(""); - strings.emplace_back("$$$$ Test string rescanning and executing"); - strings.emplace_back("{ECHO(OFF)}"); - strings.emplace_back("{Test = ' This is line 1: {a = atan2(0,-1)}"); - strings.emplace_back(" This is line 2: {sin(a/4)}"); - strings.emplace_back(" This is line 3: {cos(a/4)}'}"); - strings.emplace_back(R("{Test2 = 'This has an embedded string: {T = " This is a string "}'}")); - strings.emplace_back("{ECHO(ON)}"); - strings.emplace_back("Original String:"); - strings.emplace_back("{Test}"); - strings.emplace_back("Rescanned String:"); - strings.emplace_back("{rescan(Test)} "); - strings.emplace_back("Original String:"); - strings.emplace_back("{Test2}"); - strings.emplace_back("Print Value of variable T = {T}"); - strings.emplace_back("Rescanned String:"); - strings.emplace_back("{rescan(Test2)} "); - strings.emplace_back("Print Value of variable T = {T}"); - strings.emplace_back(""); - strings.emplace_back(R("Original String: {t1 = " atan2(0, -1) "}")); - strings.emplace_back("Executed String: {execute(t1)}"); - strings.emplace_back(""); - strings.emplace_back(R("string = {_string = " one two, three "}")); - strings.emplace_back(R("delimiter " { _delm = " ," } "")); - strings.emplace_back("word count = {word_count(_string,_delm)}"); - strings.emplace_back(R("second word = " { get_word(2, _string, _delm) } "")); - strings.emplace_back(""); - strings.emplace_back(R("string = {_string = " (one two, three * four - five"}")); - strings.emplace_back(R("delimiter " { - _delm = " ,(*-" } "")); - strings.emplace_back("word count = {word_count(_string,_delm)}"); - strings.emplace_back(R("second word = "{ - get_word(2, _string, _delm)}"")); - strings.emplace_back(""); - strings.emplace_back(""); - strings.emplace_back(R("string = {_string = " one two, three"}")); - strings.emplace_back(R("delimiter " { - _delm = " ," } "")); - strings.emplace_back("word count = { iwords = word_count(_string,_delm)}"); - strings.emplace_back(""); - strings.emplace_back("{_n = 0}"); - strings.emplace_back("{loop(iwords)}"); - strings.emplace_back(R("word {++_n} = "{ - get_word(_n, _string, _delm)}"")); - strings.emplace_back("{endloop}"); - strings.emplace_back(""); - strings.emplace_back("$ Check parsing of escaped braces..."); - strings.emplace_back("\\{ int a = b + {PI/2} \\}"); - strings.emplace_back("\\{ \\}"); - strings.emplace_back(" "); - + std::vector strings = build_strings(); bool result = aprepro.parse_strings(strings, "My list of strings"); - if (result) { std::string res_str = aprepro.parsing_results().str(); std::cout << res_str; } - aprepro.clear_results(); } + +std::vector build_strings() +{ + std::vector strings; + + strings.emplace_back(R"($ Test program for Aprepro)"); + strings.emplace_back(R"($)"); + strings.emplace_back(R"(Test number representations)"); + strings.emplace_back(R"({1} {10e-1} {10.e-1} {.1e+1} {.1e1})"); + strings.emplace_back(R"({1} {10E-1} {10.E-1} {.1E+1} {.1E1})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(Test assign statements:)"); + strings.emplace_back(R"({_a = 5} {b=_a} $ Should print 5 5)"); + strings.emplace_back(R"({_a +=b} {_a} $ Should print 10 10)"); + strings.emplace_back(R"({_a -=b} {_a} $ Should print 5 5)"); + strings.emplace_back(R"({_a *=b} {_a} $ Should print 25 25)"); + strings.emplace_back(R"({_a /=b} {_a} $ Should print 5 5)"); + strings.emplace_back(R"({_a ^=b} {_a} $ Should print 3125 3125)"); + strings.emplace_back(R"({_a = b} {_a**=b} {_a} $ Should print 5 3125 3125)"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(Test trigonometric functions (radians))"); + strings.emplace_back(R"({pi = d2r(180)} {atan2(0,-1)} {4*atan(1.0)} $ Three values of pi)"); + strings.emplace_back(R"({_a = sin(pi/4)} {pi-4*asin(_a)} $ sin(pi/4))"); + strings.emplace_back(R"({_b = cos(pi/4)} {pi-4*acos(_b)} $ cos(pi/4))"); + strings.emplace_back(R"({_c = tan(pi/4)} {pi-4*atan(_c)} $ tan(pi/4))"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(Test trigonometric functions (degrees))"); + strings.emplace_back(R"({r2d(pi)} {pid = atan2d(0,-1)} {4 * atand(1.0)})"); + strings.emplace_back(R"({ad = sind(180/4)} {180-4*asind(ad)} $ sin(180/4))"); + strings.emplace_back(R"({bd = cosd(180/4)} {180-4*acosd(bd)} $ cos(180/4))"); + strings.emplace_back(R"({cd = tand(180/4)} {180-4*atand(cd)} $ tan(180/4))"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(Test max, min, sign, dim, abs)"); + strings.emplace_back(R"({pmin = min(0.5, 1.0)} {nmin = min(-0.5, -1.0)} $ Should be 0.5, -1)"); + strings.emplace_back(R"({pmax = max(0.5, 1.0)} {nmax = max(-0.5, -1.0)} $ Should be 1.0, -0.5)"); + strings.emplace_back(R"({zero = 0} {sign(0.5, zero) + sign(0.5, -zero)} $ Should be 0 1)"); + strings.emplace_back(R"({nonzero = 1} {sign(0.5, nonzero) + sign(0.5, -nonzero)} $ Should be 1 0)"); + strings.emplace_back(R"({dim(5.5, 4.5)} {dim(4.5, 5.5)} $ Should be 1 0)"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({ifyes = 1} {ifno = 0})"); + strings.emplace_back(R"($ Test ternary...)"); + strings.emplace_back(R"({ifyes == 1 ? "correct" : "incorrect"})"); + strings.emplace_back(R"({ifno == 1 ? "incorrect" : "correct"})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test ifdef lines)"); + strings.emplace_back(R"( {Ifdef(ifyes)})"); + strings.emplace_back(R"(This line should be echoed. (a))"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"(This line should be echoed. (b))"); + strings.emplace_back(R"( {Ifdef(ifno)})"); + strings.emplace_back(R"(This line should not be echoed)"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"(This line should be echoed. (c))"); + strings.emplace_back(R"( {Ifdef(ifundefined)})"); + strings.emplace_back(R"(This line should not be echoed)"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"(This line should be echoed. (d))"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test ifdef - else lines)"); + strings.emplace_back(R"( {Ifdef(ifyes)})"); + strings.emplace_back(R"(This line should be echoed. (1))"); + strings.emplace_back(R"( {Else})"); + strings.emplace_back(R"(This line should not be echoed (2))"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"( {Ifdef(ifno)})"); + strings.emplace_back(R"(This line should not be echoed. (3))"); + strings.emplace_back(R"( {Else})"); + strings.emplace_back(R"(This line should be echoed (4))"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test ifndef - else lines)"); + strings.emplace_back(R"( {Ifndef(ifyes)})"); + strings.emplace_back(R"(This line should not be echoed. (5))"); + strings.emplace_back(R"( {Else})"); + strings.emplace_back(R"(This line should be echoed (6))"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"( {Ifndef(ifno)})"); + strings.emplace_back(R"(This line should be echoed. (7))"); + strings.emplace_back(R"( {Else})"); + strings.emplace_back(R"(This line should not be echoed (8))"); + strings.emplace_back(R"( {Endif})"); + strings.emplace_back(R"($ Lines a, b, c, d, 1, 4, 6, 7 should be echoed)"); + strings.emplace_back(R"($ Check line counting -- should be on line 78: {Parse Error})"); + strings.emplace_back(R"({ifdef(ifyes)} {This should be an error})"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ ========================================================================)"); + strings.emplace_back(R"($ Test string if lines)"); + strings.emplace_back(R"({if("Greg")})"); + strings.emplace_back(R"( This line should be echoed ("greg"))"); + strings.emplace_back(R"({else})"); + strings.emplace_back(R"( This line should not be echoed ("greg"))"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({empty=""})"); + strings.emplace_back(R"({if(empty)})"); + strings.emplace_back(R"( This line should not be echoed (empty))"); + strings.emplace_back(R"({else})"); + strings.emplace_back(R"( This line should be echoed (empty))"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ ========================================================================)"); + strings.emplace_back(R"($ Test if lines)"); + strings.emplace_back(R"({if(sqrt(4) == 2)})"); + strings.emplace_back(R"( This line should be echoed. (a))"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"( This line should be echoed. (b))"); + strings.emplace_back(R"({if(sqrt(2) == 2 || sqrt(3) == 2)})"); + strings.emplace_back(R"( This line should not be echoed)"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"(This line should be echoed. (c))"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({diff = sqrt(3)*sqrt(3) - 3})"); + strings.emplace_back(R"($ Test if - else lines)"); + strings.emplace_back(R"({if(sqrt(3)*sqrt(3) - 3 == diff)})"); + strings.emplace_back(R"( complex if works)"); + strings.emplace_back(R"({else})"); + strings.emplace_back(R"( complex if does not work)"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({if (sqrt(4) == 2)})"); + strings.emplace_back(R"( {if (sqrt(9) == 3)})"); + strings.emplace_back(R"( {if (sqrt(16) == 4)})"); + strings.emplace_back(R"( square roots work)"); + strings.emplace_back(R"( {else})"); + strings.emplace_back(R"( sqrt(16) does not work)"); + strings.emplace_back(R"( {endif})"); + strings.emplace_back(R"( {else})"); + strings.emplace_back(R"( sqrt(9) does not work)"); + strings.emplace_back(R"( {endif})"); + strings.emplace_back(R"({else})"); + strings.emplace_back(R"( sqrt(4) does not work)"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({v1 = 1} {v2 = 2})"); + strings.emplace_back(R"({if (v1 == v2)})"); + strings.emplace_back(R"( Bad if)"); + strings.emplace_back(R"( {if (v1 != v2)})"); + strings.emplace_back(R"( should not see (1))"); + strings.emplace_back(R"( {else})"); + strings.emplace_back(R"( should not see (2))"); + strings.emplace_back(R"( {endif})"); + strings.emplace_back(R"( should not see (3))"); + strings.emplace_back(R"({else})"); + strings.emplace_back(R"( {if (v1 != v2)})"); + strings.emplace_back(R"( good nested if)"); + strings.emplace_back(R"( {else})"); + strings.emplace_back(R"( bad nested if)"); + strings.emplace_back(R"( {endif})"); + strings.emplace_back(R"( good)"); + strings.emplace_back(R"( make sure it is still good)"); + strings.emplace_back(R"({endif})"); + strings.emplace_back(R"($ ========================================================================)"); + strings.emplace_back(R"($ Test switch)"); + strings.emplace_back(R"({switch(PI)})"); + strings.emplace_back(R"(This is in a switch, but prior to any case, it should not run)"); + strings.emplace_back(R"({a = 0.5} Should not execute)"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({case (1)})"); + strings.emplace_back(R"(This should not echo)"); + strings.emplace_back(R"({a = 1})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({case (2)})"); + strings.emplace_back(R"(This should not echo)"); + strings.emplace_back(R"({a = 2})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({case (PI)})"); + strings.emplace_back(R"(This should echo)"); + strings.emplace_back(R"({a = PI})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({case (PI)})"); + strings.emplace_back(R"(This should not echo since a previous case matched.)"); + strings.emplace_back(R"({a = 2})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({default})"); + strings.emplace_back(R"({a=4})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"({endswitch})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(This should be equal to PI -- {PI})"); + strings.emplace_back(R"($ Test int and [] (shortcut for int))"); + strings.emplace_back(R"({int(5.01)} {int(-5.01)})"); + strings.emplace_back(R"({[5.01]} {[-5.01]})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test looping - print sin, cos from 0 to 90 by 5)"); + strings.emplace_back(R"({Loop(19, _angle, 0, 5)})"); + strings.emplace_back(R"({_angle} {_sa=sind(_angle)} {_ca=cosd(_angle)} {hypot(_sa, _ca)} )"); + strings.emplace_back(R"({EndLoop})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($$$$ Test formatting and string concatenation)"); + strings.emplace_back(R"({_SAVE = _FORMAT})"); + strings.emplace_back(R"({loop(20)})"); + strings.emplace_back(R"({IO(__loop_1+1)} Using the format {_FORMAT = "%." // tostring(__loop_1+1) // "g"}, PI = {PI})"); + strings.emplace_back(R"({endloop})"); + strings.emplace_back(R"(Reset format to default: {_FORMAT = _SAVE})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($$$$ Test string rescanning and executing)"); + strings.emplace_back(R"({ECHO(OFF)})"); + strings.emplace_back(R"({Test = ' This is line 1: {a = atan2(0,-1)})"); + strings.emplace_back(R"( This is line 2: {sin(a/4)})"); + strings.emplace_back(R"( This is line 3: {cos(a/4)}'})"); + strings.emplace_back(R"({Test2 = 'This has an embedded string: {T = "This is a string"}'})"); + strings.emplace_back(R"({ECHO(ON)})"); + strings.emplace_back(R"(Original String:)"); + strings.emplace_back(R"({Test})"); + strings.emplace_back(R"(Rescanned String:)"); + strings.emplace_back(R"({rescan(Test)} )"); + strings.emplace_back(R"(Original String:)"); + strings.emplace_back(R"({Test2})"); + strings.emplace_back(R"(Print Value of variable T = {T})"); + strings.emplace_back(R"(Rescanned String:)"); + strings.emplace_back(R"({rescan(Test2)} )"); + strings.emplace_back(R"(Print Value of variable T = {T})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"d(Original String: {t1 = "atan2(0,-1)"})d"); + strings.emplace_back(R"(Executed String: {execute(t1)})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(string = {_string = " one two, three"})"); + strings.emplace_back(R"(delimiter "{_delm = " ,"}")"); + strings.emplace_back(R"(word count = {word_count(_string,_delm)})"); + strings.emplace_back(R"(second word = "{get_word(2,_string,_delm)}")"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(string = {_string = " (one two, three * four - five"})"); + strings.emplace_back(R"(delimiter "{_delm = " ,(*-"}")"); + strings.emplace_back(R"(word count = {word_count(_string,_delm)})"); + strings.emplace_back(R"(second word = "{get_word(2,_string,_delm)}")"); + strings.emplace_back(R"()"); + strings.emplace_back(R"()"); + strings.emplace_back(R"(string = {_string = " one two, three"})"); + strings.emplace_back(R"(delimiter "{_delm = " ,"}")"); + strings.emplace_back(R"(word count = { iwords = word_count(_string,_delm)})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"( {loop(iwords, _n, 1)})"); + strings.emplace_back(R"(word {_n} = "{get_word(_n,_string,_delm)}")"); + strings.emplace_back(R"( {endloop})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Check parsing of escaped braces...)"); + strings.emplace_back(R"(\{ int a = b + {PI/2} \})"); + strings.emplace_back(R"(\{ \})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test variable deletion)"); + strings.emplace_back(R"({new_var = sqrt(2) * sqrt(3)})"); + strings.emplace_back(R"({new_var})"); + strings.emplace_back(R"({delete("new_var")})"); + strings.emplace_back(R"({new_var} This should print warning about undefined variable)"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test extract)"); + strings.emplace_back(R"({ex_found = extract("The test string is found", "test", "")})"); + strings.emplace_back(R"({ex_null = extract("The test string is not found", "xxxx", "yyyy")})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($ Test string tokenization optimization)"); + strings.emplace_back(R"({list1 ='51,52,53,54,61,62,63,64'})"); + strings.emplace_back(R"({list2 ='71,72,73,74,81,82,83,84'})"); + strings.emplace_back(R"({loop(8, _i, 1)})"); + strings.emplace_back(R"(Word {_i} of list1 and list2 are {get_word(_i,list1,',')} and {get_word(_i,list2,',')})"); + strings.emplace_back(R"({endloop})"); + strings.emplace_back(R"()"); + strings.emplace_back(R"($End of test file)"); + + return strings; +} diff --git a/packages/seacas/libraries/aprepro_lib/test-array.gold b/packages/seacas/libraries/aprepro_lib/test-array.gold index 3eb314924d..9b65097169 100644 --- a/packages/seacas/libraries/aprepro_lib/test-array.gold +++ b/packages/seacas/libraries/aprepro_lib/test-array.gold @@ -1,8 +1,6 @@ 27 21 -0 -0 a[0,0] = 0 a[0,1] = 1 a[0,2] = 1 @@ -24,8 +22,6 @@ a[0,17] = 0 a[0,18] = 0 a[0,19] = 0 a[0,20] = 0 -0 -0 a[1,0] = 1 a[1,1] = 0.99987325 a[1,2] = 0.9998324 @@ -47,8 +43,6 @@ a[1,17] = 0.00027661075 a[1,18] = 0.00027661075 a[1,19] = -0.0057027978 a[1,20] = -5.5178336e-05 -1 -0 a[2,0] = 2 a[2,1] = 0.99845402 a[2,2] = 0.99795569 @@ -70,8 +64,6 @@ a[2,17] = 0.0009683687 a[2,18] = 0.0009683687 a[2,19] = -0.019904266 a[2,20] = -0.00019329815 -2 -0 a[3,0] = 3 a[3,1] = 0.98850008 a[3,2] = 0.98478703 @@ -93,8 +85,6 @@ a[3,17] = 0.0026867021 a[3,18] = 0.0026867021 a[3,19] = -0.054060764 a[3,20] = -0.0005387864 -3 -0 a[4,0] = 4 a[4,1] = 0.93725124 a[4,2] = 0.91675084 @@ -116,8 +106,6 @@ a[4,17] = 0.0068817499 a[4,18] = 0.0068817499 a[4,19] = -0.12385676 a[4,20] = -0.0014128781 -4 -0 a[5,0] = 5 a[5,1] = 0.78303105 a[5,2] = 0.70605164 @@ -139,8 +127,6 @@ a[5,17] = 0.017841674 a[5,18] = 0.017841674 a[5,19] = -0.2249124 a[5,20] = -0.0039246734 -5 -0 a[6,0] = 6 a[6,1] = 0.58749345 a[6,2] = 0.38695099 @@ -162,8 +148,6 @@ a[6,17] = 0.04687771 a[6,18] = 0.04687771 a[6,19] = -0.36388926 a[6,20] = -0.011322374 -6 -0 a[7,0] = 7 a[7,1] = 0.46344872 a[7,2] = 0.10229219 @@ -185,8 +169,6 @@ a[7,17] = 0.091142312 a[7,18] = 0.091142312 a[7,19] = -0.5376443 a[7,20] = -0.023508048 -7 -0 a[8,0] = 8 a[8,1] = 0.33229323 a[8,2] = -0.16617592 @@ -208,8 +190,6 @@ a[8,17] = 0.14188296 a[8,18] = 0.14188296 a[8,19] = -0.65939491 a[8,20] = -0.038766269 -8 -0 a[9,0] = 9 a[9,1] = 0.17891649 a[9,2] = -0.38710265 @@ -231,8 +211,6 @@ a[9,17] = 0.19927048 a[9,18] = 0.19927048 a[9,19] = -0.67346847 a[9,20] = -0.058633647 -9 -0 a[10,0] = 10 a[10,1] = -0.13164902 a[10,2] = -0.34780142 @@ -254,8 +232,6 @@ a[10,17] = 0.21231109 a[10,18] = 0.21231109 a[10,19] = -0.16937775 a[10,20] = -0.070083742 -10 -0 a[11,0] = 11 a[11,1] = -0.3035429 a[11,2] = -0.27338056 @@ -277,8 +253,6 @@ a[11,17] = 0.12496344 a[11,18] = 0.12496344 a[11,19] = 0.14814128 a[11,20] = -0.034715875 -11 -0 a[12,0] = 12 a[12,1] = -0.44522164 a[12,2] = -0.17411905 @@ -300,8 +274,6 @@ a[12,17] = 0.013153708 a[12,18] = 0.013153708 a[12,19] = 0.41583551 a[12,20] = 0.01075339 -12 -0 a[13,0] = 13 a[13,1] = -0.45323429 a[13,2] = -0.16423295 @@ -323,8 +295,6 @@ a[13,17] = 0.0070692183 a[13,18] = 0.0070692183 a[13,19] = 0.42910234 a[13,20] = 0.013542511 -13 -0 a[14,0] = 14 a[14,1] = -0.45726698 a[14,2] = -0.15867506 @@ -346,8 +316,6 @@ a[14,17] = 0.0041556594 a[14,18] = 0.0041556594 a[14,19] = 0.43539545 a[14,20] = 0.014960681 -14 -0 a[15,0] = 15 a[15,1] = -0.45911461 a[15,2] = -0.15590224 @@ -369,8 +337,6 @@ a[15,17] = 0.0028475236 a[15,18] = 0.0028475236 a[15,19] = 0.4381761 a[15,20] = 0.015623524 -15 -0 a[16,0] = 16 a[16,1] = -0.46066116 a[16,2] = -0.1534213 @@ -392,8 +358,6 @@ a[16,17] = 0.0017609882 a[16,18] = 0.0017609882 a[16,19] = 0.44044676 a[16,20] = 0.016190051 -16 -0 a[17,0] = 17 a[17,1] = -0.46131249 a[17,2] = -0.15232075 @@ -415,8 +379,6 @@ a[17,17] = 0.0013045344 a[17,18] = 0.0013045344 a[17,19] = 0.44138589 a[17,20] = 0.01643313 -17 -0 a[18,0] = 18 a[18,1] = -0.46186461 a[18,2] = -0.15135669 @@ -438,8 +400,6 @@ a[18,17] = 0.0009176024 a[18,18] = 0.0009176024 a[18,19] = 0.44217335 a[18,20] = 0.01664184 -18 -0 a[19,0] = 19 a[19,1] = -0.46209974 a[19,2] = -0.15093647 @@ -461,8 +421,6 @@ a[19,17] = 0.0007527215 a[19,18] = 0.0007527215 a[19,19] = 0.44250617 a[19,20] = 0.016731567 -19 -0 a[20,0] = 20 a[20,1] = -0.46230071 a[20,2] = -0.15057238 @@ -484,8 +442,6 @@ a[20,17] = 0.00061170959 a[20,18] = 0.00061170959 a[20,19] = 0.44278939 a[20,20] = 0.016808699 -20 -0 a[21,0] = 21 a[21,1] = -0.46247259 a[21,2] = -0.15025718 @@ -507,8 +463,6 @@ a[21,17] = 0.0004910241 a[21,18] = 0.0004910241 a[21,19] = 0.4430307 a[21,20] = 0.016875009 -21 -0 a[22,0] = 22 a[22,1] = -0.46261969 a[22,2] = -0.14998454 @@ -530,8 +484,6 @@ a[22,17] = 0.00038766956 a[22,18] = 0.00038766956 a[22,19] = 0.44323651 a[22,20] = 0.016932021 -22 -0 a[23,0] = 23 a[23,1] = -0.46274565 a[23,2] = -0.14974888 @@ -553,8 +505,6 @@ a[23,17] = 0.00029910796 a[23,18] = 0.00029910796 a[23,19] = 0.44341222 a[23,20] = 0.01698104 -23 -0 a[24,0] = 24 a[24,1] = -0.46285356 a[24,2] = -0.14954531 @@ -576,8 +526,6 @@ a[24,17] = 0.00022318514 a[24,18] = 0.00022318514 a[24,19] = 0.44356236 a[24,20] = 0.01702319 -24 -0 a[25,0] = 25 a[25,1] = -0.46294605 a[25,2] = -0.14936957 @@ -599,8 +547,6 @@ a[25,17] = 0.00015806979 a[25,18] = 0.00015806979 a[25,19] = 0.44369076 a[25,20] = 0.017059434 -25 -0 a[26,0] = 26 a[26,1] = -0.46310439 a[26,2] = -0.1490659 @@ -622,34 +568,33 @@ a[26,17] = 4.649547e-05 a[26,18] = 4.649547e-05 a[26,19] = 0.44390995 a[26,20] = 0.017121745 -26 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 - 1 0.999873 0.999832 0.999907 0.999898 0.999925 0.999847 0.999944 0.999944 0.999832 0.999963 -0.00452743 0.0057028 -0.00585599 0.0019344 -0.000780655 -0.00883995 0.000276611 0.000276611 -0.0057028 -5.51783e-05 - 2 0.998454 0.997956 0.99886 0.998754 0.999085 0.998137 0.99932 0.99932 0.997956 0.999545 -0.0158135 0.0199043 -0.0204344 0.00676292 -0.00273061 -0.0308503 0.000968369 0.000968369 -0.0199043 -0.000193298 - 3 0.9885 0.984787 0.991559 0.990719 0.9932 0.986176 0.994937 0.994937 0.984787 0.996607 -0.0431721 0.0540608 -0.0554122 0.0185875 -0.0075306 -0.0837226 0.0026867 0.0026867 -0.0540608 -0.000538786 - 4 0.937251 0.916751 0.955005 0.948911 0.963021 0.925509 0.972207 0.972207 0.916751 0.981228 -0.101638 0.123857 -0.125722 0.0453522 -0.0186964 -0.190875 0.00688175 0.00688175 -0.123857 -0.00141288 - 5 0.783031 0.706052 0.858357 0.816945 0.874477 0.753076 0.901742 0.901742 0.706052 0.931506 -0.201385 0.224912 -0.21633 0.101573 -0.0439245 -0.337204 0.0178417 0.0178417 -0.224912 -0.00392467 - 6 0.587493 0.386951 0.791377 0.618137 0.778518 0.566564 0.80515 0.80515 0.386951 0.852702 -0.359302 0.363889 -0.286077 0.222437 -0.0993392 -0.487505 0.0468777 0.0468777 -0.363889 -0.0113224 - 7 0.463449 0.102292 0.808299 0.440292 0.736982 0.484754 0.728381 0.728381 0.102292 0.773159 -0.542376 0.537644 -0.331173 0.388923 -0.173033 -0.627366 0.0911423 0.0911423 -0.537644 -0.023508 - 8 0.332293 -0.166176 0.816825 0.238693 0.677847 0.396021 0.613956 0.613956 -0.166176 0.643172 -0.69547 0.659395 -0.373148 0.543102 -0.248479 -0.740677 0.141883 0.141883 -0.659395 -0.0387663 - 9 0.178916 -0.387103 0.777598 0.024505 0.586197 0.247539 0.41731 0.41731 -0.387103 0.371602 -0.788217 0.673468 -0.431381 0.653529 -0.321609 -0.80977 0.19927 0.19927 -0.673468 -0.0586336 - 10 -0.131649 -0.347801 0.435212 -0.162899 0.373888 -0.185893 0.14518 0.14518 -0.347801 -0.0563094 -0.490017 0.169378 -0.466717 0.450316 -0.315911 -0.495294 0.212311 0.212311 -0.169378 -0.0700837 - 11 -0.303543 -0.273381 0.41333 -0.217871 0.221594 -0.338191 0.0702492 0.0702492 -0.273381 -0.031344 -0.317064 -0.148141 -0.501882 0.190653 -0.251762 -0.407793 0.124963 0.124963 0.148141 -0.0347159 - 12 -0.445222 -0.174119 0.394445 -0.253131 0.0399691 -0.462478 -0.0267525 -0.0267525 -0.174119 -0.0101022 -0.134017 -0.415836 -0.531824 -0.0904316 -0.163274 -0.312139 0.0131537 0.0131537 0.415836 0.0107534 - 13 -0.453234 -0.164233 0.387393 -0.256267 0.0297529 -0.470572 -0.0329712 -0.0329712 -0.164233 -0.0096751 -0.120799 -0.429102 -0.533969 -0.107166 -0.159858 -0.29943 0.00706922 0.00706922 0.429102 0.0135425 - 14 -0.457267 -0.158675 0.382818 -0.258147 0.0248439 -0.474706 -0.0361136 -0.0361136 -0.158675 -0.00953276 -0.113859 -0.435395 -0.535098 -0.115565 -0.158604 -0.291894 0.00415566 0.00415566 0.435395 0.0149607 - 15 -0.459115 -0.155902 0.380363 -0.259097 0.0226342 -0.476617 -0.0375729 -0.0375729 -0.155902 -0.00948304 -0.110537 -0.438176 -0.535614 -0.119457 -0.158158 -0.288026 0.00284752 0.00284752 0.438176 0.0156235 - 16 -0.460661 -0.153421 0.378067 -0.259946 0.020795 -0.478225 -0.0388134 -0.0388134 -0.153421 -0.00944873 -0.107645 -0.440447 -0.536038 -0.122765 -0.157855 -0.284504 0.00176099 0.00176099 0.440447 0.0161901 - 17 -0.461312 -0.152321 0.377019 -0.26032 0.020021 -0.478906 -0.0393434 -0.0393434 -0.152321 -0.00943625 -0.106387 -0.441386 -0.536212 -0.124177 -0.15775 -0.282924 0.00130453 0.00130453 0.441386 0.0164331 - 18 -0.461865 -0.151357 0.376085 -0.260647 0.0193641 -0.479484 -0.0397972 -0.0397972 -0.151357 -0.0094266 -0.105297 -0.442173 -0.536357 -0.125387 -0.157671 -0.28153 0.000917602 0.000917602 0.442173 0.0166418 - 19 -0.4621 -0.150936 0.375674 -0.260788 0.019084 -0.479731 -0.0399919 -0.0399919 -0.150936 -0.00942274 -0.104825 -0.442506 -0.536418 -0.125907 -0.157641 -0.28092 0.000752721 0.000752721 0.442506 0.0167316 - 20 -0.462301 -0.150572 0.375316 -0.260911 0.0188443 -0.479942 -0.0401591 -0.0401591 -0.150572 -0.00941956 -0.104418 -0.442789 -0.53647 -0.126353 -0.157617 -0.28039 0.00061171 0.00061171 0.442789 0.0168087 - 21 -0.462473 -0.150257 0.375004 -0.261016 0.018639 -0.480123 -0.0403027 -0.0403027 -0.150257 -0.00941693 -0.104067 -0.443031 -0.536514 -0.126736 -0.157597 -0.279931 0.000491024 0.000491024 0.443031 0.016875 - 22 -0.46262 -0.149985 0.374733 -0.261108 0.0184632 -0.480278 -0.0404261 -0.0404261 -0.149985 -0.00941475 -0.103765 -0.443237 -0.536551 -0.127065 -0.157582 -0.279532 0.00038767 0.00038767 0.443237 0.016932 - 23 -0.462746 -0.149749 0.374498 -0.261186 0.0183125 -0.480411 -0.0405321 -0.0405321 -0.149749 -0.00941293 -0.103504 -0.443412 -0.536582 -0.127347 -0.157569 -0.279187 0.000299108 0.000299108 0.443412 0.016981 - 24 -0.462854 -0.149545 0.374294 -0.261254 0.0181832 -0.480524 -0.0406231 -0.0406231 -0.149545 -0.0094114 -0.103279 -0.443562 -0.536609 -0.12759 -0.157558 -0.278889 0.000223185 0.000223185 0.443562 0.0170232 - 25 -0.462946 -0.14937 0.374117 -0.261313 0.0180723 -0.480622 -0.0407014 -0.0407014 -0.14937 -0.00941012 -0.103086 -0.443691 -0.536632 -0.127799 -0.15755 -0.278631 0.00015807 0.00015807 0.443691 0.0170594 - 26 -0.463104 -0.149066 0.373812 -0.261413 0.0178823 -0.480789 -0.0408358 -0.0408358 -0.149066 -0.00940798 -0.102752 -0.44391 -0.536671 -0.128158 -0.157536 -0.278185 4.64955e-05 4.64955e-05 0.44391 0.0171217 + 1 0.99987325 0.9998324 0.99990651 0.99989789 0.99992499 0.99984721 0.99994427 0.99994427 0.9998324 0.99996271 -0.0045274345 0.0057027978 -0.0058559869 0.0019343975 -0.00078065548 -0.0088399481 0.00027661075 0.00027661075 -0.0057027978 -5.5178336e-05 + 2 0.99845402 0.99795569 0.99886038 0.99875437 0.99908526 0.99813713 0.99932017 0.99932017 0.99795569 0.99954507 -0.015813503 0.019904266 -0.020434428 0.0067629179 -0.0027306099 -0.030850279 0.0009683687 0.0009683687 -0.019904266 -0.00019329815 + 3 0.98850008 0.98478703 0.99155875 0.99071948 0.99319953 0.98617577 0.9949374 0.9949374 0.98478703 0.99660735 -0.043172077 0.054060764 -0.055412197 0.018587476 -0.0075305988 -0.083722618 0.0026867021 0.0026867021 -0.054060764 -0.0005387864 + 4 0.93725124 0.91675084 0.95500497 0.94891136 0.9630209 0.9255086 0.97220689 0.97220689 0.91675084 0.98122817 -0.10163823 0.12385676 -0.12572195 0.045352196 -0.018696437 -0.19087532 0.0068817499 0.0068817499 -0.12385676 -0.0014128781 + 5 0.78303105 0.70605164 0.85835725 0.81694487 0.87447745 0.75307557 0.9017422 0.9017422 0.70605164 0.93150588 -0.20138474 0.2249124 -0.21632996 0.10157337 -0.04392447 -0.33720391 0.017841674 0.017841674 -0.2249124 -0.0039246734 + 6 0.58749345 0.38695099 0.79137664 0.61813726 0.7785177 0.56656449 0.80515035 0.80515035 0.38695099 0.85270233 -0.3593023 0.36388926 -0.28607711 0.22243683 -0.099339161 -0.48750546 0.04687771 0.04687771 -0.36388926 -0.011322374 + 7 0.46344872 0.10229219 0.80829933 0.44029196 0.73698231 0.48475397 0.72838129 0.72838129 0.10229219 0.77315948 -0.54237647 0.5376443 -0.33117305 0.38892284 -0.17303342 -0.62736563 0.091142312 0.091142312 -0.5376443 -0.023508048 + 8 0.33229323 -0.16617592 0.8168248 0.23869311 0.67784736 0.39602058 0.61395585 0.61395585 -0.16617592 0.64317238 -0.69546982 0.65939491 -0.37314835 0.54310201 -0.24847898 -0.74067666 0.14188296 0.14188296 -0.65939491 -0.038766269 + 9 0.17891649 -0.38710265 0.77759846 0.024504973 0.58619655 0.24753853 0.41731032 0.41731032 -0.38710265 0.37160176 -0.78821686 0.67346847 -0.4313815 0.65352921 -0.32160908 -0.80977014 0.19927048 0.19927048 -0.67346847 -0.058633647 + 10 -0.13164902 -0.34780142 0.43521191 -0.16289891 0.37388776 -0.1858933 0.14518026 0.14518026 -0.34780142 -0.056309359 -0.49001652 0.16937775 -0.46671727 0.4503163 -0.31591122 -0.49529438 0.21231109 0.21231109 -0.16937775 -0.070083742 + 11 -0.3035429 -0.27338056 0.41332959 -0.21787127 0.22159388 -0.33819096 0.070249167 0.070249167 -0.27338056 -0.031344002 -0.31706446 -0.14814128 -0.50188227 0.19065277 -0.25176215 -0.40779282 0.12496344 0.12496344 0.14814128 -0.034715875 + 12 -0.44522164 -0.17411905 0.39444488 -0.253131 0.039969083 -0.46247794 -0.026752493 -0.026752493 -0.17411905 -0.010102207 -0.13401686 -0.41583551 -0.53182392 -0.09043161 -0.1632736 -0.31213863 0.013153708 0.013153708 0.41583551 0.01075339 + 13 -0.45323429 -0.16423295 0.38739292 -0.25626728 0.029752934 -0.47057195 -0.032971178 -0.032971178 -0.16423295 -0.0096751029 -0.12079852 -0.42910234 -0.53396874 -0.10716627 -0.15985789 -0.29942973 0.0070692183 0.0070692183 0.42910234 0.013542511 + 14 -0.45726698 -0.15867506 0.38281814 -0.25814655 0.024843886 -0.47470613 -0.03611364 -0.03611364 -0.15867506 -0.0095327622 -0.11385876 -0.43539545 -0.53509827 -0.11556516 -0.15860438 -0.29189408 0.0041556594 0.0041556594 0.43539545 0.014960681 + 15 -0.45911461 -0.15590224 0.38036274 -0.25909681 0.022634211 -0.47661652 -0.03757291 -0.03757291 -0.15590224 -0.0094830365 -0.11053679 -0.4381761 -0.53561397 -0.11945747 -0.15815753 -0.28802619 0.0028475236 0.0028475236 0.4381761 0.015623524 + 16 -0.46066116 -0.1534213 0.37806694 -0.25994574 0.020794998 -0.47822516 -0.038813403 -0.038813403 -0.1534213 -0.0094487263 -0.10764499 -0.44044676 -0.53603753 -0.12276455 -0.15785521 -0.28450448 0.0017609882 0.0017609882 0.44044676 0.016190051 + 17 -0.46131249 -0.15232075 0.37701862 -0.26032025 0.020020999 -0.47890567 -0.039343381 -0.039343381 -0.15232075 -0.0094362538 -0.10638658 -0.44138589 -0.53621194 -0.12417743 -0.15774968 -0.28292397 0.0013045344 0.0013045344 0.44138589 0.01643313 + 18 -0.46186461 -0.15135669 0.37608528 -0.26064663 0.019364133 -0.47948413 -0.039797192 -0.039797192 -0.15135669 -0.0094265965 -0.10529653 -0.44217335 -0.53635716 -0.12538742 -0.15767126 -0.28153034 0.0009176024 0.0009176024 0.44217335 0.01664184 + 19 -0.46209974 -0.15093647 0.37567407 -0.26078828 0.019083993 -0.47973095 -0.039991917 -0.039991917 -0.15093647 -0.0094227387 -0.10482499 -0.44250617 -0.53641813 -0.12590669 -0.15764111 -0.28092024 0.0007527215 0.0007527215 0.44250617 0.016731567 + 20 -0.46230071 -0.15057238 0.37531563 -0.26091069 0.018844288 -0.47994216 -0.040159119 -0.040159119 -0.15057238 -0.0094195623 -0.10441818 -0.44278939 -0.53646977 -0.12635262 -0.15761694 -0.28039033 0.00061170959 0.00061170959 0.44278939 0.016808699 + 21 -0.46247259 -0.15025718 0.37500374 -0.26101639 0.018639044 -0.48012298 -0.040302721 -0.040302721 -0.15025718 -0.009416934 -0.10406733 -0.4430307 -0.53651357 -0.12673565 -0.15759747 -0.27993062 0.0004910241 0.0004910241 0.4430307 0.016875009 + 22 -0.46261969 -0.14998454 0.37473275 -0.26110761 0.018463203 -0.48027787 -0.040426076 -0.040426076 -0.14998454 -0.0094147496 -0.10376482 -0.44323651 -0.53655077 -0.12706471 -0.15758171 -0.27953225 0.00038766956 0.00038766956 0.44323651 0.016932021 + 23 -0.46274565 -0.14974888 0.37449762 -0.2611863 0.018312477 -0.48041061 -0.040532058 -0.040532058 -0.14974888 -0.0094129267 -0.10350408 -0.44341222 -0.53658239 -0.12734745 -0.15756888 -0.27918738 0.00029910796 0.00029910796 0.44341222 0.01698104 + 24 -0.46285356 -0.14954531 0.37429385 -0.26125414 0.01818322 -0.4805244 -0.040623125 -0.040623125 -0.14954531 -0.0094114 -0.1032794 -0.44356236 -0.53660931 -0.12759042 -0.1575584 -0.27888908 0.00022318514 0.00022318514 0.44356236 0.01702319 + 25 -0.46294605 -0.14936957 0.37411743 -0.26131261 0.018072332 -0.48062199 -0.040701387 -0.040701387 -0.14936957 -0.0094101171 -0.10308583 -0.44369076 -0.53663226 -0.12779925 -0.15754978 -0.27863125 0.00015806979 0.00015806979 0.44369076 0.017059434 + 26 -0.46310439 -0.1490659 0.37381151 -0.26141341 0.017882259 -0.4807892 -0.040835831 -0.040835831 -0.1490659 -0.009407976 -0.10275225 -0.44390995 -0.53667124 -0.12815802 -0.15753586 -0.2781851 4.649547e-05 4.649547e-05 0.44390995 0.017121745 @@ -685,8 +630,8 @@ sum = e + e = 1552 1624 e+e-2*e = 0 0 0 0 -scale = 1 1.04639 - 1.81186 1.89691 +scale = 1 1.046391753 + 1.81185567 1.896907216 17 diff --git a/packages/seacas/libraries/aprepro_lib/test-array.i b/packages/seacas/libraries/aprepro_lib/test-array.i index 69f7392350..22871f0e25 100644 --- a/packages/seacas/libraries/aprepro_lib/test-array.i +++ b/packages/seacas/libraries/aprepro_lib/test-array.i @@ -1,13 +1,10 @@ {a = csv_array("rect.csv")} {_therow = rows(a)} {_col = cols(a)} -{_r = 0} -{loop(_therow)} -{_c = 0} -{loop(_col)} -a[{_r},{_c}] = {a[_r,_c++]} +{loop(_therow, _r)} +{loop(_col, _c)} +a[{_r},{_c}] = {a[_r,_c]} {endloop} -{_r++} {endloop} {print_array(a)} @@ -15,13 +12,10 @@ a[{_r},{_c}] = {a[_r,_c++]} {NOECHO} {_therow = rows(b)} {_col = cols(b)} -{_r = 0} -{loop(_therow)} -{_c = 0} -{loop(_col)} -{b[_r,_c] = 10*(_r+1) + _c++ + 1} +{loop(_therow, _r)} +{loop(_col, _c)} +{b[_r,_c] = 10*(_r+1) + _c + 1} {endloop} -{_r++} {endloop} {ECHO} b = {print_array(b)} @@ -30,13 +24,10 @@ b = {print_array(b)} {NOECHO} {_therow = rows(c)} {_col = cols(c)} -{_r = 0} -{loop(_therow)} -{_c = 0} -{loop(_col)} -{c[_r,_c] = 10*(_r+1) + _c++ + 1} +{loop(_therow, _r)} +{loop(_col, _c)} +{c[_r,_c] = 10*(_r+1) + _c + 1} {endloop} -{_r++} {endloop} {ECHO} c = {print_array(c)} diff --git a/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold b/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold index b5ddd29471..22eee4190f 100644 --- a/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold +++ b/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold @@ -2,9 +2,7 @@ $ Variable = Value $ {BirthYear = 1958} $ {Greg = "Is the author of this code"} (immutable) -$ {_c = 3} $ {_col = 3} -$ {_r = 2} $ {_therow = 2} $ {a (array) rows = 27, cols = 21} $ {a_rows = 27} diff --git a/packages/seacas/libraries/aprepro_lib/test.inp_app b/packages/seacas/libraries/aprepro_lib/test.inp_app index ba97fc74cf..e89ca173fb 100644 --- a/packages/seacas/libraries/aprepro_lib/test.inp_app +++ b/packages/seacas/libraries/aprepro_lib/test.inp_app @@ -3,7 +3,7 @@ $ Test number representations {1} {10e-1} {10.e-1} {.1e+1} {.1e1} {1} {10E-1} {10.E-1} {.1E+1} {.1E1} - + Test assign statements: {_a = 5} {b=_a} $ Should print 5 5 {_a +=b} {_a} $ Should print 10 10 @@ -179,15 +179,14 @@ $ Test int and [] (shortcut for int) {[5.01]} {[-5.01]} $ Test looping - print sin, cos from 0 to 90 by 5 -{_angle = -5} -{Loop(19)} -{_angle += 5} {_sa=sind(_angle)} {_ca=cosd(_angle)} {hypot(_sa, _ca)} +{Loop(19, _angle, 0, 5)} +{_angle} {_sa=sind(_angle)} {_ca=cosd(_angle)} {hypot(_sa, _ca)} {EndLoop} $$$$ Test formatting and string concatenation -{_i = 0} {_SAVE = _FORMAT} +{_SAVE = _FORMAT} {loop(20)} -{IO(++_i)} Using the format {_FORMAT = "%." // tostring(_i) // "g"}, PI = {PI} +{IO(__loop_1+1)} Using the format {_FORMAT = "%." // tostring(__loop_1+1) // "g"}, PI = {PI} {endloop} Reset format to default: {_FORMAT = _SAVE} @@ -227,9 +226,8 @@ string = {_string = " one two, three"} delimiter "{_delm = " ,"}" word count = { iwords = word_count(_string,_delm)} -{_n = 0} - {loop(iwords)} -word {++_n} = "{get_word(_n,_string,_delm)}" + {loop(iwords, _n, 1)} +word {_n} = "{get_word(_n,_string,_delm)}" {endloop} $ Check parsing of escaped braces... @@ -247,11 +245,10 @@ $ Test extract {ex_null = extract("The test string is not found", "xxxx", "yyyy")} $ Test string tokenization optimization -{_i=1} {list1 ='51,52,53,54,61,62,63,64'} {list2 ='71,72,73,74,81,82,83,84'} -{loop(8)} -Word {_i} of list1 and list2 are {get_word(_i,list1,',')} and {get_word(_i++,list2,',')} +{loop(8, _i, 1)} +Word {_i} of list1 and list2 are {get_word(_i,list1,',')} and {get_word(_i,list2,',')} {endloop} $End of test file diff --git a/packages/seacas/libraries/aprepro_lib/test_standard.out b/packages/seacas/libraries/aprepro_lib/test_standard.out index 87b7dfadc8..547666f429 100644 --- a/packages/seacas/libraries/aprepro_lib/test_standard.out +++ b/packages/seacas/libraries/aprepro_lib/test_standard.out @@ -89,7 +89,6 @@ $ Test int and [] (shortcut for int) 5 -5 $ Test looping - print sin, cos from 0 to 90 by 5 --5 0 0 1 1 5 0.08715574275 0.9961946981 1 10 0.1736481777 0.984807753 1 @@ -111,7 +110,7 @@ $ Test looping - print sin, cos from 0 to 90 by 5 90 1 6.123233996e-17 1 $$$$ Test formatting and string concatenation -0 %.10g +%.10g 1 Using the format %.1g, PI = 3 2 Using the format %.2g, PI = 3.1 3 Using the format %.3g, PI = 3.14 @@ -169,7 +168,6 @@ string = one two, three delimiter " ," word count = 3 -0 word 1 = "one" word 2 = "two" word 3 = "three" @@ -189,7 +187,6 @@ test string is found $ Test string tokenization optimization -1 51,52,53,54,61,62,63,64 71,72,73,74,81,82,83,84 Word 1 of list1 and list2 are 51 and 71 diff --git a/packages/seacas/libraries/chaco/connect/connect_enforce.c b/packages/seacas/libraries/chaco/connect/connect_enforce.c index 7958a22729..bcfc8cf421 100644 --- a/packages/seacas/libraries/chaco/connect/connect_enforce.c +++ b/packages/seacas/libraries/chaco/connect/connect_enforce.c @@ -48,7 +48,7 @@ void connect_enforce(struct vtx_data **graph, /* data structure for graph int *degree; /* number of neighbors of a vertex */ int *comp_flag; /* component number for each vtx */ double ewgt; /* edge weight */ - int nbndy; /* number of sets adjecent to component */ + int nbndy; /* number of sets adjacent to component */ int domain; /* which subdomain I'm working on */ int new_domain; /* subdomain to move some vertices to */ double max_bndy; /* max connectivity to other domain */ diff --git a/packages/seacas/libraries/chaco/eigen/lanczos_FO.c b/packages/seacas/libraries/chaco/eigen/lanczos_FO.c index a1e3a5724a..a214454bdf 100644 --- a/packages/seacas/libraries/chaco/eigen/lanczos_FO.c +++ b/packages/seacas/libraries/chaco/eigen/lanczos_FO.c @@ -27,7 +27,7 @@ /* Convergence check uses Paige bji estimate over the whole spectrum of T. This is a lot of work, but we are trying to be extra safe. Since we are orthogonalizing fully, we assume the - bji esitmates are very good and don't provide a contingency for + bji estimates are very good and don't provide a contingency for when they don't match the residuals. */ /* A lot of the time in this routine (say half) is spent in ql finding the evals of T on each iteration. This could be reduced by only using diff --git a/packages/seacas/libraries/chaco/main/chaco.h b/packages/seacas/libraries/chaco/main/chaco.h index cf8ba7bc2f..2e08d02ee1 100644 --- a/packages/seacas/libraries/chaco/main/chaco.h +++ b/packages/seacas/libraries/chaco/main/chaco.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -98,7 +98,7 @@ * argument 16 below, is set to 7. A description of what functionality can be used * with an input assignment can be found in x4.4 * NOTE: This argument was a short in the original implementation and documentation. - * Since this limits the processor decompositon to < 32,768 processors, it needed + * Since this limits the processor decomposition to < 32,768 processors, it needed * to be changed to an integer as were all other shorts in the library. * * D. Description of the target machine. diff --git a/packages/seacas/libraries/chaco/optimize/opt3d.c b/packages/seacas/libraries/chaco/optimize/opt3d.c index cf3f4cffce..85c9342c43 100644 --- a/packages/seacas/libraries/chaco/optimize/opt3d.c +++ b/packages/seacas/libraries/chaco/optimize/opt3d.c @@ -29,8 +29,8 @@ void opt3d(struct vtx_data **graph, /* data structure containing vertex weight double coeffs[25]; /* various products of yvecs */ double vars[3]; /* angular variables */ double best[3]; /* best minimizer found so far */ - double grad[3]; /* gradiant of the function */ - double gradc[3]; /* gradiant of the constraint */ + double grad[3]; /* gradient of the function */ + double gradc[3]; /* gradient of the constraint */ double hess[3][3]; /* hessian of the function */ double hessc[3][3]; /* hessian of the constraint */ double step[3]; /* Newton step in optimization */ diff --git a/packages/seacas/libraries/chaco/refine_map/refine_cube.c b/packages/seacas/libraries/chaco/refine_map/refine_cube.c index c9b9f8ed14..a49067c17a 100644 --- a/packages/seacas/libraries/chaco/refine_map/refine_cube.c +++ b/packages/seacas/libraries/chaco/refine_map/refine_cube.c @@ -57,7 +57,7 @@ int refine_cube(struct vtx_data **comm_graph, /* graph for communication require /* This is really just ndims_tot different 1-D problems. */ - /* Allocate space for and inititalize the vertex data. */ + /* Allocate space for and initialize the vertex data. */ vdata = (struct refine_vdata *)smalloc_ret((ndims_tot * nsets_tot + 1) * sizeof(struct refine_vdata)); if (vdata == NULL) { diff --git a/packages/seacas/libraries/exodus/CustomDoxygen.css b/packages/seacas/libraries/exodus/CustomDoxygen.css new file mode 100644 index 0000000000..0d96812b42 --- /dev/null +++ b/packages/seacas/libraries/exodus/CustomDoxygen.css @@ -0,0 +1,619 @@ + +/* function descriptions */ +.memtitle { + padding: 8px; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url(); + background-repeat: repeat-x; + background-color: #fff; + line-height: 1.25; + font-weight: 600; + float: left; +} + +dt { + font-weight: 600; +} + +p.reference, p.definition { + font: 400 14px/22px -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;; + margin-top: 0px; + margin-bottom: 5px; + padding-top: 8px; + border-top: 1px solid #eee; +} + +/* parameter names */ +.params .paramname, .retval .paramname, .tparams .paramname { + font-weight: 600; + vertical-align: top; +} + +/* parameter data types */ +.paramtype { + white-space: nowrap; + color: #008141; +} + +/* headers */ +h1, h2, h3, h4, h5, h6 { + font-weight: 600; +} + +/* parameter names */ +.paramname { + color: #db0303; + white-space: nowrap; +} + +/* overall style */ +body, table, div, p, dl { + font-style: normal; + font-variant-ligatures: normal; + font-variant-caps: normal; + font-variant-numeric: normal; + font-variant-east-asian: normal; + font-weight: 500; + font-stretch: normal; + font-size: 14px; + line-height: 22px; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} + +/* project name */ +#projectname { + /* markdown font */ + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + margin: 0; + padding: 2px 0; +} +/* title area */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} + +h2.groupheader { + border-bottom: 1px solid #eee; + color: #000; + font-size: 150%; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + margin-top: 1em; + padding-top: 12px; + padding-bottom: 4px; + width: 100%; +} + +/* function description text box */ +.memdoc, dl.reflist dd { + + border-bottom: none; + border-left: none; + border-right: none; + padding: 0px 10px 0px 10px; + background-color: #FFF; + border-top-width: 0; + background-image: none; + background-repeat: repeat-x; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0) 5px 5px 5px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); +} + +/* function prototype text box */ +.memproto, dl.reflist dt { + border-bottom: 1px solid #999; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 0px 0 0px 0; + color: #000; + font-weight: bold; + text-shadow: none; + background-color: #f9f9f9; + box-shadow: none; + border-top-right-radius: 4px; + -moz-box-shadow: none; + -moz-border-radius-topright: 4px; + -webkit-box-shadow: none; + -webkit-border-top-right-radius: 4px; +} + +/* function prototype */ +.memname td { + + vertical-align: bottom; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + +} + + +/* icon for each data type */ +.icon { + background-color: #026ea1; +} +/* arrows for treenav */ + +.arrow { + color: #09A716; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} +/* colors and fonts for description pages */ + +table, div, p, dl { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: black; +} + +.sm li, .sm a { + position: relative; + color: black; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: #FFF; + min-height: 100%; + overflow-x: hidden; + background: #fff; +} + +/* file member function descriptions */ +.memberdecls td, .fieldtable tr { + + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 501; +} + +/* function descriptor */ +td.mdescLeft, td.mdescRight { + padding: 0 8px 4px 8px; + color: #000; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 400; +} + +/* headers for #include descriptions */ +tt, code, kbd, samp { + display: inline-block; + direction: ltr; + background-color: #f8f8f8; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* list for file members */ +div.contents { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* links to a class or struct on the class list page */ +a.el { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* header dividers */ +hr { + height: 0; + border: none; + border-top: 1px solid #eee; +} + +#side-nav { + padding: 0 0 0 0; + margin: 0; + display: block; + position: absolute; + left: 0; + width: 250; +} +/* nav tree arrow symbol */ + +#nav-sync img { + opacity: 0; +} +#nav-sync img:hover { + opacity: 0.9; +} +/* The main page button */ + +.sm-dox>li:first-child>a, .sm-dox>li:first-child> :not(ul) a { + padding-right: 12px; +} +/* content of for all class members list */ + +#doc-content { + overflow: auto; + display: block; + padding: 0; + margin: 0; + margin-left: 0; + -webkit-overflow-scrolling: touch; + background-color: #FFF; +} +/* label for which tree menu you are on (displays in the doc menu */ + +.title { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + font-size: 150%; + margin: -2px 0 0 2px; + background-color: white; +} +/* title for each section (class List, Class index) */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} +/* title for each section (class List, Class index) */ + +div.headertitle { + padding: none; + background-color: white; +} +/* actual header for each section */ + +div.header { + background-image: none; + background-repeat: repeat-x; + background-color: #FFF; + margin: 0; + border-bottom: 1px solid #eee; +} +/* for class and function lists */ + +table.directory { + font-style: normal; + font-variant-caps: normal; + font-weight: normal; + font-stretch: normal; + line-height: normal; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-size-adjust: none; + font-kerning: auto; + font-optical-sizing: auto; + font-variant-alternates: normal; + font-variant-east-asian: normal; + font-variant-ligatures: normal; + font-variant-numeric: normal; + font-variant-position: normal; + font-language-override: normal; + font-feature-settings: normal; + font-variation-settings: normal; +} +/* main page, classes, files banner */ + +.sm-dox { + padding: 0 0; + background-image: none; + line-height: 36px; + background-color: #7fbdff; +} +/* item list on botton left */ + +.navpath li.navelem a { + height: 32px; + display: block; + text-decoration: none; + outline: none; + color: #FFF; + font-family: 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; + text-shadow: none; + text-decoration: none; +} +.navpath li { + list-style-type: none; + float: left; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #364D7C; +} +/* top menu, Classes button */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:active, .sm-dox a.highlighted, .sm-dox a.highlighted { + padding-right: 12px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + background-color: #7fbdff; + color: #b8b8b8; + padding-left: 12px; +} + +.sm-dox a.has-submenu { + padding-right: 24px; +} + +.sm a { + display: block; +} +/* top menu, main buttons label */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:visited, .sm-dox a:visited { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + color: #000; + text-shadow: none; +} +/* hover over class/main page, files buttons */ + +.sm-dox a:hover { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + text-decoration: none; + text-decoration-line: none; + text-decoration-style: solid; + text-decoration-color: currentcolor; + text-shadow: none; + color: #FFF; + outline: 0; + outline-color: currentcolor; + outline-style: none; + outline-width: 0; + background-color: #156ac9; + background-image: none; +} + +.sm-dox ul a:hover { + background-image: none; + background-repeat: repeat-x; + color: white; + background-color: #000; + text-shadow: none; +} + +/* top list items */ + +.sm-dox ul { + color: #FFF; + border-top-color: rgb(187, 187, 187); + border-top-style: solid; + border-top-width: 1px; + border-right-color: rgb(187, 187, 187); + border-right-style: solid; + border-right-width: 1px; + border-bottom-color: rgb(187, 187, 187); + border-bottom-style: solid; + border-bottom-width: 1px; + border-left-color: rgb(187, 187, 187); + border-left-style: solid; + border-left-width: 1px; + border-image-outset: 0; + border-image-repeat: stretch; + border-image-slice: 100%; + border-image-source: none; + border-image-width: 1; + padding: 5px 0; + background: #fff; + background-color: rgb(255, 255, 255); + background-position-x: 0%; + background-position-y: 0%; + background-repeat: repeat; + background-attachment: scroll; + background-image: none; + background-size: auto; + background-origin: padding-box; + background-clip: border-box; + -moz-border-radius: 5px !important; + -webkit-border-radius: 5px; + border-radius: 5px !important; + -moz-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); +} +.sm-dox ul a:hover { + background-image: none; +} +/* dividers for class/function lists */ + +div.directory { + margin: 10px 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + width: 100%; +} +/* for navigation tree links */ + +#nav-tree .label a { + padding-top: 1px; + padding-right: 1px; + padding-bottom: 1px; + margin-left: 12px; + color: #FFF; + font-weight: 700; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} +/* hovering over tree view items */ + +#nav-tree .label a:hover { + padding-top: 2px; + padding-right: 2px; + padding-bottom: -3px; + margin-left: 12px; + color: #000; + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; + background-color: #FFF +} +/* nav tree labels */ + +#nav-tree .label { + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; +} +/* still for the navtree, but not labels */ + +#nav-tree { + padding: 0 0; + background-color: #404040; + font-size: normal; + overflow: auto; + background-image: none; + margin-right: 16px; +} + +span.lineno { + background-color: #f7f7f7; +} + +a { + color: #4d95c4; +} + +span.lineno a { + background-color: #e6e5e5; +} + +div.fragment { + padding: 0 0 1px 0; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #eee; +} + +.permalink { + color: #476092; + font-size: 85%; +} + +/* selected nav tree */ +#nav-tree .selected { + background-image: none; + background-repeat: repeat-x; + color: #fff; + background-color: #000; +} +/* selected nav tree link */ + +#nav-tree .selected a { + background-image: none; + background-repeat: repeat-x; + color: #fff; +} +/* visited nav tree link */ + +#nav-tree .visited a { + background-image: none; + background-repeat: repeat-x; + color: #127FCF; +} +/* bar separator for tree view */ + +.ui-resizable-e { + background-image: none; + background-size: 100%; + background-repeat: repeat-y; + background-attachment: scroll; + cursor: ew-resize; + height: 100%; + right: 0; + top: 0; + width: 0; + background-color: black; +} +/* visited links in general */ + +a:visited { + color: #4d95c4; +} +/* bottom bar */ + +a.code, a.code:visited, a.line, a.line:visited { + color: #4d95c4; +} + +.contents a:visited { + color: #4d95c4; +} + +.navpath ul { + font-size: 11px; + background-image: none; + background-repeat: repeat-x; + background-position: 0 -5px; + height: 30px; + line-height: 30px; + color: #fff; + border: none; + overflow: hidden; + margin: 0; + padding: 0; + background-color: #181818; +} +/* text 'Generated by doxygen' */ + +.navpath li.footer { + list-style-type: none; + float: right; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #FFF; + font-size: 8pt; +} + +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 400; + src: url("../fonts/RobotoSlab/roboto-slab.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype") +} +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 700; + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype") +} diff --git a/packages/seacas/libraries/exodus/Doxyfile b/packages/seacas/libraries/exodus/Doxyfile index 5a2727fbcb..c5d403dc3b 100644 --- a/packages/seacas/libraries/exodus/Doxyfile +++ b/packages/seacas/libraries/exodus/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = Exodus # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 7.22 +PROJECT_NUMBER = 8.24 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -1317,7 +1317,7 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = CustomDoxygen.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note diff --git a/packages/seacas/libraries/exodus/include/exodusII.h b/packages/seacas/libraries/exodus/include/exodusII.h index 92e42d6c25..b386c6af66 100644 --- a/packages/seacas/libraries/exodus/include/exodusII.h +++ b/packages/seacas/libraries/exodus/include/exodusII.h @@ -52,12 +52,12 @@ #endif /* EXODUS version number */ -#define EXODUS_VERSION "8.23" +#define EXODUS_VERSION "8.25" #define EXODUS_VERSION_MAJOR 8 -#define EXODUS_VERSION_MINOR 23 -#define EXODUS_RELEASE_DATE "July 13, 2023" +#define EXODUS_VERSION_MINOR 25 +#define EXODUS_RELEASE_DATE "July 28, 2023" -#define EX_API_VERS 8.23f +#define EX_API_VERS 8.25f #define EX_API_VERS_NODOT (100 * EXODUS_VERSION_MAJOR + EXODUS_VERSION_MINOR) #define EX_VERS EX_API_VERS @@ -617,6 +617,11 @@ EXODUS_EXPORT int ex_put_var(int exoid, int time_step, ex_entity_type var_type, ex_entity_id obj_id, int64_t num_entries_this_obj, const void *var_vals); +/* Write Edge Face or Element Variable Values Defined On Blocks or Sets Through Time */ +EXODUS_EXPORT int ex_put_var_multi_time(int exoid, ex_entity_type var_type, int var_index, + ex_entity_id obj_id, int64_t num_entries_this_obj, + int beg_time_step, int end_time_step, const void *var_vals); + /* Write Partial Edge Face or Element Variable Values on Blocks or Sets at a Time Step */ EXODUS_EXPORT int ex_put_partial_var(int exoid, int time_step, ex_entity_type var_type, int var_index, ex_entity_id obj_id, int64_t start_index, @@ -631,6 +636,16 @@ EXODUS_EXPORT int ex_put_reduction_vars(int exoid, int time_step, ex_entity_type EXODUS_EXPORT int ex_get_var(int exoid, int time_step, ex_entity_type var_type, int var_index, ex_entity_id obj_id, int64_t num_entry_this_obj, void *var_vals); +/* Read Edge Face or Element Variable Values Defined On Blocks or Sets at a Time Step */ +EXODUS_EXPORT int ex_get_var_multi_time(int exoid, ex_entity_type var_type, int var_index, + ex_entity_id obj_id, int64_t num_entry_this_obj, + int beg_time_step, int end_time_step, void *var_vals); + +/* Read Edge Face or Element Variable Values Defined On Blocks or Sets Through Time */ +EXODUS_EXPORT int ex_get_var_time(int exoid, ex_entity_type var_type, int var_index, int64_t id, + int beg_time_step, int end_time_step, void *var_vals); + +/* Read Partial Edge Face or Element Variable Values on Blocks or Sets at a Time Step */ EXODUS_EXPORT int ex_get_partial_var(int exoid, int time_step, ex_entity_type var_type, int var_index, ex_entity_id obj_id, int64_t start_index, int64_t num_entities, void *var_vals); @@ -639,10 +654,6 @@ EXODUS_EXPORT int ex_get_partial_var(int exoid, int time_step, ex_entity_type va EXODUS_EXPORT int ex_get_reduction_vars(int exoid, int time_step, ex_entity_type obj_type, ex_entity_id obj_id, int64_t num_variables, void *var_vals); -/* Read Edge Face or Element Variable Values Defined On Blocks or Sets Through Time */ -EXODUS_EXPORT int ex_get_var_time(int exoid, ex_entity_type var_type, int var_index, int64_t id, - int beg_time_step, int end_time_step, void *var_vals); - /*! @} */ /* ======================================================================== diff --git a/packages/seacas/libraries/exodus/include/exodusII_int.h b/packages/seacas/libraries/exodus/include/exodusII_int.h index a2e651ab02..aa0c7c9652 100644 --- a/packages/seacas/libraries/exodus/include/exodusII_int.h +++ b/packages/seacas/libraries/exodus/include/exodusII_int.h @@ -810,16 +810,22 @@ EXODUS_EXPORT char *ex__canonicalize_filename(const char *path); EXODUS_EXPORT int ex__get_dimension(int exoid, const char *DIMENSION, const char *label, size_t *count, int *dimid, const char *routine); -EXODUS_EXPORT int ex__get_nodal_var(int exoid, int time_step, int nodal_var_index, - int64_t num_nodes, void *nodal_var_vals); - -EXODUS_EXPORT int ex__put_nodal_var(int exoid, int time_step, int nodal_var_index, - int64_t num_nodes, const void *nodal_var_vals); - EXODUS_EXPORT int ex__get_nodal_var_time(int exoid, int nodal_var_index, int64_t node_number, int beg_time_step, int end_time_step, void *nodal_var_vals); +EXODUS_EXPORT int ex__put_nodal_var_multi_time(int exoid, int nodal_var_index, int64_t num_nodes, + int beg_time_step, int end_time_step, + const void *nodal_var_vals); + +EXODUS_EXPORT int ex__get_nodal_var_multi_time(int exoid, int nodal_var_index, int64_t node_number, + int beg_time_step, int end_time_step, + void *nodal_var_vals); + +EXODUS_EXPORT int ex__put_nodal_var_time(int exoid, int nodal_var_index, int64_t num_nodes, + int beg_time_step, int end_time_step, + const void *nodal_var_vals); + EXODUS_EXPORT int ex__get_partial_nodal_var(int exoid, int time_step, int nodal_var_index, int64_t start_node, int64_t num_nodes, void *var_vals); @@ -829,6 +835,9 @@ EXODUS_EXPORT int ex__put_partial_nodal_var(int exoid, int time_step, int nodal_ EXODUS_EXPORT int ex__get_glob_vars(int exoid, int time_step, int num_glob_vars, void *glob_var_vals); +EXODUS_EXPORT int ex__get_glob_vars_multi_time(int exoid, int num_glob_vars, int beg_time_step, + int end_time_step, void *glob_var_vals); + EXODUS_EXPORT int ex__get_glob_var_time(int exoid, int glob_var_index, int beg_time_step, int end_time_step, void *glob_var_vals); diff --git a/packages/seacas/libraries/exodus/src/ex__get_glob_vars_multi_time.c b/packages/seacas/libraries/exodus/src/ex__get_glob_vars_multi_time.c new file mode 100644 index 0000000000..13f1cbbe00 --- /dev/null +++ b/packages/seacas/libraries/exodus/src/ex__get_glob_vars_multi_time.c @@ -0,0 +1,75 @@ +/* + * Copyright(C) 2023 National Technology & Engineering Solutions + * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with + * NTESS, the U.S. Government retains certain rights in this software. + * + * See packages/seacas/LICENSE for details + */ +/***************************************************************************** + * + * exggv - ex_get_glob_vars + * + * entry conditions - + * input parameters: + * int exoid exodus file id + * int time_step time step number + * int num_glob_vars number of global vars in file + * + * exit conditions - + * float* glob_var_vals array of global variable values + * + * revision history - + * + * + *****************************************************************************/ + +#include "exodusII.h" // for ex_err, etc +#include "exodusII_int.h" // for ex__comp_ws, EX_FATAL, etc + +/*! + Internal function. Do not use in client code. + */ + +int ex__get_glob_vars_multi_time(int exoid, int num_glob_vars, int beg_time_step, int end_time_step, + void *glob_var_vals) +{ + int varid; + int status; + size_t start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + EX_FUNC_ENTER(); + if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) { + EX_FUNC_LEAVE(EX_FATAL); + } + + /* inquire previously defined variable */ + if ((status = nc_inq_varid(exoid, VAR_GLO_VAR, &varid)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "Warning: failed to locate global variables in file id %d", + exoid); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_WARN); + } + + /* read values of global variables */ + start[0] = --beg_time_step; + start[1] = 0; + + count[0] = end_time_step - beg_time_step; + count[1] = num_glob_vars; + + if (ex__comp_ws(exoid) == 4) { + status = nc_get_vara_float(exoid, varid, start, count, glob_var_vals); + } + else { + status = nc_get_vara_double(exoid, varid, start, count, glob_var_vals); + } + + if (status != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get global variable values from file id %d", + exoid); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + EX_FUNC_LEAVE(EX_NOERR); +} diff --git a/packages/seacas/libraries/exodus/src/ex_get_nodal_var_int.c b/packages/seacas/libraries/exodus/src/ex__get_nodal_var_multi_time.c similarity index 73% rename from packages/seacas/libraries/exodus/src/ex_get_nodal_var_int.c rename to packages/seacas/libraries/exodus/src/ex__get_nodal_var_multi_time.c index adaf133f99..763b978b36 100644 --- a/packages/seacas/libraries/exodus/src/ex_get_nodal_var_int.c +++ b/packages/seacas/libraries/exodus/src/ex__get_nodal_var_multi_time.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -12,11 +12,11 @@ /*! \internal \ingroup ResultsData -\note This function is called internally by ex_get_var() to handle +\note This function is called internally by ex_get_var_multi_time() to handle the reading of nodal variable values. -The function ex__get_nodal_var() reads the values of a single nodal -variable for a single time step. Memory must be allocated for the +The function ex__get_nodal_var_multi_time() reads the values of a single nodal +variable for a one or more time steps. Memory must be allocated for the nodal variable values array before this function is invoked. Because nodal variables are floating point values, the application @@ -24,7 +24,7 @@ code must declare the array passed to be the appropriate type (float or double) to match the compute word size passed in ex_create() or ex_open(). -\return In case of an error, ex__get_nodal_var() returns a negative +\return In case of an error, ex__get_nodal_var_multi_time() returns a negative number; a warning will return a positive number. Possible causes of errors include: - data file not properly opened with call to ex_create() or ex_open() @@ -35,24 +35,16 @@ errors include: ex_create() or ex_open(). -\param[in] time_step The time step, as described under ex_put_time(), -at which the -nodal variable values are desired. This is -essentially an index (in -the time dimension) into the nodal variable -values array stored in -the database. The first time step is 1. - \param[in] nodal_var_index The index of the desired nodal variable. The -first variable -has an index of 1. + first variable has an index of 1. \param[in] num_nodes The number of nodal points. +\param[in] beg_time_step The first time step to get values for. +\param[in] end_time_step The last time step to get values for. \param[out] nodal_var_vals Returned array of num_nodes values of the -nodal_var_index-th -nodal variable for the time_step-th time -step. + nodal_var_index-th nodal variable for the + desired timesteps. For example, the following demonstrates how this function would be used: @@ -66,14 +58,14 @@ time_step = 1; var_index = 2; var_values = (float *) calloc (num_nodes, sizeof(float)); -error = ex_get_nodal_var(exoid, time_step, var_index, num_nodes, -var_values); +error = ex__get_nodal_var_multi_time(exoid, var_index, num_nodes, + time_step, time_step, var_values); ~~~ */ -int ex__get_nodal_var(int exoid, int time_step, int nodal_var_index, int64_t num_nodes, - void *nodal_var_vals) +int ex__get_nodal_var_multi_time(int exoid, int nodal_var_index, int64_t num_nodes, + int beg_time_step, int end_time_step, void *nodal_var_vals) { int varid; int status; @@ -100,11 +92,11 @@ int ex__get_nodal_var(int exoid, int time_step, int nodal_var_index, int64_t num return (EX_WARN); } - start[0] = --time_step; + start[0] = --beg_time_step; start[1] = --nodal_var_index; start[2] = 0; - count[0] = 1; + count[0] = end_time_step - beg_time_step; count[1] = 1; count[2] = num_nodes; } @@ -118,10 +110,10 @@ int ex__get_nodal_var(int exoid, int time_step, int nodal_var_index, int64_t num return (EX_WARN); } - start[0] = --time_step; + start[0] = --beg_time_step; start[1] = 0; - count[0] = 1; + count[0] = end_time_step - beg_time_step; count[1] = num_nodes; } diff --git a/packages/seacas/libraries/exodus/src/ex_put_nodal_var_int.c b/packages/seacas/libraries/exodus/src/ex__put_nodal_var_multi_time.c similarity index 75% rename from packages/seacas/libraries/exodus/src/ex_put_nodal_var_int.c rename to packages/seacas/libraries/exodus/src/ex__put_nodal_var_multi_time.c index 2092c3f982..928909c94a 100644 --- a/packages/seacas/libraries/exodus/src/ex_put_nodal_var_int.c +++ b/packages/seacas/libraries/exodus/src/ex__put_nodal_var_multi_time.c @@ -12,11 +12,11 @@ /*! \internal \ingroup ResultsData -\note This function is called internally by ex_put_var() to handle +\note This function is called internally by ex_put_var_time() to handle the writing of nodal variable values. -The function ex__put_nodal_var() writes the values of a single nodal -variable for a single time step. The function ex_put_variable_param() +The function ex__put_nodal_var_time() writes the values of a single nodal +variable for multiple time steps. The function ex_put_variable_param() must be invoked before this call is made. Because nodal variables are floating point values, the application @@ -37,17 +37,19 @@ nodal variables. ex_create() or ex_open(). -\param[in] time_step The time step number, as described under -ex_put_time(). This - is essentially a counter that is incremented when -results variables - are output. The first time step is 1. - \param[in] nodal_var_index The index of the nodal variable. The first variable has an index of 1. \param[in] num_nodes The number of nodal points. +\param[in] beg_time_step The beginning time step number, as described under ex_put_time(). + This is counter that is incremented when results variables + are output. The first time step is 1. + +\param[in] end_time_step The ending time step number, as described under ex_put_time(). + This is counter that is incremented when results variables + are output. The first time step is 1. + \param[in] nodal_var_vals Array of num_nodes values of the nodal_var_index-th nodal variable for the time_step-th time step. @@ -66,15 +68,15 @@ for (k=1; k <= num_nod_vars; k++) { \comment{application code fills in this array} nodal_var_vals[j] = 10.0; } - error = ex_put_nodal_var(exoid, time_step, k, num_nodes, + error = ex_put_var_time(exoid, EX_NODAL, k, 0, num_nodes, beg_time_step, end_time_step nodal_var_vals); } ~~~ */ -int ex__put_nodal_var(int exoid, int time_step, int nodal_var_index, int64_t num_nodes, - const void *nodal_var_vals) +int ex__put_nodal_var_time(int exoid, int nodal_var_index, int64_t num_nodes, int beg_time_step, + int end_time_step, const void *nodal_var_vals) { int status; @@ -88,10 +90,10 @@ int ex__put_nodal_var(int exoid, int time_step, int nodal_var_index, int64_t num ex_err_fn(exoid, __func__, errmsg, status); return (EX_WARN); } - start[0] = --time_step; + start[0] = --beg_time_step; start[1] = 0; - count[0] = 1; + count[0] = end_time_step - beg_time_step; count[1] = num_nodes; if (ex__comp_ws(exoid) == 4) { diff --git a/packages/seacas/libraries/exodus/src/ex_close.c b/packages/seacas/libraries/exodus/src/ex_close.c index 708cb86611..27cae705c9 100644 --- a/packages/seacas/libraries/exodus/src/ex_close.c +++ b/packages/seacas/libraries/exodus/src/ex_close.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -63,17 +63,10 @@ int ex_close(int exoid) * call ex__rm_file_item and ex__rm_stat_ptr on each group. */ -#if NC_HAS_HDF5 - /* nc_inq_grp_parent() will return NC_ENOGRP error if exoid - * refers to the root group (which is what we want) + /* + * Get exoid of root group */ - int parent_id = 0; - if ((status = nc_inq_grp_parent(exoid, &parent_id)) != NC_ENOGRP) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: file id %d does not refer to root group.", exoid); - ex_err_fn(exoid, __func__, errmsg, status); - EX_FUNC_LEAVE(EX_FATAL); - } -#endif + exoid &= EX_FILE_ID_MASK; if ((status1 = nc_sync(exoid)) != NC_NOERR) { snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to update file id %d", exoid); diff --git a/packages/seacas/libraries/exodus/src/ex_cvt_nodes_to_sides.c b/packages/seacas/libraries/exodus/src/ex_cvt_nodes_to_sides.c index 85864bd4d8..da23e7962f 100644 --- a/packages/seacas/libraries/exodus/src/ex_cvt_nodes_to_sides.c +++ b/packages/seacas/libraries/exodus/src/ex_cvt_nodes_to_sides.c @@ -203,44 +203,6 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n is also the side number. */ - /* 1 2 3 4 node 1 */ - static int shell_table[2][8] = { - {2, 4, 3, 1, 4, 2, 1, 3}, /* node 2 */ - {1, 2, 1, 2, 1, 2, 1, 2} /* side # */ - }; - - /* 1 2 3 4 node 1 */ - static int shell_edge_table[2][8] = { - {2, 4, 3, 1, 4, 2, 1, 3}, /* node 2 */ - {3, 6, 4, 3, 5, 4, 6, 5} /* side # */ - }; - - /* 1 2 3 node 1 */ - static int trishell_table[2][6] = { - {2, 3, 3, 1, 1, 2}, /* node 2 */ - {1, 2, 1, 2, 1, 2} /* side # */ - }; - - /* 1 2 3 4 node 1 */ - static int tetra_table[2][12] = { - {2, 3, 4, 1, 3, 4, 4, 1, 2, 1, 2, 3}, /* node 2 */ - {1, 4, 3, 4, 2, 1, 2, 3, 4, 1, 2, 3} /* side # */ - }; - -#if 0 - static int wedge_table[2][18] = { - /* 1 2 3 4 5 6 node 1 */ - {2,4,3, 5,1,3, 6,1,2, 1,6,5, 6,2,4, 4,3,5}, /* node 2 */ - {1,3,4, 1,4,2, 2,3,4, 1,3,5, 5,2,1, 5,3,2} /* side # */ - }; -#endif - - static int hex_table[2][24] = { - /* 1 2 3 4 5 6 7 8 node 1 */ - {4, 2, 5, 1, 3, 6, 7, 4, 2, 3, 1, 8, 6, 8, 1, 5, 2, 7, 8, 6, 3, 7, 5, 4}, /* node 2 */ - {5, 1, 4, 5, 2, 1, 2, 3, 5, 5, 4, 3, 6, 4, 1, 1, 2, 6, 6, 2, 3, 3, 6, 4} /* side # */ - }; - char errmsg[MAX_ERR_LENGTH]; EX_FUNC_ENTER(); @@ -678,6 +640,12 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n } case EX_EL_TRISHELL: { /* use table to find which node to compare to next */ + /* 1 2 3 node 1 */ + static const int trishell_table[2][6] = { + {2, 3, 3, 1, 1, 2}, /* node 2 */ + {1, 2, 1, 2, 1, 2} /* side # */ + }; + assert(n < 3); if (ss_node1 == get_node(connect, @@ -717,6 +685,12 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n } if (num_node_per_side >= 4) { + /* 1 2 3 4 node 1 */ + static const int shell_table[2][8] = { + {2, 4, 3, 1, 4, 2, 1, 3}, /* node 2 */ + {1, 2, 1, 2, 1, 2, 1, 2} /* side # */ + }; + /* Front or Back side of shell */ if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) + (shell_table[0][2 * n] - 1), @@ -743,6 +717,12 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n } else { /* Edge sides of shell */ + /* 1 2 3 4 node 1 */ + static const int shell_edge_table[2][8] = { + {2, 4, 3, 1, 4, 2, 1, 3}, /* node 2 */ + {3, 6, 4, 3, 5, 4, 6, 5} /* side # */ + }; + if (ss_node1 == get_node(connect, num_nodes_per_elem * (elem_num_pos) + (shell_edge_table[0][2 * n] - 1), @@ -771,6 +751,13 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n } case EX_EL_HEX: { /* use table to find which node to compare to next */ + static const int hex_table[2][24] = { + /* 1 2 3 4 5 6 7 8 node 1 + */ + {4, 2, 5, 1, 3, 6, 7, 4, 2, 3, 1, 8, 6, 8, 1, 5, 2, 7, 8, 6, 3, 7, 5, 4}, /* node 2 */ + {5, 1, 4, 5, 2, 1, 2, 3, 5, 5, 4, 3, 6, 4, 1, 1, 2, 6, 6, 2, 3, 3, 6, 4} /* side # */ + }; + assert(n < 8); if (ss_node1 == get_node(connect, @@ -803,6 +790,12 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n } case EX_EL_TETRA: { /* use table to find which node to compare to next */ + /* 1 2 3 4 node 1 */ + static const int tetra_table[2][12] = { + {2, 3, 4, 1, 3, 4, 4, 1, 2, 1, 2, 3}, /* node 2 */ + {1, 4, 3, 4, 2, 1, 2, 3, 4, 1, 2, 3} /* side # */ + }; + assert(n < 4); if (ss_node1 == @@ -847,6 +840,14 @@ int ex_cvt_nodes_to_sides(int exoid, void_int *num_elem_per_set, void_int *num_n case EX_EL_WEDGE: { /* NOTE: WEDGE elements in side set node lists are currently not * supported */ +#if 0 + static const int wedge_table[2][18] = { + /* 1 2 3 4 5 6 node 1 */ + {2,4,3, 5,1,3, 6,1,2, 1,6,5, 6,2,4, 4,3,5}, /* node 2 */ + {1,3,4, 1,4,2, 2,3,4, 1,3,5, 5,2,1, 5,3,2} /* side # */ + }; +#endif + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: unsupported WEDGE element found in side set " "node list in file id %d", diff --git a/packages/seacas/libraries/exodus/src/ex_err.c b/packages/seacas/libraries/exodus/src/ex_err.c index 68cf7b395a..0ed67d5185 100644 --- a/packages/seacas/libraries/exodus/src/ex_err.c +++ b/packages/seacas/libraries/exodus/src/ex_err.c @@ -106,9 +106,7 @@ void ex_err(const char *module_name, const char *message, int err_num) if (err_num == EX_PRTLASTMSG) { fprintf(stderr, "\n[%s] %s\n", EX_PNAME, EX_ERRMSG); fprintf(stderr, " exerrval = %d\n", EX_ERR_NUM); - if (EX_ERR_NUM < 0) { - fprintf(stderr, "\t%s\n", ex_strerror(EX_ERR_NUM)); - } + fprintf(stderr, "\t%s\n", ex_strerror(EX_ERR_NUM)); EX_FUNC_VOID(); } @@ -128,9 +126,7 @@ void ex_err(const char *module_name, const char *message, int err_num) else if (exoptval & EX_VERBOSE) { /* check see if we really want to hear this */ fprintf(stderr, "\nExodus Library Warning/Error: [%s]\n\t%s\n", module_name, message); - if (err_num < 0) { - fprintf(stderr, "\t%s\n", ex_strerror(err_num)); - } + fprintf(stderr, "\t%s\n", ex_strerror(err_num)); } fflush(stderr); @@ -147,7 +143,7 @@ void ex_err(const char *module_name, const char *message, int err_num) The function ex_err_fn() logs an error to stderr. It is intended to provide explanatory messages for error codes returned from other exodus routines. The main difference between ex_err_fn() and ex_err() is -that ex_err_fn() will print the name of the exodus file that the error occured on. +that ex_err_fn() will print the name of the exodus file that the error occurred on. The passed in error codes and corresponding messages are listed in \file{exodusII.h}. The programmer may supplement the error message printed @@ -228,10 +224,7 @@ void ex_err_fn(int exoid, const char *module_name, const char *message, int err_ } fprintf(stderr, " exerrval = %d\n", EX_ERR_NUM); - - if (EX_ERR_NUM < 0) { - fprintf(stderr, "\t%s\n", ex_strerror(EX_ERR_NUM)); - } + fprintf(stderr, "\t%s\n", ex_strerror(EX_ERR_NUM)); EX_FUNC_VOID(); } @@ -268,9 +261,7 @@ void ex_err_fn(int exoid, const char *module_name, const char *message, int err_ else { fprintf(stderr, "\nExodus Library Warning/Error: [%s]\n\t%s\n", module_name, message); } - if (err_num < 0) { - fprintf(stderr, "\t%s\n", ex_strerror(err_num)); - } + fprintf(stderr, "\t%s\n", ex_strerror(err_num)); } fflush(stderr); diff --git a/packages/seacas/libraries/exodus/src/ex_get_side_set_node_list.c b/packages/seacas/libraries/exodus/src/ex_get_side_set_node_list.c index ba586de870..996adc5e7e 100644 --- a/packages/seacas/libraries/exodus/src/ex_get_side_set_node_list.c +++ b/packages/seacas/libraries/exodus/src/ex_get_side_set_node_list.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -87,131 +87,6 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid tables were generated by following the right-hand rule for determining the outward normal. */ - /* triangle */ - static int tri_table[3][3] = { - {1, 2, 4}, /* side 1 */ - {2, 3, 5}, /* side 2 */ - {3, 1, 6} /* side 3 */ - }; - - /* triangle 3d */ - static int tri3_table[5][7] = { - {1, 2, 3, 4, 5, 6, 7}, /* side 1 (face) */ - {3, 2, 1, 6, 5, 4, 7}, /* side 2 (face) */ - {1, 2, 4, 0, 0, 0, 0}, /* side 3 (edge) */ - {2, 3, 5, 0, 0, 0, 0}, /* side 4 (edge) */ - {3, 1, 6, 0, 0, 0, 0} /* side 5 (edge) */ - }; - - /* quad */ - static int quad_table[4][3] = { - {1, 2, 5}, /* side 1 */ - {2, 3, 6}, /* side 2 */ - {3, 4, 7}, /* side 3 */ - {4, 1, 8} /* side 4 */ - }; - - /* shell */ - static int shell_table[6][9] = { - {1, 2, 3, 4, 5, 6, 7, 8, 9}, /* side 1 (face) */ - {1, 4, 3, 2, 8, 7, 6, 5, 9}, /* side 2 (face) */ - {1, 2, 5, 0, 0, 0, 0, 0, 0}, /* side 3 (edge) */ - {2, 3, 6, 0, 0, 0, 0, 0, 0}, /* side 4 (edge) */ - {3, 4, 7, 0, 0, 0, 0, 0, 0}, /* side 5 (edge) */ - {4, 1, 8, 0, 0, 0, 0, 0, 0} /* side 6 (edge) */ - }; - - /* tetra */ - static int tetra_table[4][7] = { - {1, 2, 4, 5, 9, 8, 14}, /* Side 1 nodes */ - {2, 3, 4, 6, 10, 9, 12}, /* Side 2 nodes */ - {1, 4, 3, 8, 10, 7, 13}, /* Side 3 nodes */ - {1, 3, 2, 7, 6, 5, 11} /* Side 4 nodes */ - }; - - /* wedge */ - /* wedge 6 or 7 */ - static int wedge6_table[5][4] = { - {1, 2, 5, 4}, /* Side 1 nodes -- quad */ - {2, 3, 6, 5}, /* Side 2 nodes -- quad */ - {1, 4, 6, 3}, /* Side 3 nodes -- quad */ - {1, 3, 2, 0}, /* Side 4 nodes -- triangle */ - {4, 5, 6, 0} /* Side 5 nodes -- triangle */ - }; - - /* wedge 12 -- localization element */ - static int wedge12_table[5][6] = { - {1, 2, 5, 4, 7, 10}, /* Side 1 nodes -- quad */ - {2, 3, 6, 5, 8, 11}, /* Side 2 nodes -- quad */ - {1, 4, 6, 3, 9, 12}, /* Side 3 nodes -- quad */ - {1, 3, 2, 9, 8, 7}, /* Side 4 nodes -- triangle */ - {4, 5, 6, 10, 11, 12} /* Side 5 nodes -- triangle */ - }; - - /* wedge 15 or 16 */ - static int wedge15_table[5][8] = { - {1, 2, 5, 4, 7, 11, 13, 10}, /* Side 1 nodes -- quad */ - {2, 3, 6, 5, 8, 12, 14, 11}, /* Side 2 nodes -- quad */ - {1, 4, 6, 3, 10, 15, 12, 9}, /* Side 3 nodes -- quad */ - {1, 3, 2, 9, 8, 7, 0, 0}, /* Side 4 nodes -- triangle */ - {4, 5, 6, 13, 14, 15, 0, 0} /* Side 5 nodes -- triangle */ - }; - - /* wedge 20 */ - static int wedge20_table[5][9] = { - {1, 2, 5, 4, 7, 11, 13, 10, 20}, /* Side 1 nodes -- quad */ - {2, 3, 6, 5, 8, 12, 14, 11, 18}, /* Side 2 nodes -- quad */ - {1, 4, 6, 3, 10, 15, 12, 9, 19}, /* Side 3 nodes -- quad */ - {1, 3, 2, 9, 8, 7, 16, 0, 0}, /* Side 4 nodes -- triangle */ - {4, 5, 6, 13, 14, 15, 17, 0, 0} /* Side 5 nodes -- triangle */ - }; - - /* wedge 21 */ - static int wedge21_table[5][9] = { - {1, 2, 5, 4, 7, 11, 13, 10, 21}, /* Side 1 nodes -- quad */ - {2, 3, 6, 5, 8, 12, 14, 11, 19}, /* Side 2 nodes -- quad */ - {1, 4, 6, 3, 10, 15, 12, 9, 20}, /* Side 3 nodes -- quad */ - {1, 3, 2, 9, 8, 7, 17, 0, 0}, /* Side 4 nodes -- triangle */ - {4, 5, 6, 13, 14, 15, 18, 0, 0} /* Side 5 nodes -- triangle */ - }; - - /* wedge 18 */ - static int wedge18_table[5][9] = { - {1, 2, 5, 4, 7, 11, 13, 10, 16}, /* Side 1 nodes -- quad */ - {2, 3, 6, 5, 8, 12, 14, 11, 17}, /* Side 2 nodes -- quad */ - {1, 4, 6, 3, 10, 15, 12, 9, 18}, /* Side 3 nodes -- quad */ - {1, 3, 2, 9, 8, 7, 0, 0, 0}, /* Side 4 nodes -- triangle */ - {4, 5, 6, 13, 14, 15, 0, 0, 0} /* Side 5 nodes -- triangle */ - }; - - /* hex */ - static int hex_table[6][9] = { - {1, 2, 6, 5, 9, 14, 17, 13, 26}, /* side 1 */ - {2, 3, 7, 6, 10, 15, 18, 14, 25}, /* side 2 */ - {3, 4, 8, 7, 11, 16, 19, 15, 27}, /* side 3 */ - {1, 5, 8, 4, 13, 20, 16, 12, 24}, /* side 4 */ - {1, 4, 3, 2, 12, 11, 10, 9, 22}, /* side 5 */ - {5, 6, 7, 8, 17, 18, 19, 20, 23} /* side 6 */ - }; - - /* hex 16 -- localization element */ - static int hex16_table[6][8] = { - {1, 2, 6, 5, 9, 13, 0, 0}, /* side 1 -- 6 node quad */ - {2, 3, 7, 6, 10, 14, 0, 0}, /* side 2 -- 6 node quad */ - {3, 4, 8, 7, 11, 15, 0, 0}, /* side 3 -- 6 node quad */ - {4, 1, 5, 8, 12, 16, 0, 0}, /* side 4 -- 6 node quad */ - {1, 4, 3, 2, 12, 11, 10, 9}, /* side 5 -- 8 node quad */ - {5, 6, 7, 8, 13, 14, 15, 16} /* side 6 -- 8 node quad */ - }; - - /* pyramid */ - static int pyramid_table[5][9] = { - {1, 2, 5, 0, 6, 11, 10, 0, 15}, /* side 1 (tri) */ - {2, 3, 5, 0, 7, 12, 11, 0, 16}, /* side 2 (tri) */ - {3, 4, 5, 0, 8, 13, 12, 0, 17}, /* side 3 (tri) */ - {1, 5, 4, 0, 10, 13, 9, 0, 18}, /* side 4 (tri) */ - {1, 4, 3, 2, 9, 8, 7, 6, 14} /* side 5 (quad) */ - }; char errmsg[MAX_ERR_LENGTH]; @@ -621,6 +496,12 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid } case EX_EL_TRIANGLE: { if (ndim == 2) { /* 2d TRIs */ + static const int tri_table[3][3] = { + {1, 2, 4}, /* side 1 */ + {2, 3, 5}, /* side 2 */ + {3, 1, 6} /* side 3 */ + }; + if (check_valid_side(side_num, 3, "triangle", exoid) != EX_NOERR) { goto cleanup; } @@ -640,6 +521,14 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid goto cleanup; } + static const int tri3_table[5][7] = { + {1, 2, 3, 4, 5, 6, 7}, /* side 1 (face) */ + {3, 2, 1, 6, 5, 4, 7}, /* side 2 (face) */ + {1, 2, 4, 0, 0, 0, 0}, /* side 3 (edge) */ + {2, 3, 5, 0, 0, 0, 0}, /* side 4 (edge) */ + {3, 1, 6, 0, 0, 0, 0} /* side 5 (edge) */ + }; + get_nodes(exoid, side_set_node_list, node_pos, connect, connect_offset + tri3_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos + 1, connect, @@ -707,6 +596,13 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid goto cleanup; } + static const int quad_table[4][3] = { + {1, 2, 5}, /* side 1 */ + {2, 3, 6}, /* side 2 */ + {3, 4, 7}, /* side 3 */ + {4, 1, 8} /* side 4 */ + }; + get_nodes(exoid, side_set_node_list, node_pos + 0, connect, connect_offset + quad_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos + 1, connect, @@ -722,6 +618,15 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid goto cleanup; } + static const int shell_table[6][9] = { + {1, 2, 3, 4, 5, 6, 7, 8, 9}, /* side 1 (face) */ + {1, 4, 3, 2, 8, 7, 6, 5, 9}, /* side 2 (face) */ + {1, 2, 5, 0, 0, 0, 0, 0, 0}, /* side 3 (edge) */ + {2, 3, 6, 0, 0, 0, 0, 0, 0}, /* side 4 (edge) */ + {3, 4, 7, 0, 0, 0, 0, 0, 0}, /* side 5 (edge) */ + {4, 1, 8, 0, 0, 0, 0, 0, 0} /* side 6 (edge) */ + }; + get_nodes(exoid, side_set_node_list, node_pos + 0, connect, connect_offset + shell_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos + 1, connect, @@ -775,6 +680,13 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid goto cleanup; } + static const int tetra_table[4][7] = { + {1, 2, 4, 5, 9, 8, 14}, /* Side 1 nodes */ + {2, 3, 4, 6, 10, 9, 12}, /* Side 2 nodes */ + {1, 4, 3, 8, 10, 7, 13}, /* Side 3 nodes */ + {1, 3, 2, 7, 6, 5, 11} /* Side 4 nodes */ + }; + get_nodes(exoid, side_set_node_list, node_pos + 0, connect, connect_offset + tetra_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos + 1, connect, @@ -802,6 +714,13 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid } if (num_nodes_per_elem == 6 || num_nodes_per_elem == 7) { + static const int wedge6_table[5][4] = { + {1, 2, 5, 4}, /* Side 1 nodes -- quad */ + {2, 3, 6, 5}, /* Side 2 nodes -- quad */ + {1, 4, 6, 3}, /* Side 3 nodes -- quad */ + {1, 3, 2, 0}, /* Side 4 nodes -- triangle */ + {4, 5, 6, 0} /* Side 5 nodes -- triangle */ + }; get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + wedge6_table[side_num][node_off++] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -821,6 +740,14 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid } else if (num_nodes_per_elem == 15 || num_nodes_per_elem == 16) { + static const int wedge15_table[5][8] = { + {1, 2, 5, 4, 7, 11, 13, 10}, /* Side 1 nodes -- quad */ + {2, 3, 6, 5, 8, 12, 14, 11}, /* Side 2 nodes -- quad */ + {1, 4, 6, 3, 10, 15, 12, 9}, /* Side 3 nodes -- quad */ + {1, 3, 2, 9, 8, 7, 0, 0}, /* Side 4 nodes -- triangle */ + {4, 5, 6, 13, 14, 15, 0, 0} /* Side 5 nodes -- triangle */ + }; + get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + wedge15_table[side_num][node_off++] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -850,6 +777,14 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid else if (num_nodes_per_elem == 12) { /* Wedge 12 - 6-node quad faces (0,1,2) and 6-node tri faces (3,4) */ /* All faces (quad or tri) have 6 nodes */ + static const int wedge12_table[5][6] = { + {1, 2, 5, 4, 7, 10}, /* Side 1 nodes -- quad */ + {2, 3, 6, 5, 8, 11}, /* Side 2 nodes -- quad */ + {1, 4, 6, 3, 9, 12}, /* Side 3 nodes -- quad */ + {1, 3, 2, 9, 8, 7}, /* Side 4 nodes -- triangle */ + {4, 5, 6, 10, 11, 12} /* Side 5 nodes -- triangle */ + }; + get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + wedge12_table[side_num][node_off++] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -866,6 +801,14 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid } else if (num_nodes_per_elem == 20) { + static const int wedge20_table[5][9] = { + {1, 2, 5, 4, 7, 11, 13, 10, 20}, /* Side 1 nodes -- quad */ + {2, 3, 6, 5, 8, 12, 14, 11, 18}, /* Side 2 nodes -- quad */ + {1, 4, 6, 3, 10, 15, 12, 9, 19}, /* Side 3 nodes -- quad */ + {1, 3, 2, 9, 8, 7, 16, 0, 0}, /* Side 4 nodes -- triangle */ + {4, 5, 6, 13, 14, 15, 17, 0, 0} /* Side 5 nodes -- triangle */ + }; + get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + wedge20_table[side_num][node_off++] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -894,6 +837,13 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid } } else if (num_nodes_per_elem == 21) { + static const int wedge21_table[5][9] = { + {1, 2, 5, 4, 7, 11, 13, 10, 21}, /* Side 1 nodes -- quad */ + {2, 3, 6, 5, 8, 12, 14, 11, 19}, /* Side 2 nodes -- quad */ + {1, 4, 6, 3, 10, 15, 12, 9, 20}, /* Side 3 nodes -- quad */ + {1, 3, 2, 9, 8, 7, 17, 0, 0}, /* Side 4 nodes -- triangle */ + {4, 5, 6, 13, 14, 15, 18, 0, 0} /* Side 5 nodes -- triangle */ + }; get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + wedge21_table[side_num][node_off++] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -923,6 +873,14 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid /* Wedge 18 - 9-node quad faces (0,1,2) and 6-node tri faces (3,4) */ /* All faces (quad or tri) have at least 6 nodes */ /* This gets nodes 1-6 */ + static const int wedge18_table[5][9] = { + {1, 2, 5, 4, 7, 11, 13, 10, 16}, /* Side 1 nodes -- quad */ + {2, 3, 6, 5, 8, 12, 14, 11, 17}, /* Side 2 nodes -- quad */ + {1, 4, 6, 3, 10, 15, 12, 9, 18}, /* Side 3 nodes -- quad */ + {1, 3, 2, 9, 8, 7, 0, 0, 0}, /* Side 4 nodes -- triangle */ + {4, 5, 6, 13, 14, 15, 0, 0, 0} /* Side 5 nodes -- triangle */ + }; + get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + wedge18_table[side_num][node_off++] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -964,6 +922,14 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid goto cleanup; } + static const int pyramid_table[5][9] = { + {1, 2, 5, 0, 6, 11, 10, 0, 15}, /* side 1 (tri) */ + {2, 3, 5, 0, 7, 12, 11, 0, 16}, /* side 2 (tri) */ + {3, 4, 5, 0, 8, 13, 12, 0, 17}, /* side 3 (tri) */ + {1, 5, 4, 0, 10, 13, 9, 0, 18}, /* side 4 (tri) */ + {1, 4, 3, 2, 9, 8, 7, 6, 14} /* side 5 (quad) */ + }; + get_nodes(exoid, side_set_node_list, node_pos++, connect, connect_offset + pyramid_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos++, connect, @@ -1016,6 +982,15 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid if (num_nodes_per_elem == 16) { /* Localization element -- four 6-node sides and two 8-node sides */ + static const int hex16_table[6][8] = { + {1, 2, 6, 5, 9, 13, 0, 0}, /* side 1 -- 6 node quad */ + {2, 3, 7, 6, 10, 14, 0, 0}, /* side 2 -- 6 node quad */ + {3, 4, 8, 7, 11, 15, 0, 0}, /* side 3 -- 6 node quad */ + {4, 1, 5, 8, 12, 16, 0, 0}, /* side 4 -- 6 node quad */ + {1, 4, 3, 2, 12, 11, 10, 9}, /* side 5 -- 8 node quad */ + {5, 6, 7, 8, 13, 14, 15, 16} /* side 6 -- 8 node quad */ + }; + get_nodes(exoid, side_set_node_list, node_pos + 0, connect, connect_offset + hex16_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos + 1, connect, @@ -1036,6 +1011,15 @@ int ex_get_side_set_node_list(int exoid, ex_entity_id side_set_id, void_int *sid } } else { + static const int hex_table[6][9] = { + {1, 2, 6, 5, 9, 14, 17, 13, 26}, /* side 1 */ + {2, 3, 7, 6, 10, 15, 18, 14, 25}, /* side 2 */ + {3, 4, 8, 7, 11, 16, 19, 15, 27}, /* side 3 */ + {1, 5, 8, 4, 13, 20, 16, 12, 24}, /* side 4 */ + {1, 4, 3, 2, 12, 11, 10, 9, 22}, /* side 5 */ + {5, 6, 7, 8, 17, 18, 19, 20, 23} /* side 6 */ + }; + get_nodes(exoid, side_set_node_list, node_pos + 0, connect, connect_offset + hex_table[side_num][0] - 1); get_nodes(exoid, side_set_node_list, node_pos + 1, connect, diff --git a/packages/seacas/libraries/exodus/src/ex_get_var.c b/packages/seacas/libraries/exodus/src/ex_get_var.c index ee882e682c..8e7f9dd264 100644 --- a/packages/seacas/libraries/exodus/src/ex_get_var.c +++ b/packages/seacas/libraries/exodus/src/ex_get_var.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -68,79 +68,6 @@ error = ex_get_var (idexo, time_step, EX_ELEM_BLOCK, var_index, blk_id, int ex_get_var(int exoid, int time_step, ex_entity_type var_type, int var_index, ex_entity_id obj_id, int64_t num_entry_this_obj, void *var_vals) { - int status; - int varid, obj_id_ndx; - size_t start[2], count[2]; - char errmsg[MAX_ERR_LENGTH]; - - EX_FUNC_ENTER(); - if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) { - EX_FUNC_LEAVE(EX_FATAL); - } - - if (var_type == EX_NODAL) { - /* FIXME: Special case: ignore obj_id, possible large_file complications, - * etc. */ - status = ex__get_nodal_var(exoid, time_step, var_index, num_entry_this_obj, var_vals); - EX_FUNC_LEAVE(status); - } - if (var_type == EX_GLOBAL) { - /* FIXME: Special case: all vars stored in 2-D single array. */ - status = ex__get_glob_vars(exoid, time_step, num_entry_this_obj, var_vals); - EX_FUNC_LEAVE(status); - } - - /* Determine index of obj_id in VAR_ID_EL_BLK array */ - obj_id_ndx = ex__id_lkup(exoid, var_type, obj_id); - if (obj_id_ndx <= 0) { - ex_get_err(NULL, NULL, &status); - - if (status != 0) { - if (status == EX_NULLENTITY) { - snprintf(errmsg, MAX_ERR_LENGTH, - "Warning: no %s variables for NULL block %" PRId64 " in file id %d", - ex_name_of_object(var_type), obj_id, exoid); - ex_err_fn(exoid, __func__, errmsg, EX_NULLENTITY); - EX_FUNC_LEAVE(EX_WARN); - } - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in id variable in file id %d", - ex_name_of_object(var_type), obj_id, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - EX_FUNC_LEAVE(EX_FATAL); - } - } - - /* inquire previously defined variable */ - - if ((status = nc_inq_varid(exoid, ex__name_var_of_object(var_type, var_index, obj_id_ndx), - &varid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate %s %" PRId64 " var %d in file id %d", - ex_name_of_object(var_type), obj_id, var_index, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - EX_FUNC_LEAVE(EX_FATAL); - } - - /* read values of element variable */ - start[0] = --time_step; - start[1] = 0; - - count[0] = 1; - count[1] = num_entry_this_obj; - - if (ex__comp_ws(exoid) == 4) { - status = nc_get_vara_float(exoid, varid, start, count, var_vals); - } - else { - status = nc_get_vara_double(exoid, varid, start, count, var_vals); - } - - if (status != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to get %s %" PRId64 " variable %d in file id %d", - ex_name_of_object(var_type), obj_id, var_index, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - EX_FUNC_LEAVE(EX_FATAL); - } - EX_FUNC_LEAVE(EX_NOERR); + return ex_get_var_multi_time(exoid, var_type, var_index, obj_id, num_entry_this_obj, time_step, + time_step, var_vals); } diff --git a/packages/seacas/libraries/exodus/src/ex_get_var_multi_time.c b/packages/seacas/libraries/exodus/src/ex_get_var_multi_time.c new file mode 100644 index 0000000000..a4735c2916 --- /dev/null +++ b/packages/seacas/libraries/exodus/src/ex_get_var_multi_time.c @@ -0,0 +1,148 @@ +/* + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions + * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with + * NTESS, the U.S. Government retains certain rights in this software. + * + * See packages/seacas/LICENSE for details + */ + +#include "exodusII.h" // for ex_err, ex_name_of_object, etc +#include "exodusII_int.h" // for ex__check_valid_file_id, etc + +/*! +\ingroup ResultsData + +The function ex_get_var() reads the values of the +selected entity variables for a single time step. Memory must be allocated for +the variables values array before this function is invoked. + +Because variables are floating point values, the application +code must declare the array passed to be the appropriate type +(float or double) to match the compute word size passed in +ex_create() or ex_open(). + +In case of an error, ex_get_var() returns a negative +number; a warning will return a positive number. Possible causes of +errors include: + + - data file not properly opened with call to ex_create() or ex_open() + - variable does not exist for the desired block or set. + - invalid block or set. + - no variables of the selected type stored in the file. + - a warning value is returned if no variables of the selected entity type are stored in the file. + +\param[in] exoid exodus file ID returned from a previous call to +ex_create() or ex_open(). + +\param[in] var_type block/variable type node, edge/face/element block, or + node/edge/face/side/element set of type ex_entity_type. +\param[in] var_index variable index; 1-based +\param[in] obj_id object id, see ex_get_ids() +\param[in] num_entry_this_obj The number of entities in this object stored in the database. +\param[in] beg_time_step The first time step to access variable data from. 1-based. +\param[in] end_time_step The last time step to access variable data from. 1-based. + +\param[out] var_vals Returned array of num_entry_this_obj variable values + for the time_step'th time step. + +The following is an example code segment that reads the 10th element +variable for element block with id 100 over all 10 time steps. There +are 'num_elements_this_block' elements in element block 100. + +~~~{.c} +int num_elements_this_block, error, time_step; +int var_index = 10; +int blk_id = 100; +int num_time_step = 10; +int num_variables; +float *var_values; + +var_values = (float *) calloc(num_elements_this_block * num_time_step, sizeof(float)); +error = ex_get_var_multi_time (idexo, EX_ELEM_BLOCK, var_index, blk_id, + num_elements_this_block, 1, num_time_step, var_values); +~~~ + + */ + +int ex_get_var_multi_time(int exoid, ex_entity_type var_type, int var_index, ex_entity_id obj_id, + int64_t num_entry_this_obj, int beg_time_step, int end_time_step, + void *var_vals) +{ + int status; + int varid, obj_id_ndx; + size_t start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + EX_FUNC_ENTER(); + if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) { + EX_FUNC_LEAVE(EX_FATAL); + } + + if (var_type == EX_NODAL) { + /* FIXME: Special case: ignore obj_id, possible large_file complications, + * etc. */ + status = ex__get_nodal_var_multi_time(exoid, var_index, num_entry_this_obj, beg_time_step, + end_time_step, var_vals); + EX_FUNC_LEAVE(status); + } + if (var_type == EX_GLOBAL) { + /* FIXME: Special case: all vars stored in 2-D single array. */ + status = ex__get_glob_vars_multi_time(exoid, num_entry_this_obj, beg_time_step, end_time_step, + var_vals); + EX_FUNC_LEAVE(status); + } + + /* Determine index of obj_id in VAR_ID_EL_BLK array */ + obj_id_ndx = ex__id_lkup(exoid, var_type, obj_id); + if (obj_id_ndx <= 0) { + ex_get_err(NULL, NULL, &status); + + if (status != 0) { + if (status == EX_NULLENTITY) { + snprintf(errmsg, MAX_ERR_LENGTH, + "Warning: no %s variables for NULL block %" PRId64 " in file id %d", + ex_name_of_object(var_type), obj_id, exoid); + ex_err_fn(exoid, __func__, errmsg, EX_NULLENTITY); + EX_FUNC_LEAVE(EX_WARN); + } + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate %s id %" PRId64 " in id variable in file id %d", + ex_name_of_object(var_type), obj_id, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + } + + /* inquire previously defined variable */ + + if ((status = nc_inq_varid(exoid, ex__name_var_of_object(var_type, var_index, obj_id_ndx), + &varid)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate %s %" PRId64 " var %d in file id %d", + ex_name_of_object(var_type), obj_id, var_index, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + /* read values of element variable */ + start[0] = --beg_time_step; + start[1] = 0; + + count[0] = end_time_step - beg_time_step; + count[1] = num_entry_this_obj; + + if (ex__comp_ws(exoid) == 4) { + status = nc_get_vara_float(exoid, varid, start, count, var_vals); + } + else { + status = nc_get_vara_double(exoid, varid, start, count, var_vals); + } + + if (status != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to get %s %" PRId64 " variable %d in file id %d", + ex_name_of_object(var_type), obj_id, var_index, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + EX_FUNC_LEAVE(EX_NOERR); +} diff --git a/packages/seacas/libraries/exodus/src/ex_get_var_time.c b/packages/seacas/libraries/exodus/src/ex_get_var_time.c index c82f2d4f3b..6679eebb59 100644 --- a/packages/seacas/libraries/exodus/src/ex_get_var_time.c +++ b/packages/seacas/libraries/exodus/src/ex_get_var_time.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -48,7 +48,6 @@ int ex_get_var_time(int exoid, ex_entity_type var_type, int var_index, int64_t i int status; int *stat_vals = NULL; size_t numel = 0; - size_t offset; size_t num_obj, i; size_t num_entries_this_obj = 0; size_t start[2], count[2]; @@ -215,7 +214,7 @@ int ex_get_var_time(int exoid, ex_entity_type var_type, int var_index, int64_t i numel += num_entries_this_obj; } } - offset = id - (numel - num_entries_this_obj); + size_t offset = id - (numel - num_entries_this_obj); /* inquire previously defined variable */ if ((status = nc_inq_varid(exoid, ex__name_var_of_object(var_type, var_index, i + 1), &varid)) != diff --git a/packages/seacas/libraries/exodus/src/ex_put_num_map.c b/packages/seacas/libraries/exodus/src/ex_put_num_map.c index 92dac8ebf1..9b82befaee 100644 --- a/packages/seacas/libraries/exodus/src/ex_put_num_map.c +++ b/packages/seacas/libraries/exodus/src/ex_put_num_map.c @@ -117,7 +117,6 @@ int ex_put_num_map(int exoid, ex_entity_type map_type, ex_entity_id map_id, cons ex_err_fn(exoid, __func__, errmsg, status); EX_FUNC_LEAVE(EX_FATAL); } - int num_maps = num_entries; /* Keep track of the total number of maps defined using a counter stored in a linked list keyed by exoid. @@ -126,6 +125,7 @@ int ex_put_num_map(int exoid, ex_entity_type map_type, ex_entity_id map_id, cons */ int cur_num_maps = ex__get_file_item(exoid, ex__get_counter_list(map_type)); if (!overwrite_map) { + int num_maps = num_entries; if (cur_num_maps >= num_maps) { snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: exceeded number of %ss (%d) specified in file id %d", ex_name_of_object(map_type), num_maps, exoid); diff --git a/packages/seacas/libraries/exodus/src/ex_put_var.c b/packages/seacas/libraries/exodus/src/ex_put_var.c index 600be23f9f..2795aac99c 100644 --- a/packages/seacas/libraries/exodus/src/ex_put_var.c +++ b/packages/seacas/libraries/exodus/src/ex_put_var.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -9,163 +9,6 @@ #include "exodusII.h" // for ex_err, etc #include "exodusII_int.h" // for EX_FATAL, etc -static int ex__look_up_var(int exoid, ex_entity_type var_type, int var_index, ex_entity_id obj_id, - const char *VOBJID, const char *VOBJTAB, const char *DNUMOBJ, - const char *DNUMOBJVAR, int *varid) -{ - int status; - int obj_id_ndx; - int dimid, time_dim, numobjdim, dims[2]; - - size_t num_obj; - size_t num_obj_var; - size_t num_entity; - - int *obj_var_truth_tab; - char errmsg[MAX_ERR_LENGTH]; - - if (var_type == EX_ASSEMBLY) { - status = nc_inq_varid(exoid, VAR_ENTITY_ASSEMBLY(obj_id), varid); - if (status != 0) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in %s array in file id %d", - ex_name_of_object(var_type), obj_id, VOBJID, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return (EX_FATAL); - } - obj_id_ndx = obj_id; - } - else if (var_type == EX_BLOB) { - status = nc_inq_varid(exoid, VAR_ENTITY_BLOB(obj_id), varid); - if (status != 0) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in %s array in file id %d", - ex_name_of_object(var_type), obj_id, VOBJID, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return (EX_FATAL); - } - obj_id_ndx = obj_id; - } - else { - /* Determine index of obj_id in VOBJID array */ - obj_id_ndx = ex__id_lkup(exoid, var_type, obj_id); - if (obj_id_ndx <= 0) { - ex_get_err(NULL, NULL, &status); - - if (status != 0) { - if (status == EX_NULLENTITY) { - snprintf(errmsg, MAX_ERR_LENGTH, - "Warning: no variables allowed for NULL block %" PRId64 " in file id %d", obj_id, - exoid); - ex_err_fn(exoid, __func__, errmsg, EX_NULLENTITY); - return (EX_WARN); - } - - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to locate %s id %" PRId64 " in %s array in file id %d", - ex_name_of_object(var_type), obj_id, VOBJID, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return (EX_FATAL); - } - } - } - - if ((status = nc_inq_varid(exoid, ex__name_var_of_object(var_type, var_index, obj_id_ndx), - varid)) != NC_NOERR) { - if (status == NC_ENOTVAR) { /* variable doesn't exist, create it! */ - /* check for the existence of an TNAME variable truth table */ - if (nc_inq_varid(exoid, VOBJTAB, varid) == NC_NOERR) { - /* find out number of TNAMEs and TNAME variables */ - status = ex__get_dimension(exoid, DNUMOBJ, ex_name_of_object(var_type), &num_obj, &dimid, - __func__); - if (status != NC_NOERR) { - return (status); - } - - status = ex__get_dimension(exoid, DNUMOBJVAR, ex_name_of_object(var_type), &num_obj_var, - &dimid, __func__); - if (status != NC_NOERR) { - return (status); - } - - if (!(obj_var_truth_tab = malloc(num_obj * num_obj_var * sizeof(int)))) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to allocate memory for %s variable " - "truth table in file id %d", - ex_name_of_object(var_type), exoid); - ex_err_fn(exoid, __func__, errmsg, EX_MEMFAIL); - return (EX_FATAL); - } - - /* read in the TNAME variable truth table */ - if ((status = nc_get_var_int(exoid, *varid, obj_var_truth_tab)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get truth table from file id %d", - exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return (EX_FATAL); - } - - if (obj_var_truth_tab[num_obj_var * (obj_id_ndx - 1) + var_index - 1] == 0L) { - free(obj_var_truth_tab); - snprintf( - errmsg, MAX_ERR_LENGTH, "ERROR: Invalid %s variable %d, %s %" PRId64 " in file id %d", - ex_name_of_object(var_type), var_index, ex_name_of_object(var_type), obj_id, exoid); - ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); - return (EX_FATAL); - } - free(obj_var_truth_tab); - } - - if ((status = nc_inq_dimid(exoid, DIM_TIME, &time_dim)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate time dimension in file id %d", - exoid); - ex_err_fn(exoid, __func__, errmsg, status); - goto error_ret; /* exit define mode and return */ - } - - ex__get_dimension(exoid, ex__dim_num_entries_in_object(var_type, obj_id_ndx), - ex_name_of_object(var_type), &num_entity, &numobjdim, __func__); - - /* variable doesn't exist so put file into define mode */ - if ((status = nc_redef(exoid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to put file id %d into define mode", exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return (EX_FATAL); - } - - /* define netCDF variable to store TNAME variable values */ - dims[0] = time_dim; - dims[1] = numobjdim; - if ((status = nc_def_var(exoid, ex__name_var_of_object(var_type, var_index, obj_id_ndx), - nc_flt_code(exoid), 2, dims, varid)) != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to define %s variable %d in file id %d", - ex_name_of_object(var_type), var_index, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - goto error_ret; - } - ex__compress_variable(exoid, *varid, 2); - - /* leave define mode */ - if ((status = ex__leavedef(exoid, __func__)) != NC_NOERR) { - return (EX_FATAL); - } - } - else { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate %s variable %s in file id %d", - ex_name_of_object(var_type), ex__name_var_of_object(var_type, var_index, obj_id_ndx), - exoid); - ex_err_fn(exoid, __func__, errmsg, status); - return (EX_FATAL); - } - } - return (EX_NOERR); - -/* Fatal error: exit definition mode and return */ -error_ret: - ex__leavedef(exoid, __func__); - return (EX_FATAL); -} - /*! \ingroup ResultsData writes the values of a single variable of the specified type for a @@ -234,128 +77,6 @@ for (k=1; k <= num_nod_vars; k++) { int ex_put_var(int exoid, int time_step, ex_entity_type var_type, int var_index, ex_entity_id obj_id, int64_t num_entries_this_obj, const void *var_vals) { - int varid; - size_t start[2], count[2]; - int status; - char errmsg[MAX_ERR_LENGTH]; - - EX_FUNC_ENTER(); - - if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) { - EX_FUNC_LEAVE(EX_FATAL); - } - - switch (var_type) { - case EX_GLOBAL: - if (num_entries_this_obj <= 0) { - snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no global variables specified for file id %d", - exoid); - ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); - - EX_FUNC_LEAVE(EX_WARN); - } - - /* inquire previously defined variable */ - if ((status = nc_inq_varid(exoid, VAR_GLO_VAR, &varid)) != NC_NOERR) { - if (status == NC_ENOTVAR) { - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: no global variables defined in file id %d", exoid); - ex_err_fn(exoid, __func__, errmsg, status); - } - else { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to get global variables parameters in file id %d", exoid); - ex_err_fn(exoid, __func__, errmsg, status); - } - EX_FUNC_LEAVE(EX_FATAL); - } - break; - case EX_NODAL: - status = ex__put_nodal_var(exoid, time_step, var_index, num_entries_this_obj, var_vals); - EX_FUNC_LEAVE(status); - break; - case EX_ASSEMBLY: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, "", VAR_ASSEMBLY_TAB, - DIM_NUM_ASSEMBLY, DIM_NUM_ASSEMBLY_VAR, &varid); - break; - case EX_BLOB: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, "", VAR_BLOB_TAB, DIM_NUM_BLOB, - DIM_NUM_BLOB_VAR, &varid); - break; - case EX_EDGE_BLOCK: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ID_ED_BLK, VAR_EBLK_TAB, - DIM_NUM_ED_BLK, DIM_NUM_EDG_VAR, &varid); - break; - case EX_FACE_BLOCK: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ID_FA_BLK, VAR_FBLK_TAB, - DIM_NUM_FA_BLK, DIM_NUM_FAC_VAR, &varid); - break; - case EX_ELEM_BLOCK: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ID_EL_BLK, VAR_ELEM_TAB, - DIM_NUM_EL_BLK, DIM_NUM_ELE_VAR, &varid); - break; - case EX_NODE_SET: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_NS_IDS, VAR_NSET_TAB, - DIM_NUM_NS, DIM_NUM_NSET_VAR, &varid); - break; - case EX_EDGE_SET: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ES_IDS, VAR_ESET_TAB, - DIM_NUM_ES, DIM_NUM_ESET_VAR, &varid); - break; - case EX_FACE_SET: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_FS_IDS, VAR_FSET_TAB, - DIM_NUM_FS, DIM_NUM_FSET_VAR, &varid); - break; - case EX_SIDE_SET: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_SS_IDS, VAR_SSET_TAB, - DIM_NUM_SS, DIM_NUM_SSET_VAR, &varid); - break; - case EX_ELEM_SET: - status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ELS_IDS, VAR_ELSET_TAB, - DIM_NUM_ELS, DIM_NUM_ELSET_VAR, &varid); - break; - default: - snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: invalid variable type (%d) specified for file id %d", - var_type, exoid); - ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); - EX_FUNC_LEAVE(EX_FATAL); - } - - if (status != EX_NOERR) { - EX_FUNC_LEAVE(status); - } - - /* store element variable values */ - start[0] = time_step - 1; - start[1] = 0; - - if (var_type == EX_GLOBAL) { - /* global variables may be written - * - all at once (by setting var_index to 1 and num_entries_this_obj to - * num_glob, or - * - one at a time (by setting var_index to the desired index and - * num_entries_this_obj to 1. - */ - count[0] = var_index; - } - else { - count[0] = 1; - } - count[1] = num_entries_this_obj; - - if (ex__comp_ws(exoid) == 4) { - status = nc_put_vara_float(exoid, varid, start, count, var_vals); - } - else { - status = nc_put_vara_double(exoid, varid, start, count, var_vals); - } - - if (status != NC_NOERR) { - snprintf(errmsg, MAX_ERR_LENGTH, - "ERROR: failed to store %s %" PRId64 " variable %d at step %d in file id %d", - ex_name_of_object(var_type), obj_id, var_index, time_step, exoid); - ex_err_fn(exoid, __func__, errmsg, status); - EX_FUNC_LEAVE(EX_FATAL); - } - - EX_FUNC_LEAVE(EX_NOERR); + return ex_put_var_multi_time(exoid, var_type, var_index, obj_id, num_entries_this_obj, time_step, + time_step, var_vals); } diff --git a/packages/seacas/libraries/exodus/src/ex_put_var_multi_time.c b/packages/seacas/libraries/exodus/src/ex_put_var_multi_time.c new file mode 100644 index 0000000000..7d08241b9a --- /dev/null +++ b/packages/seacas/libraries/exodus/src/ex_put_var_multi_time.c @@ -0,0 +1,365 @@ +/* + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions + * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with + * NTESS, the U.S. Government retains certain rights in this software. + * + * See packages/seacas/LICENSE for details + */ + +#include "exodusII.h" // for ex_err, etc +#include "exodusII_int.h" // for EX_FATAL, etc + +static int ex__look_up_var(int exoid, ex_entity_type var_type, int var_index, ex_entity_id obj_id, + const char *VOBJID, const char *VOBJTAB, const char *DNUMOBJ, + const char *DNUMOBJVAR, int *varid) +{ + int status; + int obj_id_ndx; + int dimid, time_dim, numobjdim, dims[2]; + + size_t num_obj; + size_t num_obj_var; + size_t num_entity; + + int *obj_var_truth_tab; + char errmsg[MAX_ERR_LENGTH]; + + if (var_type == EX_ASSEMBLY) { + status = nc_inq_varid(exoid, VAR_ENTITY_ASSEMBLY(obj_id), varid); + if (status != 0) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate %s id %" PRId64 " in %s array in file id %d", + ex_name_of_object(var_type), obj_id, VOBJID, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return (EX_FATAL); + } + obj_id_ndx = obj_id; + } + else if (var_type == EX_BLOB) { + status = nc_inq_varid(exoid, VAR_ENTITY_BLOB(obj_id), varid); + if (status != 0) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate %s id %" PRId64 " in %s array in file id %d", + ex_name_of_object(var_type), obj_id, VOBJID, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return (EX_FATAL); + } + obj_id_ndx = obj_id; + } + else { + /* Determine index of obj_id in VOBJID array */ + obj_id_ndx = ex__id_lkup(exoid, var_type, obj_id); + if (obj_id_ndx <= 0) { + ex_get_err(NULL, NULL, &status); + + if (status != 0) { + if (status == EX_NULLENTITY) { + snprintf(errmsg, MAX_ERR_LENGTH, + "Warning: no variables allowed for NULL block %" PRId64 " in file id %d", obj_id, + exoid); + ex_err_fn(exoid, __func__, errmsg, EX_NULLENTITY); + return (EX_WARN); + } + + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to locate %s id %" PRId64 " in %s array in file id %d", + ex_name_of_object(var_type), obj_id, VOBJID, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return (EX_FATAL); + } + } + } + + if ((status = nc_inq_varid(exoid, ex__name_var_of_object(var_type, var_index, obj_id_ndx), + varid)) != NC_NOERR) { + if (status == NC_ENOTVAR) { /* variable doesn't exist, create it! */ + /* check for the existence of an TNAME variable truth table */ + if (nc_inq_varid(exoid, VOBJTAB, varid) == NC_NOERR) { + /* find out number of TNAMEs and TNAME variables */ + status = ex__get_dimension(exoid, DNUMOBJ, ex_name_of_object(var_type), &num_obj, &dimid, + __func__); + if (status != NC_NOERR) { + return (status); + } + + status = ex__get_dimension(exoid, DNUMOBJVAR, ex_name_of_object(var_type), &num_obj_var, + &dimid, __func__); + if (status != NC_NOERR) { + return (status); + } + + if (!(obj_var_truth_tab = malloc(num_obj * num_obj_var * sizeof(int)))) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to allocate memory for %s variable " + "truth table in file id %d", + ex_name_of_object(var_type), exoid); + ex_err_fn(exoid, __func__, errmsg, EX_MEMFAIL); + return (EX_FATAL); + } + + /* read in the TNAME variable truth table */ + if ((status = nc_get_var_int(exoid, *varid, obj_var_truth_tab)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to get truth table from file id %d", + exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return (EX_FATAL); + } + + if (obj_var_truth_tab[num_obj_var * (obj_id_ndx - 1) + var_index - 1] == 0L) { + free(obj_var_truth_tab); + snprintf( + errmsg, MAX_ERR_LENGTH, "ERROR: Invalid %s variable %d, %s %" PRId64 " in file id %d", + ex_name_of_object(var_type), var_index, ex_name_of_object(var_type), obj_id, exoid); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + return (EX_FATAL); + } + free(obj_var_truth_tab); + } + + if ((status = nc_inq_dimid(exoid, DIM_TIME, &time_dim)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate time dimension in file id %d", + exoid); + ex_err_fn(exoid, __func__, errmsg, status); + goto error_ret; /* exit define mode and return */ + } + + ex__get_dimension(exoid, ex__dim_num_entries_in_object(var_type, obj_id_ndx), + ex_name_of_object(var_type), &num_entity, &numobjdim, __func__); + + /* variable doesn't exist so put file into define mode */ + if ((status = nc_redef(exoid)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to put file id %d into define mode", exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return (EX_FATAL); + } + + /* define netCDF variable to store TNAME variable values */ + dims[0] = time_dim; + dims[1] = numobjdim; + if ((status = nc_def_var(exoid, ex__name_var_of_object(var_type, var_index, obj_id_ndx), + nc_flt_code(exoid), 2, dims, varid)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to define %s variable %d in file id %d", + ex_name_of_object(var_type), var_index, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + goto error_ret; + } + ex__compress_variable(exoid, *varid, 2); + + /* leave define mode */ + if ((status = ex__leavedef(exoid, __func__)) != NC_NOERR) { + return (EX_FATAL); + } + } + else { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate %s variable %s in file id %d", + ex_name_of_object(var_type), ex__name_var_of_object(var_type, var_index, obj_id_ndx), + exoid); + ex_err_fn(exoid, __func__, errmsg, status); + return (EX_FATAL); + } + } + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + ex__leavedef(exoid, __func__); + return (EX_FATAL); +} + +/*! +\ingroup ResultsData +writes the values of a single variable of the specified type for a +single time step. The function ex_put_variable_param() must be invoked +before this call is made. + +Because variables are floating point values, the application +code must declare the array passed to be the appropriate type +(float or double) to match the compute word size passed in +ex_create() or ex_open(). + +\return In case of an error, ex_put_var() returns a negative number; a +warning will return a positive number. Possible causes of errors +include: + - data file not properly opened with call to ex_create() or ex_open() + - data file opened for read only. + - data file not initialized properly with call to ex_put_init(). + - ex_put_variable_param() not called previously specifying the number of +variables. + +\param[in] exoid +exodus file ID returned from a previous call to +ex_create() or ex_open(). + +\param[in] var_type +type (edge block, face block, edge set, ... ) + +\param[in] var_index +The index of the variable. The first variable has an index of 1. + +\param[in] obj_id +entity block/set id (ignored for global and nodal variables) + +\param[in] num_entries_this_obj +The number of items in this block/set + +\param[in] beg_time_step +The beginning time step number, as described under ex_put_time(). This +is essentially a counter that is incremented when results variables +are output. The first time step is 1. + +\param[in] end_time_step +The last step number to put values. The first time step is 1. + +\param[in] var_vals +Array of `num_entries_this_obj` values of the `var_index`-th variable for the requested time +step(s). + +As an example, the following code segment writes all the nodal +variables for a single time step: + +~~~{.c} +int num_nod_vars, num_nodes, error, exoid, beg_time_step, end_time_step; +float *nodal_var_vals; + +\comment{write nodal variables} +nodal_var_vals = (float *) calloc(num_nodes*num_steps, sizeof(float)); +for (k=1; k <= num_nod_vars; k++) { + for (t=1, t < num_steps; t++) { + for (j=0; j < num_nodes; j++) { + \comment{application code fills in this array} + nodal_var_vals[j] = 10.0; + } + } + error = ex_put_var(exoid, EX_NODAL, 0, k, num_nodes, + 1, 1+num_steps, nodal_var_vals); +} +~~~ + */ + +int ex_put_var_multi_time(int exoid, ex_entity_type var_type, int var_index, ex_entity_id obj_id, + int64_t num_entries_this_obj, int beg_time_step, int end_time_step, + const void *var_vals) +{ + int varid; + size_t start[2], count[2]; + int status; + char errmsg[MAX_ERR_LENGTH]; + + EX_FUNC_ENTER(); + + if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) { + EX_FUNC_LEAVE(EX_FATAL); + } + + switch (var_type) { + case EX_GLOBAL: + if (num_entries_this_obj <= 0) { + snprintf(errmsg, MAX_ERR_LENGTH, "Warning: no global variables specified for file id %d", + exoid); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + + EX_FUNC_LEAVE(EX_WARN); + } + + /* inquire previously defined variable */ + if ((status = nc_inq_varid(exoid, VAR_GLO_VAR, &varid)) != NC_NOERR) { + if (status == NC_ENOTVAR) { + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: no global variables defined in file id %d", exoid); + ex_err_fn(exoid, __func__, errmsg, status); + } + else { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to get global variables parameters in file id %d", exoid); + ex_err_fn(exoid, __func__, errmsg, status); + } + EX_FUNC_LEAVE(EX_FATAL); + } + break; + case EX_NODAL: + status = ex__put_nodal_var_time(exoid, var_index, num_entries_this_obj, beg_time_step, + end_time_step, var_vals); + EX_FUNC_LEAVE(status); + case EX_ASSEMBLY: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, "", VAR_ASSEMBLY_TAB, + DIM_NUM_ASSEMBLY, DIM_NUM_ASSEMBLY_VAR, &varid); + break; + case EX_BLOB: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, "", VAR_BLOB_TAB, DIM_NUM_BLOB, + DIM_NUM_BLOB_VAR, &varid); + break; + case EX_EDGE_BLOCK: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ID_ED_BLK, VAR_EBLK_TAB, + DIM_NUM_ED_BLK, DIM_NUM_EDG_VAR, &varid); + break; + case EX_FACE_BLOCK: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ID_FA_BLK, VAR_FBLK_TAB, + DIM_NUM_FA_BLK, DIM_NUM_FAC_VAR, &varid); + break; + case EX_ELEM_BLOCK: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ID_EL_BLK, VAR_ELEM_TAB, + DIM_NUM_EL_BLK, DIM_NUM_ELE_VAR, &varid); + break; + case EX_NODE_SET: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_NS_IDS, VAR_NSET_TAB, + DIM_NUM_NS, DIM_NUM_NSET_VAR, &varid); + break; + case EX_EDGE_SET: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ES_IDS, VAR_ESET_TAB, + DIM_NUM_ES, DIM_NUM_ESET_VAR, &varid); + break; + case EX_FACE_SET: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_FS_IDS, VAR_FSET_TAB, + DIM_NUM_FS, DIM_NUM_FSET_VAR, &varid); + break; + case EX_SIDE_SET: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_SS_IDS, VAR_SSET_TAB, + DIM_NUM_SS, DIM_NUM_SSET_VAR, &varid); + break; + case EX_ELEM_SET: + status = ex__look_up_var(exoid, var_type, var_index, obj_id, VAR_ELS_IDS, VAR_ELSET_TAB, + DIM_NUM_ELS, DIM_NUM_ELSET_VAR, &varid); + break; + default: + snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: invalid variable type (%d) specified for file id %d", + var_type, exoid); + ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM); + EX_FUNC_LEAVE(EX_FATAL); + } + + if (status != EX_NOERR) { + EX_FUNC_LEAVE(status); + } + + /* store element variable values */ + start[0] = beg_time_step - 1; + start[1] = 0; + + if (var_type == EX_GLOBAL) { + /* global variables may be written + * - all at once (by setting var_index to 1 and num_entries_this_obj to + * num_glob, or + * - one at a time (by setting var_index to the desired index and + * num_entries_this_obj to 1. + */ + start[1] = var_index - 1; + } + count[0] = end_time_step - beg_time_step + 1; + count[1] = num_entries_this_obj; + + if (ex__comp_ws(exoid) == 4) { + status = nc_put_vara_float(exoid, varid, start, count, var_vals); + } + else { + status = nc_put_vara_double(exoid, varid, start, count, var_vals); + } + + if (status != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to store %s %" PRId64 " variable %d at steps %d to %d in file id %d", + ex_name_of_object(var_type), obj_id, var_index, beg_time_step, end_time_step, exoid); + ex_err_fn(exoid, __func__, errmsg, status); + EX_FUNC_LEAVE(EX_FATAL); + } + + EX_FUNC_LEAVE(EX_NOERR); +} diff --git a/packages/seacas/libraries/exodus/src/ex_put_variable_param.c b/packages/seacas/libraries/exodus/src/ex_put_variable_param.c index d23e8dbb38..f284899958 100644 --- a/packages/seacas/libraries/exodus/src/ex_put_variable_param.c +++ b/packages/seacas/libraries/exodus/src/ex_put_variable_param.c @@ -18,7 +18,6 @@ static int ex_prepare_result_var(int exoid, int num_vars, char *type_name, char int varid; int dims[2]; int dim_str_name; - int fill = NC_FILL_CHAR; char errmsg[MAX_ERR_LENGTH]; @@ -62,6 +61,7 @@ static int ex_prepare_result_var(int exoid, int num_vars, char *type_name, char } ex__set_compact_storage(exoid, varid); #if defined(EX_CAN_USE_NC_DEF_VAR_FILL) + int fill = NC_FILL_CHAR; nc_def_var_fill(exoid, varid, 0, &fill); #endif return (EX_NOERR); diff --git a/packages/seacas/libraries/exodus/src/ex_utils.c b/packages/seacas/libraries/exodus/src/ex_utils.c index e92cffdea5..5e8f3c36b1 100644 --- a/packages/seacas/libraries/exodus/src/ex_utils.c +++ b/packages/seacas/libraries/exodus/src/ex_utils.c @@ -1099,20 +1099,20 @@ void ex__rm_stat_ptr(int exoid, struct ex__obj_stats **obj_ptr) struct ex__obj_stats *tmp_ptr = *obj_ptr; struct ex__obj_stats *last_head_list_ptr = *obj_ptr; /* save last head pointer */ - while (tmp_ptr) /* Walk linked list of file ids/vals */ + while (tmp_ptr) /* Walk linked list of file ids/vals */ { - if (exoid == tmp_ptr->exoid) /* linear search for exodus file id */ + if (exoid == tmp_ptr->exoid) /* linear search for exodus file id */ { - if (tmp_ptr == *obj_ptr) { /* Are we at the head of the list? */ - *obj_ptr = (*obj_ptr)->next; /* yes, reset ptr to head of list */ + if (tmp_ptr == *obj_ptr) { /* Are we at the head of the list? */ + *obj_ptr = (*obj_ptr)->next; /* yes, reset ptr to head of list */ } - else { /* no, remove this record from chain*/ + else { /* no, remove this record from chain*/ last_head_list_ptr->next = tmp_ptr->next; } free(tmp_ptr->id_vals); /* free up memory */ free(tmp_ptr->stat_vals); free(tmp_ptr); - break; /* Quit if found */ + break; /* Quit if found */ } last_head_list_ptr = tmp_ptr; /* save last head pointer */ tmp_ptr = tmp_ptr->next; /* Loop back if not */ @@ -1199,12 +1199,12 @@ struct ex__list_item **ex__get_counter_list(ex_entity_type obj_type) int ex__inc_file_item(int exoid, /* file id */ struct ex__list_item **list_ptr) /* ptr to ptr to list_item */ { - struct ex__list_item *tlist_ptr = *list_ptr; /* use temp list ptr to walk linked list */ - while (tlist_ptr) { /* Walk linked list of file ids/vals */ - if (exoid == tlist_ptr->exo_id) { /* linear search for exodus file id */ - break; /* Quit if found */ + struct ex__list_item *tlist_ptr = *list_ptr; /* use temp list ptr to walk linked list */ + while (tlist_ptr) { /* Walk linked list of file ids/vals */ + if (exoid == tlist_ptr->exo_id) { /* linear search for exodus file id */ + break; /* Quit if found */ } - tlist_ptr = tlist_ptr->next; /* Loop back if not */ + tlist_ptr = tlist_ptr->next; /* Loop back if not */ } if (!tlist_ptr) { /* ptr NULL? */ @@ -1257,7 +1257,7 @@ int ex__get_file_item(int exoid, /* file id */ if (exoid == tlist_ptr->exo_id) { /* linear search for exodus file id */ break; /* Quit if found */ } - tlist_ptr = tlist_ptr->next; /* Loop back if not */ + tlist_ptr = tlist_ptr->next; /* Loop back if not */ } if (!tlist_ptr) { /* ptr NULL? */ @@ -1304,11 +1304,11 @@ void ex__rm_file_item(int exoid, /* file id */ if (tlist_ptr == *list_ptr) { /* Are we at the head of the list? */ *list_ptr = (*list_ptr)->next; /* yes, reset ptr to head of list */ } - else { /* no, remove this record from chain*/ + else { /* no, remove this record from chain*/ last_head_list_ptr->next = tlist_ptr->next; } - free(tlist_ptr); /* free up memory */ - break; /* Quit if found */ + free(tlist_ptr); /* free up memory */ + break; /* Quit if found */ } last_head_list_ptr = tlist_ptr; /* save last head pointer */ tlist_ptr = tlist_ptr->next; /* Loop back if not */ @@ -1569,7 +1569,7 @@ static void ex_int_iisort64(int64_t v[], int64_t iv[], int64_t N) * \internal * The following 'indexed qsort' routine is modified from Sedgewicks * algorithm It selects the pivot based on the median of the left, - * right, and center values to try to avoid degenerate cases ocurring + * right, and center values to try to avoid degenerate cases occurring * when a single value is chosen. It performs a quicksort on * intervals down to the #EX_QSORT_CUTOFF size and then performs a final * insertion sort on the almost sorted final array. Based on data in diff --git a/packages/seacas/libraries/exodus/test/testwt-results.c b/packages/seacas/libraries/exodus/test/testwt-results.c index a4651324dc..6277f3d71b 100644 --- a/packages/seacas/libraries/exodus/test/testwt-results.c +++ b/packages/seacas/libraries/exodus/test/testwt-results.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -16,7 +16,7 @@ One of the ultimate goals is to make per-timestep output of results data faster since do not need the mesh definition bulk data - (coordinates, connectivty, ...) for each step + (coordinates, connectivity, ...) for each step EXPERIMENTAL -- DO NOT USE THIS CAPABILITY/CONCEPT FOR PRODUCTION WORK *****************************************************************************/ diff --git a/packages/seacas/libraries/ioss/CustomDoxygen.css b/packages/seacas/libraries/ioss/CustomDoxygen.css new file mode 100644 index 0000000000..0d96812b42 --- /dev/null +++ b/packages/seacas/libraries/ioss/CustomDoxygen.css @@ -0,0 +1,619 @@ + +/* function descriptions */ +.memtitle { + padding: 8px; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url(); + background-repeat: repeat-x; + background-color: #fff; + line-height: 1.25; + font-weight: 600; + float: left; +} + +dt { + font-weight: 600; +} + +p.reference, p.definition { + font: 400 14px/22px -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;; + margin-top: 0px; + margin-bottom: 5px; + padding-top: 8px; + border-top: 1px solid #eee; +} + +/* parameter names */ +.params .paramname, .retval .paramname, .tparams .paramname { + font-weight: 600; + vertical-align: top; +} + +/* parameter data types */ +.paramtype { + white-space: nowrap; + color: #008141; +} + +/* headers */ +h1, h2, h3, h4, h5, h6 { + font-weight: 600; +} + +/* parameter names */ +.paramname { + color: #db0303; + white-space: nowrap; +} + +/* overall style */ +body, table, div, p, dl { + font-style: normal; + font-variant-ligatures: normal; + font-variant-caps: normal; + font-variant-numeric: normal; + font-variant-east-asian: normal; + font-weight: 500; + font-stretch: normal; + font-size: 14px; + line-height: 22px; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} + +/* project name */ +#projectname { + /* markdown font */ + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + margin: 0; + padding: 2px 0; +} +/* title area */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} + +h2.groupheader { + border-bottom: 1px solid #eee; + color: #000; + font-size: 150%; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + margin-top: 1em; + padding-top: 12px; + padding-bottom: 4px; + width: 100%; +} + +/* function description text box */ +.memdoc, dl.reflist dd { + + border-bottom: none; + border-left: none; + border-right: none; + padding: 0px 10px 0px 10px; + background-color: #FFF; + border-top-width: 0; + background-image: none; + background-repeat: repeat-x; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0) 5px 5px 5px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0); +} + +/* function prototype text box */ +.memproto, dl.reflist dt { + border-bottom: 1px solid #999; + border-top: 1px solid #999; + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 0px 0 0px 0; + color: #000; + font-weight: bold; + text-shadow: none; + background-color: #f9f9f9; + box-shadow: none; + border-top-right-radius: 4px; + -moz-box-shadow: none; + -moz-border-radius-topright: 4px; + -webkit-box-shadow: none; + -webkit-border-top-right-radius: 4px; +} + +/* function prototype */ +.memname td { + + vertical-align: bottom; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + +} + + +/* icon for each data type */ +.icon { + background-color: #026ea1; +} +/* arrows for treenav */ + +.arrow { + color: #09A716; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} +/* colors and fonts for description pages */ + +table, div, p, dl { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: black; +} + +.sm li, .sm a { + position: relative; + color: black; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: normal; + color: #FFF; + min-height: 100%; + overflow-x: hidden; + background: #fff; +} + +/* file member function descriptions */ +.memberdecls td, .fieldtable tr { + + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 501; +} + +/* function descriptor */ +td.mdescLeft, td.mdescRight { + padding: 0 8px 4px 8px; + color: #000; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 400; +} + +/* headers for #include descriptions */ +tt, code, kbd, samp { + display: inline-block; + direction: ltr; + background-color: #f8f8f8; + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* list for file members */ +div.contents { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* links to a class or struct on the class list page */ +a.el { + font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; + font-weight: 550; +} + +/* header dividers */ +hr { + height: 0; + border: none; + border-top: 1px solid #eee; +} + +#side-nav { + padding: 0 0 0 0; + margin: 0; + display: block; + position: absolute; + left: 0; + width: 250; +} +/* nav tree arrow symbol */ + +#nav-sync img { + opacity: 0; +} +#nav-sync img:hover { + opacity: 0.9; +} +/* The main page button */ + +.sm-dox>li:first-child>a, .sm-dox>li:first-child> :not(ul) a { + padding-right: 12px; +} +/* content of for all class members list */ + +#doc-content { + overflow: auto; + display: block; + padding: 0; + margin: 0; + margin-left: 0; + -webkit-overflow-scrolling: touch; + background-color: #FFF; +} +/* label for which tree menu you are on (displays in the doc menu */ + +.title { + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-weight: 600; + font-size: 150%; + margin: -2px 0 0 2px; + background-color: white; +} +/* title for each section (class List, Class index) */ + +#titlearea { + padding: 0; + margin: 0; + width: 100%; + border-bottom: none; +} +/* title for each section (class List, Class index) */ + +div.headertitle { + padding: none; + background-color: white; +} +/* actual header for each section */ + +div.header { + background-image: none; + background-repeat: repeat-x; + background-color: #FFF; + margin: 0; + border-bottom: 1px solid #eee; +} +/* for class and function lists */ + +table.directory { + font-style: normal; + font-variant-caps: normal; + font-weight: normal; + font-stretch: normal; + line-height: normal; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; + font-size-adjust: none; + font-kerning: auto; + font-optical-sizing: auto; + font-variant-alternates: normal; + font-variant-east-asian: normal; + font-variant-ligatures: normal; + font-variant-numeric: normal; + font-variant-position: normal; + font-language-override: normal; + font-feature-settings: normal; + font-variation-settings: normal; +} +/* main page, classes, files banner */ + +.sm-dox { + padding: 0 0; + background-image: none; + line-height: 36px; + background-color: #7fbdff; +} +/* item list on botton left */ + +.navpath li.navelem a { + height: 32px; + display: block; + text-decoration: none; + outline: none; + color: #FFF; + font-family: 'Lucida Grande', Geneva, Helvetica, Arial, sans-serif; + text-shadow: none; + text-decoration: none; +} +.navpath li { + list-style-type: none; + float: left; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #364D7C; +} +/* top menu, Classes button */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:active, .sm-dox a.highlighted, .sm-dox a.highlighted { + padding-right: 12px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + background-color: #7fbdff; + color: #b8b8b8; + padding-left: 12px; +} + +.sm-dox a.has-submenu { + padding-right: 24px; +} + +.sm a { + display: block; +} +/* top menu, main buttons label */ + +.sm-dox a, .sm-dox a:focus, .sm-dox a:visited, .sm-dox a:visited { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + color: #000; + text-shadow: none; +} +/* hover over class/main page, files buttons */ + +.sm-dox a:hover { + font-family: "Lucida Grande", "Geneva", "Helvetica", Arial, sans-serif; + font-size: 14px; + font-weight: bold; + line-height: 36px; + text-decoration: none; + text-decoration-line: none; + text-decoration-style: solid; + text-decoration-color: currentcolor; + text-shadow: none; + color: #FFF; + outline: 0; + outline-color: currentcolor; + outline-style: none; + outline-width: 0; + background-color: #156ac9; + background-image: none; +} + +.sm-dox ul a:hover { + background-image: none; + background-repeat: repeat-x; + color: white; + background-color: #000; + text-shadow: none; +} + +/* top list items */ + +.sm-dox ul { + color: #FFF; + border-top-color: rgb(187, 187, 187); + border-top-style: solid; + border-top-width: 1px; + border-right-color: rgb(187, 187, 187); + border-right-style: solid; + border-right-width: 1px; + border-bottom-color: rgb(187, 187, 187); + border-bottom-style: solid; + border-bottom-width: 1px; + border-left-color: rgb(187, 187, 187); + border-left-style: solid; + border-left-width: 1px; + border-image-outset: 0; + border-image-repeat: stretch; + border-image-slice: 100%; + border-image-source: none; + border-image-width: 1; + padding: 5px 0; + background: #fff; + background-color: rgb(255, 255, 255); + background-position-x: 0%; + background-position-y: 0%; + background-repeat: repeat; + background-attachment: scroll; + background-image: none; + background-size: auto; + background-origin: padding-box; + background-clip: border-box; + -moz-border-radius: 5px !important; + -webkit-border-radius: 5px; + border-radius: 5px !important; + -moz-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 9px rgba(0, 0, 0, 0.2); +} +.sm-dox ul a:hover { + background-image: none; +} +/* dividers for class/function lists */ + +div.directory { + margin: 10px 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + width: 100%; +} +/* for navigation tree links */ + +#nav-tree .label a { + padding-top: 1px; + padding-right: 1px; + padding-bottom: 1px; + margin-left: 12px; + color: #FFF; + font-weight: 700; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} +/* hovering over tree view items */ + +#nav-tree .label a:hover { + padding-top: 2px; + padding-right: 2px; + padding-bottom: -3px; + margin-left: 12px; + color: #000; + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; + background-color: #FFF +} +/* nav tree labels */ + +#nav-tree .label { + font-weight: 700; + font-family: "Lucida Grande", Geneva, Helvetica, Arial, sans-serif; +} +/* still for the navtree, but not labels */ + +#nav-tree { + padding: 0 0; + background-color: #404040; + font-size: normal; + overflow: auto; + background-image: none; + margin-right: 16px; +} + +span.lineno { + background-color: #f7f7f7; +} + +a { + color: #4d95c4; +} + +span.lineno a { + background-color: #e6e5e5; +} + +div.fragment { + padding: 0 0 1px 0; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #eee; +} + +.permalink { + color: #476092; + font-size: 85%; +} + +/* selected nav tree */ +#nav-tree .selected { + background-image: none; + background-repeat: repeat-x; + color: #fff; + background-color: #000; +} +/* selected nav tree link */ + +#nav-tree .selected a { + background-image: none; + background-repeat: repeat-x; + color: #fff; +} +/* visited nav tree link */ + +#nav-tree .visited a { + background-image: none; + background-repeat: repeat-x; + color: #127FCF; +} +/* bar separator for tree view */ + +.ui-resizable-e { + background-image: none; + background-size: 100%; + background-repeat: repeat-y; + background-attachment: scroll; + cursor: ew-resize; + height: 100%; + right: 0; + top: 0; + width: 0; + background-color: black; +} +/* visited links in general */ + +a:visited { + color: #4d95c4; +} +/* bottom bar */ + +a.code, a.code:visited, a.line, a.line:visited { + color: #4d95c4; +} + +.contents a:visited { + color: #4d95c4; +} + +.navpath ul { + font-size: 11px; + background-image: none; + background-repeat: repeat-x; + background-position: 0 -5px; + height: 30px; + line-height: 30px; + color: #fff; + border: none; + overflow: hidden; + margin: 0; + padding: 0; + background-color: #181818; +} +/* text 'Generated by doxygen' */ + +.navpath li.footer { + list-style-type: none; + float: right; + padding-left: 10px; + padding-right: 15px; + background-image: none; + background-repeat: no-repeat; + background-position: right; + color: #FFF; + font-size: 8pt; +} + +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 400; + src: url("../fonts/RobotoSlab/roboto-slab.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-regular.ttf") format("truetype") +} +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 700; + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot"); + src: url("../fonts/RobotoSlab/roboto-slab-v7-bold.eot?#iefix") format("embedded-opentype"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff2") format("woff2"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.woff") format("woff"), url("../fonts/RobotoSlab/roboto-slab-v7-bold.ttf") format("truetype") +} diff --git a/packages/seacas/libraries/ioss/Doxyfile b/packages/seacas/libraries/ioss/Doxyfile index 70960abf4b..fdda9d803d 100644 --- a/packages/seacas/libraries/ioss/Doxyfile +++ b/packages/seacas/libraries/ioss/Doxyfile @@ -1307,7 +1307,7 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = CustomDoxygen.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note diff --git a/packages/seacas/libraries/ioss/src/Ioss_Assembly.C b/packages/seacas/libraries/ioss/src/Ioss_Assembly.C index 4325e5d7fb..468567a5b6 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Assembly.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Assembly.C @@ -17,7 +17,7 @@ #include namespace { - std::string id_str() { return std::string("id"); } + std::string id_str() { return {"id"}; } void check_is_valid(const Ioss::Assembly *assem, const Ioss::GroupingEntity *member) { // Ensure that `member` is not already a member and that its type matches @@ -147,10 +147,10 @@ int64_t Ioss::Assembly::internal_get_zc_field_data(const Field &field, void **da Ioss::Property Ioss::Assembly::get_implicit_property(const std::string &my_name) const { if (my_name == "member_count") { - return Ioss::Property(my_name, static_cast(m_members.size())); + return {my_name, static_cast(m_members.size())}; } if (my_name == "member_type") { - return Ioss::Property(my_name, static_cast(m_type)); + return {my_name, static_cast(m_type)}; } return Ioss::GroupingEntity::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Assembly.h b/packages/seacas/libraries/ioss/src/Ioss_Assembly.h index 72389918d7..a4d7a039cd 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Assembly.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Assembly.h @@ -51,7 +51,7 @@ namespace Ioss { void remove_members(); size_t member_count() const { return m_members.size(); } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Blob.h b/packages/seacas/libraries/ioss/src/Ioss_Blob.h index 5b97e54cec..d6842a9e7e 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Blob.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Blob.h @@ -39,7 +39,7 @@ namespace Ioss { std::string contains_string() const override { return "Entries"; } EntityType type() const override { return BLOB; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C index ebada1d01e..b6220ef3c6 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.C @@ -47,12 +47,10 @@ namespace { std::vector get_adjacent_blocks(Ioss::Region ®ion, const std::string &surface_list) { - auto selected_surfaces = Ioss::tokenize(surface_list, ","); - std::vector adjacent_blocks; - const Ioss::SideSetContainer &fss = region.get_sidesets(); - for (const auto &fs : fss) { - if (surface_list == "ALL" || std::find(selected_surfaces.begin(), selected_surfaces.end(), - fs->name()) != selected_surfaces.end()) { + std::vector adjacent_blocks; + if (surface_list == "ALL") { + const Ioss::SideSetContainer &fss = region.get_sidesets(); + for (const auto &fs : fss) { // Save a list of all blocks that are adjacent to the surfaces... std::vector blocks; fs->block_membership(blocks); @@ -61,14 +59,65 @@ namespace { } } } + else { + auto selected_surfaces = Ioss::tokenize(surface_list, ","); + for (const auto &surface : selected_surfaces) { + auto *sset = region.get_sideset(surface); + if (sset != nullptr) { + // Save a list of all blocks that are adjacent to the surfaces... + std::vector blocks; + sset->block_membership(blocks); + for (const auto &block : blocks) { + adjacent_blocks.push_back(block); // May have duplicates at this point. + } + } + else { + fmt::print("\nWARNING: Surface '{}' does not exist in this model.\n", surface); + } + } + } + Ioss::Utils::uniquify(adjacent_blocks); return adjacent_blocks; } + template + void get_line_front(Ioss::SideSet *fs, const Ioss::ElementBlock *block, + const std::string &adj_block, Ioss::chain_t &element_chains, + front_t &front) + { + std::vector blocks; + fs->block_membership(blocks); + for (const auto &fs_block : blocks) { + if (fs_block == adj_block) { + // This faceset has some elements that are in `adj_block` -- put those in the `front` + // list. Get list of "sides" in this faceset... + std::vector element_side; + assert(fs->side_block_count() == 1); + const auto *fb = fs->get_block(0); + fb->get_field_data("element_side_raw", element_side); + + // Mark each element so we know it is on the sideset(s) + for (size_t i = 0; i < element_side.size(); i += 2) { + auto element = element_side[i]; + if (block->contains(element)) { + if (element_chains[element - 1] == Ioss::chain_entry_t()) { + int side = static_cast(element_side[i + 1]); // 1-based sides + element_chains[element - 1] = Ioss::chain_entry_t{element, 0}; + front.push_back(std::make_pair(element, side)); + if (debug & 16) { + fmt::print("Putting element {}, side {} in front.\n", element, side); + } + } + } + } + } + } + } + template front_t get_line_front(Ioss::Region ®ion, const std::string &adj_block, - Ioss::chain_t &element_chains, const std::string &surface_list, - INT /*dummy*/) + Ioss::chain_t &element_chains, const std::string &surface_list) { front_t front; @@ -80,38 +129,18 @@ namespace { return front; } - auto selected_surfaces = Ioss::tokenize(surface_list, ","); - // Now find the facesets that have faces on this block... - const Ioss::SideSetContainer &fss = region.get_sidesets(); - for (const auto &fs : fss) { - if (surface_list == "ALL" || std::find(selected_surfaces.begin(), selected_surfaces.end(), - fs->name()) != selected_surfaces.end()) { - std::vector blocks; - fs->block_membership(blocks); - for (const auto &fs_block : blocks) { - if (fs_block == adj_block) { - // This faceset has some elements that are in `adj_block` -- put those in the `front` - // list. Get list of "sides" in this faceset... - std::vector element_side; - assert(fs->side_block_count() == 1); - const auto *fb = fs->get_block(0); - fb->get_field_data("element_side_raw", element_side); - - // Mark each element so we know it is on the sideset(s) - for (size_t i = 0; i < element_side.size(); i += 2) { - auto element = element_side[i]; - if (block->contains(element)) { - if (element_chains[element - 1] == Ioss::chain_entry_t()) { - int side = static_cast(element_side[i + 1]); // 1-based sides - element_chains[element - 1] = Ioss::chain_entry_t{element, 0}; - front.push_back(std::make_pair(element, side)); - if (debug & 16) { - fmt::print("Putting element {}, side {} in front.\n", element, side); - } - } - } - } - } + if (surface_list == "ALL") { + const Ioss::SideSetContainer &fss = region.get_sidesets(); + for (const auto &fs : fss) { + get_line_front(fs, block, adj_block, element_chains, front); + } + } + else { + auto selected_surfaces = Ioss::tokenize(surface_list, ","); + for (const auto &surface : selected_surfaces) { + auto *sset = region.get_sideset(surface); + if (sset != nullptr) { + get_line_front(sset, block, adj_block, element_chains, front); } } } @@ -122,9 +151,9 @@ namespace { connectivity_t &face_connectivity) { for (const auto &face : faces) { - for (int i = 0; i < face.elementCount_; i++) { - auto element = face.element[i] / 10 - offset; - auto side = face.element[i] % 10; // 0-based side + for (const auto &face_element : face.element) { + auto element = face_element / 10 - offset; + auto side = face_element % 10; // 0-based side face_connectivity[element][side] = &face; } } @@ -179,13 +208,18 @@ namespace Ioss { // The `adjacent_blocks` contains the names of all element blocks that are adjacent to the // surface(s) that specify the faces at the 'root' of the lines... std::vector adjacent_blocks = get_adjacent_blocks(region, surface_list); + if (adjacent_blocks.empty()) { + fmt::print("WARNING: No surfaces in the model matched the input surface list ({}).\n\tNo " + "chains will be generated.\n", + surface_list); + } for (const auto &adj_block : adjacent_blocks) { // Get the offset into the element_chains vector... const auto *block = region.get_element_block(adj_block); auto offset = block->get_offset() + 1; auto count = block->entity_count(); - auto front = get_line_front(region, adj_block, element_chains, surface_list, (INT)0); + auto front = get_line_front(region, adj_block, element_chains, surface_list); if (front.empty()) { continue; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.h b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.h index 50339f3522..45912f09d3 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ChainGenerator.h @@ -14,9 +14,9 @@ namespace Ioss { template struct chain_entry_t { - bool operator==(const chain_entry_t &other) { return (element == other.element); } + bool operator==(const chain_entry_t &other) const { return (other.element == element); } int64_t element{}; // Element at root of chain - int link{}; // How far is this element in the chain (1-based) + int link{-1}; // How far is this element in the chain (1-based) }; template using chain_t = std::vector>; diff --git a/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h b/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h index e4f75590d4..b60eb0911f 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h +++ b/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h @@ -24,10 +24,10 @@ namespace Ioss { using IJK_t = std::array; } // namespace Ioss -inline std::string IOSS_SCALAR() { return std::string("scalar"); } -inline std::string IOSS_VECTOR_2D() { return std::string("vector_2d"); } -inline std::string IOSS_VECTOR_3D() { return std::string("vector_3d"); } -inline std::string IOSS_SYM_TENSOR() { return std::string("sym_tensor_33"); } +inline std::string IOSS_SCALAR() { return {"scalar"}; } +inline std::string IOSS_VECTOR_2D() { return {"vector_2d"}; } +inline std::string IOSS_VECTOR_3D() { return {"vector_3d"}; } +inline std::string IOSS_SYM_TENSOR() { return {"sym_tensor_33"}; } #if defined(BUILT_IN_SIERRA) #define SEACAS_HAVE_MPI @@ -55,6 +55,7 @@ inline std::string IOSS_SYM_TENSOR() { return std::string("sym_tensor_33"); } #include using Ioss_MPI_Comm = MPI_Comm; #define IOSS_PAR_UNUSED(x) +#define ADIOS2_USE_MPI 1 #else using Ioss_MPI_Comm = int; #if (__cplusplus >= 201703L) @@ -83,7 +84,7 @@ using Complex = std::complex; using Kokkos_Complex = Kokkos::complex; #endif #else -using Complex = std::complex; +using Complex = std::complex; #ifdef SEACAS_HAVE_KOKKOS using Kokkos_Complex = Kokkos::complex; #endif diff --git a/packages/seacas/libraries/ioss/src/Ioss_CommSet.h b/packages/seacas/libraries/ioss/src/Ioss_CommSet.h index 7c576b3149..48375a668a 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CommSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_CommSet.h @@ -35,7 +35,7 @@ namespace Ioss { std::string contains_string() const override { return "Entity/Processor pair"; } EntityType type() const override { return COMMSET; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Compare.C b/packages/seacas/libraries/ioss/src/Ioss_Compare.C index 16048568cf..4b752bfba0 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Compare.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Compare.C @@ -1182,20 +1182,16 @@ namespace { } template - bool compare_sets(const std::vector &in_sets_1, const std::vector &in_sets_const_2, + bool compare_sets(const std::vector &in_sets_1, const std::vector &in_sets_2, const Ioss::MeshCopyOptions & /* options */, std::ostringstream & /* buf */) { bool overall_result = true; - if (in_sets_1.size() != in_sets_const_2.size()) { - fmt::print(Ioss::WarnOut(), COUNT_MISMATCH, "set", in_sets_1.size(), in_sets_const_2.size()); + if (in_sets_1.size() != in_sets_2.size()) { + fmt::print(Ioss::WarnOut(), COUNT_MISMATCH, "set", in_sets_1.size(), in_sets_2.size()); return false; } - // COPY the const input vector so that we remove elements as they're matched without - // affecting the original data structure. - std::vector in_sets_2 = in_sets_const_2; - if (!in_sets_1.empty()) { for (const auto &in_set_1 : in_sets_1) { const auto &name = in_set_1->name(); diff --git a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C index 221dbb9096..66d7351ccd 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ConcreteVariableType.C @@ -11,45 +11,45 @@ #include namespace { - std::string X() { return std::string("x"); } - std::string Y() { return std::string("y"); } - std::string Z() { return std::string("z"); } - std::string Q() { return std::string("q"); } - std::string S() { return std::string("s"); } - - std::string XX() { return std::string("xx"); } - std::string YY() { return std::string("yy"); } - std::string ZZ() { return std::string("zz"); } - std::string XY() { return std::string("xy"); } - std::string YZ() { return std::string("yz"); } - std::string ZX() { return std::string("zx"); } - std::string YX() { return std::string("yx"); } - std::string ZY() { return std::string("zy"); } - std::string XZ() { return std::string("xz"); } - - std::string invalid() { return std::string("invalid"); } - std::string scalar() { return std::string("scalar"); } - std::string vector_2d() { return std::string("vector_2d"); } - std::string vector_3d() { return std::string("vector_3d"); } - std::string quaternion_2d() { return std::string("quaternion_2d"); } - std::string quaternion_3d() { return std::string("quaternion_3d"); } - std::string full_tensor_36() { return std::string("full_tensor_36"); } - std::string full_tensor_32() { return std::string("full_tensor_32"); } - std::string full_tensor_22() { return std::string("full_tensor_22"); } - std::string full_tensor_16() { return std::string("full_tensor_16"); } - std::string full_tensor_12() { return std::string("full_tensor_12"); } - std::string sym_tensor_33() { return std::string("sym_tensor_33"); } - std::string sym_tensor_31() { return std::string("sym_tensor_31"); } - std::string sym_tensor_21() { return std::string("sym_tensor_21"); } - std::string sym_tensor_13() { return std::string("sym_tensor_13"); } - std::string sym_tensor_11() { return std::string("sym_tensor_11"); } - std::string sym_tensor_10() { return std::string("sym_tensor_10"); } - std::string asym_tensor_03() { return std::string("asym_tensor_03"); } - std::string asym_tensor_02() { return std::string("asym_tensor_02"); } - std::string asym_tensor_01() { return std::string("asym_tensor_01"); } - std::string matrix_22() { return std::string("matrix_22"); } - std::string matrix_33() { return std::string("matrix_33"); } - std::string testonly() { return std::string("testonly"); } + std::string X() { return {"x"}; } + std::string Y() { return {"y"}; } + std::string Z() { return {"z"}; } + std::string Q() { return {"q"}; } + std::string S() { return {"s"}; } + + std::string XX() { return {"xx"}; } + std::string YY() { return {"yy"}; } + std::string ZZ() { return {"zz"}; } + std::string XY() { return {"xy"}; } + std::string YZ() { return {"yz"}; } + std::string ZX() { return {"zx"}; } + std::string YX() { return {"yx"}; } + std::string ZY() { return {"zy"}; } + std::string XZ() { return {"xz"}; } + + std::string invalid() { return {"invalid"}; } + std::string scalar() { return {"scalar"}; } + std::string vector_2d() { return {"vector_2d"}; } + std::string vector_3d() { return {"vector_3d"}; } + std::string quaternion_2d() { return {"quaternion_2d"}; } + std::string quaternion_3d() { return {"quaternion_3d"}; } + std::string full_tensor_36() { return {"full_tensor_36"}; } + std::string full_tensor_32() { return {"full_tensor_32"}; } + std::string full_tensor_22() { return {"full_tensor_22"}; } + std::string full_tensor_16() { return {"full_tensor_16"}; } + std::string full_tensor_12() { return {"full_tensor_12"}; } + std::string sym_tensor_33() { return {"sym_tensor_33"}; } + std::string sym_tensor_31() { return {"sym_tensor_31"}; } + std::string sym_tensor_21() { return {"sym_tensor_21"}; } + std::string sym_tensor_13() { return {"sym_tensor_13"}; } + std::string sym_tensor_11() { return {"sym_tensor_11"}; } + std::string sym_tensor_10() { return {"sym_tensor_10"}; } + std::string asym_tensor_03() { return {"asym_tensor_03"}; } + std::string asym_tensor_02() { return {"asym_tensor_02"}; } + std::string asym_tensor_01() { return {"asym_tensor_01"}; } + std::string matrix_22() { return {"matrix_22"}; } + std::string matrix_33() { return {"matrix_33"}; } + std::string testonly() { return {"testonly"}; } } // namespace Ioss::StorageInitializer::StorageInitializer() diff --git a/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C b/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C index 5723d053f1..d87c3a233e 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C +++ b/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C @@ -1435,8 +1435,7 @@ namespace { std::vector ids; ns->get_field_data("ids_raw", ids); owned = 0; - for (size_t n = 0; n < ids.size(); n++) { - INT id = ids[n]; + for (auto id : ids) { if (my_data[id - 1] == my_processor) { ++owned; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C index 5af4c212b1..5606d5bf66 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.C @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -151,16 +152,13 @@ namespace { } template - std::vector get_all_block_offsets(const std::string &field_name, - const std::vector &entity_container) + std::vector get_entity_offsets(const std::string &field_name, + const std::vector &entity_container) { - size_t num_blocks = entity_container.size(); - + size_t num_blocks = entity_container.size(); std::vector offsets(num_blocks + 1, 0); - for (size_t i = 0; i < num_blocks; i++) { - T *entity = entity_container[i]; - + for (auto [i, entity] : enumerate(entity_container)) { if (entity->field_exists(field_name)) { Ioss::Field field = entity->get_field(field_name); offsets[i + 1] = entity->entity_count() * field.raw_storage()->component_count(); @@ -744,8 +742,8 @@ namespace Ioss { get_region()->add(new_set); // Find the member SideSets... - for (size_t i = 1; i < group_spec.size(); i++) { - SideSet *set = get_region()->get_sideset(group_spec[i]); + for (const auto &spec : group_spec) { + SideSet *set = get_region()->get_sideset(spec); if (set != nullptr) { const SideBlockContainer &side_blocks = set->get_side_blocks(); for (const auto &sbold : side_blocks) { @@ -777,7 +775,7 @@ namespace Ioss { fmt::print(Ioss::WarnOut(), "While creating the grouped surface '{}', the surface '{}' does not exist. " "This surface will skipped and not added to the group.\n\n", - group_spec[0], group_spec[i]); + group_spec[0], spec); } } } @@ -1297,9 +1295,8 @@ namespace Ioss { util().global_array_minmax(minmax, Ioss::ParallelUtils::DO_MIN); - for (size_t i = 0; i < element_blocks.size(); i++) { - Ioss::ElementBlock *block = element_blocks[i]; - const std::string &name = block->name(); + for (auto [i, block] : enumerate(element_blocks)) { + const std::string &name = block->name(); AxisAlignedBoundingBox bbox(minmax[6 * i + 0], minmax[6 * i + 1], minmax[6 * i + 2], -minmax[6 * i + 3], -minmax[6 * i + 4], -minmax[6 * i + 5]); elementBlockBoundingBoxes[name] = bbox; @@ -1362,18 +1359,22 @@ namespace Ioss { return {xx.first, yy.first, zz.first, xx.second, yy.second, zz.second}; } - std::vector DatabaseIO::get_all_block_field_data(const std::string &field_name, - void *data, size_t data_size) const - { - const Ioss::ElementBlockContainer &elem_blocks = get_region()->get_element_blocks(); - size_t num_blocks = elem_blocks.size(); - - std::vector offset = get_all_block_offsets(field_name, elem_blocks); - - for (size_t i = 0; i < num_blocks; i++) { +#ifndef DOXYGEN_SKIP_THIS + template std::vector + DatabaseIO::get_entity_field_data_internal(const std::string &field_name, + const std::vector &elem_blocks, + void *data, size_t data_size) const; +#endif - Ioss::ElementBlock *entity = elem_blocks[i]; + template + std::vector + DatabaseIO::get_entity_field_data_internal(const std::string &field_name, + const std::vector &entity_container, void *data, + size_t data_size) const + { + std::vector offset = get_entity_offsets(field_name, entity_container); + for (const auto [i, entity] : enumerate(entity_container)) { if (entity->field_exists(field_name)) { auto num_to_get_for_block = offset[i + 1] - offset[i]; Ioss::Field field = entity->get_field(field_name); @@ -1390,6 +1391,7 @@ namespace Ioss { } size_t expected_data_size = offset[i + 1] * field_byte_size; + if (data_size < expected_data_size) { std::ostringstream errmsg; fmt::print( @@ -1400,7 +1402,8 @@ namespace Ioss { } size_t block_data_offset = offset[i] * field_byte_size; - auto retval = + + auto retval = get_field_internal(entity, field, (char *)data + block_data_offset, block_data_size); size_t block_component_count = field.raw_storage()->component_count(); @@ -1422,6 +1425,14 @@ namespace Ioss { return offset; } + std::vector + DatabaseIO::get_entity_field_data(const std::string &field_name, + const std::vector &elem_blocks, + void *data, size_t data_size) const + { + return get_entity_field_data_internal(field_name, elem_blocks, data, data_size); + } + int64_t DatabaseIO::get_zc_field_internal(const Ioss::Region *reg, const Ioss::Field &field, void **, size_t *) const { diff --git a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h index 4c9c7ced61..f5843af844 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/Ioss_DatabaseIO.h @@ -150,7 +150,7 @@ namespace Ioss { } /** \brief We call this ONLY after we assure that using_dw() is TRUE - * \ returns mount point of Datawarp namespace, e.g: `/opt/cray/....` + * \returns mount point of Datawarp namespace, e.g: `/opt/cray/....` */ std::string get_dw_path() const { return dwPath; } @@ -179,7 +179,7 @@ namespace Ioss { /** \brief Get a file-per-processor filename associated with the database. * - * \ returns The file-per-processor name for a file on this processor. + * \returns The file-per-processor name for a file on this processor. */ const std::string &decoded_filename() const; @@ -568,8 +568,10 @@ namespace Ioss { } } - virtual std::vector get_all_block_field_data(const std::string &field_name, void *data, - size_t data_size) const; + virtual std::vector + get_entity_field_data(const std::string &field_name, + const std::vector &elem_blocks, void *data, + size_t data_size) const; protected: DatabaseIO(Region *region, std::string filename, Ioss::DatabaseUsage db_usage, @@ -873,6 +875,11 @@ namespace Ioss { virtual int64_t get_zc_field_internal(const StructuredBlock *sb, const Field &field, void **data, size_t *data_size) const; + template + std::vector get_entity_field_data_internal(const std::string &field_name, + const std::vector &entity_container, + void *data, size_t data_size) const; + mutable std::map elementBlockBoundingBoxes; Ioss::ParallelUtils util_; // Encapsulate parallel and other utility functions. diff --git a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C index 2dc9aac1cc..151e08783e 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.C @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -158,106 +159,112 @@ namespace Ioss { return valid_methods; } - size_t get_all_block_ioss_element_size(const std::vector &blocks) + size_t + ElementBlockBatchOffset::get_ioss_element_size(const std::vector &blockSubsetIndex) const { size_t count = 0; - for (const Ioss::BlockDecompositionData &block : blocks) { - // Determine total number of ioss decomp elements + // Determine total number of ioss subset decomp elements + for (int64_t i : blockSubsetIndex) { + const Ioss::BlockDecompositionData &block = m_data[i]; count += (block.importMap.size() + block.localMap.size()); } return count; } - size_t get_all_block_ioss_offset_size(const std::vector &blocks, - const std::vector &block_field_component_count) + size_t ElementBlockBatchOffset::get_ioss_offset_size( + const std::vector &blockSubsetIndex, + const std::vector &blockSubsetFieldComponentCount) const { size_t count = 0; - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &block = blocks[blk_seq]; - // Determine total number of ioss decomp entries based on field component count per block. - count += - block_field_component_count[blk_seq] * (block.importMap.size() + block.localMap.size()); + for (auto [i, blk_seq] : enumerate(blockSubsetIndex)) { + const Ioss::BlockDecompositionData &block = m_data[blk_seq]; + // Determine total number of ioss decomp entries based on subset field component count per + // block. + count += blockSubsetFieldComponentCount[i] * (block.importMap.size() + block.localMap.size()); } return count; } - std::vector get_all_block_ioss_offset(const std::vector &blocks, - const std::vector &block_component_count) + std::vector ElementBlockBatchOffset::get_ioss_offset( + const std::vector &blockSubsetIndex, + const std::vector &blockSubsetFieldComponentCount) const { - std::vector ioss_offset(blocks.size() + 1, 0); + std::vector offset(blockSubsetIndex.size() + 1, 0); - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &block = blocks[blk_seq]; + for (auto [i, blk_seq] : enumerate(blockSubsetIndex)) { + const Ioss::BlockDecompositionData &block = m_data[blk_seq]; - // Determine number of ioss decomp entries based on field component count per block. - ioss_offset[blk_seq + 1] = - block_component_count[blk_seq] * (block.importMap.size() + block.localMap.size()); + // Determine number of ioss decomp entries based on subset field component count per block. + offset[i + 1] = + blockSubsetFieldComponentCount[i] * (block.importMap.size() + block.localMap.size()); } // Compute offsets - for (size_t i = 1; i <= blocks.size(); ++i) { - ioss_offset[i] += ioss_offset[i - 1]; + for (size_t i = 1; i <= blockSubsetIndex.size(); ++i) { + offset[i] += offset[i - 1]; } - return ioss_offset; + return offset; } - std::vector get_all_block_import_offset(const std::vector &blocks, - const std::vector &block_component_count) + std::vector ElementBlockBatchOffset::get_import_offset( + const std::vector &blockSubsetIndex, + const std::vector &blockSubsetFieldComponentCount) const { - std::vector ioss_offset(blocks.size() + 1, 0); + std::vector offset(blockSubsetIndex.size() + 1, 0); - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &block = blocks[blk_seq]; + for (auto [i, blk_seq] : enumerate(blockSubsetIndex)) { + const Ioss::BlockDecompositionData &block = m_data[blk_seq]; - // Determine number of imported ioss decomp entries based on field component count per block. - ioss_offset[blk_seq + 1] = block_component_count[blk_seq] * block.importMap.size(); + // Determine number of imported ioss decomp entries based on subset field component count per + // block. + offset[i + 1] = blockSubsetFieldComponentCount[i] * block.importMap.size(); } // Compute offsets - for (size_t i = 1; i <= blocks.size(); ++i) { - ioss_offset[i] += ioss_offset[i - 1]; + for (size_t i = 1; i <= blockSubsetIndex.size(); ++i) { + offset[i] += offset[i - 1]; } - return ioss_offset; + return offset; } - std::vector - get_all_block_connectivity_ioss_component_count(const std::vector &blocks) + std::vector ElementBlockBatchOffset::get_connectivity_ioss_component_count( + const std::vector &blockSubsetIndex) const { - std::vector block_connectivity_component_count(blocks.size()); + std::vector blockSubsetConnectivityComponentCount(blockSubsetIndex.size()); - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &block = blocks[blk_seq]; - block_connectivity_component_count[blk_seq] = block.nodesPerEntity; + for (auto [i, blk_seq] : enumerate(blockSubsetIndex)) { + const Ioss::BlockDecompositionData &block = m_data[blk_seq]; + blockSubsetConnectivityComponentCount[i] = block.nodesPerEntity; } - return block_connectivity_component_count; + return blockSubsetConnectivityComponentCount; } - size_t - get_all_block_connectivity_ioss_offset_size(const std::vector &blocks) + size_t ElementBlockBatchOffset::get_connectivity_ioss_offset_size( + const std::vector &blockSubsetIndex) const { - return get_all_block_ioss_offset_size(blocks, - get_all_block_connectivity_ioss_component_count(blocks)); + return get_ioss_offset_size(blockSubsetIndex, + get_connectivity_ioss_component_count(blockSubsetIndex)); } - std::vector - get_all_block_connectivity_ioss_offset(const std::vector &blocks) + std::vector ElementBlockBatchOffset::get_connectivity_ioss_offset( + const std::vector &blockSubsetIndex) const { - return get_all_block_ioss_offset(blocks, - get_all_block_connectivity_ioss_component_count(blocks)); + return get_ioss_offset(blockSubsetIndex, + get_connectivity_ioss_component_count(blockSubsetIndex)); } - std::vector - get_all_block_connectivity_import_offset(const std::vector &blocks) + std::vector ElementBlockBatchOffset::get_connectivity_import_offset( + const std::vector &blockSubsetIndex) const { - return get_all_block_import_offset(blocks, - get_all_block_connectivity_ioss_component_count(blocks)); + return get_import_offset(blockSubsetIndex, + get_connectivity_ioss_component_count(blockSubsetIndex)); } template IOSS_EXPORT Decomposition::Decomposition(const Ioss::PropertyManager &props, @@ -337,13 +344,12 @@ namespace Ioss { // local_map[0] size_t proc = 0; std::vector imp_index(el_blocks.size()); - for (size_t i = 0; i < importElementMap.size(); i++) { - size_t elem = importElementMap[i]; + for (auto [i, elem] : enumerate(importElementMap)) { while (i >= (size_t)importElementIndex[proc + 1]) { proc++; } - size_t b = Ioss::Utils::find_index_location(elem, m_fileBlockIndex); + size_t b = Ioss::Utils::find_index_location((size_t)elem, m_fileBlockIndex); size_t off = std::max(m_fileBlockIndex[b], m_elementOffset); if (!el_blocks[b].localMap.empty() && elem < el_blocks[b].localMap[0] + off) { @@ -358,13 +364,12 @@ namespace Ioss { // Now for the exported data... proc = 0; - for (size_t i = 0; i < exportElementMap.size(); i++) { - size_t elem = exportElementMap[i]; + for (auto [i, elem] : enumerate(exportElementMap)) { while (i >= (size_t)exportElementIndex[proc + 1]) { proc++; } - size_t b = Ioss::Utils::find_index_location(elem, m_fileBlockIndex); + size_t b = Ioss::Utils::find_index_location((size_t)elem, m_fileBlockIndex); size_t off = std::max(m_fileBlockIndex[b], m_elementOffset); el_blocks[b].exportMap.push_back(elem - off); @@ -539,8 +544,7 @@ namespace Ioss { std::vector node_comm_send(sums); { std::vector recv_tmp(m_processorCount); - for (size_t i = 0; i < owner.size(); i++) { - int proc = owner[i]; + for (auto [i, proc] : enumerate(owner)) { if (proc != m_processor) { INT node = m_adjacency[i]; size_t position = recv_disp[proc] + recv_tmp[proc]++; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h index 773b309baa..4caade27bd 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h @@ -133,32 +133,42 @@ namespace Ioss { bool distributionFactorConstant{false}; // T if all distribution factors the same value. }; - IOSS_EXPORT size_t - get_all_block_ioss_element_size(const std::vector &blocks); + class IOSS_EXPORT ElementBlockBatchOffset + { + public: + ElementBlockBatchOffset(const std::vector &data) : m_data(data) {} + + ElementBlockBatchOffset() = delete; + ElementBlockBatchOffset(const ElementBlockBatchOffset &) = delete; + ElementBlockBatchOffset(ElementBlockBatchOffset &&) = delete; - IOSS_EXPORT size_t - get_all_block_ioss_offset_size(const std::vector &blocks, - const std::vector &block_component_count); + ~ElementBlockBatchOffset() = default; - IOSS_EXPORT std::vector - get_all_block_ioss_offset(const std::vector &blocks, - const std::vector &block_component_count); + size_t get_ioss_element_size(const std::vector &blockSubsetIndex) const; - IOSS_EXPORT std::vector - get_all_block_import_offset(const std::vector &blocks, - const std::vector &block_component_count); + std::vector get_ioss_offset(const std::vector &blockSubsetIndex, + const std::vector &blockComponentCount) const; - IOSS_EXPORT std::vector get_all_block_connectivity_ioss_component_count( - const std::vector &blocks); + std::vector get_import_offset(const std::vector &blockSubsetIndex, + const std::vector &blockComponentCount) const; - IOSS_EXPORT size_t - get_all_block_connectivity_ioss_offset_size(const std::vector &blocks); + size_t get_connectivity_ioss_offset_size(const std::vector &blockSubsetIndex) const; - IOSS_EXPORT std::vector - get_all_block_connectivity_ioss_offset(const std::vector &blocks); + std::vector + get_connectivity_ioss_component_count(const std::vector &blockSubsetIndex) const; + + private: + const std::vector &m_data; - IOSS_EXPORT std::vector - get_all_block_connectivity_import_offset(const std::vector &blocks); + size_t get_ioss_offset_size(const std::vector &blockSubsetIndex, + const std::vector &blockComponentCount) const; + + std::vector + get_connectivity_ioss_offset(const std::vector &blockSubsetIndex) const; + + std::vector + get_connectivity_import_offset(const std::vector &blockSubsetIndex) const; + }; template class Decomposition { @@ -529,17 +539,19 @@ namespace Ioss { } template - std::vector do_communicate_all_block_data( + std::vector do_communicate_entity_data( T *file_data, U *ioss_data, const std::vector &blocks, - const std::vector &file_offset, const std::vector &block_component_count) const + const std::vector &blockSubsetIndex, const std::vector &fileOffset, + const std::vector &blockComponentCount) const { size_t export_size = 0; size_t import_size = 0; - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &blk = blocks[blk_seq]; + for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) { + int64_t blk_seq = blockSubsetIndex[bsi]; + const Ioss::BlockDecompositionData &blk = blocks[blk_seq]; - size_t comp_count = block_component_count[blk_seq]; + size_t comp_count = blockComponentCount[bsi]; export_size += blk.exportMap.size() * comp_count; import_size += blk.importMap.size() * comp_count; } @@ -551,10 +563,11 @@ namespace Ioss { int nProc = util_.parallel_size(); for (int proc = 0; proc < nProc; proc++) { - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { + for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) { + int64_t blk_seq = blockSubsetIndex[bsi]; const Ioss::BlockDecompositionData &blk = blocks[blk_seq]; - size_t comp_count = block_component_count[blk_seq]; - size_t fileDataOffset = file_offset[blk_seq]; + size_t comp_count = blockComponentCount[bsi]; + size_t fileDataOffset = fileOffset[bsi]; for (int n = 0; n < blk.exportCount[proc]; n++) { int exportIndex = blk.exportIndex[proc] + n; @@ -573,9 +586,10 @@ namespace Ioss { std::vector import_count(nProc, 0); std::vector import_disp(nProc, 0); - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { + for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) { + int64_t blk_seq = blockSubsetIndex[bsi]; const Ioss::BlockDecompositionData &blk = blocks[blk_seq]; - size_t comp_count = block_component_count[blk_seq]; + size_t comp_count = blockComponentCount[bsi]; int proc = 0; for (int i : blk.exportCount) { @@ -599,59 +613,63 @@ namespace Ioss { m_comm); show_progress("\tCommunication 1 finished"); - std::vector ioss_offset = - Ioss::get_all_block_ioss_offset(blocks, block_component_count); - std::vector import_offset = - Ioss::get_all_block_import_offset(blocks, block_component_count); + Ioss::ElementBlockBatchOffset batchOffset(blocks); + std::vector iossOffset = + batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount); + std::vector importOffset = + batchOffset.get_import_offset(blockSubsetIndex, blockComponentCount); // Map local and imported data to ioss_data. - for (size_t blk_seq = 0; blk_seq < blocks.size(); blk_seq++) { + for (size_t bsi = 0; bsi < blockSubsetIndex.size(); bsi++) { + int64_t blk_seq = blockSubsetIndex[bsi]; const Ioss::BlockDecompositionData &block = blocks[blk_seq]; - size_t comp_count = block_component_count[blk_seq]; + size_t comp_count = blockComponentCount[bsi]; for (size_t i = 0; i < block.localMap.size(); i++) { for (size_t j = 0; j < comp_count; j++) { - unsigned fileIndex = file_offset[blk_seq] + block.localMap[i] * comp_count + j; - unsigned iossIndex = - ioss_offset[blk_seq] + (i + block.localIossOffset) * comp_count + j; + size_t fileIndex = fileOffset[bsi] + block.localMap[i] * comp_count + j; + size_t iossIndex = iossOffset[bsi] + (i + block.localIossOffset) * comp_count + j; ioss_data[iossIndex] = file_data[fileIndex]; } } for (size_t i = 0; i < block.importMap.size(); i++) { for (size_t j = 0; j < comp_count; j++) { - unsigned importIndex = import_offset[blk_seq] + i * comp_count + j; + size_t importIndex = importOffset[bsi] + i * comp_count + j; - size_t dataOffset = ioss_offset[blk_seq]; - unsigned iossIndex = dataOffset + block.importMap[i] * comp_count + j; + size_t dataOffset = iossOffset[bsi]; + size_t iossIndex = dataOffset + block.importMap[i] * comp_count + j; ioss_data[iossIndex] = imports[importIndex]; } } } - return ioss_offset; + return iossOffset; } template - std::vector communicate_all_block_data( - T *file_data, U *ioss_data, const std::vector &blocks, - const std::vector &file_offset, const std::vector &block_component_count) const + std::vector communicate_entity_data(T *file_data, U *ioss_data, + const std::vector &blocks, + const std::vector &blockSubsetIndex, + const std::vector &fileOffset, + const std::vector &blockComponentCount) const { show_progress(__func__); if (m_method == "LINEAR") { // For "LINEAR" decomposition method, the `file_data` is the // same as `ioss_data` Transfer all local data from file_data // to ioss_data... - auto size = file_offset[blocks.size()]; + auto size = fileOffset[blockSubsetIndex.size()]; std::copy(file_data, file_data + size, ioss_data); - return Ioss::get_all_block_ioss_offset(blocks, block_component_count); + Ioss::ElementBlockBatchOffset batchOffset(blocks); + return batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount); ; } - auto retval = do_communicate_all_block_data(file_data, ioss_data, blocks, file_offset, - block_component_count); + auto retval = do_communicate_entity_data(file_data, ioss_data, blocks, blockSubsetIndex, + fileOffset, blockComponentCount); return retval; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_EdgeBlock.h b/packages/seacas/libraries/ioss/src/Ioss_EdgeBlock.h index 830d7bd27e..5e4e5c8a0b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_EdgeBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_EdgeBlock.h @@ -39,7 +39,7 @@ namespace Ioss { std::string contains_string() const override { return "Edge"; } EntityType type() const override { return EDGEBLOCK; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'edge_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h b/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h index 08a83b54ed..0b52e3dbd4 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_EdgeSet.h @@ -38,7 +38,7 @@ namespace Ioss { std::string contains_string() const override { return "Edge"; } EntityType type() const override { return EDGESET; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h b/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h index 6bd7b0ca66..541db19b82 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementBlock.h @@ -34,7 +34,7 @@ namespace Ioss { std::string contains_string() const override { return "Element"; } EntityType type() const override { return ELEMENTBLOCK; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h b/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h index d33573c9f2..867ccab11b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementSet.h @@ -38,7 +38,7 @@ namespace Ioss { std::string contains_string() const override { return "Element"; } EntityType type() const override { return ELEMENTSET; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C b/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C index 1fc7dac108..0e4bea10c0 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ElementTopology.C @@ -298,7 +298,7 @@ Ioss::IntVector Ioss::ElementTopology::boundary_connectivity(int bnd_number) con return Ioss::IntVector{bnd_number - 1}; } } - return Ioss::IntVector(); + return {}; } Ioss::ElementTopology *Ioss::ElementTopology::boundary_type(int bnd_number) const diff --git a/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C b/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C index 303705dcda..df7ac400c3 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_EntityBlock.C @@ -61,7 +61,7 @@ Ioss::EntityBlock::EntityBlock(Ioss::DatabaseIO *io_database, const std::string /** \brief Calculate and get an implicit property. * - * These are calcuated from data stored in the EntityBlock instead of having + * These are calculated from data stored in the EntityBlock instead of having * an explicit value assigned. An example would be 'topology_node_count' for an ElementBlock. * Note that even though this is a pure virtual function, an implementation * is provided to return properties that are common to all 'block'-type grouping entities. @@ -71,10 +71,10 @@ Ioss::EntityBlock::EntityBlock(Ioss::DatabaseIO *io_database, const std::string Ioss::Property Ioss::EntityBlock::get_implicit_property(const std::string &my_name) const { if (my_name == "topology_node_count") { - return Ioss::Property(my_name, topology()->number_nodes()); + return {my_name, topology()->number_nodes()}; } if (my_name == "topology_type") { - return Ioss::Property(my_name, topology()->name()); + return {my_name, topology()->name()}; } return Ioss::GroupingEntity::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Enumerate.h b/packages/seacas/libraries/ioss/src/Ioss_Enumerate.h new file mode 100644 index 0000000000..135113315b --- /dev/null +++ b/packages/seacas/libraries/ioss/src/Ioss_Enumerate.h @@ -0,0 +1,36 @@ +// https://www.reedbeta.com/blog/python-like-enumerate-in-cpp17/ +// std::vector things; +// ... +// for (auto [i, thing] : enumerate(things)) +// { +// .. `i` gets the index and `thing` gets the Thing in each iteration +// } + +#include + +namespace Ioss { + template ())), + typename = decltype(std::end(std::declval()))> + constexpr auto enumerate(T &&iterable) + { + struct iterator + { + size_t i; + TIter iter; + bool operator!=(const iterator &other) const { return iter != other.iter; } + void operator++() + { + ++i; + ++iter; + } + auto operator*() const { return std::tie(i, *iter); } + }; + struct iterable_wrapper + { + T iterable; + auto begin() { return iterator{0, std::begin(iterable)}; } + auto end() { return iterator{0, std::end(iterable)}; } + }; + return iterable_wrapper{std::forward(iterable)}; + } +} // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceBlock.h b/packages/seacas/libraries/ioss/src/Ioss_FaceBlock.h index 57cf15a556..ed57c93ac2 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceBlock.h @@ -39,7 +39,7 @@ namespace Ioss { std::string contains_string() const override { return "Face"; } EntityType type() const override { return FACEBLOCK; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'face_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h b/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h index 99461b50aa..81e4e7eb22 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceGenerator.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -90,6 +90,8 @@ namespace Ioss { // find a difference and the function will return 'true' // However, for some reason, removing this check does not change the execution time // appreiciably... + + // TODO: Loop can probably be replaced by std::all_of... for (auto lvert : left.connectivity_) { if (std::find(right.connectivity_.cbegin(), right.connectivity_.cend(), lvert) == right.connectivity_.cend()) { diff --git a/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h b/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h index ab7f55e2b1..b4c72772fc 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FaceSet.h @@ -38,7 +38,7 @@ namespace Ioss { std::string contains_string() const override { return "Face"; } EntityType type() const override { return FACESET; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Field.C b/packages/seacas/libraries/ioss/src/Ioss_Field.C index 994064ed62..f36e599938 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Field.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Field.C @@ -347,14 +347,14 @@ std::string Ioss::Field::type_string() const { return type_string(get_type()); } std::string Ioss::Field::type_string(Ioss::Field::BasicType type) { switch (type) { - case Ioss::Field::REAL: return std::string("real"); - case Ioss::Field::INTEGER: return std::string("integer"); - case Ioss::Field::INT64: return std::string("64-bit integer"); - case Ioss::Field::COMPLEX: return std::string("complex"); - case Ioss::Field::STRING: return std::string("string"); - case Ioss::Field::CHARACTER: return std::string("char"); - case Ioss::Field::INVALID: return std::string("invalid"); - default: return std::string("internal error"); + case Ioss::Field::REAL: return {"real"}; + case Ioss::Field::INTEGER: return {"integer"}; + case Ioss::Field::INT64: return {"64-bit integer"}; + case Ioss::Field::COMPLEX: return {"complex"}; + case Ioss::Field::STRING: return {"string"}; + case Ioss::Field::CHARACTER: return {"char"}; + case Ioss::Field::INVALID: return {"invalid"}; + default: return {"internal error"}; } } @@ -363,14 +363,14 @@ std::string Ioss::Field::role_string() const { return role_string(get_role()); } std::string Ioss::Field::role_string(Ioss::Field::RoleType role) { switch (role) { - case Ioss::Field::INTERNAL: return std::string("Internal"); - case Ioss::Field::MESH: return std::string("Mesh"); - case Ioss::Field::ATTRIBUTE: return std::string("Attribute"); - case Ioss::Field::COMMUNICATION: return std::string("Communication"); - case Ioss::Field::MESH_REDUCTION: return std::string("Mesh Reduction"); - case Ioss::Field::REDUCTION: return std::string("Reduction"); - case Ioss::Field::TRANSIENT: return std::string("Transient"); - default: return std::string("internal error"); + case Ioss::Field::INTERNAL: return {"Internal"}; + case Ioss::Field::MESH: return {"Mesh"}; + case Ioss::Field::ATTRIBUTE: return {"Attribute"}; + case Ioss::Field::COMMUNICATION: return {"Communication"}; + case Ioss::Field::MESH_REDUCTION: return {"Mesh Reduction"}; + case Ioss::Field::REDUCTION: return {"Reduction"}; + case Ioss::Field::TRANSIENT: return {"Transient"}; + default: return {"internal error"}; } } diff --git a/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h b/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h index 15cb457960..9a6d13787b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h +++ b/packages/seacas/libraries/ioss/src/Ioss_FieldManager.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -35,7 +35,10 @@ namespace Ioss { { public: FieldManager() = default; - FieldManager(const FieldManager &other) : fields(other.fields) {} + FieldManager(const FieldManager &other) : fields(other.fields) + { /* Do not make this `=default` since that breaks the thread-safe build */ + } + FieldManager &operator=(const FieldManager &) = delete; ~FieldManager() = default; diff --git a/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C b/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C index 5b3450fd03..50e012cf52 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C +++ b/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C @@ -22,8 +22,8 @@ #define X_OK 1 /* execute permission - unsupported in windows*/ #define F_OK 0 /* Test for existence. */ #ifndef S_ISREG -#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) -#define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR) +#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) +#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) #endif #else #include @@ -283,7 +283,7 @@ namespace Ioss { return filename_.substr(ind + 1, filename_.size()); } - return std::string(); + return {}; } std::string FileInfo::pathname() const @@ -293,7 +293,7 @@ namespace Ioss { return filename_.substr(0, ind); } - return std::string(); + return {}; } std::string FileInfo::tailname() const diff --git a/packages/seacas/libraries/ioss/src/Ioss_Getline.C b/packages/seacas/libraries/ioss/src/Ioss_Getline.C index 56eef77840..79d1a24c50 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Getline.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Getline.C @@ -39,6 +39,7 @@ #endif /********************* C library headers ********************************/ +#include #include #include #include @@ -721,9 +722,9 @@ namespace { #define HIST_SIZE 100 #endif - int hist_pos = 0, hist_last = 0; - char *hist_buf[HIST_SIZE]; - char hist_empty_elem[2] = ""; + int hist_pos = 0, hist_last = 0; + std::array hist_buf; + char hist_empty_elem[2] = ""; void hist_init() { diff --git a/packages/seacas/libraries/ioss/src/Ioss_Glob.h b/packages/seacas/libraries/ioss/src/Ioss_Glob.h index b8f574e446..c627960c4a 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Glob.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Glob.h @@ -22,7 +22,7 @@ namespace Ioss::glob { class IOSS_EXPORT Error : public std::exception { public: - explicit Error(const std::string &msg) : msg_{msg} {} + explicit Error(std::string msg) : msg_{std::move(msg)} {} ~Error() override; const char *what() const noexcept override { return msg_.c_str(); } @@ -94,7 +94,7 @@ namespace Ioss::glob { std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -107,7 +107,7 @@ namespace Ioss::glob { std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -205,14 +205,14 @@ namespace Ioss::glob { // the string if (comp_end) { if ((state_pos == match_state_) && (str_pos == str.length())) { - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } - return std::tuple(false, str_pos); + return {false, str_pos}; } // if comp_end is false, compare only if the states reached the // match state - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } void ResetStates() @@ -262,7 +262,7 @@ namespace Ioss::glob { bool Check(const String &, size_t) override { - // as it match any char, it is always trye + // as it match any char, it is always tried return true; } @@ -284,7 +284,7 @@ namespace Ioss::glob { bool Check(const String &, size_t) override { - // as it match any char, it is always trye + // as it match any char, it is always tried return true; } @@ -361,6 +361,7 @@ namespace Ioss::glob { bool SetCheck(const String &str, size_t pos) const { + // TODO: Replace with std::any_of() for (auto &item : items_) { // if any item match, then the set match with char if (item.get()->Check(str[pos])) { @@ -422,11 +423,11 @@ namespace Ioss::glob { for (auto &automata : automatas_) { std::tie(r, str_pos) = automata->Exec(str_part, false); if (r) { - return std::tuple(r, pos + str_pos); + return {r, pos + str_pos}; } } - return std::tuple(false, pos + str_pos); + return {false, pos + str_pos}; } bool Check(const String &str, size_t pos) override @@ -472,7 +473,7 @@ namespace Ioss::glob { return NextNeg(str, pos); } } - return std::tuple(0, 0); + return {0, 0}; } std::tuple NextNeg(const String &str, size_t pos) @@ -593,7 +594,7 @@ namespace Ioss::glob { template class Token { public: - Token(TokenKind kind) : kind_{kind} {} + explicit Token(TokenKind kind) : kind_{kind} {} Token(TokenKind kind, charT value) : kind_{kind}, value_{value} {} TokenKind Kind() const { return kind_; } @@ -627,7 +628,7 @@ namespace Ioss::glob { public: static const char kEndOfInput = -1; - Lexer(const String &str) : str_(str), c_{str[0]} {} + explicit Lexer(const String &str) : str_(str), c_{str[0]} {} std::vector> Scanner() { @@ -831,7 +832,7 @@ namespace Ioss::glob { virtual void Accept(AstVisitor *visitor) = 0; protected: - AstNode(Type type) : type_{type} {} + explicit AstNode(Type type) : type_{type} {} private: Type type_; @@ -1412,7 +1413,7 @@ namespace Ioss::glob { template class ExtendedGlob { public: - ExtendedGlob(const String &pattern) + explicit ExtendedGlob(const String &pattern) { Lexer l(pattern); std::vector> tokens = l.Scanner(); @@ -1450,7 +1451,7 @@ namespace Ioss::glob { template class SimpleGlob { public: - SimpleGlob(const String &pattern) { Parser(pattern); } + explicit SimpleGlob(const String &pattern) { Parser(pattern); } SimpleGlob(const SimpleGlob &) = delete; SimpleGlob &operator=(SimpleGlob &) = delete; diff --git a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C index 9083663786..0f6324fee6 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C +++ b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.C @@ -106,7 +106,7 @@ std::string Ioss::GroupingEntity::get_filename() const { // Ok for database_ to be nullptr at this point. if (database_ == nullptr) { - return std::string(); + return {}; } return database_->get_filename(); @@ -146,7 +146,7 @@ Ioss::State Ioss::GroupingEntity::get_state() const { return entityState; } /** \brief Calculate and get an implicit property. * - * These are calcuated from data stored in the EntityBlock instead of having + * These are calculated from data stored in the EntityBlock instead of having * an explicit value assigned. An example would be 'element_block_count' for a region. * Note that even though this is a pure virtual function, an implementation * is provided to return properties that are common to all 'block'-type grouping entities. @@ -159,7 +159,7 @@ Ioss::Property Ioss::GroupingEntity::get_implicit_property(const std::string &my // These include: if (my_name == "attribute_count") { count_attributes(); - return Ioss::Property(my_name, static_cast(attributeCount)); + return {my_name, static_cast(attributeCount)}; } // End of the line. No property of this name exists. diff --git a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h index f055cb8861..e85af86977 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h +++ b/packages/seacas/libraries/ioss/src/Ioss_GroupingEntity.h @@ -50,7 +50,7 @@ namespace Ioss { * A Region is also a grouping entity, except that its list of subentites * are other GroupingEntities. That is, it maintains a list of NodeBlocks, * ElementBlocks, NodeLists, CommLists and Surfaces. [Similar to the - * "Composite Patter" in Design Patterns] All interface to GroupingEntities + * "Composite Pattern" in Design Patterns] All interface to GroupingEntities * is through the Region class; clients of the IO subsystem have no direct * access to the underlying GroupingEntities (other than the Region). * @@ -279,7 +279,7 @@ namespace Ioss { // private and provide friend... void really_delete_database(); - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. // Note that even though this is a pure virtual function, an implementation @@ -524,7 +524,7 @@ int64_t Ioss::GroupingEntity::get_field_data(const std::string &field_name, verify_field_exists(field_name, "input"); Ioss::Field field = get_field(field_name); - field.check_type(Ioss::Field::get_field_type(T(0))); + field.check_type(Ioss::Field::get_field_type(static_cast(0))); data.resize(field.raw_count() * field.raw_storage()->component_count()); size_t data_size = data.size() * sizeof(T); @@ -572,7 +572,7 @@ int64_t Ioss::GroupingEntity::put_field_data(const std::string &field_name, verify_field_exists(field_name, "output"); Ioss::Field field = get_field(field_name); - field.check_type(Ioss::Field::get_field_type(T(0))); + field.check_type(Ioss::Field::get_field_type(static_cast(0))); size_t data_size = data.size() * sizeof(T); T *my_data = const_cast(data.data()); field.transform(my_data); diff --git a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h index 2b3f0c7b37..7f609d038a 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.h @@ -52,7 +52,7 @@ namespace Ioss { Ioss_MPI_Comm communicator, const Ioss::PropertyManager &properties) const = 0; - virtual std::string show_config() const { return std::string(""); } + virtual std::string show_config() const { return {""}; } static void alias(const std::string &base, const std::string &syn); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Initializer.C b/packages/seacas/libraries/ioss/src/Ioss_Initializer.C index 633eb60708..b1cbb23a8c 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Initializer.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Initializer.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -103,5 +103,3 @@ Ioss::Initializer::Initializer() Ioss::Super::factory(); } - -Ioss::Initializer::~Initializer() = default; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Initializer.h b/packages/seacas/libraries/ioss/src/Ioss_Initializer.h index 66ab7b5918..e450bcf888 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Initializer.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Initializer.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -12,7 +12,7 @@ namespace Ioss { { public: Initializer(); - ~Initializer(); + ~Initializer() = default; // Assignment operator // Copy constructor }; diff --git a/packages/seacas/libraries/ioss/src/Ioss_NodeBlock.h b/packages/seacas/libraries/ioss/src/Ioss_NodeBlock.h index 39a7e13613..105079d105 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_NodeBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_NodeBlock.h @@ -52,7 +52,7 @@ namespace Ioss { return GroupingEntity::contained_in(); } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_NodeSet.h b/packages/seacas/libraries/ioss/src/Ioss_NodeSet.h index c0a8e6eb8e..d8c96c3547 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_NodeSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_NodeSet.h @@ -37,7 +37,7 @@ namespace Ioss { std::string contains_string() const override { return "Node"; } EntityType type() const override { return NODESET; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_NullEntity.h b/packages/seacas/libraries/ioss/src/Ioss_NullEntity.h index 796efe0746..58de53d1db 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_NullEntity.h +++ b/packages/seacas/libraries/ioss/src/Ioss_NullEntity.h @@ -26,7 +26,7 @@ namespace Ioss { std::string contains_string() const override { return "Nothing"; } EntityType type() const override { return INVALID_TYPE; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override diff --git a/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C b/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C index b025b37726..8d94677091 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C +++ b/packages/seacas/libraries/ioss/src/Ioss_ParallelUtils.C @@ -594,7 +594,7 @@ void Ioss::ParallelUtils::all_gather(std::vector &my_values, std::vector & result = my_values; } #else - result = my_values; + result = my_values; #endif } @@ -602,7 +602,7 @@ void Ioss::ParallelUtils::progress(const std::string &output) const { static double begin = Utils::timer(); - int64_t MiB = 1024 * 1024; + int64_t MiB = static_cast(1024) * static_cast(1024); int64_t min = 0, max = 0, avg = 0; memory_stats(min, max, avg); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Property.C b/packages/seacas/libraries/ioss/src/Ioss_Property.C index 55ef27c425..f5858906f2 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Property.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Property.C @@ -16,14 +16,14 @@ namespace { std::string type_string(Ioss::Property::BasicType type) { switch (type) { - case Ioss::Property::INVALID: return std::string("invalid"); - case Ioss::Property::REAL: return std::string("real"); - case Ioss::Property::INTEGER: return std::string("integer"); - case Ioss::Property::POINTER: return std::string("pointer"); - case Ioss::Property::STRING: return std::string("string"); - case Ioss::Property::VEC_INTEGER: return std::string("vector"); - case Ioss::Property::VEC_DOUBLE: return std::string("vector"); - default: return std::string("internal error"); + case Ioss::Property::INVALID: return {"invalid"}; + case Ioss::Property::REAL: return {"real"}; + case Ioss::Property::INTEGER: return {"integer"}; + case Ioss::Property::POINTER: return {"pointer"}; + case Ioss::Property::STRING: return {"string"}; + case Ioss::Property::VEC_INTEGER: return {"vector"}; + case Ioss::Property::VEC_DOUBLE: return {"vector"}; + default: return {"internal error"}; } } @@ -45,9 +45,8 @@ namespace { * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, int value, Origin origin) - : name_(std::move(name)), type_(INTEGER), origin_(origin) + : name_(std::move(name)), type_(INTEGER), origin_(origin), data_(static_cast(value)) { - data_.ival = value; } /** \brief Create an INTEGER type property using an int64_t variable. @@ -57,9 +56,8 @@ Ioss::Property::Property(std::string name, int value, Origin origin) * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, int64_t value, Origin origin) - : name_(std::move(name)), type_(INTEGER), origin_(origin) + : name_(std::move(name)), type_(INTEGER), origin_(origin), data_(value) { - data_.ival = value; } /** \brief Create a REAL type property. @@ -69,9 +67,8 @@ Ioss::Property::Property(std::string name, int64_t value, Origin origin) * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, double value, Origin origin) - : name_(std::move(name)), type_(REAL), origin_(origin) + : name_(std::move(name)), type_(REAL), origin_(origin), data_(value) { - data_.rval = value; } /** \brief Create a STRING type property. @@ -81,9 +78,8 @@ Ioss::Property::Property(std::string name, double value, Origin origin) * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, const std::string &value, Origin origin) - : name_(std::move(name)), type_(STRING), origin_(origin) + : name_(std::move(name)), type_(STRING), origin_(origin), data_(value) { - data_.sval = new std::string(value); } /** \brief Create a VEC_INTEGER type property. @@ -93,9 +89,8 @@ Ioss::Property::Property(std::string name, const std::string &value, Origin orig * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, const std::vector &value, Origin origin) - : name_(std::move(name)), type_(VEC_INTEGER), origin_(origin) + : name_(std::move(name)), type_(VEC_INTEGER), origin_(origin), data_(value) { - data_.ivec = new std::vector(value); } /** \brief Create a VEC_DOUBLE type property. @@ -105,9 +100,8 @@ Ioss::Property::Property(std::string name, const std::vector &value, Origin * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, const std::vector &value, Origin origin) - : name_(std::move(name)), type_(VEC_DOUBLE), origin_(origin) + : name_(std::move(name)), type_(VEC_DOUBLE), origin_(origin), data_(value) { - data_.dvec = new std::vector(value); } /** \brief Create a STRING type property from const char* argument. @@ -117,9 +111,8 @@ Ioss::Property::Property(std::string name, const std::vector &value, Ori * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, const char *value, Origin origin) - : name_(std::move(name)), type_(STRING), origin_(origin) + : name_(std::move(name)), type_(STRING), origin_(origin), data_(std::string(value)) { - data_.sval = new std::string(value); } /** \brief Create a POINTER type property. @@ -129,9 +122,8 @@ Ioss::Property::Property(std::string name, const char *value, Origin origin) * \param[in] origin The origin of the property - IMPLICIT, or EXTERNAL, or ATTRIBUTE */ Ioss::Property::Property(std::string name, void *value, Origin origin) - : name_(std::move(name)), type_(POINTER), origin_(origin) + : name_(std::move(name)), type_(POINTER), origin_(origin), data_(value) { - data_.pval = value; } /** \brief Set implicit property with a specified type. @@ -143,50 +135,7 @@ Ioss::Property::Property(std::string name, void *value, Origin origin) Ioss::Property::Property(const Ioss::GroupingEntity *ge, std::string name, const BasicType type) : name_(std::move(name)), type_(type), origin_(IMPLICIT) { - data_.ge = ge; -} - -/** \brief Copy constructor. - * - * \param[in] from The Ioss::Property to copy - */ -Ioss::Property::Property(const Ioss::Property &from) - : name_(from.name_), type_(from.type_), origin_(from.origin_) -{ - if (!is_implicit() && type_ == STRING) { - data_.sval = new std::string(*(from.data_.sval)); - } - else if (!is_implicit() && type_ == VEC_DOUBLE) { - data_.dvec = new std::vector(*(from.data_.dvec)); - } - else if (!is_implicit() && type_ == VEC_INTEGER) { - data_.ivec = new std::vector(*(from.data_.ivec)); - } - else { - data_ = from.data_; - } -} - -Ioss::Property::~Property() -{ - if (!is_implicit() && type_ == STRING) { - delete data_.sval; - } - else if (!is_implicit() && type_ == VEC_DOUBLE) { - delete data_.dvec; - } - else if (!is_implicit() && type_ == VEC_INTEGER) { - delete data_.ivec; - } -} - -Ioss::Property &Ioss::Property::operator=(Ioss::Property rhs) -{ - std::swap(this->name_, rhs.name_); - std::swap(this->type_, rhs.type_); - std::swap(this->origin_, rhs.origin_); - std::swap(this->data_, rhs.data_); - return *this; + data_ = ge; } bool Ioss::Property::operator==(const Ioss::Property &rhs) const @@ -199,6 +148,10 @@ bool Ioss::Property::operator==(const Ioss::Property &rhs) const return false; } + if (this->origin_ != rhs.origin_) { + return false; + } + switch (this->type_) { case INVALID: break; case REAL: @@ -248,7 +201,6 @@ bool Ioss::Property::operator==(const Ioss::Property &rhs) const } break; } - return true; } @@ -342,12 +294,14 @@ bool Ioss::Property::get_value(int64_t *value) const { bool valid_request = type_ == INTEGER; if (is_explicit()) { - *value = data_.ival; + assert(std::holds_alternative(data_)); + *value = std::get(data_); } else { - const Ioss::GroupingEntity *ge = data_.ge; - const Ioss::Property implicit = ge->get_implicit_property(name_); - valid_request = implicit.get_value(value); + assert(std::holds_alternative(data_)); + const auto *ge = std::get(data_); + const auto implicit = ge->get_implicit_property(name_); + valid_request = implicit.get_value(value); } return valid_request; } @@ -356,12 +310,14 @@ bool Ioss::Property::get_value(double *value) const { bool valid_request = type_ == REAL; if (is_explicit()) { - *value = data_.rval; + assert(std::holds_alternative(data_)); + *value = std::get(data_); } else { - const Ioss::GroupingEntity *ge = data_.ge; - const Ioss::Property implicit = ge->get_implicit_property(name_); - valid_request = implicit.get_value(value); + assert(std::holds_alternative(data_)); + const auto *ge = std::get(data_); + const auto implicit = ge->get_implicit_property(name_); + valid_request = implicit.get_value(value); } return valid_request; } @@ -370,12 +326,14 @@ bool Ioss::Property::get_value(std::string *value) const { bool valid_request = type_ == STRING; if (is_explicit()) { - *value = *(data_.sval); + assert(std::holds_alternative(data_)); + *value = std::get(data_); } else { - const Ioss::GroupingEntity *ge = data_.ge; - const Ioss::Property implicit = ge->get_implicit_property(name_); - valid_request = implicit.get_value(value); + assert(std::holds_alternative(data_)); + const auto *ge = std::get(data_); + const auto implicit = ge->get_implicit_property(name_); + valid_request = implicit.get_value(value); } return valid_request; } @@ -384,12 +342,15 @@ bool Ioss::Property::get_value(std::vector *value) const { bool valid_request = type_ == VEC_INTEGER; if (is_explicit()) { - std::copy(data_.ivec->begin(), data_.ivec->end(), std::back_inserter(*value)); + assert(std::holds_alternative>(data_)); + auto ivec = std::get>(data_); + std::copy(ivec.begin(), ivec.end(), std::back_inserter(*value)); } else { - const Ioss::GroupingEntity *ge = data_.ge; - const Ioss::Property implicit = ge->get_implicit_property(name_); - valid_request = implicit.get_value(value); + assert(std::holds_alternative(data_)); + const auto *ge = std::get(data_); + const auto implicit = ge->get_implicit_property(name_); + valid_request = implicit.get_value(value); } return valid_request; } @@ -398,12 +359,15 @@ bool Ioss::Property::get_value(std::vector *value) const { bool valid_request = type_ == VEC_DOUBLE; if (is_explicit()) { - std::copy(data_.dvec->begin(), data_.dvec->end(), std::back_inserter(*value)); + assert(std::holds_alternative>(data_)); + auto dvec = std::get>(data_); + std::copy(dvec.begin(), dvec.end(), std::back_inserter(*value)); } else { - const Ioss::GroupingEntity *ge = data_.ge; - const Ioss::Property implicit = ge->get_implicit_property(name_); - valid_request = implicit.get_value(value); + assert(std::holds_alternative(data_)); + const auto *ge = std::get(data_); + const auto implicit = ge->get_implicit_property(name_); + valid_request = implicit.get_value(value); } return valid_request; } @@ -412,12 +376,14 @@ bool Ioss::Property::get_value(void *&value) const { bool valid_request = type_ == POINTER; if (is_explicit()) { - value = data_.pval; + assert(std::holds_alternative(data_)); + value = std::get(data_); } else { - const Ioss::GroupingEntity *ge = data_.ge; - const Ioss::Property implicit = ge->get_implicit_property(name_); - valid_request = implicit.get_value(value); + assert(std::holds_alternative(data_)); + const auto *ge = std::get(data_); + const auto implicit = ge->get_implicit_property(name_); + valid_request = implicit.get_value(value); } return valid_request; } diff --git a/packages/seacas/libraries/ioss/src/Ioss_Property.h b/packages/seacas/libraries/ioss/src/Ioss_Property.h index 9e3e26f2a2..2a76a0a99b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Property.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Property.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -10,6 +10,7 @@ #include // for int64_t #include // for string +#include #include namespace Ioss { @@ -46,10 +47,10 @@ namespace Ioss { // To set implicit property Property(const GroupingEntity *ge, std::string name, BasicType type); - Property(const Property &from); - Property &operator=(Property rhs); + Property(const Property &from) = default; + Property &operator=(Property &rhs); - ~Property(); + ~Property() = default; std::string get_string() const; int64_t get_int() const; @@ -101,6 +102,15 @@ namespace Ioss { bool operator!=(const Ioss::Property &rhs) const; bool operator==(const Ioss::Property &rhs) const; + friend void swap(Ioss::Property &first, Ioss::Property &second) // nothrow + { + using std::swap; + swap(first.name_, second.name_); + swap(first.type_, second.type_); + swap(first.origin_, second.origin_); + swap(first.data_, second.data_); + } + private: std::string name_{}; BasicType type_{INVALID}; @@ -118,15 +128,8 @@ namespace Ioss { /// The actual value of the property. Use 'type_' to /// discriminate the actual type of the property. - union Data { - std::string *sval; - void *pval{nullptr}; - const GroupingEntity *ge; - double rval; - int64_t ival; - std::vector *dvec; - std::vector *ivec; - }; - Data data_{}; + std::variant, + std::vector, void *> + data_; }; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C index 6d492ff6fd..a9797beb73 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C +++ b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.C @@ -14,11 +14,6 @@ #include #include -Ioss::PropertyManager::PropertyManager(const PropertyManager &from) - : m_properties(from.m_properties) -{ -} - Ioss::PropertyManager::~PropertyManager() { try { @@ -39,7 +34,7 @@ void Ioss::PropertyManager::add(const Ioss::Property &new_prop) if (iter != m_properties.end()) { m_properties.erase(iter); } - m_properties.insert(ValuePair(new_prop.get_name(), new_prop)); + m_properties.emplace(new_prop.get_name(), new_prop); } /** \brief Checks if a property exists in the database. diff --git a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h index 828a8a95bd..453aba7480 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h +++ b/packages/seacas/libraries/ioss/src/Ioss_PropertyManager.h @@ -35,7 +35,9 @@ namespace Ioss { { public: PropertyManager() = default; - PropertyManager(const PropertyManager &from); + PropertyManager(const PropertyManager &from) : m_properties(from.m_properties) + { /* Do not make this `=default` since that breaks the thread-safe build */ + } PropertyManager &operator=(const PropertyManager &from) = delete; ~PropertyManager(); diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.C b/packages/seacas/libraries/ioss/src/Ioss_Region.C index 0865ba319c..9faa37d063 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.C @@ -51,10 +51,10 @@ #include namespace { - std::string id_str() { return std::string("id"); } - std::string db_name_str() { return std::string("db_name"); } - std::string orig_topo_str() { return std::string("original_topology_type"); } - std::string orig_block_order() { return std::string("original_block_order"); } + std::string id_str() { return {"id"}; } + std::string db_name_str() { return {"db_name"}; } + std::string orig_topo_str() { return {"original_topology_type"}; } + std::string orig_block_order() { return {"original_block_order"}; } template Ioss::GroupingEntity *get_entity_internal(int64_t id, const std::vector &entities) @@ -295,64 +295,6 @@ namespace { entity->field_erase(role); } } - - template - Ioss::Field::RoleType - verify_field_exists_on_any_entity_group(const std::string &field_name, const Ioss::Region ®ion, - const std::vector &entity_container, - const std::string &inout) - { - bool found = false; - Ioss::Field::RoleType role = Ioss::Field::RoleType::INTERNAL; - - for (const T *entity : entity_container) { - if (entity->field_exists(field_name)) { - Ioss::Field field = entity->get_field(field_name); - - if (found == true && field.get_role() != role) { - std::string filename = region.get_database()->get_filename(); - std::ostringstream errmsg; - fmt::print(errmsg, - "\nERROR: On database '{}', Field '{}' does not have a consistent role across " - "element blocks on {}\n\n", - filename, field_name, region.name()); - IOSS_ERROR(errmsg); - } - - found = true; - role = field.get_role(); - } - } - - if (!found) { - std::string filename = region.get_database()->get_filename(); - std::ostringstream errmsg; - fmt::print(errmsg, - "\nERROR: On database '{}', Field '{}' does not exist for any {} element blocks " - "on {} {}\n\n", - filename, field_name, inout, region.type_string(), region.name()); - IOSS_ERROR(errmsg); - } - - return role; - } - - template - size_t get_all_block_field_data_count(const std::string &field_name, - const std::vector &entity_container) - { - size_t count = 0; - - for (const T *entity : entity_container) { - if (entity->field_exists(field_name)) { - Ioss::Field field = entity->get_field(field_name); - - count += entity->entity_count() * field.raw_storage()->component_count(); - } - } - - return count; - } } // namespace namespace Ioss { @@ -2457,7 +2399,7 @@ namespace Ioss { IOSS_ERROR(errmsg); } - /** \brief Get an implicit property -- These are calcuated from data stored + /** \brief Get an implicit property -- These are calculated from data stored * in the grouping entity instead of having an explicit value assigned. * * An example would be 'element_block_count' for a region. @@ -2472,71 +2414,71 @@ namespace Ioss { return nodeBlocks[0]->get_property("component_degree"); } - return Property(my_name, 0); + return {my_name, 0}; } if (my_name == "node_block_count") { - return Property(my_name, static_cast(nodeBlocks.size())); + return {my_name, static_cast(nodeBlocks.size())}; } if (my_name == "edge_block_count") { - return Property(my_name, static_cast(edgeBlocks.size())); + return {my_name, static_cast(edgeBlocks.size())}; } if (my_name == "face_block_count") { - return Property(my_name, static_cast(faceBlocks.size())); + return {my_name, static_cast(faceBlocks.size())}; } if (my_name == "element_block_count") { - return Property(my_name, static_cast(elementBlocks.size())); + return {my_name, static_cast(elementBlocks.size())}; } if (my_name == "structured_block_count") { - return Property(my_name, static_cast(structuredBlocks.size())); + return {my_name, static_cast(structuredBlocks.size())}; } if (my_name == "assembly_count") { - return Property(my_name, static_cast(assemblies.size())); + return {my_name, static_cast(assemblies.size())}; } if (my_name == "blob_count") { - return Property(my_name, static_cast(blobs.size())); + return {my_name, static_cast(blobs.size())}; } if (my_name == "side_set_count") { - return Property(my_name, static_cast(sideSets.size())); + return {my_name, static_cast(sideSets.size())}; } if (my_name == "node_set_count") { - return Property(my_name, static_cast(nodeSets.size())); + return {my_name, static_cast(nodeSets.size())}; } if (my_name == "edge_set_count") { - return Property(my_name, static_cast(edgeSets.size())); + return {my_name, static_cast(edgeSets.size())}; } if (my_name == "face_set_count") { - return Property(my_name, static_cast(faceSets.size())); + return {my_name, static_cast(faceSets.size())}; } if (my_name == "element_set_count") { - return Property(my_name, static_cast(elementSets.size())); + return {my_name, static_cast(elementSets.size())}; } if (my_name == "comm_set_count") { - return Property(my_name, static_cast(commSets.size())); + return {my_name, static_cast(commSets.size())}; } if (my_name == "coordinate_frame_count") { - return Property(my_name, static_cast(coordinateFrames.size())); + return {my_name, static_cast(coordinateFrames.size())}; } if (my_name == "state_count") { - return Property(my_name, stateCount); + return {my_name, stateCount}; } if (my_name == "current_state") { - return Property(my_name, currentState); + return {my_name, currentState}; } if (my_name == "element_count") { @@ -2544,7 +2486,7 @@ namespace Ioss { for (const auto &eb : elementBlocks) { count += eb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "cell_count") { @@ -2552,7 +2494,7 @@ namespace Ioss { for (const auto &eb : structuredBlocks) { count += eb->get_property("cell_count").get_int(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "face_count") { @@ -2560,7 +2502,7 @@ namespace Ioss { for (const auto &fb : faceBlocks) { count += fb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "edge_count") { @@ -2568,7 +2510,7 @@ namespace Ioss { for (const auto &eb : edgeBlocks) { count += eb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "node_count") { @@ -2576,12 +2518,12 @@ namespace Ioss { for (const auto &nb : nodeBlocks) { count += nb->entity_count(); } - return Property(my_name, count); + return {my_name, count}; } if (my_name == "database_name") { std::string filename = get_database()->get_filename(); - return Property(my_name, filename); + return {my_name, filename}; } { @@ -2801,41 +2743,4 @@ namespace Ioss { } } - std::vector Region::internal_get_all_block_field_data(const std::string &field_name, - void *data, size_t data_size) const - { - return get_database()->get_all_block_field_data(field_name, data, data_size); - } - - template IOSS_EXPORT std::vector - Region::get_all_block_field_data(const std::string &field_name, - std::vector &field_data) const; - template IOSS_EXPORT std::vector - Region::get_all_block_field_data(const std::string &field_name, - std::vector &field_data) const; - template IOSS_EXPORT std::vector - Region::get_all_block_field_data(const std::string &field_name, - std::vector &field_data) const; - - template - std::vector Region::get_all_block_field_data(const std::string &field_name, - std::vector &field_data) const - { - const Ioss::ElementBlockContainer &elem_blocks = get_element_blocks(); - - verify_field_exists_on_any_entity_group(field_name, *this, elem_blocks, "input"); - - size_t field_count = get_all_block_field_data_count(field_name, elem_blocks); - field_data.resize(field_count); - - size_t data_size = field_count * sizeof(T); - std::vector offsets = - internal_get_all_block_field_data(field_name, field_data.data(), data_size); - - assert(offsets.size() == (elem_blocks.size() + 1)); - assert(offsets[elem_blocks.size()] == field_count); - - return offsets; - } - } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/Ioss_Region.h b/packages/seacas/libraries/ioss/src/Ioss_Region.h index 00d5152318..5d94933e8e 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Region.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Region.h @@ -18,12 +18,15 @@ #include // for State #include // for size_t, nullptr #include // for int64_t -#include // for less -#include // for ostream -#include // for map, map<>::value_compare -#include // for string, operator< -#include // for pair -#include // for vector +#include +#include // for less +#include // for ostream +#include // for map, map<>::value_compare +#include +#include // for string, operator< +#include // for pair +#include // for vector + namespace Ioss { class Assembly; class Blob; @@ -252,7 +255,7 @@ namespace Ioss { // or greater than number of cell-nodes in database) StructuredBlock *get_structured_block(size_t global_offset) const; - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; @@ -265,9 +268,10 @@ namespace Ioss { void add_qa_record(const std::string &code, const std::string &code_qa, const std::string &date = "", const std::string &time = ""); - template - std::vector get_all_block_field_data(const std::string &field_name, - std::vector &field_data) const; + template + std::vector get_entity_field_data(const std::string &field_name, + const std::vector &entity_container, + std::vector &field_data) const; protected: int64_t internal_get_field_data(const Field &field, void *data, @@ -280,8 +284,10 @@ namespace Ioss { size_t *data_size) const override; private: - std::vector internal_get_all_block_field_data(const std::string &field_name, void *data, - size_t data_size = 0) const; + template + std::vector internal_get_entity_field_data(const std::string &field_name, + const std::vector &entity_container, + void *data, size_t data_size = 0) const; // Add the name 'alias' as an alias for the database entity with the // name 'db_name'. Returns true if alias added; false if problems @@ -405,3 +411,88 @@ inline const std::vector &Ioss::Region::get_qa_records() const IOSS_FUNC_ENTER(m_); return get_database()->get_qa_records(); } + +namespace Ioss { + + template + bool verify_field_exists_in_entity_group(const std::string &field_name, + const std::vector &entity_container) + { + bool found = false; + Ioss::Field::RoleType role = Ioss::Field::RoleType::INTERNAL; + + for (const T *entity : entity_container) { + if (entity->field_exists(field_name)) { + Ioss::Field field = entity->get_field(field_name); + + if (found && field.get_role() != role) { + std::ostringstream errmsg; + fmt::print(errmsg, + "ERROR: Field {} with role {} on entity {} does not match previously found " + "role {}.\n", + field.get_name(), field.role_string(), entity->name(), + Ioss::Field::role_string(role)); + IOSS_ERROR(errmsg); + } + + found = true; + role = field.get_role(); + } + } + + return found; + } + + namespace impl { + template + size_t get_field_data_count_for_entities(const std::string &field_name, + const std::vector &entity_container) + { + size_t count = 0; + + for (const T *entity : entity_container) { + if (entity->field_exists(field_name)) { + Ioss::Field field = entity->get_field(field_name); + + count += entity->entity_count() * field.raw_storage()->component_count(); + } + } + + return count; + } + } // namespace impl +} // namespace Ioss + +template +std::vector Ioss::Region::get_entity_field_data(const std::string &field_name, + const std::vector &entity_container, + std::vector &field_data) const +{ + bool field_exists = verify_field_exists_in_entity_group(field_name, entity_container); + + if (!field_exists) { + return std::vector(entity_container.size() + 1, 0); + } + + size_t field_count = impl::get_field_data_count_for_entities(field_name, entity_container); + + field_data.resize(field_count); + size_t data_size = field_count * sizeof(U); + + std::vector offsets = + internal_get_entity_field_data(field_name, entity_container, field_data.data(), data_size); + + assert(offsets.size() == (entity_container.size() + 1)); + assert(offsets[entity_container.size()] == field_count); + + return offsets; +} + +template +std::vector +Ioss::Region::internal_get_entity_field_data(const std::string &field_name, + const std::vector &entity_container, void *data, + size_t data_size) const +{ + return get_database()->get_entity_field_data(field_name, entity_container, data, data_size); +} diff --git a/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h b/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h index 4f298234be..4f6dff0f82 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h +++ b/packages/seacas/libraries/ioss/src/Ioss_ScopeGuard.h @@ -21,7 +21,7 @@ namespace Ioss { public: explicit RefHolder(T &ref) : ref_(ref) {} - operator T &() const { return ref_; } + explicit operator T &() const { return ref_; } RefHolder &operator=(const RefHolder &) = delete; }; @@ -61,7 +61,7 @@ namespace Ioss { #ifndef _MSC_VER __attribute__((unused)) #endif - typedef const ScopeGuardImplBase &ScopeGuard; + typedef const ScopeGuardImplBase &ScopeGuard; // NOLINT template class ScopeGuardImpl0 : public ScopeGuardImplBase { @@ -210,14 +210,14 @@ namespace Ioss { } template - inline ObjScopeGuardImpl1 MakeGuard(Ret (Obj2::*memFun)(P1a), + inline ObjScopeGuardImpl1 MakeGuard(Ret (Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) { return ObjScopeGuardImpl1::MakeObjGuard(obj, memFun, p1); } template - inline ObjScopeGuardImpl1 MakeGuard(Ret (Obj2::*memFun)(P1a), + inline ObjScopeGuardImpl1 MakeGuard(Ret (Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) { return ObjScopeGuardImpl1::MakeObjGuard(*obj, memFun, p1); diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C index bf7b193f66..422f62a1c7 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.C @@ -131,12 +131,12 @@ Ioss::Property Ioss::SideBlock::get_implicit_property(const std::string &my_name if (field_exists("distribution_factors")) { int64_t nnodes = topology()->number_nodes(); int64_t nside = entity_count(); - return Ioss::Property(my_name, nnodes * nside); + return {my_name, nnodes * nside}; } - return Ioss::Property(my_name, 0); + return {my_name, 0}; } if (my_name == "parent_topology_type") { - return Ioss::Property(my_name, parent_element_topology()->name()); + return {my_name, parent_element_topology()->name()}; } return Ioss::EntityBlock::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h index 70ac34c045..c304ba40bb 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_SideBlock.h @@ -79,7 +79,7 @@ namespace Ioss { void block_membership(std::vector &block_members) override; - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideSet.C b/packages/seacas/libraries/ioss/src/Ioss_SideSet.C index 1405e59d1c..ef9cbe3bce 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideSet.C +++ b/packages/seacas/libraries/ioss/src/Ioss_SideSet.C @@ -20,7 +20,7 @@ #include "Ioss_PropertyManager.h" namespace { - std::string id_str() { return std::string("id"); } + std::string id_str() { return {"id"}; } void check_for_duplicate_names(const Ioss::SideSet *sset, const Ioss::SideBlock *side_block) { const std::string &name = side_block->name(); @@ -134,10 +134,10 @@ int64_t Ioss::SideSet::internal_get_zc_field_data(const Field &field, void **dat Ioss::Property Ioss::SideSet::get_implicit_property(const std::string &my_name) const { if (my_name == "side_block_count") { - return Ioss::Property(my_name, static_cast(sideBlocks.size())); + return {my_name, static_cast(sideBlocks.size())}; } if (my_name == "block_count") { - return Ioss::Property(my_name, static_cast(sideBlocks.size())); + return {my_name, static_cast(sideBlocks.size())}; } return Ioss::GroupingEntity::get_implicit_property(my_name); diff --git a/packages/seacas/libraries/ioss/src/Ioss_SideSet.h b/packages/seacas/libraries/ioss/src/Ioss_SideSet.h index 2305306164..9f5b49a7fa 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SideSet.h +++ b/packages/seacas/libraries/ioss/src/Ioss_SideSet.h @@ -47,7 +47,7 @@ namespace Ioss { void block_membership(std::vector &block_members) override; - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_SmartAssert.h b/packages/seacas/libraries/ioss/src/Ioss_SmartAssert.h index 60c483ceb5..6e8daebbad 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_SmartAssert.h +++ b/packages/seacas/libraries/ioss/src/Ioss_SmartAssert.h @@ -333,7 +333,7 @@ namespace Ioss { .SMART_ASSERT_A /**/ #else -// "release" mode + // "release" mode #define SMART_ASSERT(expr) \ if (true) \ ; \ diff --git a/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C b/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C index fea2dc0a89..999a2dd7eb 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C +++ b/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.C @@ -274,22 +274,22 @@ namespace Ioss { Property StructuredBlock::get_implicit_property(const std::string &my_name) const { if (my_name == "ni_global") { - return Ioss::Property(my_name, m_ijkGlobal[0]); + return {my_name, m_ijkGlobal[0]}; } if (my_name == "nj_global") { - return Ioss::Property(my_name, m_ijkGlobal[1]); + return {my_name, m_ijkGlobal[1]}; } if (my_name == "nk_global") { - return Ioss::Property(my_name, m_ijkGlobal[2]); + return {my_name, m_ijkGlobal[2]}; } if (my_name == "offset_i") { - return Ioss::Property(my_name, m_offset[0]); + return {my_name, m_offset[0]}; } if (my_name == "offset_j") { - return Ioss::Property(my_name, m_offset[1]); + return {my_name, m_offset[1]}; } if (my_name == "offset_k") { - return Ioss::Property(my_name, m_offset[2]); + return {my_name, m_offset[2]}; } return EntityBlock::get_implicit_property(my_name); } diff --git a/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.h b/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.h index 594fd03f17..5e4bb07405 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.h +++ b/packages/seacas/libraries/ioss/src/Ioss_StructuredBlock.h @@ -126,7 +126,7 @@ namespace Ioss { */ bool is_active() const { return m_ijk[0] * m_ijk[1] * m_ijk[2] > 0; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Property get_implicit_property(const std::string &my_name) const override; diff --git a/packages/seacas/libraries/ioss/src/Ioss_Utils.C b/packages/seacas/libraries/ioss/src/Ioss_Utils.C index 4e9477d871..fa64c33959 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Utils.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Utils.C @@ -486,7 +486,7 @@ namespace { if (!found_valid) { // Return an invalid field... - return Ioss::Field("", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1); + return {"", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1}; } // At this point, name[index] should be a valid potential field @@ -617,7 +617,7 @@ namespace { } suffix_size--; } - return Ioss::Field("", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1); + return {"", Ioss::Field::INVALID, IOSS_SCALAR(), fld_role, 1}; } // common @@ -953,44 +953,44 @@ int64_t Ioss::Utils::get_side_offset(const Ioss::SideBlock *sb) std::string Ioss::Utils::shape_to_string(const Ioss::ElementShape &shape) { switch (shape) { - case Ioss::ElementShape::UNKNOWN: return std::string("Unknown"); - case Ioss::ElementShape::POINT: return std::string("Point"); - case Ioss::ElementShape::SPHERE: return std::string("Sphere"); - case Ioss::ElementShape::LINE: return std::string("Line"); - case Ioss::ElementShape::SPRING: return std::string("Spring"); - case Ioss::ElementShape::TRI: return std::string("Tri"); - case Ioss::ElementShape::QUAD: return std::string("Quad"); - case Ioss::ElementShape::TET: return std::string("Tet"); - case Ioss::ElementShape::PYRAMID: return std::string("Pyramid"); - case Ioss::ElementShape::WEDGE: return std::string("Wedge"); - case Ioss::ElementShape::HEX: return std::string("Hex"); - case Ioss::ElementShape::SUPER: return std::string("Super"); + case Ioss::ElementShape::UNKNOWN: return {"Unknown"}; + case Ioss::ElementShape::POINT: return {"Point"}; + case Ioss::ElementShape::SPHERE: return {"Sphere"}; + case Ioss::ElementShape::LINE: return {"Line"}; + case Ioss::ElementShape::SPRING: return {"Spring"}; + case Ioss::ElementShape::TRI: return {"Tri"}; + case Ioss::ElementShape::QUAD: return {"Quad"}; + case Ioss::ElementShape::TET: return {"Tet"}; + case Ioss::ElementShape::PYRAMID: return {"Pyramid"}; + case Ioss::ElementShape::WEDGE: return {"Wedge"}; + case Ioss::ElementShape::HEX: return {"Hex"}; + case Ioss::ElementShape::SUPER: return {"Super"}; } - return std::string("Invalid shape [") + std::to_string(unsigned(shape)) + std::string("]"); + return fmt::format("Invalid shape [{}]", unsigned(shape)); } std::string Ioss::Utils::entity_type_to_string(const Ioss::EntityType &type) { switch (type) { - case Ioss::EntityType::NODEBLOCK: return std::string("NODEBLOCK"); - case Ioss::EntityType::EDGEBLOCK: return std::string("EDGEBLOCK"); - case Ioss::EntityType::FACEBLOCK: return std::string("FACEBLOCK"); - case Ioss::EntityType::ELEMENTBLOCK: return std::string("ELEMENTBLOCK"); - case Ioss::EntityType::NODESET: return std::string("NODESET"); - case Ioss::EntityType::EDGESET: return std::string("EDGESET"); - case Ioss::EntityType::FACESET: return std::string("FACESET"); - case Ioss::EntityType::ELEMENTSET: return std::string("ELEMENTSET"); - case Ioss::EntityType::SIDESET: return std::string("SIDESET"); - case Ioss::EntityType::COMMSET: return std::string("COMMSET"); - case Ioss::EntityType::SIDEBLOCK: return std::string("SIDEBLOCK"); - case Ioss::EntityType::REGION: return std::string("REGION"); - case Ioss::EntityType::SUPERELEMENT: return std::string("SUPERELEMENT"); - case Ioss::EntityType::STRUCTUREDBLOCK: return std::string("STRUCTUREDBLOCK"); - case Ioss::EntityType::ASSEMBLY: return std::string("ASSEMBLY"); - case Ioss::EntityType::BLOB: return std::string("BLOB"); - case Ioss::EntityType::INVALID_TYPE: return std::string("INVALID_TYPE"); + case Ioss::EntityType::NODEBLOCK: return {"NODEBLOCK"}; + case Ioss::EntityType::EDGEBLOCK: return {"EDGEBLOCK"}; + case Ioss::EntityType::FACEBLOCK: return {"FACEBLOCK"}; + case Ioss::EntityType::ELEMENTBLOCK: return {"ELEMENTBLOCK"}; + case Ioss::EntityType::NODESET: return {"NODESET"}; + case Ioss::EntityType::EDGESET: return {"EDGESET"}; + case Ioss::EntityType::FACESET: return {"FACESET"}; + case Ioss::EntityType::ELEMENTSET: return {"ELEMENTSET"}; + case Ioss::EntityType::SIDESET: return {"SIDESET"}; + case Ioss::EntityType::COMMSET: return {"COMMSET"}; + case Ioss::EntityType::SIDEBLOCK: return {"SIDEBLOCK"}; + case Ioss::EntityType::REGION: return {"REGION"}; + case Ioss::EntityType::SUPERELEMENT: return {"SUPERELEMENT"}; + case Ioss::EntityType::STRUCTUREDBLOCK: return {"STRUCTUREDBLOCK"}; + case Ioss::EntityType::ASSEMBLY: return {"ASSEMBLY"}; + case Ioss::EntityType::BLOB: return {"BLOB"}; + case Ioss::EntityType::INVALID_TYPE: return {"INVALID_TYPE"}; } - return std::string("Invalid entity type [") + std::to_string(unsigned(type)) + std::string("]"); + return fmt::format("Invalid entity type [{}]", unsigned(type)); } unsigned int Ioss::Utils::hash(const std::string &name) @@ -1159,7 +1159,7 @@ namespace { // Convert to base-26 'number' hashval %= HASHSIZE; char word[3] = {char(hashval / 26 + 'a'), char(hashval % 26 + 'a'), '\0'}; - return (std::string(word)); + return {word}; } } // namespace diff --git a/packages/seacas/libraries/ioss/src/Ioss_Utils.h b/packages/seacas/libraries/ioss/src/Ioss_Utils.h index ddf93952cd..f1a320f278 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Utils.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Utils.h @@ -17,13 +17,9 @@ #include // for sort, lower_bound, copy, etc #include #include -#include // for size_t -#include // for int64_t -#include // for nullptrr -#if __has_include() -#include -#define HAS_FILESYSTEM -#endif +#include // for size_t +#include // for int64_t +#include // for nullptrr #include // for ostringstream, etcstream, etc #include // for runtime_error #include // for string @@ -115,18 +111,17 @@ namespace Ioss { } } + // NOTE: This code previously checked for existence of filesystem include, but + // gcc-8.X has the include but needs a library, also intel and clang + // pretend to be gcc, so macro to test for usability of filesystem + // was complicated and we can easily get by with the following code. static bool is_path_absolute(const std::string &path) { if (!path.empty()) { -#ifdef HAS_FILESYSTEM - std::filesystem::path p1 = path; - return p1.is_absolute(); -#else #ifdef __IOSS_WINDOWS__ return path[0] == '\\' && path[1] == ':'; #else return path[0] == '/'; -#endif #endif } return false; @@ -231,7 +226,7 @@ namespace Ioss { if (number == 0) { return 1; } - int width = int(std::floor(std::log10(number))) + 1; + int width = static_cast(std::floor(std::log10(number))) + 1; if (use_commas) { width += ((width - 1) / 3); } diff --git a/packages/seacas/libraries/ioss/src/Ioss_VariableType.h b/packages/seacas/libraries/ioss/src/Ioss_VariableType.h index 0f4cc035ec..ec74a3ca1b 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_VariableType.h +++ b/packages/seacas/libraries/ioss/src/Ioss_VariableType.h @@ -43,7 +43,7 @@ namespace Ioss { struct IOSS_EXPORT Suffix { explicit Suffix(const char *new_data) : m_data(new_data) {} - explicit Suffix(const std::string &new_data) : m_data(new_data) {} + explicit Suffix(std::string new_data) : m_data(std::move(new_data)) {} bool operator==(const std::string &str) const { return Utils::str_equal(m_data, str); } bool operator!=(const std::string &str) const { return !Utils::str_equal(m_data, str); } bool is_uppercase() const { return isalpha(m_data[0]) && isupper(m_data[0]); } diff --git a/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.C b/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.C index 6886c0231b..63de1523f7 100644 --- a/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.C +++ b/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.C @@ -12,9 +12,9 @@ namespace Ioad { AdiosWrapper::AdiosWrapper(Ioss_MPI_Comm comm, const std::string &filename, bool is_input, unsigned long rank, const Ioss::PropertyManager &properties) - : adios2::ADIOS(comm), adios2::IO(IOInit(properties, is_input)), adios2::Engine(EngineInit( - filename, is_input)), - m_Rank(rank), m_Communicator(comm), m_OpenStep(false) + : adios2::ADIOS(comm), adios2::IO(IOInit(properties, is_input)), + adios2::Engine(EngineInit(filename, is_input)), m_Rank(rank), m_Communicator(comm), + m_OpenStep(false) { } diff --git a/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.h b/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.h index 598ec252b1..fab957328a 100644 --- a/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.h +++ b/packages/seacas/libraries/ioss/src/adios/AdiosWrapper.h @@ -8,6 +8,7 @@ #include "ioad_export.h" +#include #include #include #include @@ -69,7 +70,7 @@ namespace Ioad { const std::string m_MetaSeparator{"::"}; - const int m_Rank; + const int m_Rank; const Ioss_MPI_Comm m_Communicator; bool m_OpenStep; diff --git a/packages/seacas/libraries/ioss/src/adios/CMakeLists.txt b/packages/seacas/libraries/ioss/src/adios/CMakeLists.txt index b574784591..5af0e96ac5 100644 --- a/packages/seacas/libraries/ioss/src/adios/CMakeLists.txt +++ b/packages/seacas/libraries/ioss/src/adios/CMakeLists.txt @@ -24,9 +24,3 @@ generate_export_header(Ioad) target_include_directories(Ioad PUBLIC "$") - -IF (BUILD_TESTING) - ENABLE_TESTING() -ENDIF() - -TRIBITS_ADD_TEST_DIRECTORIES(utest) diff --git a/packages/seacas/libraries/ioss/src/adios/Ioad_Constants.h b/packages/seacas/libraries/ioss/src/adios/Ioad_Constants.h index 401ce80052..8aed57339b 100644 --- a/packages/seacas/libraries/ioss/src/adios/Ioad_Constants.h +++ b/packages/seacas/libraries/ioss/src/adios/Ioad_Constants.h @@ -15,25 +15,25 @@ namespace Ioad { // Constant variables - IOAD_EXPORT const std::string Schema_version_string = "IOSS_adios_version"; - IOAD_EXPORT const std::string Sideblock_separator = "::"; - IOAD_EXPORT const std::string Name_separator = "/"; - IOAD_EXPORT const std::string Role_meta = "role"; - IOAD_EXPORT const std::string Var_type_meta = "var_type"; - IOAD_EXPORT const std::string Topology_meta = "topology"; - IOAD_EXPORT const std::string property_meta = "property_"; - IOAD_EXPORT const std::string Parent_topology_meta = "parent_topology"; - IOAD_EXPORT const std::string Time_scale_factor = "time_scale_factor"; - IOAD_EXPORT const std::string Time_meta = "time"; - IOAD_EXPORT const std::string Processor_id_meta = "processor_id"; - IOAD_EXPORT const std::string Processor_number_meta = "processor_number"; - IOAD_EXPORT const std::string globals_entity_type = "globals"; - IOAD_EXPORT const std::string globals_entity_name = ""; - IOAD_EXPORT const std::string region_name = "no_name"; - IOAD_EXPORT const std::string original_name = "original_name"; - constexpr const char *sideblock_names = "sideblock_names"; + IOAD_EXPORT const std::string Schema_version_string = "IOSS_adios_version"; + IOAD_EXPORT const std::string Sideblock_separator = "::"; + IOAD_EXPORT const std::string Name_separator = "/"; + IOAD_EXPORT const std::string Role_meta = "role"; + IOAD_EXPORT const std::string Var_type_meta = "var_type"; + IOAD_EXPORT const std::string Topology_meta = "topology"; + IOAD_EXPORT const std::string property_meta = "property_"; + IOAD_EXPORT const std::string Parent_topology_meta = "parent_topology"; + IOAD_EXPORT const std::string Time_scale_factor = "time_scale_factor"; + IOAD_EXPORT const std::string Time_meta = "time"; + IOAD_EXPORT const std::string Processor_id_meta = "processor_id"; + IOAD_EXPORT const std::string Processor_number_meta = "processor_number"; + IOAD_EXPORT const std::string globals_entity_type = "globals"; + IOAD_EXPORT const std::string globals_entity_name = ""; + IOAD_EXPORT const std::string region_name = "no_name"; + IOAD_EXPORT const std::string original_name = "original_name"; + constexpr const char *sideblock_names = "sideblock_names"; - IOAD_EXPORT const std::string coordinate_frame_name = "CoordinateFrame"; + IOAD_EXPORT const std::string coordinate_frame_name = "CoordinateFrame"; IOAD_EXPORT const std::map> Use_transformed_storage_map = { {"ElementBlock", {"connectivity_edge", "connectivity_face"}}, {"FaceBlock", {"connectivity_edge"}}}; diff --git a/packages/seacas/libraries/ioss/src/adios/Ioad_Helper.h b/packages/seacas/libraries/ioss/src/adios/Ioad_Helper.h index 5e7ea44f7a..c18be10120 100644 --- a/packages/seacas/libraries/ioss/src/adios/Ioad_Helper.h +++ b/packages/seacas/libraries/ioss/src/adios/Ioad_Helper.h @@ -22,13 +22,13 @@ namespace Ioad { typename std::enable_if::value, bool>::type; template - using IossHas3ParametersConstructor = decltype(DerivedFromIossGroupingEntity{}, - T(nullptr, std::string{}, int64_t{})); + using IossHas3ParametersConstructor = + decltype(DerivedFromIossGroupingEntity{}, T(nullptr, std::string{}, int64_t{})); template - using IossHas4ParametersConstructor = decltype(DerivedFromIossGroupingEntity{}, - T(nullptr, std::string{}, std::string{}, - int64_t{})); + using IossHas4ParametersConstructor = + decltype(DerivedFromIossGroupingEntity{}, + T(nullptr, std::string{}, std::string{}, int64_t{})); // Takes an extra unused parameter "entity_type" to match the API of the function // "NewEntity" used for objects that are not EntitySets which require that parameter. @@ -51,21 +51,24 @@ namespace Ioad { return new T(io_database, my_name, entity_type, entity_count); } - IOAD_EXPORT int find_field_in_mapset(const std::string &entity_type, const std::string &field_name, - const std::map> &mapset); + IOAD_EXPORT int find_field_in_mapset(const std::string &entity_type, + const std::string &field_name, + const std::map> &mapset); - IOAD_EXPORT std::string get_property_variable_name(const std::string &property_name); - IOAD_EXPORT std::vector properties_to_save(const Ioss::GroupingEntity *const entity_block); + IOAD_EXPORT std::string get_property_variable_name(const std::string &property_name); + IOAD_EXPORT std::vector + properties_to_save(const Ioss::GroupingEntity *const entity_block); IOAD_EXPORT std::string stringify_side_block_names(const Ioss::SideBlockContainer &sblocks); IOAD_EXPORT std::string encode_field_name(std::vector names); - IOAD_EXPORT std::string encode_sideblock_name(const std::string &type_string, const std::string &name); + IOAD_EXPORT std::string encode_sideblock_name(const std::string &type_string, + const std::string &name); IOAD_EXPORT bool is_sideblock_name(const std::string &name); IOAD_EXPORT bool use_transformed_storage(const Ioss::Field &field, const std::string &entity_type, - const std::string &field_name); + const std::string &field_name); } // namespace Ioad diff --git a/packages/seacas/libraries/ioss/src/adios/utest/CMakeLists.txt b/packages/seacas/libraries/ioss/src/adios/utest/CMakeLists.txt deleted file mode 100644 index 23d861ef12..0000000000 --- a/packages/seacas/libraries/ioss/src/adios/utest/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -TRIBITS_ADD_EXECUTABLE( -Ut_ioad -SOURCES Ut_ioad.C -IMPORTEDLIBS Ionit -) - -TRIBITS_ADD_TEST( - Ut_ioad - NAME Ut_ioad - NUM_MPI_PROCS 1 -) - -TRIBITS_INCLUDE_DIRECTORIES( - "${CMAKE_CURRENT_SOURCE_DIR}/../" - "${CMAKE_CURRENT_BINARY_DIR}/../" - "${CMAKE_CURRENT_SOURCE_DIR}/../../" -) diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h index 1b2f666217..c7ff45c0f3 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.h @@ -195,7 +195,6 @@ namespace Iocgns { const Ioss::Map &get_map(Ioss::Map &entity_map, int64_t entityCount, int64_t file_offset, int64_t file_count, entity_type type) const; - private: mutable int m_cgnsFilePtr{-1}; mutable int m_cgnsBasePtr{ -1}; // If using links to file-per-state, the file pointer for "base" file. diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_StructuredZoneData.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_StructuredZoneData.C index 9cebe6774e..b1a70ebc1d 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_StructuredZoneData.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_StructuredZoneData.C @@ -8,8 +8,11 @@ #include #include #include +#if !defined __NVCC__ #include +#endif #include +#include #include namespace { @@ -362,7 +365,9 @@ namespace Iocgns { fmt::print( Ioss::DebugOut(), "{}", fmt::format( +#if !defined __NVCC__ fg(fmt::color::cyan), +#endif "\nSplit Zone {} ({}) Adam {} ({}) with intervals {:>12},\twork = {:12}, offset {} " "{} {}, ordinal {}, ratio {:.3f}\n", m_name, m_zone, m_adam->m_name, m_adam->m_zone, diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C index 2ff4986cc5..bd558c1d23 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C @@ -36,10 +36,13 @@ #include #include +#if !defined __NVCC__ #include +#endif #include #include #include +#include #include #include @@ -63,7 +66,7 @@ } while (0) namespace { -#if defined(__IOSS_WINDOWS__) +#if defined(__IOSS_WINDOWS__) || defined(__CYGWIN__) const char *strcasestr(const char *haystack, const char *needle) { std::string lneedle(Ioss::Utils::lowercase(needle)); @@ -1067,7 +1070,7 @@ size_t Iocgns::Utils::common_write_meta_data(int file_ptr, const Ioss::Region &r std::string code_version = region.get_optional_property("code_version", "unknown"); std::string code_name = region.get_optional_property("code_name", "unknown"); - std::string mpi_version = ""; + std::string mpi_version{}; #if CG_BUILD_PARALLEL { char version[MPI_MAX_LIBRARY_VERSION_STRING]; @@ -2562,7 +2565,10 @@ void Iocgns::Utils::decompose_model(std::vector &z px++; if (verbose && rank == 0) { fmt::print(Ioss::DebugOut(), "{}", - fmt::format(fg(fmt::color::red), + fmt::format( +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "\nProcessor {} work: {}, workload ratio: {} (exceeds)", i, fmt::group_digits(work_vector[i]), workload_ratio)); } @@ -2578,7 +2584,7 @@ void Iocgns::Utils::decompose_model(std::vector &z fmt::print(Ioss::DebugOut(), "\n\nWorkload threshold exceeded on {} processors.\n", px); } bool single_zone = zones.size() == 1; - if (single_zone) { + if (single_zone) { // GDS: Don't understand this code... !single_zone? auto active = std::count_if(zones.begin(), zones.end(), [](Iocgns::StructuredZoneData *a) { return a->is_active(); }); if (active >= proc_count) { @@ -2714,19 +2720,21 @@ int Iocgns::Utils::pre_split(std::vector &zones, d int new_zone_id = static_cast(zones.size()) + 1; // See if can split each zone over a set of procs... - std::vector splits(zones.size()); + std::vector splits(zones.size(), 1); - for (size_t i = 0; i < zones.size(); i++) { - auto zone = zones[i]; - if (zone->m_lineOrdinal != 7) { - double work = zone->work(); - if (load_balance <= 1.2) { - splits[i] = int(std::ceil(work / avg_work)); - } - else { - splits[i] = int(std::round(work / avg_work + 0.2)); + if ((int)zones.size() < proc_count) { + for (size_t i = 0; i < zones.size(); i++) { + auto zone = zones[i]; + if (zone->m_lineOrdinal != 7) { + double work = zone->work(); + if (load_balance <= 1.2) { + splits[i] = int(std::ceil(work / avg_work)); + } + else { + splits[i] = int(std::round(work / avg_work + 0.2)); + } + splits[i] = splits[i] == 0 ? 1 : splits[i]; } - splits[i] = splits[i] == 0 ? 1 : splits[i]; } } @@ -2734,32 +2742,34 @@ int Iocgns::Utils::pre_split(std::vector &zones, d int diff = proc_count - num_splits; bool adjustment_needed = diff > 0; - while (diff != 0) { - // Adjust splits so sum is equal to proc_count. - // Adjust the largest split count(s) - int step = diff < 0 ? -1 : 1; - size_t min_z = 0; - double min_delta = 1.0e27; - for (size_t i = 0; i < zones.size(); i++) { - auto zone = zones[i]; - double work = zone->work(); - - if (splits[i] == 0) { - continue; - } - if ((splits[i] + step) > 0) { - double delta = std::abs(avg_work - work / (double)(splits[i] + step)); - if (delta < min_delta) { - min_delta = delta; - min_z = i; + if (num_splits != (int)zones.size()) { + while (diff != 0) { + // Adjust splits so sum is equal to proc_count. + // Adjust the largest split count(s) + int step = diff < 0 ? -1 : 1; + size_t min_z = 0; + double min_delta = 1.0e27; + for (size_t i = 0; i < zones.size(); i++) { + auto zone = zones[i]; + double work = zone->work(); + + if (splits[i] == 0) { + continue; + } + if ((splits[i] + step) > 0) { + double delta = std::abs(avg_work - work / (double)(splits[i] + step)); + if (delta < min_delta) { + min_delta = delta; + min_z = i; + } } } + splits[min_z] += step; + diff -= step; } - splits[min_z] += step; - diff -= step; + assert(diff == 0); + assert(std::accumulate(splits.begin(), splits.end(), 0) == proc_count); } - assert(diff == 0); - assert(std::accumulate(splits.begin(), splits.end(), 0) == proc_count); // See if splits result in avg_work for all zones in range... double min_avg = avg_work / load_balance; diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h index 6d99694a27..fa3affb691 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.h @@ -184,21 +184,21 @@ namespace Iocgns { switch (parent_topo->shape()) { case Ioss::ElementShape::HEX: { - static int hex_map[] = {0, 5, 1, 2, 3, 4, 6}; + static std::array hex_map = {0, 5, 1, 2, 3, 4, 6}; for (size_t i = 0; i < num_to_get; i++) { idata[2 * i + 1] = hex_map[idata[2 * i + 1]]; } } break; case Ioss::ElementShape::TET: { - static int tet_map[] = {0, 4, 1, 2, 3}; + static std::array tet_map = {0, 4, 1, 2, 3}; for (size_t i = 0; i < num_to_get; i++) { idata[2 * i + 1] = tet_map[idata[2 * i + 1]]; } } break; case Ioss::ElementShape::PYRAMID: { - static int pyr_map[] = {0, 5, 1, 2, 3, 4}; + static std::array pyr_map = {0, 5, 1, 2, 3, 4}; for (size_t i = 0; i < num_to_get; i++) { idata[2 * i + 1] = pyr_map[idata[2 * i + 1]]; } @@ -206,7 +206,7 @@ namespace Iocgns { case Ioss::ElementShape::WEDGE: #if 0 - static int wed_map[] = {0, 1, 2, 3, 4, 5}; // Same + static std::array wed_map = {0, 1, 2, 3, 4, 5}; // Same // Not needed -- maps 1 to 1 for (size_t i=0; i < num_to_get; i++) { idata[2*i+1] = wed_map[idata[2*i+1]]; diff --git a/packages/seacas/libraries/ioss/src/doctest.h b/packages/seacas/libraries/ioss/src/doctest.h index 5c754cde08..0c7a9a0e86 100644 --- a/packages/seacas/libraries/ioss/src/doctest.h +++ b/packages/seacas/libraries/ioss/src/doctest.h @@ -1,4 +1,5 @@ -// ====================================================================== lgtm [cpp/missing-header-guard] +// ====================================================================== lgtm +// [cpp/missing-header-guard] // == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == // ====================================================================== // @@ -42,6 +43,7 @@ #ifndef DOCTEST_LIBRARY_INCLUDED #define DOCTEST_LIBRARY_INCLUDED +// NOLINTBEGIN // ================================================================================================= // == VERSION ====================================================================================== // ================================================================================================= @@ -52,15 +54,14 @@ // util we need here #define DOCTEST_TOSTR_IMPL(x) #x -#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) #define DOCTEST_VERSION_STR \ - DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ - DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ - DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) + DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) \ + "." DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) #define DOCTEST_VERSION \ - (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) + (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) // ================================================================================================= // == COMPILER VERSION ============================================================================= @@ -82,13 +83,13 @@ #define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) #else // MSVC #define DOCTEST_MSVC \ - DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) + DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) #endif // MSVC #endif // MSVC #if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) #define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ - !defined(__INTEL_COMPILER) + !defined(__INTEL_COMPILER) #define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #endif // GCC #if defined(__INTEL_COMPILER) @@ -113,12 +114,12 @@ // ================================================================================================= #if DOCTEST_CLANG && !DOCTEST_ICC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) #define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") -#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) -#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") #define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) #else // DOCTEST_CLANG #define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH #define DOCTEST_CLANG_SUPPRESS_WARNING(w) @@ -127,12 +128,12 @@ #endif // DOCTEST_CLANG #if DOCTEST_GCC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) #define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") -#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) -#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") +#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") #define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) + DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) #else // DOCTEST_GCC #define DOCTEST_GCC_SUPPRESS_WARNING_PUSH #define DOCTEST_GCC_SUPPRESS_WARNING(w) @@ -142,10 +143,10 @@ #if DOCTEST_MSVC #define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) -#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) -#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) #define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) #else // DOCTEST_MSVC #define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH #define DOCTEST_MSVC_SUPPRESS_WARNING(w) @@ -160,56 +161,56 @@ // both the header and the implementation suppress all of these, // so it only makes sense to aggregate them like so #define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - /* these 4 also disabled globally via cmake: */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ - /* common ones */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ - /* static analysis */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + /* these 4 also disabled globally via cmake: */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ + /* common ones */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ + /* static analysis */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ #define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH @@ -226,25 +227,25 @@ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ #define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP @@ -279,7 +280,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #endif // DOCTEST_CONFIG_NO_WINDOWS_SEH #if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ - !defined(__EMSCRIPTEN__) && !defined(__wasi__) + !defined(__EMSCRIPTEN__) && !defined(__wasi__) #define DOCTEST_CONFIG_POSIX_SIGNALS #endif // _WIN32 #if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS) @@ -287,8 +288,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ - || defined(__wasi__) +#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) || \ + defined(__wasi__) #define DOCTEST_CONFIG_NO_EXCEPTIONS #endif // no exceptions #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -355,8 +356,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_UNUSED #define DOCTEST_ALIGNMENT(x) #else -#define DOCTEST_NOINLINE __attribute__((noinline)) -#define DOCTEST_UNUSED __attribute__((unused)) +#define DOCTEST_NOINLINE __attribute__((noinline)) +#define DOCTEST_UNUSED __attribute__((unused)) #define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) #endif @@ -384,10 +385,10 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #ifndef DOCTEST_CONSTEXPR #if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_CONSTEXPR const +#define DOCTEST_CONSTEXPR const #define DOCTEST_CONSTEXPR_FUNC inline #else // DOCTEST_MSVC -#define DOCTEST_CONSTEXPR constexpr +#define DOCTEST_CONSTEXPR constexpr #define DOCTEST_CONSTEXPR_FUNC constexpr #endif // DOCTEST_MSVC #endif // DOCTEST_CONSTEXPR @@ -405,19 +406,18 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define // ================================================================================================= #define DOCTEST_DECLARE_INTERFACE(name) \ - virtual ~name(); \ - name() = default; \ - name(const name&) = delete; \ - name(name&&) = delete; \ - name& operator=(const name&) = delete; \ - name& operator=(name&&) = delete; + virtual ~name(); \ + name() = default; \ + name(const name &) = delete; \ + name(name &&) = delete; \ + name &operator=(const name &) = delete; \ + name &operator=(name &&) = delete; -#define DOCTEST_DEFINE_INTERFACE(name) \ - name::~name() = default; +#define DOCTEST_DEFINE_INTERFACE(name) name::~name() = default; // internal macros for string concatenation and anonymous variable name generation #define DOCTEST_CAT_IMPL(s1, s2) s1##s2 -#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) +#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) #ifdef __COUNTER__ // not standard and may be missing for some compilers #define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) #else // __COUNTER__ @@ -425,7 +425,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #endif // __COUNTER__ #ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE -#define DOCTEST_REF_WRAP(x) x& +#define DOCTEST_REF_WRAP(x) x & #else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE #define DOCTEST_REF_WRAP(x) x #endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE @@ -443,14 +443,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly define #define DOCTEST_PLATFORM_LINUX #endif // DOCTEST_PLATFORM -namespace doctest { namespace detail { - static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } -}} +namespace doctest { + namespace detail { + static DOCTEST_CONSTEXPR int consume(const int *, int) noexcept { return 0; } + } // namespace detail +} // namespace doctest -#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ - static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP +#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ + static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #ifndef DOCTEST_BREAK_INTO_DEBUGGER // should probably take a look at https://github.com/scottt/debugbreak @@ -467,7 +469,11 @@ namespace doctest { namespace detail { #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) #elif defined(__ppc__) || defined(__ppc64__) // https://www.cocoawithlove.com/2008/03/break-into-debugger.html -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler) +#define DOCTEST_BREAK_INTO_DEBUGGER() \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : \ + : \ + : "memory", "r0", "r3", "r4") // NOLINT(hicpp-no-assembler) #else #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler) #endif @@ -511,39 +517,32 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include -#include #include +#include DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #else // DOCTEST_CONFIG_USE_STD_HEADERS // Forward declaring 'X' in namespace std is not permitted by the C++ Standard. DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) -namespace std { // NOLINT(cert-dcl58-cpp) -typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) -typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) -template -struct char_traits; -template <> -struct char_traits; -template -class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) -typedef basic_ostream> ostream; // NOLINT(modernize-use-using) -template -// NOLINTNEXTLINE -basic_ostream& operator<<(basic_ostream&, const char*); -template -class basic_istream; -typedef basic_istream> istream; // NOLINT(modernize-use-using) -template -class tuple; +namespace std { // NOLINT(cert-dcl58-cpp) + typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) + typedef decltype(sizeof(void *)) size_t; // NOLINT(modernize-use-using) + template struct char_traits; + template <> struct char_traits; + template class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) + typedef basic_ostream> ostream; // NOLINT(modernize-use-using) + template + // NOLINTNEXTLINE + basic_ostream &operator<<(basic_ostream &, const char *); + template class basic_istream; + typedef basic_istream> istream; // NOLINT(modernize-use-using) + template class tuple; #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -template -class allocator; -template -class basic_string; -using string = basic_string, allocator>; + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + template class allocator; + template class basic_string; + using string = basic_string, allocator>; #endif // VS 2019 } // namespace std @@ -557,94 +556,95 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP namespace doctest { -using std::size_t; + using std::size_t; -DOCTEST_INTERFACE extern bool is_running_in_test; + DOCTEST_INTERFACE extern bool is_running_in_test; #ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE #define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned #endif -// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length -// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for: -// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) -// - if small - capacity left before going on the heap - using the lowest 5 bits -// - if small - 2 bits are left unused - the second and third highest ones -// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) -// and the "is small" bit remains "0" ("as well as the capacity left") so its OK -// Idea taken from this lecture about the string implementation of facebook/folly - fbstring -// https://www.youtube.com/watch?v=kPR8h4-qZdk -// TODO: -// - optimizations - like not deleting memory unnecessarily in operator= and etc. -// - resize/reserve/clear -// - replace -// - back/front -// - iterator stuff -// - find & friends -// - push_back/pop_back -// - assign/insert/erase -// - relational operators as free functions - taking const char* as one of the params -class DOCTEST_INTERFACE String -{ -public: + // A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings + // with length of up to 23 chars on the stack before going on the heap - the last byte of the + // buffer is used for: + // - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) + // - if small - capacity left before going on the heap - using the lowest 5 bits + // - if small - 2 bits are left unused - the second and third highest ones + // - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) + // and the "is small" bit remains "0" ("as well as the capacity left") so its OK + // Idea taken from this lecture about the string implementation of facebook/folly - fbstring + // https://www.youtube.com/watch?v=kPR8h4-qZdk + // TODO: + // - optimizations - like not deleting memory unnecessarily in operator= and etc. + // - resize/reserve/clear + // - replace + // - back/front + // - iterator stuff + // - find & friends + // - push_back/pop_back + // - assign/insert/erase + // - relational operators as free functions - taking const char* as one of the params + class DOCTEST_INTERFACE String + { + public: using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; -private: - static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members - static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members + private: + static DOCTEST_CONSTEXPR size_type len = 24; //! OCLINT avoid private static members + static DOCTEST_CONSTEXPR size_type last = len - 1; //! OCLINT avoid private static members struct view // len should be more than sizeof(view) - because of the final byte for flags { - char* ptr; - size_type size; - size_type capacity; + char *ptr; + size_type size; + size_type capacity; }; - union - { - char buf[len]; // NOLINT(*-avoid-c-arrays) - view data; + union { + char buf[len]; // NOLINT(*-avoid-c-arrays) + view data; }; - char* allocate(size_type sz); + char *allocate(size_type sz); bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } void setOnHeap() noexcept; void setLast(size_type in = last) noexcept; void setSize(size_type sz) noexcept; - void copy(const String& other); + void copy(const String &other); -public: + public: static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); String() noexcept; ~String(); // cppcheck-suppress noExplicitConstructor - String(const char* in); - String(const char* in, size_type in_size); + String(const char *in); + String(const char *in, size_type in_size); - String(std::istream& in, size_type in_size); + String(std::istream &in, size_type in_size); - String(const String& other); - String& operator=(const String& other); + String(const String &other); + String &operator=(const String &other); - String& operator+=(const String& other); + String &operator+=(const String &other); - String(String&& other) noexcept; - String& operator=(String&& other) noexcept; + String(String &&other) noexcept; + String &operator=(String &&other) noexcept; char operator[](size_type i) const; - char& operator[](size_type i); + char &operator[](size_type i); // the only functions I'm willing to leave in the interface - available for inlining - const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT - char* c_str() { - if (isOnStack()) { - return reinterpret_cast(buf); - } - return data.ptr; + const char *c_str() const { return const_cast(this)->c_str(); } // NOLINT + char *c_str() + { + if (isOnStack()) { + return reinterpret_cast(buf); + } + return data.ptr; } size_type size() const; @@ -656,162 +656,161 @@ class DOCTEST_INTERFACE String size_type find(char ch, size_type pos = 0) const; size_type rfind(char ch, size_type pos = npos) const; - int compare(const char* other, bool no_case = false) const; - int compare(const String& other, bool no_case = false) const; + int compare(const char *other, bool no_case = false) const; + int compare(const String &other, bool no_case = false) const; -friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); -}; + friend DOCTEST_INTERFACE std::ostream &operator<<(std::ostream &s, const String &in); + }; -DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + DOCTEST_INTERFACE String operator+(const String &lhs, const String &rhs); -DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator==(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator!=(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator<(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator>(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator<=(const String &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator>=(const String &lhs, const String &rhs); -class DOCTEST_INTERFACE Contains { -public: - explicit Contains(const String& string); + class DOCTEST_INTERFACE Contains + { + public: + explicit Contains(const String &string); - bool checkWith(const String& other) const; + bool checkWith(const String &other) const; String string; -}; - -DOCTEST_INTERFACE String toString(const Contains& in); - -DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); - -namespace Color { - enum Enum - { - None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White + }; + + DOCTEST_INTERFACE String toString(const Contains &in); + + DOCTEST_INTERFACE bool operator==(const String &lhs, const Contains &rhs); + DOCTEST_INTERFACE bool operator==(const Contains &lhs, const String &rhs); + DOCTEST_INTERFACE bool operator!=(const String &lhs, const Contains &rhs); + DOCTEST_INTERFACE bool operator!=(const Contains &lhs, const String &rhs); + + namespace Color { + enum Enum { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White }; - DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); -} // namespace Color + DOCTEST_INTERFACE std::ostream &operator<<(std::ostream &s, Color::Enum code); + } // namespace Color -namespace assertType { - enum Enum - { - // macro traits + namespace assertType { + enum Enum { + // macro traits - is_warn = 1, - is_check = 2 * is_warn, - is_require = 2 * is_check, + is_warn = 1, + is_check = 2 * is_warn, + is_require = 2 * is_check, - is_normal = 2 * is_require, - is_throws = 2 * is_normal, - is_throws_as = 2 * is_throws, - is_throws_with = 2 * is_throws_as, - is_nothrow = 2 * is_throws_with, + is_normal = 2 * is_require, + is_throws = 2 * is_normal, + is_throws_as = 2 * is_throws, + is_throws_with = 2 * is_throws_as, + is_nothrow = 2 * is_throws_with, - is_false = 2 * is_nothrow, - is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types + is_false = 2 * is_nothrow, + is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types - is_eq = 2 * is_unary, - is_ne = 2 * is_eq, + is_eq = 2 * is_unary, + is_ne = 2 * is_eq, - is_lt = 2 * is_ne, - is_gt = 2 * is_lt, + is_lt = 2 * is_ne, + is_gt = 2 * is_lt, - is_ge = 2 * is_gt, - is_le = 2 * is_ge, + is_ge = 2 * is_gt, + is_le = 2 * is_ge, - // macro types + // macro types - DT_WARN = is_normal | is_warn, - DT_CHECK = is_normal | is_check, - DT_REQUIRE = is_normal | is_require, + DT_WARN = is_normal | is_warn, + DT_CHECK = is_normal | is_check, + DT_REQUIRE = is_normal | is_require, - DT_WARN_FALSE = is_normal | is_false | is_warn, - DT_CHECK_FALSE = is_normal | is_false | is_check, - DT_REQUIRE_FALSE = is_normal | is_false | is_require, + DT_WARN_FALSE = is_normal | is_false | is_warn, + DT_CHECK_FALSE = is_normal | is_false | is_check, + DT_REQUIRE_FALSE = is_normal | is_false | is_require, - DT_WARN_THROWS = is_throws | is_warn, - DT_CHECK_THROWS = is_throws | is_check, - DT_REQUIRE_THROWS = is_throws | is_require, + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, - DT_WARN_THROWS_AS = is_throws_as | is_warn, - DT_CHECK_THROWS_AS = is_throws_as | is_check, - DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, - DT_WARN_THROWS_WITH = is_throws_with | is_warn, - DT_CHECK_THROWS_WITH = is_throws_with | is_check, - DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + DT_WARN_THROWS_WITH = is_throws_with | is_warn, + DT_CHECK_THROWS_WITH = is_throws_with | is_check, + DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, - DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, - DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, - DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, - DT_WARN_NOTHROW = is_nothrow | is_warn, - DT_CHECK_NOTHROW = is_nothrow | is_check, - DT_REQUIRE_NOTHROW = is_nothrow | is_require, + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, - DT_WARN_EQ = is_normal | is_eq | is_warn, - DT_CHECK_EQ = is_normal | is_eq | is_check, - DT_REQUIRE_EQ = is_normal | is_eq | is_require, + DT_WARN_EQ = is_normal | is_eq | is_warn, + DT_CHECK_EQ = is_normal | is_eq | is_check, + DT_REQUIRE_EQ = is_normal | is_eq | is_require, - DT_WARN_NE = is_normal | is_ne | is_warn, - DT_CHECK_NE = is_normal | is_ne | is_check, - DT_REQUIRE_NE = is_normal | is_ne | is_require, + DT_WARN_NE = is_normal | is_ne | is_warn, + DT_CHECK_NE = is_normal | is_ne | is_check, + DT_REQUIRE_NE = is_normal | is_ne | is_require, - DT_WARN_GT = is_normal | is_gt | is_warn, - DT_CHECK_GT = is_normal | is_gt | is_check, - DT_REQUIRE_GT = is_normal | is_gt | is_require, + DT_WARN_GT = is_normal | is_gt | is_warn, + DT_CHECK_GT = is_normal | is_gt | is_check, + DT_REQUIRE_GT = is_normal | is_gt | is_require, - DT_WARN_LT = is_normal | is_lt | is_warn, - DT_CHECK_LT = is_normal | is_lt | is_check, - DT_REQUIRE_LT = is_normal | is_lt | is_require, + DT_WARN_LT = is_normal | is_lt | is_warn, + DT_CHECK_LT = is_normal | is_lt | is_check, + DT_REQUIRE_LT = is_normal | is_lt | is_require, - DT_WARN_GE = is_normal | is_ge | is_warn, - DT_CHECK_GE = is_normal | is_ge | is_check, - DT_REQUIRE_GE = is_normal | is_ge | is_require, + DT_WARN_GE = is_normal | is_ge | is_warn, + DT_CHECK_GE = is_normal | is_ge | is_check, + DT_REQUIRE_GE = is_normal | is_ge | is_require, - DT_WARN_LE = is_normal | is_le | is_warn, - DT_CHECK_LE = is_normal | is_le | is_check, - DT_REQUIRE_LE = is_normal | is_le | is_require, + DT_WARN_LE = is_normal | is_le | is_warn, + DT_CHECK_LE = is_normal | is_le | is_check, + DT_REQUIRE_LE = is_normal | is_le | is_require, - DT_WARN_UNARY = is_normal | is_unary | is_warn, - DT_CHECK_UNARY = is_normal | is_unary | is_check, - DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + DT_WARN_UNARY = is_normal | is_unary | is_warn, + DT_CHECK_UNARY = is_normal | is_unary | is_check, + DT_REQUIRE_UNARY = is_normal | is_unary | is_require, - DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, - DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, - DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, }; -} // namespace assertType + } // namespace assertType -DOCTEST_INTERFACE const char* assertString(assertType::Enum at); -DOCTEST_INTERFACE const char* failureString(assertType::Enum at); -DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); + DOCTEST_INTERFACE const char *assertString(assertType::Enum at); + DOCTEST_INTERFACE const char *failureString(assertType::Enum at); + DOCTEST_INTERFACE const char *skipPathFromFilename(const char *file); -struct DOCTEST_INTERFACE TestCaseData -{ + struct DOCTEST_INTERFACE TestCaseData + { String m_file; // the file in which the test was registered (using String - see #350) unsigned m_line; // the line where the test was registered - const char* m_name; // name of the test case - const char* m_test_suite; // the test suite in which the test was added - const char* m_description; + const char *m_name; // name of the test case + const char *m_test_suite; // the test suite in which the test was added + const char *m_description; bool m_skip; bool m_no_breaks; bool m_no_output; @@ -819,16 +818,16 @@ struct DOCTEST_INTERFACE TestCaseData bool m_should_fail; int m_expected_failures; double m_timeout; -}; + }; -struct DOCTEST_INTERFACE AssertData -{ + struct DOCTEST_INTERFACE AssertData + { // common - for all asserts - const TestCaseData* m_test_case; + const TestCaseData *m_test_case; assertType::Enum m_at; - const char* m_file; + const char *m_file; int m_line; - const char* m_expr; + const char *m_expr; bool m_failed; // exception-related - for all asserts @@ -839,63 +838,67 @@ struct DOCTEST_INTERFACE AssertData String m_decomp; // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; + bool m_threw_as; + const char *m_exception_type; - class DOCTEST_INTERFACE StringContains { - private: - Contains content; - bool isContains; + class DOCTEST_INTERFACE StringContains + { + private: + Contains content; + bool isContains; - public: - StringContains(const String& str) : content(str), isContains(false) { } - StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } + public: + StringContains(const String &str) : content(str), isContains(false) {} + StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) {} - bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + bool check(const String &str) + { + return isContains ? (content == str) : (content.string == str); + } - operator const String&() const { return content.string; } + operator const String &() const { return content.string; } - const char* c_str() const { return content.string.c_str(); } + const char *c_str() const { return content.string.c_str(); } } m_exception_string; - AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string); -}; + AssertData(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const StringContains &exception_string); + }; -struct DOCTEST_INTERFACE MessageData -{ + struct DOCTEST_INTERFACE MessageData + { String m_string; - const char* m_file; + const char *m_file; int m_line; assertType::Enum m_severity; -}; + }; -struct DOCTEST_INTERFACE SubcaseSignature -{ + struct DOCTEST_INTERFACE SubcaseSignature + { String m_name; - const char* m_file; + const char *m_file; int m_line; - bool operator==(const SubcaseSignature& other) const; - bool operator<(const SubcaseSignature& other) const; -}; + bool operator==(const SubcaseSignature &other) const; + bool operator<(const SubcaseSignature &other) const; + }; -struct DOCTEST_INTERFACE IContextScope -{ + struct DOCTEST_INTERFACE IContextScope + { DOCTEST_DECLARE_INTERFACE(IContextScope) - virtual void stringify(std::ostream*) const = 0; -}; + virtual void stringify(std::ostream *) const = 0; + }; -namespace detail { + namespace detail { struct DOCTEST_INTERFACE TestCase; -} // namespace detail + } // namespace detail -struct ContextOptions //!OCLINT too many fields -{ - std::ostream* cout = nullptr; // stdout stream + struct ContextOptions //! OCLINT too many fields + { + std::ostream *cout = nullptr; // stdout stream String binary_name; // the test binary name - const detail::TestCase* currentTest = nullptr; + const detail::TestCase *currentTest = nullptr; // == parameters from the command line String out; // output filename @@ -936,150 +939,210 @@ struct ContextOptions //!OCLINT too many fields bool list_test_cases; // to list all tests matching the filters bool list_test_suites; // to list all suites matching the filters bool list_reporters; // lists all registered reporters -}; + }; -namespace detail { + namespace detail { namespace types { #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - using namespace std; + using namespace std; #else - template - struct enable_if { }; - - template - struct enable_if { using type = T; }; - - struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; - struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; - - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - - template struct is_rvalue_reference : false_type { }; - template struct is_rvalue_reference : true_type { }; - - template struct remove_const { using type = T; }; - template struct remove_const { using type = T; }; - - // Compiler intrinsics - template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; - template struct underlying_type { using type = __underlying_type(T); }; - - template struct is_pointer : false_type { }; - template struct is_pointer : true_type { }; - - template struct is_array : false_type { }; - // NOLINTNEXTLINE(*-avoid-c-arrays) - template struct is_array : true_type { }; + template struct enable_if + { + }; + + template struct enable_if + { + using type = T; + }; + + struct true_type + { + static DOCTEST_CONSTEXPR bool value = true; + }; + struct false_type + { + static DOCTEST_CONSTEXPR bool value = false; + }; + + template struct remove_reference + { + using type = T; + }; + template struct remove_reference + { + using type = T; + }; + template struct remove_reference + { + using type = T; + }; + + template struct is_rvalue_reference : false_type + { + }; + template struct is_rvalue_reference : true_type + { + }; + + template struct remove_const + { + using type = T; + }; + template struct remove_const + { + using type = T; + }; + + // Compiler intrinsics + template struct is_enum + { + static DOCTEST_CONSTEXPR bool value = __is_enum(T); + }; + template struct underlying_type + { + using type = __underlying_type(T); + }; + + template struct is_pointer : false_type + { + }; + template struct is_pointer : true_type + { + }; + + template struct is_array : false_type + { + }; + // NOLINTNEXTLINE(*-avoid-c-arrays) + template struct is_array : true_type + { + }; #endif - } + } // namespace types // - template - T&& declval(); + template T &&declval(); template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { - return static_cast(t); + DOCTEST_CONSTEXPR_FUNC T && + forward(typename types::remove_reference::type &t) DOCTEST_NOEXCEPT + { + return static_cast(t); } template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { - return static_cast(t); + DOCTEST_CONSTEXPR_FUNC T && + forward(typename types::remove_reference::type &&t) DOCTEST_NOEXCEPT + { + return static_cast(t); } - template - struct deferred_false : types::false_type { }; + template struct deferred_false : types::false_type + { + }; // MSVS 2015 :( #if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 - template - struct has_global_insertion_operator : types::false_type { }; + template struct has_global_insertion_operator : types::false_type + { + }; template - struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; + struct has_global_insertion_operator< + T, decltype(::operator<<(declval(), declval()), void())> + : types::true_type + { + }; - template - struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; + template struct has_insertion_operator + { + static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; + }; - template - struct insert_hack; + template struct insert_hack; - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } + template struct insert_hack + { + static void insert(std::ostream &os, const T &t) { ::operator<<(os, t); } }; - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { operator<<(os, t); } + template struct insert_hack + { + static void insert(std::ostream &os, const T &t) { operator<<(os, t); } }; template using insert_hack_t = insert_hack::value>; #else - template - struct has_insertion_operator : types::false_type { }; + template struct has_insertion_operator : types::false_type + { + }; #endif template - struct has_insertion_operator(), declval()), void())> : types::true_type { }; + struct has_insertion_operator< + T, decltype(operator<<(declval(), declval()), void())> + : types::true_type + { + }; - template - struct should_stringify_as_underlying_type { - static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; + template struct should_stringify_as_underlying_type + { + static DOCTEST_CONSTEXPR bool value = + detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; }; - DOCTEST_INTERFACE std::ostream* tlssPush(); - DOCTEST_INTERFACE String tlssPop(); + DOCTEST_INTERFACE std::ostream *tlssPush(); + DOCTEST_INTERFACE String tlssPop(); - template - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T)) { + template struct StringMakerBase + { + template static String convert(const DOCTEST_REF_WRAP(T)) + { #ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES - static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); + static_assert(deferred_false::value, + "No stringification detected for type T. See string conversion manual"); #endif - return "{?}"; - } + return "{?}"; + } }; - template - struct filldata; + template struct filldata; - template - void filloss(std::ostream* stream, const T& in) { - filldata::fill(stream, in); + template void filloss(std::ostream *stream, const T &in) + { + filldata::fill(stream, in); } - template - void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) - // T[N], T(&)[N], T(&&)[N] have same behaviour. - // Hence remove reference. - filloss::type>(stream, in); + template void filloss(std::ostream *stream, const T (&in)[N]) + { // NOLINT(*-avoid-c-arrays) + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filloss::type>(stream, in); } - template - String toStream(const T& in) { - std::ostream* stream = tlssPush(); - filloss(stream, in); - return tlssPop(); + template String toStream(const T &in) + { + std::ostream *stream = tlssPush(); + filloss(stream, in); + return tlssPop(); } - template <> - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T) in) { - return toStream(in); - } + template <> struct StringMakerBase + { + template static String convert(const DOCTEST_REF_WRAP(T) in) + { + return toStream(in); + } }; -} // namespace detail + } // namespace detail -template -struct StringMaker : public detail::StringMakerBase< - detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> -{}; + template + struct StringMaker : public detail::StringMakerBase::value || + detail::types::is_pointer::value || + detail::types::is_array::value> + { + }; #ifndef DOCTEST_STRINGIFY #ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY @@ -1089,157 +1152,172 @@ struct StringMaker : public detail::StringMakerBase< #endif #endif -template -String toString() { + template String toString() + { #if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) String::size_type beginPos = ret.find('<'); - return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); + return ret.substr(beginPos + 1, + ret.size() - beginPos - static_cast(sizeof(">(void)"))); #else - String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] + String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] String::size_type begin = ret.find('=') + 2; return ret.substr(begin, ret.size() - begin - 1); #endif -} + } -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { + template ::value, bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T) value) + { return StringMaker::convert(value); -} + } #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -DOCTEST_INTERFACE String toString(const char* in); + DOCTEST_INTERFACE String toString(const char *in); #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -DOCTEST_INTERFACE String toString(const std::string& in); + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + DOCTEST_INTERFACE String toString(const std::string &in); #endif // VS 2019 -DOCTEST_INTERFACE String toString(String in); - -DOCTEST_INTERFACE String toString(std::nullptr_t); - -DOCTEST_INTERFACE String toString(bool in); - -DOCTEST_INTERFACE String toString(float in); -DOCTEST_INTERFACE String toString(double in); -DOCTEST_INTERFACE String toString(double long in); - -DOCTEST_INTERFACE String toString(char in); -DOCTEST_INTERFACE String toString(char signed in); -DOCTEST_INTERFACE String toString(char unsigned in); -DOCTEST_INTERFACE String toString(short in); -DOCTEST_INTERFACE String toString(short unsigned in); -DOCTEST_INTERFACE String toString(signed in); -DOCTEST_INTERFACE String toString(unsigned in); -DOCTEST_INTERFACE String toString(long in); -DOCTEST_INTERFACE String toString(long unsigned in); -DOCTEST_INTERFACE String toString(long long in); -DOCTEST_INTERFACE String toString(long long unsigned in); - -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { + DOCTEST_INTERFACE String toString(String in); + + DOCTEST_INTERFACE String toString(std::nullptr_t); + + DOCTEST_INTERFACE String toString(bool in); + + DOCTEST_INTERFACE String toString(float in); + DOCTEST_INTERFACE String toString(double in); + DOCTEST_INTERFACE String toString(double long in); + + DOCTEST_INTERFACE String toString(char in); + DOCTEST_INTERFACE String toString(char signed in); + DOCTEST_INTERFACE String toString(char unsigned in); + DOCTEST_INTERFACE String toString(short in); + DOCTEST_INTERFACE String toString(short unsigned in); + DOCTEST_INTERFACE String toString(signed in); + DOCTEST_INTERFACE String toString(unsigned in); + DOCTEST_INTERFACE String toString(long in); + DOCTEST_INTERFACE String toString(long unsigned in); + DOCTEST_INTERFACE String toString(long long in); + DOCTEST_INTERFACE String toString(long long unsigned in); + + template ::value, + bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T) value) + { using UT = typename detail::types::underlying_type::type; return (DOCTEST_STRINGIFY(static_cast(value))); -} + } -namespace detail { - template - struct filldata + namespace detail { + template struct filldata { - static void fill(std::ostream* stream, const T& in) { + static void fill(std::ostream *stream, const T &in) + { #if defined(_MSC_VER) && _MSC_VER <= 1900 insert_hack_t::insert(*stream, in); #else operator<<(*stream, in); #endif - } + } }; -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) -// NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const T(&in)[N]) { - *stream << "["; - for (size_t i = 0; i < N; i++) { - if (i != 0) { *stream << ", "; } - *stream << (DOCTEST_STRINGIFY(in[i])); - } - *stream << "]"; - } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + // NOLINTBEGIN(*-avoid-c-arrays) + template struct filldata + { + static void fill(std::ostream *stream, const T (&in)[N]) + { + *stream << "["; + for (size_t i = 0; i < N; i++) { + if (i != 0) { + *stream << ", "; + } + *stream << (DOCTEST_STRINGIFY(in[i])); + } + *stream << "]"; + } }; -// NOLINTEND(*-avoid-c-arrays) -DOCTEST_MSVC_SUPPRESS_WARNING_POP + // NOLINTEND(*-avoid-c-arrays) + DOCTEST_MSVC_SUPPRESS_WARNING_POP // Specialized since we don't want the terminating null byte! -// NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const char (&in)[N]) { - *stream << String(in, in[N - 1] ? N : N - 1); - } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + // NOLINTBEGIN(*-avoid-c-arrays) + template struct filldata + { + static void fill(std::ostream *stream, const char (&in)[N]) + { + *stream << String(in, in[N - 1] ? N : N - 1); + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) }; -// NOLINTEND(*-avoid-c-arrays) + // NOLINTEND(*-avoid-c-arrays) - template <> - struct filldata { - static void fill(std::ostream* stream, const void* in); + template <> struct filldata + { + static void fill(std::ostream *stream, const void *in); }; - template - struct filldata { -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) - static void fill(std::ostream* stream, const T* in) { -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") - filldata::fill(stream, + template struct filldata + { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) + static void fill(std::ostream *stream, const T *in) + { + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") + filldata::fill(stream, #if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) - reinterpret_cast(in) + reinterpret_cast(in) #else - *reinterpret_cast(&in) + *reinterpret_cast(&in) #endif - ); -DOCTEST_CLANG_SUPPRESS_WARNING_POP - } + ); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + } }; -} + } // namespace detail -struct DOCTEST_INTERFACE Approx -{ + struct DOCTEST_INTERFACE Approx + { Approx(double value); Approx operator()(double value) const; #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS template - explicit Approx(const T& value, - typename detail::types::enable_if::value>::type* = - static_cast(nullptr)) { - *this = static_cast(value); + explicit Approx(const T &value, + typename detail::types::enable_if::value>::type + * = static_cast(nullptr)) + { + *this = static_cast(value); } #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - Approx& epsilon(double newEpsilon); + Approx &epsilon(double newEpsilon); #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS template - typename std::enable_if::value, Approx&>::type epsilon( - const T& newEpsilon) { - m_epsilon = static_cast(newEpsilon); - return *this; + typename std::enable_if::value, Approx &>::type + epsilon(const T &newEpsilon) + { + m_epsilon = static_cast(newEpsilon); + return *this; } #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - Approx& scale(double newScale); + Approx &scale(double newScale); #ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS template - typename std::enable_if::value, Approx&>::type scale( - const T& newScale) { - m_scale = static_cast(newScale); - return *this; + typename std::enable_if::value, Approx &>::type + scale(const T &newScale) + { + m_scale = static_cast(newScale); + return *this; } #endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS @@ -1281,32 +1359,32 @@ struct DOCTEST_INTERFACE Approx double m_epsilon; double m_scale; double m_value; -}; + }; -DOCTEST_INTERFACE String toString(const Approx& in); + DOCTEST_INTERFACE String toString(const Approx &in); -DOCTEST_INTERFACE const ContextOptions* getContextOptions(); + DOCTEST_INTERFACE const ContextOptions *getContextOptions(); -template -struct DOCTEST_INTERFACE_DECL IsNaN -{ - F value; bool flipped; - IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } - IsNaN operator!() const { return { value, !flipped }; } + template struct DOCTEST_INTERFACE_DECL IsNaN + { + F value; + bool flipped; + IsNaN(F f, bool flip = false) : value(f), flipped(flip) {} + IsNaN operator!() const { return {value, !flipped}; } operator bool() const; -}; + }; #ifndef __MINGW32__ -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; #endif -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); #ifndef DOCTEST_CONFIG_DISABLE -namespace detail { + namespace detail { // clang-format off #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING template struct decay_array { using type = T; }; @@ -1334,30 +1412,31 @@ namespace detail { struct DOCTEST_INTERFACE Subcase { - SubcaseSignature m_signature; - bool m_entered = false; + SubcaseSignature m_signature; + bool m_entered = false; - Subcase(const String& name, const char* file, int line); - Subcase(const Subcase&) = delete; - Subcase(Subcase&&) = delete; - Subcase& operator=(const Subcase&) = delete; - Subcase& operator=(Subcase&&) = delete; - ~Subcase(); + Subcase(const String &name, const char *file, int line); + Subcase(const Subcase &) = delete; + Subcase(Subcase &&) = delete; + Subcase &operator=(const Subcase &) = delete; + Subcase &operator=(Subcase &&) = delete; + ~Subcase(); - operator bool() const; + operator bool() const; - private: - bool checkFilters(); + private: + bool checkFilters(); }; template - String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, - const DOCTEST_REF_WRAP(R) rhs) { - return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char *op, + const DOCTEST_REF_WRAP(R) rhs) + { + return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); } #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") #endif // This will check if there is any way it could find a operator like member or friend and uses it. @@ -1365,64 +1444,66 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") // this template, the template won't be instantiated due to SFINAE. Once the template is not // instantiated it can look for global operator using normal conversions. #ifdef __NVCC__ -#define SFINAE_OP(ret,op) ret +#define SFINAE_OP(ret, op) ret #else -#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) +#define SFINAE_OP(ret, op) \ + decltype((void)(doctest::detail::declval() op doctest::detail::declval()), ret{}) #endif #define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ - template \ - DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + template DOCTEST_NOINLINE SFINAE_OP(Result, op) operator op(R &&rhs) \ + { \ bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ - if(m_at & assertType::is_false) \ - res = !res; \ - if(!res || doctest::getContextOptions()->success) \ - return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ - return Result(res); \ - } + if (m_at & assertType::is_false) \ + res = !res; \ + if (!res || doctest::getContextOptions()->success) \ + return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ + return Result(res); \ + } // more checks could be added - like in Catch: // https://github.com/catchorg/Catch2/pull/1480/files // https://github.com/catchorg/Catch2/pull/1481/files #define DOCTEST_FORBIT_EXPRESSION(rt, op) \ - template \ - rt& operator op(const R&) { \ - static_assert(deferred_false::value, \ - "Expression Too Complex Please Rewrite As Binary Comparison!"); \ - return *this; \ - } + template rt &operator op(const R &) \ + { \ + static_assert(deferred_false::value, \ + "Expression Too Complex Please Rewrite As Binary Comparison!"); \ + return *this; \ + } struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) { - bool m_passed; - String m_decomp; - - Result() = default; // TODO: Why do we need this? (To remove NOLINT) - Result(bool passed, const String& decomposition = String()); - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Result, &) - DOCTEST_FORBIT_EXPRESSION(Result, ^) - DOCTEST_FORBIT_EXPRESSION(Result, |) - DOCTEST_FORBIT_EXPRESSION(Result, &&) - DOCTEST_FORBIT_EXPRESSION(Result, ||) - DOCTEST_FORBIT_EXPRESSION(Result, ==) - DOCTEST_FORBIT_EXPRESSION(Result, !=) - DOCTEST_FORBIT_EXPRESSION(Result, <) - DOCTEST_FORBIT_EXPRESSION(Result, >) - DOCTEST_FORBIT_EXPRESSION(Result, <=) - DOCTEST_FORBIT_EXPRESSION(Result, >=) - DOCTEST_FORBIT_EXPRESSION(Result, =) - DOCTEST_FORBIT_EXPRESSION(Result, +=) - DOCTEST_FORBIT_EXPRESSION(Result, -=) - DOCTEST_FORBIT_EXPRESSION(Result, *=) - DOCTEST_FORBIT_EXPRESSION(Result, /=) - DOCTEST_FORBIT_EXPRESSION(Result, %=) - DOCTEST_FORBIT_EXPRESSION(Result, <<=) - DOCTEST_FORBIT_EXPRESSION(Result, >>=) - DOCTEST_FORBIT_EXPRESSION(Result, &=) - DOCTEST_FORBIT_EXPRESSION(Result, ^=) - DOCTEST_FORBIT_EXPRESSION(Result, |=) + bool m_passed; + String m_decomp; + + Result() = default; // TODO: Why do we need this? (To remove NOLINT) + Result(bool passed, const String &decomposition = String()); + + // forbidding some expressions based on this table: + // https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Result, &) + DOCTEST_FORBIT_EXPRESSION(Result, ^) + DOCTEST_FORBIT_EXPRESSION(Result, |) + DOCTEST_FORBIT_EXPRESSION(Result, &&) + DOCTEST_FORBIT_EXPRESSION(Result, ||) + DOCTEST_FORBIT_EXPRESSION(Result, ==) + DOCTEST_FORBIT_EXPRESSION(Result, !=) + DOCTEST_FORBIT_EXPRESSION(Result, <) + DOCTEST_FORBIT_EXPRESSION(Result, >) + DOCTEST_FORBIT_EXPRESSION(Result, <=) + DOCTEST_FORBIT_EXPRESSION(Result, >=) + DOCTEST_FORBIT_EXPRESSION(Result, =) + DOCTEST_FORBIT_EXPRESSION(Result, +=) + DOCTEST_FORBIT_EXPRESSION(Result, -=) + DOCTEST_FORBIT_EXPRESSION(Result, *=) + DOCTEST_FORBIT_EXPRESSION(Result, /=) + DOCTEST_FORBIT_EXPRESSION(Result, %=) + DOCTEST_FORBIT_EXPRESSION(Result, <<=) + DOCTEST_FORBIT_EXPRESSION(Result, >>=) + DOCTEST_FORBIT_EXPRESSION(Result, &=) + DOCTEST_FORBIT_EXPRESSION(Result, ^=) + DOCTEST_FORBIT_EXPRESSION(Result, |=) }; #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION @@ -1430,23 +1511,24 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") + // DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") + // DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") + // DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") + // DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") + // DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") + // DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") DOCTEST_MSVC_SUPPRESS_WARNING_PUSH // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch - //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation + // DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type + // 'type' in operation #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION @@ -1465,11 +1547,12 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") // clang-format on #define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ - const DOCTEST_REF_WRAP(R) rhs) { \ - return lhs op rhs; \ - } + template \ + DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ + const DOCTEST_REF_WRAP(R) rhs) \ + { \ + return lhs op rhs; \ + } DOCTEST_RELATIONAL_OP(eq, ==) DOCTEST_RELATIONAL_OP(ne, !=) @@ -1498,61 +1581,62 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") // cppcheck-suppress copyCtorAndEqOperator struct Expression_lhs { - L lhs; - assertType::Enum m_at; + L lhs; + assertType::Enum m_at; - explicit Expression_lhs(L&& in, assertType::Enum at) - : lhs(static_cast(in)) - , m_at(at) {} + explicit Expression_lhs(L &&in, assertType::Enum at) : lhs(static_cast(in)), m_at(at) {} - DOCTEST_NOINLINE operator Result() { -// this is needed only for MSVC 2015 -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool - bool res = static_cast(lhs); -DOCTEST_MSVC_SUPPRESS_WARNING_POP - if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - res = !res; - } + DOCTEST_NOINLINE operator Result() + { + // this is needed only for MSVC 2015 + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + if (m_at & assertType::is_false) { //! OCLINT bitwise operator in conditional + res = !res; + } - if(!res || getContextOptions()->success) { - return { res, (DOCTEST_STRINGIFY(lhs)) }; - } - return { res }; + if (!res || getContextOptions()->success) { + return {res, (DOCTEST_STRINGIFY(lhs))}; } + return {res}; + } - /* This is required for user-defined conversions from Expression_lhs to L */ - operator L() const { return lhs; } + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } - // clang-format off + // clang-format off DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional - // clang-format on - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) - // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the - // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) + // clang-format on + + // forbidding some expressions based on this table: + // https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) + // these 2 are unfortunate because they should be allowed - they have higher precedence over + // the comparisons, but the ExpressionDecomposer class uses the left shift operator to capture + // the left operand of the binary expression... + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) }; #ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION @@ -1564,104 +1648,100 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION #if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_POP #endif struct DOCTEST_INTERFACE ExpressionDecomposer { - assertType::Enum m_at; - - ExpressionDecomposer(assertType::Enum at); - - // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) - // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... - // https://github.com/catchorg/Catch2/issues/870 - // https://github.com/catchorg/Catch2/issues/565 - template - Expression_lhs operator<<(L&& operand) { - return Expression_lhs(static_cast(operand), m_at); - } - - template ::value,void >::type* = nullptr> - Expression_lhs operator<<(const L &operand) { - return Expression_lhs(operand, m_at); - } + assertType::Enum m_at; + + ExpressionDecomposer(assertType::Enum at); + + // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator + // precedence table) but then there will be warnings from GCC about "-Wparentheses" and since + // "_Pragma()" is problematic this will stay for now... + // https://github.com/catchorg/Catch2/issues/870 + // https://github.com/catchorg/Catch2/issues/565 + template Expression_lhs operator<<(L &&operand) + { + return Expression_lhs(static_cast(operand), m_at); + } + + template ::value, + void>::type * = nullptr> + Expression_lhs operator<<(const L &operand) + { + return Expression_lhs(operand, m_at); + } }; struct DOCTEST_INTERFACE TestSuite { - const char* m_test_suite = nullptr; - const char* m_description = nullptr; - bool m_skip = false; - bool m_no_breaks = false; - bool m_no_output = false; - bool m_may_fail = false; - bool m_should_fail = false; - int m_expected_failures = 0; - double m_timeout = 0; - - TestSuite& operator*(const char* in); - - template - TestSuite& operator*(const T& in) { - in.fill(*this); - return *this; - } + const char *m_test_suite = nullptr; + const char *m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; + + TestSuite &operator*(const char *in); + + template TestSuite &operator*(const T &in) + { + in.fill(*this); + return *this; + } }; using funcType = void (*)(); struct DOCTEST_INTERFACE TestCase : public TestCaseData { - funcType m_test; // a function pointer to the test case + funcType m_test; // a function pointer to the test case - String m_type; // for templated test cases - gets appended to the real name - int m_template_id; // an ID used to distinguish between the different versions of a templated test case - String m_full_name; // contains the name (only for templated test cases!) + the template type + String m_type; // for templated test cases - gets appended to the real name + int m_template_id; // an ID used to distinguish between the different versions of a templated + // test case + String m_full_name; // contains the name (only for templated test cases!) + the template type - TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type = String(), int template_id = -1); + TestCase(funcType test, const char *file, unsigned line, const TestSuite &test_suite, + const String &type = String(), int template_id = -1); - TestCase(const TestCase& other); - TestCase(TestCase&&) = delete; + TestCase(const TestCase &other); + TestCase(TestCase &&) = delete; - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& operator=(const TestCase& other); - DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase &operator=(const TestCase &other); + DOCTEST_MSVC_SUPPRESS_WARNING_POP - TestCase& operator=(TestCase&&) = delete; + TestCase &operator=(TestCase &&) = delete; - TestCase& operator*(const char* in); + TestCase &operator*(const char *in); - template - TestCase& operator*(const T& in) { - in.fill(*this); - return *this; - } + template TestCase &operator*(const T &in) + { + in.fill(*this); + return *this; + } - bool operator<(const TestCase& other) const; + bool operator<(const TestCase &other) const; - ~TestCase() = default; + ~TestCase() = default; }; // forward declarations of functions used by the macros - DOCTEST_INTERFACE int regTest(const TestCase& tc); - DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); + DOCTEST_INTERFACE int regTest(const TestCase &tc); + DOCTEST_INTERFACE int setTestSuite(const TestSuite &ts); DOCTEST_INTERFACE bool isDebuggerActive(); - template - int instantiationHelper(const T&) { return 0; } + template int instantiationHelper(const T &) { return 0; } namespace binaryAssertComparison { - enum Enum - { - eq = 0, - ne, - gt, - lt, - ge, - le - }; + enum Enum { eq = 0, ne, gt, lt, ge, le }; } // namespace binaryAssertComparison // clang-format off @@ -1680,311 +1760,311 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP struct DOCTEST_INTERFACE ResultBuilder : public AssertData { - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = "", const String& exception_string = ""); + ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type = "", const String &exception_string = ""); - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string); + ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const Contains &exception_string); - void setResult(const Result& res); + void setResult(const Result &res); - template - DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - m_failed = !RelationalComparator()(lhs, rhs); - if (m_failed || getContextOptions()->success) { - m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); - } - return !m_failed; + template + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) + { + m_failed = !RelationalComparator()(lhs, rhs); + if (m_failed || getContextOptions()->success) { + m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); } + return !m_failed; + } - template - DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { - m_failed = !val; - - if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - m_failed = !m_failed; - } + template DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) + { + m_failed = !val; - if (m_failed || getContextOptions()->success) { - m_decomp = (DOCTEST_STRINGIFY(val)); - } + if (m_at & assertType::is_false) { //! OCLINT bitwise operator in conditional + m_failed = !m_failed; + } - return !m_failed; + if (m_failed || getContextOptions()->success) { + m_decomp = (DOCTEST_STRINGIFY(val)); } - void translateException(); + return !m_failed; + } + + void translateException(); - bool log(); - void react() const; + bool log(); + void react() const; }; namespace assertAction { - enum Enum - { - nothing = 0, - dbgbreak = 1, - shouldthrow = 2 - }; + enum Enum { nothing = 0, dbgbreak = 1, shouldthrow = 2 }; } // namespace assertAction - DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); + DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData &ad); - DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, - const char* expr, const Result& result); + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char *file, int line, + const char *expr, const Result &result); #define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ - do { \ - if(!is_running_in_test) { \ - if(failed) { \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - rb.m_decomp = decomp; \ - failed_out_of_a_testing_context(rb); \ - if(isDebuggerActive() && !getContextOptions()->no_breaks) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if(checkIfShouldThrow(at)) \ - throwException(); \ - } \ - return !failed; \ - } \ - } while(false) + do { \ + if (!is_running_in_test) { \ + if (failed) { \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + rb.m_decomp = decomp; \ + failed_out_of_a_testing_context(rb); \ + if (isDebuggerActive() && !getContextOptions()->no_breaks) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if (checkIfShouldThrow(at)) \ + throwException(); \ + } \ + return !failed; \ + } \ + } while (false) #define DOCTEST_ASSERT_IN_TESTS(decomp) \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - if(rb.m_failed || getContextOptions()->success) \ - rb.m_decomp = decomp; \ - if(rb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if(rb.m_failed && checkIfShouldThrow(at)) \ - throwException() + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + if (rb.m_failed || getContextOptions()->success) \ + rb.m_decomp = decomp; \ + if (rb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if (rb.m_failed && checkIfShouldThrow(at)) \ + throwException() template - DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - bool failed = !RelationalComparator()(lhs, rhs); - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - return !failed; + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char *file, int line, + const char *expr, const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) + { + bool failed = !RelationalComparator()(lhs, rhs); + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; } template - DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) val) { - bool failed = !val; - - if(at & assertType::is_false) //!OCLINT bitwise operator in conditional - failed = !failed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); - DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); - return !failed; + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char *file, int line, + const char *expr, const DOCTEST_REF_WRAP(L) val) + { + bool failed = !val; + + if (at & assertType::is_false) //! OCLINT bitwise operator in conditional + failed = !failed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); + DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); + return !failed; } struct DOCTEST_INTERFACE IExceptionTranslator { - DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) - virtual bool translate(String&) const = 0; + DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) + virtual bool translate(String &) const = 0; }; template - class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class + class ExceptionTranslator : public IExceptionTranslator //! OCLINT destructor of virtual class { public: - explicit ExceptionTranslator(String (*translateFunction)(T)) - : m_translateFunction(translateFunction) {} + explicit ExceptionTranslator(String (*translateFunction)(T)) + : m_translateFunction(translateFunction) + { + } - bool translate(String& res) const override { + bool translate(String &res) const override + { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { - throw; // lgtm [cpp/rethrow-no-exception] - // cppcheck-suppress catchExceptionByValue - } catch(const T& ex) { - res = m_translateFunction(ex); //!OCLINT parameter reassignment - return true; - } catch(...) {} //!OCLINT - empty catch statement -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - static_cast(res); // to silence -Wunused-parameter - return false; + try { + throw; // lgtm [cpp/rethrow-no-exception] + // cppcheck-suppress catchExceptionByValue + } + catch (const T &ex) { + res = m_translateFunction(ex); //! OCLINT parameter reassignment + return true; } + catch (...) { + } //! OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter + return false; + } private: - String (*m_translateFunction)(T); + String (*m_translateFunction)(T); }; - DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); + DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator *et); // ContextScope base class used to allow implementing methods of ContextScope // that don't depend on the template parameter in doctest.cpp. - struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { - ContextScopeBase(const ContextScopeBase&) = delete; + struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope + { + ContextScopeBase(const ContextScopeBase &) = delete; - ContextScopeBase& operator=(const ContextScopeBase&) = delete; - ContextScopeBase& operator=(ContextScopeBase&&) = delete; + ContextScopeBase &operator=(const ContextScopeBase &) = delete; + ContextScopeBase &operator=(ContextScopeBase &&) = delete; - ~ContextScopeBase() override = default; + ~ContextScopeBase() override = default; protected: - ContextScopeBase(); - ContextScopeBase(ContextScopeBase&& other) noexcept; + ContextScopeBase(); + ContextScopeBase(ContextScopeBase &&other) noexcept; - void destroy(); - bool need_to_destroy{true}; + void destroy(); + bool need_to_destroy{true}; }; template class ContextScope : public ContextScopeBase { - L lambda_; + L lambda_; public: - explicit ContextScope(const L &lambda) : lambda_(lambda) {} - explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } + explicit ContextScope(const L &lambda) : lambda_(lambda) {} + explicit ContextScope(L &&lambda) : lambda_(static_cast(lambda)) {} - ContextScope(const ContextScope&) = delete; - ContextScope(ContextScope&&) noexcept = default; + ContextScope(const ContextScope &) = delete; + ContextScope(ContextScope &&) noexcept = default; - ContextScope& operator=(const ContextScope&) = delete; - ContextScope& operator=(ContextScope&&) = delete; + ContextScope &operator=(const ContextScope &) = delete; + ContextScope &operator=(ContextScope &&) = delete; - void stringify(std::ostream* s) const override { lambda_(s); } + void stringify(std::ostream *s) const override { lambda_(s); } - ~ContextScope() override { - if (need_to_destroy) { - destroy(); - } + ~ContextScope() override + { + if (need_to_destroy) { + destroy(); } + } }; struct DOCTEST_INTERFACE MessageBuilder : public MessageData { - std::ostream* m_stream; - bool logged = false; + std::ostream *m_stream; + bool logged = false; - MessageBuilder(const char* file, int line, assertType::Enum severity); + MessageBuilder(const char *file, int line, assertType::Enum severity); - MessageBuilder(const MessageBuilder&) = delete; - MessageBuilder(MessageBuilder&&) = delete; + MessageBuilder(const MessageBuilder &) = delete; + MessageBuilder(MessageBuilder &&) = delete; - MessageBuilder& operator=(const MessageBuilder&) = delete; - MessageBuilder& operator=(MessageBuilder&&) = delete; + MessageBuilder &operator=(const MessageBuilder &) = delete; + MessageBuilder &operator=(MessageBuilder &&) = delete; - ~MessageBuilder(); + ~MessageBuilder(); - // the preferred way of chaining parameters for stringification -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) - template - MessageBuilder& operator,(const T& in) { - *m_stream << (DOCTEST_STRINGIFY(in)); - return *this; - } -DOCTEST_MSVC_SUPPRESS_WARNING_POP + // the preferred way of chaining parameters for stringification + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + template MessageBuilder &operator,(const T &in) + { + *m_stream << (DOCTEST_STRINGIFY(in)); + return *this; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP - // kept here just for backwards-compatibility - the comma operator should be preferred now - template - MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + // kept here just for backwards-compatibility - the comma operator should be preferred now + template MessageBuilder &operator<<(const T &in) { return this->operator,(in); } - // the `,` operator has the lowest operator precedence - if `<<` is used by the user then - // the `,` operator will be called last which is not what we want and thus the `*` operator - // is used first (has higher operator precedence compared to `<<`) so that we guarantee that - // an operator of the MessageBuilder class is called first before the rest of the parameters - template - MessageBuilder& operator*(const T& in) { return this->operator,(in); } + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template MessageBuilder &operator*(const T &in) { return this->operator,(in); } - bool log(); - void react(); + bool log(); + void react(); }; - template - ContextScope MakeContextScope(const L &lambda) { - return ContextScope(lambda); + template ContextScope MakeContextScope(const L &lambda) + { + return ContextScope(lambda); } -} // namespace detail + } // namespace detail #define DOCTEST_DEFINE_DECORATOR(name, type, def) \ - struct name \ - { \ - type data; \ - name(type in = def) \ - : data(in) {} \ - void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \ - void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ - } - -DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); -DOCTEST_DEFINE_DECORATOR(description, const char*, ""); -DOCTEST_DEFINE_DECORATOR(skip, bool, true); -DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); -DOCTEST_DEFINE_DECORATOR(no_output, bool, true); -DOCTEST_DEFINE_DECORATOR(timeout, double, 0); -DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); - -template -int registerExceptionTranslator(String (*translateFunction)(T)) { + struct name \ + { \ + type data; \ + name(type in = def) : data(in) {} \ + void fill(detail::TestCase &state) const { state.DOCTEST_CAT(m_, name) = data; } \ + void fill(detail::TestSuite &state) const { state.DOCTEST_CAT(m_, name) = data; } \ + } + + DOCTEST_DEFINE_DECORATOR(test_suite, const char *, ""); + DOCTEST_DEFINE_DECORATOR(description, const char *, ""); + DOCTEST_DEFINE_DECORATOR(skip, bool, true); + DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); + DOCTEST_DEFINE_DECORATOR(no_output, bool, true); + DOCTEST_DEFINE_DECORATOR(timeout, double, 0); + DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); + DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); + DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); + + template int registerExceptionTranslator(String (*translateFunction)(T)) + { DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") static detail::ExceptionTranslator exceptionTranslator(translateFunction); DOCTEST_CLANG_SUPPRESS_WARNING_POP detail::registerExceptionTranslatorImpl(&exceptionTranslator); return 0; -} + } } // namespace doctest // in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro // introduces an anonymous namespace in which getCurrentTestSuite gets overridden namespace doctest_detail_test_suite_ns { -DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); + DOCTEST_INTERFACE doctest::detail::TestSuite &getCurrentTestSuite(); } // namespace doctest_detail_test_suite_ns namespace doctest { #else // DOCTEST_CONFIG_DISABLE -template -int registerExceptionTranslator(String (*)(T)) { - return 0; -} + template int registerExceptionTranslator(String (*)(T)) { return 0; } #endif // DOCTEST_CONFIG_DISABLE -namespace detail { - using assert_handler = void (*)(const AssertData&); + namespace detail { + using assert_handler = void (*)(const AssertData &); struct ContextState; -} // namespace detail + } // namespace detail -class DOCTEST_INTERFACE Context -{ - detail::ContextState* p; + class DOCTEST_INTERFACE Context + { + detail::ContextState *p; - void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + void parseArgs(int argc, const char *const *argv, bool withDefaults = false); -public: - explicit Context(int argc = 0, const char* const* argv = nullptr); + public: + explicit Context(int argc = 0, const char *const *argv = nullptr); - Context(const Context&) = delete; - Context(Context&&) = delete; + Context(const Context &) = delete; + Context(Context &&) = delete; - Context& operator=(const Context&) = delete; - Context& operator=(Context&&) = delete; + Context &operator=(const Context &) = delete; + Context &operator=(Context &&) = delete; ~Context(); // NOLINT(performance-trivially-destructible) - void applyCommandLine(int argc, const char* const* argv); + void applyCommandLine(int argc, const char *const *argv); - void addFilter(const char* filter, const char* value); + void addFilter(const char *filter, const char *value); void clearFilters(); - void setOption(const char* option, bool value); - void setOption(const char* option, int value); - void setOption(const char* option, const char* value); + void setOption(const char *option, bool value); + void setOption(const char *option, int value); + void setOption(const char *option, const char *value); bool shouldExit(); @@ -1992,125 +2072,128 @@ class DOCTEST_INTERFACE Context void setAssertHandler(detail::assert_handler ah); - void setCout(std::ostream* out); + void setCout(std::ostream *out); int run(); -}; - -namespace TestCaseFailureReason { - enum Enum - { - None = 0, - AssertFailure = 1, // an assertion has failed in the test case - Exception = 2, // test case threw an exception - Crash = 4, // a crash... - TooManyFailedAsserts = 8, // the abort-after option - Timeout = 16, // see the timeout decorator - ShouldHaveFailedButDidnt = 32, // see the should_fail decorator - ShouldHaveFailedAndDid = 64, // see the should_fail decorator - DidntFailExactlyNumTimes = 128, // see the expected_failures decorator - FailedExactlyNumTimes = 256, // see the expected_failures decorator - CouldHaveFailedAndDid = 512 // see the may_fail decorator + }; + + namespace TestCaseFailureReason { + enum Enum { + None = 0, + AssertFailure = 1, // an assertion has failed in the test case + Exception = 2, // test case threw an exception + Crash = 4, // a crash... + TooManyFailedAsserts = 8, // the abort-after option + Timeout = 16, // see the timeout decorator + ShouldHaveFailedButDidnt = 32, // see the should_fail decorator + ShouldHaveFailedAndDid = 64, // see the should_fail decorator + DidntFailExactlyNumTimes = 128, // see the expected_failures decorator + FailedExactlyNumTimes = 256, // see the expected_failures decorator + CouldHaveFailedAndDid = 512 // see the may_fail decorator }; -} // namespace TestCaseFailureReason + } // namespace TestCaseFailureReason -struct DOCTEST_INTERFACE CurrentTestCaseStats -{ + struct DOCTEST_INTERFACE CurrentTestCaseStats + { int numAssertsCurrentTest; int numAssertsFailedCurrentTest; double seconds; int failure_flags; // use TestCaseFailureReason::Enum bool testCaseSuccess; -}; + }; -struct DOCTEST_INTERFACE TestCaseException -{ + struct DOCTEST_INTERFACE TestCaseException + { String error_string; bool is_crash; -}; + }; -struct DOCTEST_INTERFACE TestRunStats -{ + struct DOCTEST_INTERFACE TestRunStats + { unsigned numTestCases; unsigned numTestCasesPassingFilters; unsigned numTestSuitesPassingFilters; unsigned numTestCasesFailed; int numAsserts; int numAssertsFailed; -}; + }; -struct QueryData -{ - const TestRunStats* run_stats = nullptr; - const TestCaseData** data = nullptr; + struct QueryData + { + const TestRunStats *run_stats = nullptr; + const TestCaseData **data = nullptr; unsigned num_data = 0; -}; + }; -struct DOCTEST_INTERFACE IReporter -{ + struct DOCTEST_INTERFACE IReporter + { // The constructor has to accept "const ContextOptions&" as a single argument // which has most of the options for the run + a pointer to the stdout stream // Reporter(const ContextOptions& in) // called when a query should be reported (listing test cases, printing the version, etc.) - virtual void report_query(const QueryData&) = 0; + virtual void report_query(const QueryData &) = 0; // called when the whole test run starts virtual void test_run_start() = 0; // called when the whole test run ends (caching a pointer to the input doesn't make sense here) - virtual void test_run_end(const TestRunStats&) = 0; + virtual void test_run_end(const TestRunStats &) = 0; // called when a test case is started (safe to cache a pointer to the input) - virtual void test_case_start(const TestCaseData&) = 0; - // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) - virtual void test_case_reenter(const TestCaseData&) = 0; + virtual void test_case_start(const TestCaseData &) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer + // to the input) + virtual void test_case_reenter(const TestCaseData &) = 0; // called when a test case has ended - virtual void test_case_end(const CurrentTestCaseStats&) = 0; + virtual void test_case_end(const CurrentTestCaseStats &) = 0; // called when an exception is thrown from the test case (or it crashes) - virtual void test_case_exception(const TestCaseException&) = 0; + virtual void test_case_exception(const TestCaseException &) = 0; // called whenever a subcase is entered (don't cache pointers to the input) - virtual void subcase_start(const SubcaseSignature&) = 0; + virtual void subcase_start(const SubcaseSignature &) = 0; // called whenever a subcase is exited (don't cache pointers to the input) virtual void subcase_end() = 0; // called for each assert (don't cache pointers to the input) - virtual void log_assert(const AssertData&) = 0; + virtual void log_assert(const AssertData &) = 0; // called for each message (don't cache pointers to the input) - virtual void log_message(const MessageData&) = 0; + virtual void log_message(const MessageData &) = 0; - // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator - // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) - virtual void test_case_skipped(const TestCaseData&) = 0; + // called when a test case is skipped either because it doesn't pass the filters, has a skip + // decorator or isn't in the execution range (between first and last) (safe to cache a pointer + // to the input) + virtual void test_case_skipped(const TestCaseData &) = 0; DOCTEST_DECLARE_INTERFACE(IReporter) // can obtain all currently active contexts and stringify them if one wishes to do so static int get_num_active_contexts(); - static const IContextScope* const* get_active_contexts(); + static const IContextScope *const *get_active_contexts(); - // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown + // can iterate through contexts which have been stringified automatically in their destructors + // when an exception has been thrown static int get_num_stringified_contexts(); - static const String* get_stringified_contexts(); -}; + static const String *get_stringified_contexts(); + }; -namespace detail { - using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); + namespace detail { + using reporterCreatorFunc = IReporter *(*)(const ContextOptions &); - DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); + DOCTEST_INTERFACE void registerReporterImpl(const char *name, int prio, reporterCreatorFunc c, + bool isReporter); - template - IReporter* reporterCreator(const ContextOptions& o) { - return new Reporter(o); + template IReporter *reporterCreator(const ContextOptions &o) + { + return new Reporter(o); } -} // namespace detail + } // namespace detail -template -int registerReporter(const char* name, int priority, bool isReporter) { + template int registerReporter(const char *name, int priority, bool isReporter) + { detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); return 0; -} + } } // namespace doctest #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES @@ -2123,221 +2206,226 @@ int registerReporter(const char* name, int priority, bool isReporter) { #ifndef DOCTEST_CONFIG_DISABLE #ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES -#define DOCTEST_FUNC_SCOPE_BEGIN [&] -#define DOCTEST_FUNC_SCOPE_END () +#define DOCTEST_FUNC_SCOPE_BEGIN [&] +#define DOCTEST_FUNC_SCOPE_END () #define DOCTEST_FUNC_SCOPE_RET(v) return v #else -#define DOCTEST_FUNC_SCOPE_BEGIN do -#define DOCTEST_FUNC_SCOPE_END while(false) +#define DOCTEST_FUNC_SCOPE_BEGIN do +#define DOCTEST_FUNC_SCOPE_END while (false) #define DOCTEST_FUNC_SCOPE_RET(v) (void)0 #endif // common code in asserts - for convenience #define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ - if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \ - b.react(); \ - DOCTEST_FUNC_SCOPE_RET(!b.m_failed) + if (b.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + b.react(); \ + DOCTEST_FUNC_SCOPE_RET(!b.m_failed) #ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #define DOCTEST_WRAP_IN_TRY(x) x; #else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #define DOCTEST_WRAP_IN_TRY(x) \ - try { \ - x; \ - } catch(...) { DOCTEST_RB.translateException(); } + try { \ + x; \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } #endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS #ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS #define DOCTEST_CAST_TO_VOID(...) \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ - static_cast(__VA_ARGS__); \ - DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ + static_cast(__VA_ARGS__); \ + DOCTEST_GCC_SUPPRESS_WARNING_POP #else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS #define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; #endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS // registers the test by initializing a dummy var with a function #define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ - global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ - doctest::detail::regTest( \ - doctest::detail::TestCase( \ - f, __FILE__, __LINE__, \ - doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ - decorators)) + global_prefix DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ + doctest::detail::regTest( \ + doctest::detail::TestCase(f, __FILE__, __LINE__, \ + doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ + decorators)) #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ - namespace { /* NOLINT */ \ - struct der : public base \ - { \ - void f(); \ - }; \ - static DOCTEST_INLINE_NOINLINE void func() { \ - der v; \ - v.f(); \ - } \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + namespace { /* NOLINT */ \ + struct der : public base \ + { \ + void f(); \ + }; \ + static DOCTEST_INLINE_NOINLINE void func() \ + { \ + der v; \ + v.f(); \ } \ - DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + } \ + DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ - static void f(); \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ - static void f() + static void f(); \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ + static void f() #define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ - static doctest::detail::funcType proxy() { return f; } \ - DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ - static void f() + static doctest::detail::funcType proxy() { return f; } \ + DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ + static void f() // for registering tests #define DOCTEST_TEST_CASE(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) // for registering tests in classes - requires C++17 for inline variables! #if DOCTEST_CPLUSPLUS >= 201703L #define DOCTEST_TEST_CASE_CLASS(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ - decorators) + DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), decorators) #else // DOCTEST_TEST_CASE_CLASS #define DOCTEST_TEST_CASE_CLASS(...) \ - TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER + TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER #endif // DOCTEST_TEST_CASE_CLASS // for registering tests with a fixture #define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) // for converting types to strings without the header and demangling #define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ - namespace doctest { \ - template <> \ - inline String toString<__VA_ARGS__>() { \ - return str; \ - } \ - } \ - static_assert(true, "") + namespace doctest { \ + template <> inline String toString<__VA_ARGS__>() { return str; } \ + } \ + static_assert(true, "") #define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ - template \ - static void func(); \ - namespace { /* NOLINT */ \ - template \ - struct iter; \ - template \ - struct iter> \ - { \ - iter(const char* file, unsigned line, int index) { \ - doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ - doctest_detail_test_suite_ns::getCurrentTestSuite(), \ - doctest::toString(), \ - int(line) * 1000 + index) \ - * dec); \ - iter>(file, line, index + 1); \ - } \ - }; \ - template <> \ - struct iter> \ - { \ - iter(const char*, unsigned, int) {} \ - }; \ - } \ - template \ - static void func() + template static void func(); \ + namespace { /* NOLINT */ \ + template struct iter; \ + template struct iter> \ + { \ + iter(const char *file, unsigned line, int index) \ + { \ + doctest::detail::regTest( \ + doctest::detail::TestCase(func, file, line, \ + doctest_detail_test_suite_ns::getCurrentTestSuite(), \ + doctest::toString(), int(line) * 1000 + index) * \ + dec); \ + iter>(file, line, index + 1); \ + } \ + }; \ + template <> struct iter> \ + { \ + iter(const char *, unsigned, int) {} \ + }; \ + } \ + template static void func() #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) #define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ - doctest::detail::instantiationHelper( \ - DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_CAT(anon, \ + DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ + doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR) < __VA_ARGS__ > \ + (__FILE__, __LINE__, 0))) #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ - static_assert(true, "") + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), \ + std::tuple<__VA_ARGS__>) \ + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ - static_assert(true, "") + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), \ + __VA_ARGS__) \ + static_assert(true, "") #define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ - template \ - static void anon() + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ + template static void anon() #define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) + DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) // for subcases #define DOCTEST_SUBCASE(name) \ - if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ - doctest::detail::Subcase(name, __FILE__, __LINE__)) + if (const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) // for grouping tests in test suites by using code blocks #define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ - namespace ns_name { namespace doctest_detail_test_suite_ns { \ - static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ - static doctest::detail::TestSuite data{}; \ - static bool inited = false; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - if(!inited) { \ - data* decorators; \ - inited = true; \ - } \ - return data; \ - } \ + namespace ns_name { \ + namespace doctest_detail_test_suite_ns { \ + static DOCTEST_NOINLINE doctest::detail::TestSuite &getCurrentTestSuite() noexcept \ + { \ + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ + static bool inited = false; \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + if (!inited) { \ + data *decorators; \ + inited = true; \ } \ + return data; \ + } \ } \ - namespace ns_name + } \ + namespace ns_name #define DOCTEST_TEST_SUITE(decorators) \ - DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) + DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) // for starting a testsuite block #define DOCTEST_TEST_SUITE_BEGIN(decorators) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ - static_assert(true, "") + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ + static_assert(true, "") // for ending a testsuite block #define DOCTEST_TEST_SUITE_END \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ - using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ + using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int // for registering exception translators #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ - inline doctest::String translatorName(signature); \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerExceptionTranslator(translatorName)) \ - doctest::String translatorName(signature) + inline doctest::String translatorName(signature); \ + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerExceptionTranslator(translatorName)) \ + doctest::String translatorName(signature) #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ - signature) + DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), signature) // for registering reporters #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, true)) \ - static_assert(true, "") + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, true)) \ + static_assert(true, "") // for registering listeners #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, false)) \ - static_assert(true, "") + DOCTEST_GLOBAL_NO_WARNINGS( \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, false)) \ + static_assert(true, "") // clang-format off // for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 @@ -2347,24 +2435,26 @@ int registerReporter(const char* name, int priority, bool isReporter) { __VA_ARGS__) // clang-format on -#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ - auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ - [&](std::ostream* s_name) { \ +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = \ + doctest::detail::MakeContextScope([&](std::ostream *s_name) { \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ mb_name.m_stream = s_name; \ - mb_name * __VA_ARGS__; \ - }) + mb_name *__VA_ARGS__; \ + }) #define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) #define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ - mb * __VA_ARGS__; \ - if(mb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - mb.react(); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ + mb *__VA_ARGS__; \ + if (mb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + mb.react(); \ + } \ + DOCTEST_FUNC_SCOPE_END // clang-format off #define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) @@ -2372,47 +2462,49 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) // clang-format on -#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) #define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) -#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS #define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ - } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); } \ + DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) #define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY( \ - DOCTEST_RB.binary_assert( \ - __VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY( \ + DOCTEST_RB.binary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + DOCTEST_FUNC_SCOPE_END #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + DOCTEST_FUNC_SCOPE_END #else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2420,27 +2512,27 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 #define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - doctest::detail::decomp_assert( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + doctest::detail::decomp_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) << __VA_ARGS__) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP #define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ - doctest::detail::binary_assert( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) + doctest::detail::binary_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) #define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ - #__VA_ARGS__, __VA_ARGS__) + doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__, __VA_ARGS__) #endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS -#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) -#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) -#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) -#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) +#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) +#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) +#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) +#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) // clang-format off @@ -2452,75 +2544,93 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END // clang-format on -#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) -#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) +#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) +#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) #define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) -#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) -#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) +#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) +#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) #define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) -#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) -#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) +#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) +#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) #define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) -#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) -#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) +#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) +#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) #define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) -#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) -#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) +#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) +#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) #define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) -#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) -#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) +#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) +#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) #define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) -#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr, #__VA_ARGS__, message); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch(const typename doctest::detail::types::remove_const< \ - typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\ - DOCTEST_RB.translateException(); \ - DOCTEST_RB.m_threw_as = true; \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + if (!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #expr, #__VA_ARGS__, message); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } \ + catch (const typename doctest::detail::types::remove_const< \ + typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type &) { \ + DOCTEST_RB.translateException(); \ + DOCTEST_RB.m_threw_as = true; \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } \ + DOCTEST_FUNC_SCOPE_END #define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, expr_str, "", __VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + if (!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, expr_str, "", __VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } \ + DOCTEST_FUNC_SCOPE_END #define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END + DOCTEST_FUNC_SCOPE_BEGIN \ + { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ + } \ + catch (...) { \ + DOCTEST_RB.translateException(); \ + } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } \ + DOCTEST_FUNC_SCOPE_END // clang-format off #define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") @@ -2569,97 +2679,98 @@ int registerReporter(const char* name, int priority, bool isReporter) { #else // DOCTEST_CONFIG_DISABLE #define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ - namespace /* NOLINT */ { \ - template \ - struct der : public base \ - { void f(); }; \ - } \ - template \ - inline void der::f() + namespace /* NOLINT */ { \ + template struct der : public base \ + { \ + void f(); \ + }; \ + } \ + template \ + inline void der::f() #define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ - template \ - static inline void f() + template static inline void f() // for registering tests #define DOCTEST_TEST_CASE(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for registering tests in classes #define DOCTEST_TEST_CASE_CLASS(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for registering tests with a fixture #define DOCTEST_TEST_CASE_FIXTURE(x, name) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) // for converting types to strings without the header and demangling #define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") -#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") +#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") // for typed tests #define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + template inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() #define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + template inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() #define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") // for subcases #define DOCTEST_SUBCASE(name) // for a testsuite block -#define DOCTEST_TEST_SUITE(name) namespace // NOLINT +#define DOCTEST_TEST_SUITE(name) namespace // NOLINT // for starting a testsuite block #define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") // for ending a testsuite block -#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int +#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int #define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - template \ - static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) + template \ + static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define DOCTEST_INFO(...) (static_cast(0)) -#define DOCTEST_CAPTURE(x) (static_cast(0)) -#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_INFO(...) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) #define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_MESSAGE(...) (static_cast(0)) -#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) -#define DOCTEST_FAIL(...) (static_cast(0)) - -#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \ - && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) - -#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_MESSAGE(...) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) +#define DOCTEST_FAIL(...) (static_cast(0)) + +#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) && \ + defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) + +#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() #define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() namespace doctest { -namespace detail { + namespace detail { #define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } + template \ + bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) \ + { \ + return lhs op rhs; \ + } DOCTEST_RELATIONAL_OP(eq, ==) DOCTEST_RELATIONAL_OP(ne, !=) @@ -2667,147 +2778,325 @@ namespace detail { DOCTEST_RELATIONAL_OP(gt, >) DOCTEST_RELATIONAL_OP(le, <=) DOCTEST_RELATIONAL_OP(ge, >=) -} // namespace detail + } // namespace detail } // namespace doctest -#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() #define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }() -#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) - -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) - -#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) \ + [] { \ + static_assert(false, "Exception translation is not available when doctest is disabled."); \ + return false; \ + }() +#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) + +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(, , ) + +#define DOCTEST_WARN_THROWS(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_CHECK_THROWS(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_REQUIRE_THROWS(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_WARN_THROWS_AS(expr, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_CHECK_THROWS_AS(expr, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_WARN_NOTHROW(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_CHECK_NOTHROW(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_REQUIRE_NOTHROW(...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return false; \ + } \ + catch (...) { \ + return true; \ + } \ + }() +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ + [&] { \ + try { \ + expr; \ + } \ + catch (__VA_ARGS__) { \ + return true; \ + } \ + catch (...) { \ + } \ + return false; \ + }() +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) \ + [&] { \ + try { \ + __VA_ARGS__; \ + return true; \ + } \ + catch (...) { \ + return false; \ + } \ + }() #endif // DOCTEST_CONFIG_NO_EXCEPTIONS #else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED -#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -2820,8 +3109,13 @@ namespace detail { #ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS #define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \ - "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }() +#define DOCTEST_EXCEPTION_EMPTY_FUNC \ + [] { \ + static_assert(false, "Exceptions are disabled! " \ + "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to " \ + "compile with exceptions disabled."); \ + return false; \ + }() #undef DOCTEST_REQUIRE #undef DOCTEST_REQUIRE_FALSE @@ -2836,52 +3130,52 @@ namespace detail { #undef DOCTEST_REQUIRE_UNARY #undef DOCTEST_REQUIRE_UNARY_FALSE -#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC #define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC #endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC #define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC #define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC #endif // DOCTEST_CONFIG_NO_EXCEPTIONS @@ -2933,139 +3227,151 @@ namespace detail { // == SHORT VERSIONS OF THE MACROS #ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES -#define TEST_CASE(name) DOCTEST_TEST_CASE(name) -#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) -#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) -#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) -#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) -#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) -#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) -#define SUBCASE(name) DOCTEST_SUBCASE(name) -#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) -#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) -#define TEST_SUITE_END DOCTEST_TEST_SUITE_END +#define TEST_CASE(name) DOCTEST_TEST_CASE(name) +#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) +#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) +#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) +#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) +#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) +#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) +#define SUBCASE(name) DOCTEST_SUBCASE(name) +#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) +#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) +#define TEST_SUITE_END DOCTEST_TEST_SUITE_END #define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) -#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) -#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define INFO(...) DOCTEST_INFO(__VA_ARGS__) -#define CAPTURE(x) DOCTEST_CAPTURE(x) -#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) +#define REGISTER_REPORTER(name, priority, reporter) \ + DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define REGISTER_LISTENER(name, priority, reporter) \ + DOCTEST_REGISTER_LISTENER(name, priority, reporter) +#define INFO(...) DOCTEST_INFO(__VA_ARGS__) +#define CAPTURE(x) DOCTEST_CAPTURE(x) +#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) #define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) -#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) -#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) -#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) -#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) -#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) - -#define WARN(...) DOCTEST_WARN(__VA_ARGS__) -#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) -#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) -#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) -#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) -#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) -#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) -#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) -#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) -#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) -#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) +#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) +#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) +#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) +#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) +#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) + +#define WARN(...) DOCTEST_WARN(__VA_ARGS__) +#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) +#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) +#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) +#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) +#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) +#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) +#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) +#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) +#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) #define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) -#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) -#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) -#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) -#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) +#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) +#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) +#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS(expr, with, ...) \ + DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) #define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) -#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) -#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) -#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) +#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) +#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) +#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) #define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) \ + DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ + DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) #define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) -#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) +#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) #define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) -#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) -#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) \ + DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) \ + DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ + DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) #define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) \ + DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) \ + DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) \ + DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) #define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define SCENARIO(name) DOCTEST_SCENARIO(name) -#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) -#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) +#define SCENARIO(name) DOCTEST_SCENARIO(name) +#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) +#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) #define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) -#define GIVEN(name) DOCTEST_GIVEN(name) -#define WHEN(name) DOCTEST_WHEN(name) -#define AND_WHEN(name) DOCTEST_AND_WHEN(name) -#define THEN(name) DOCTEST_THEN(name) -#define AND_THEN(name) DOCTEST_AND_THEN(name) - -#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) -#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) -#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) -#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) -#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) -#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) -#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) -#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) -#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) -#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) -#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) -#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) -#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) -#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) -#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) -#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) -#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) -#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) -#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) -#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) -#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) -#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) -#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define GIVEN(name) DOCTEST_GIVEN(name) +#define WHEN(name) DOCTEST_WHEN(name) +#define AND_WHEN(name) DOCTEST_AND_WHEN(name) +#define THEN(name) DOCTEST_THEN(name) +#define AND_THEN(name) DOCTEST_AND_THEN(name) + +#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) +#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) +#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) +#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) +#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) +#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) +#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) +#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) +#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) +#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) +#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) +#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) +#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) +#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) +#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) +#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) +#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) +#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) +#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) +#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) +#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) +#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) +#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) #define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) // KEPT FOR BACKWARDS COMPATIBILITY -#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) -#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) +#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) +#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) #define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) -#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) -#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) +#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) +#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) #define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) -#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) -#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) +#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) +#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) #define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) -#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) -#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) +#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) +#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) #define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) -#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) -#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) +#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) +#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) #define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) -#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) -#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) +#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) +#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) #define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) -#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) -#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) -#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) -#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) -#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) +#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) +#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) +#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) +#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) #define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) -#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES @@ -3146,21 +3452,22 @@ DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linka DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN // required includes - will go only in one translation unit! -#include -#include #include -// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 +#include +#include +// borland (Embarcadero) compiler requires math.h and not cmath - +// https://github.com/doctest/doctest/pull/37 #ifdef __BORLANDC__ #include #endif // __BORLANDC__ -#include #include #include #include -#include -#include #include +#include +#include #include +#include #ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM #include #endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM @@ -3170,29 +3477,30 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #ifndef DOCTEST_CONFIG_NO_MULTITHREADING #include #include -#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; +#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; #define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) -#define DOCTEST_LOCK_MUTEX(name) std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); +#define DOCTEST_LOCK_MUTEX(name) \ + std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); #else // DOCTEST_CONFIG_NO_MULTITHREADING #define DOCTEST_DECLARE_MUTEX(name) #define DOCTEST_DECLARE_STATIC_MUTEX(name) #define DOCTEST_LOCK_MUTEX(name) #endif // DOCTEST_CONFIG_NO_MULTITHREADING -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include #include +#include #ifdef DOCTEST_PLATFORM_MAC +#include #include #include -#include #endif // DOCTEST_PLATFORM_MAC #ifdef DOCTEST_PLATFORM_WINDOWS @@ -3244,7 +3552,8 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END #endif #ifndef DOCTEST_THREAD_LOCAL -#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || \ + DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) #define DOCTEST_THREAD_LOCAL #else // DOCTEST_MSVC #define DOCTEST_THREAD_LOCAL thread_local @@ -3275,156 +3584,154 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END namespace doctest { -bool is_running_in_test = false; + bool is_running_in_test = false; -namespace { + namespace { using namespace detail; - template - DOCTEST_NORETURN void throw_exception(Ex const& e) { + template DOCTEST_NORETURN void throw_exception(Ex const &e) + { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - throw e; -#else // DOCTEST_CONFIG_NO_EXCEPTIONS + throw e; +#else // DOCTEST_CONFIG_NO_EXCEPTIONS #ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION - DOCTEST_CONFIG_HANDLE_EXCEPTION(e); + DOCTEST_CONFIG_HANDLE_EXCEPTION(e); #else // DOCTEST_CONFIG_HANDLE_EXCEPTION #ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - std::cerr << "doctest will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; + std::cerr << "doctest will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; #endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM #endif // DOCTEST_CONFIG_HANDLE_EXCEPTION - std::terminate(); + std::terminate(); #endif // DOCTEST_CONFIG_NO_EXCEPTIONS } #ifndef DOCTEST_INTERNAL_ERROR #define DOCTEST_INTERNAL_ERROR(msg) \ - throw_exception(std::logic_error( \ - __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) + throw_exception( \ + std::logic_error(__FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) #endif // DOCTEST_INTERNAL_ERROR // case insensitive strcmp - int stricmp(const char* a, const char* b) { - for(;; a++, b++) { - const int d = tolower(*a) - tolower(*b); - if(d != 0 || !*a) - return d; - } + int stricmp(const char *a, const char *b) + { + for (;; a++, b++) { + const int d = tolower(*a) - tolower(*b); + if (d != 0 || !*a) + return d; + } } struct Endianness { - enum Arch - { - Big, - Little - }; - - static Arch which() { - int x = 1; - // casting any data pointer to char* is allowed - auto ptr = reinterpret_cast(&x); - if(*ptr) - return Little; - return Big; - } + enum Arch { Big, Little }; + + static Arch which() + { + int x = 1; + // casting any data pointer to char* is allowed + auto ptr = reinterpret_cast(&x); + if (*ptr) + return Little; + return Big; + } }; -} // namespace + } // namespace -namespace detail { + namespace detail { DOCTEST_THREAD_LOCAL class { - std::vector stack; - std::stringstream ss; + std::vector stack; + std::stringstream ss; public: - std::ostream* push() { - stack.push_back(ss.tellp()); - return &ss; - } - - String pop() { - if (stack.empty()) - DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); - - std::streampos pos = stack.back(); - stack.pop_back(); - unsigned sz = static_cast(ss.tellp() - pos); - ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); - return String(ss, sz); - } + std::ostream *push() + { + stack.push_back(ss.tellp()); + return &ss; + } + + String pop() + { + if (stack.empty()) + DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); + + std::streampos pos = stack.back(); + stack.pop_back(); + unsigned sz = static_cast(ss.tellp() - pos); + ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); + return String(ss, sz); + } } g_oss; - std::ostream* tlssPush() { - return g_oss.push(); - } + std::ostream *tlssPush() { return g_oss.push(); } - String tlssPop() { - return g_oss.pop(); - } + String tlssPop() { return g_oss.pop(); } #ifndef DOCTEST_CONFIG_DISABLE -namespace timer_large_integer -{ + namespace timer_large_integer { #if defined(DOCTEST_PLATFORM_WINDOWS) - using type = ULONGLONG; -#else // DOCTEST_PLATFORM_WINDOWS - using type = std::uint64_t; + using type = ULONGLONG; +#else // DOCTEST_PLATFORM_WINDOWS + using type = std::uint64_t; #endif // DOCTEST_PLATFORM_WINDOWS -} + } // namespace timer_large_integer -using ticks_t = timer_large_integer::type; + using ticks_t = timer_large_integer::type; #ifdef DOCTEST_CONFIG_GETCURRENTTICKS ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); } #elif defined(DOCTEST_PLATFORM_WINDOWS) - ticks_t getCurrentTicks() { - static LARGE_INTEGER hz = { {0} }, hzo = { {0} }; - if(!hz.QuadPart) { - QueryPerformanceFrequency(&hz); - QueryPerformanceCounter(&hzo); - } - LARGE_INTEGER t; - QueryPerformanceCounter(&t); - return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; + ticks_t getCurrentTicks() + { + static LARGE_INTEGER hz = {{0}}, hzo = {{0}}; + if (!hz.QuadPart) { + QueryPerformanceFrequency(&hz); + QueryPerformanceCounter(&hzo); + } + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; } #else // DOCTEST_PLATFORM_WINDOWS - ticks_t getCurrentTicks() { - timeval t; - gettimeofday(&t, nullptr); - return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); + ticks_t getCurrentTicks() + { + timeval t; + gettimeofday(&t, nullptr); + return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); } #endif // DOCTEST_PLATFORM_WINDOWS struct Timer { - void start() { m_ticks = getCurrentTicks(); } - unsigned int getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); - } - //unsigned int getElapsedMilliseconds() const { - // return static_cast(getElapsedMicroseconds() / 1000); - //} - double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } + void start() { m_ticks = getCurrentTicks(); } + unsigned int getElapsedMicroseconds() const + { + return static_cast(getCurrentTicks() - m_ticks); + } + // unsigned int getElapsedMilliseconds() const { + // return static_cast(getElapsedMicroseconds() / 1000); + // } + double getElapsedSeconds() const + { + return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; + } private: - ticks_t m_ticks = 0; + ticks_t m_ticks = 0; }; #ifdef DOCTEST_CONFIG_NO_MULTITHREADING - template - using Atomic = T; -#else // DOCTEST_CONFIG_NO_MULTITHREADING - template - using Atomic = std::atomic; + template using Atomic = T; +#else // DOCTEST_CONFIG_NO_MULTITHREADING + template using Atomic = std::atomic; #endif // DOCTEST_CONFIG_NO_MULTITHREADING #if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING) - template - using MultiLaneAtomic = Atomic; -#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + template using MultiLaneAtomic = Atomic; +#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS // Provides a multilane implementation of an atomic variable that supports add, sub, load, // store. Instead of using a single atomic variable, this splits up into multiple ones, // each sitting on a separate cache line. The goal is to provide a speedup when most @@ -3435,157 +3742,168 @@ using ticks_t = timer_large_integer::type; // // The disadvantage is that there is a small overhead due to the use of TLS, and load/store // is slower because all atomics have to be accessed. - template - class MultiLaneAtomic + template class MultiLaneAtomic { - struct CacheLineAlignedAtomic - { - Atomic atomic{}; - char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; - }; - CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; + struct CacheLineAlignedAtomic + { + Atomic atomic{}; + char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; + }; + CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; - static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, - "guarantee one atomic takes exactly one cache line"); + static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, + "guarantee one atomic takes exactly one cache line"); public: - T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } - T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - return myAtomic().fetch_add(arg, order); - } + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT + { + return myAtomic().fetch_add(arg, order); + } - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - return myAtomic().fetch_sub(arg, order); - } + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT + { + return myAtomic().fetch_sub(arg, order); + } - operator T() const DOCTEST_NOEXCEPT { return load(); } + operator T() const DOCTEST_NOEXCEPT { return load(); } - T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { - auto result = T(); - for(auto const& c : m_atomics) { - result += c.atomic.load(order); - } - return result; + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT + { + auto result = T(); + for (auto const &c : m_atomics) { + result += c.atomic.load(order); } + return result; + } - T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] - store(desired); - return desired; - } + T operator=(T desired) DOCTEST_NOEXCEPT + { // lgtm [cpp/assignment-does-not-return-this] + store(desired); + return desired; + } - void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - // first value becomes desired", all others become 0. - for(auto& c : m_atomics) { - c.atomic.store(desired, order); - desired = {}; - } + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT + { + // first value becomes desired", all others become 0. + for (auto &c : m_atomics) { + c.atomic.store(desired, order); + desired = {}; } + } private: - // Each thread has a different atomic that it operates on. If more than NumLanes threads - // use this, some will use the same atomic. So performance will degrade a bit, but still - // everything will work. - // - // The logic here is a bit tricky. The call should be as fast as possible, so that there - // is minimal to no overhead in determining the correct atomic for the current thread. - // - // 1. A global static counter laneCounter counts continuously up. - // 2. Each successive thread will use modulo operation of that counter so it gets an atomic - // assigned in a round-robin fashion. - // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with - // little overhead. - Atomic& myAtomic() DOCTEST_NOEXCEPT { - static Atomic laneCounter; - DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = - laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; - - return m_atomics[tlsLaneIdx].atomic; - } + // Each thread has a different atomic that it operates on. If more than NumLanes threads + // use this, some will use the same atomic. So performance will degrade a bit, but still + // everything will work. + // + // The logic here is a bit tricky. The call should be as fast as possible, so that there + // is minimal to no overhead in determining the correct atomic for the current thread. + // + // 1. A global static counter laneCounter counts continuously up. + // 2. Each successive thread will use modulo operation of that counter so it gets an atomic + // assigned in a round-robin fashion. + // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with + // little overhead. + Atomic &myAtomic() DOCTEST_NOEXCEPT + { + static Atomic laneCounter; + DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = + laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; + + return m_atomics[tlsLaneIdx].atomic; + } }; #endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS // this holds both parameters from the command line and runtime data for tests struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats { - MultiLaneAtomic numAssertsCurrentTest_atomic; - MultiLaneAtomic numAssertsFailedCurrentTest_atomic; - - std::vector> filters = decltype(filters)(9); // 9 different filters - - std::vector reporters_currently_used; - - assert_handler ah = nullptr; - - Timer timer; - - std::vector stringifiedContexts; // logging from INFO() due to an exception - - // stuff for subcases - bool reachedLeaf; - std::vector subcaseStack; - std::vector nextSubcaseStack; - std::unordered_set fullyTraversedSubcases; - size_t currentSubcaseDepth; - Atomic shouldLogCurrentException; - - void resetRunData() { - numTestCases = 0; - numTestCasesPassingFilters = 0; - numTestSuitesPassingFilters = 0; - numTestCasesFailed = 0; - numAsserts = 0; - numAssertsFailed = 0; - numAssertsCurrentTest = 0; - numAssertsFailedCurrentTest = 0; - } - - void finalizeTestCaseData() { - seconds = timer.getElapsedSeconds(); - - // update the non-atomic counters - numAsserts += numAssertsCurrentTest_atomic; - numAssertsFailed += numAssertsFailedCurrentTest_atomic; - numAssertsCurrentTest = numAssertsCurrentTest_atomic; - numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; - - if(numAssertsFailedCurrentTest) - failure_flags |= TestCaseFailureReason::AssertFailure; - - if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && - Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) - failure_flags |= TestCaseFailureReason::Timeout; - - if(currentTest->m_should_fail) { - if(failure_flags) { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; - } else { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; - } - } else if(failure_flags && currentTest->m_may_fail) { - failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; - } else if(currentTest->m_expected_failures > 0) { - if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) { - failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; - } else { - failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; - } - } - - bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); - - // if any subcase has failed - the whole test case has failed - testCaseSuccess = !(failure_flags && !ok_to_fail); - if(!testCaseSuccess) - numTestCasesFailed++; - } + MultiLaneAtomic numAssertsCurrentTest_atomic; + MultiLaneAtomic numAssertsFailedCurrentTest_atomic; + + std::vector> filters = decltype(filters)(9); // 9 different filters + + std::vector reporters_currently_used; + + assert_handler ah = nullptr; + + Timer timer; + + std::vector stringifiedContexts; // logging from INFO() due to an exception + + // stuff for subcases + bool reachedLeaf; + std::vector subcaseStack; + std::vector nextSubcaseStack; + std::unordered_set fullyTraversedSubcases; + size_t currentSubcaseDepth; + Atomic shouldLogCurrentException; + + void resetRunData() + { + numTestCases = 0; + numTestCasesPassingFilters = 0; + numTestSuitesPassingFilters = 0; + numTestCasesFailed = 0; + numAsserts = 0; + numAssertsFailed = 0; + numAssertsCurrentTest = 0; + numAssertsFailedCurrentTest = 0; + } + + void finalizeTestCaseData() + { + seconds = timer.getElapsedSeconds(); + + // update the non-atomic counters + numAsserts += numAssertsCurrentTest_atomic; + numAssertsFailed += numAssertsFailedCurrentTest_atomic; + numAssertsCurrentTest = numAssertsCurrentTest_atomic; + numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; + + if (numAssertsFailedCurrentTest) + failure_flags |= TestCaseFailureReason::AssertFailure; + + if (Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && + Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) + failure_flags |= TestCaseFailureReason::Timeout; + + if (currentTest->m_should_fail) { + if (failure_flags) { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; + } + else { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; + } + } + else if (failure_flags && currentTest->m_may_fail) { + failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; + } + else if (currentTest->m_expected_failures > 0) { + if (numAssertsFailedCurrentTest == currentTest->m_expected_failures) { + failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; + } + else { + failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; + } + } + + bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); + + // if any subcase has failed - the whole test case has failed + testCaseSuccess = !(failure_flags && !ok_to_fail); + if (!testCaseSuccess) + numTestCasesFailed++; + } }; - ContextState* g_cs = nullptr; + ContextState *g_cs = nullptr; // used to avoid locks for the debug output // TODO: figure out if this is indeed necessary/correct - seems like either there still @@ -3593,241 +3911,279 @@ using ticks_t = timer_large_integer::type; DOCTEST_THREAD_LOCAL bool g_no_colors; #endif // DOCTEST_CONFIG_DISABLE -} // namespace detail + } // namespace detail -char* String::allocate(size_type sz) { + char *String::allocate(size_type sz) + { if (sz <= last) { - buf[sz] = '\0'; - setLast(last - sz); - return buf; - } else { - setOnHeap(); - data.size = sz; - data.capacity = data.size + 1; - data.ptr = new char[data.capacity]; - data.ptr[sz] = '\0'; - return data.ptr; + buf[sz] = '\0'; + setLast(last - sz); + return buf; } -} - -void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } -void String::setLast(size_type in) noexcept { buf[last] = char(in); } -void String::setSize(size_type sz) noexcept { - if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); } - else { data.ptr[sz] = '\0'; data.size = sz; } -} + else { + setOnHeap(); + data.size = sz; + data.capacity = data.size + 1; + data.ptr = new char[data.capacity]; + data.ptr[sz] = '\0'; + return data.ptr; + } + } + + void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } + void String::setLast(size_type in) noexcept { buf[last] = char(in); } + void String::setSize(size_type sz) noexcept + { + if (isOnStack()) { + buf[sz] = '\0'; + setLast(last - sz); + } + else { + data.ptr[sz] = '\0'; + data.size = sz; + } + } -void String::copy(const String& other) { - if(other.isOnStack()) { - memcpy(buf, other.buf, len); - } else { - memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + void String::copy(const String &other) + { + if (other.isOnStack()) { + memcpy(buf, other.buf, len); } -} + else { + memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + } + } -String::String() noexcept { + String::String() noexcept + { buf[0] = '\0'; setLast(); -} + } -String::~String() { - if(!isOnStack()) - delete[] data.ptr; -} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + String::~String() + { + if (!isOnStack()) + delete[] data.ptr; + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) -String::String(const char* in) - : String(in, strlen(in)) {} + String::String(const char *in) : String(in, strlen(in)) {} -String::String(const char* in, size_type in_size) { - memcpy(allocate(in_size), in, in_size); -} + String::String(const char *in, size_type in_size) { memcpy(allocate(in_size), in, in_size); } -String::String(std::istream& in, size_type in_size) { - in.read(allocate(in_size), in_size); -} + String::String(std::istream &in, size_type in_size) { in.read(allocate(in_size), in_size); } -String::String(const String& other) { copy(other); } + String::String(const String &other) { copy(other); } -String& String::operator=(const String& other) { - if(this != &other) { - if(!isOnStack()) - delete[] data.ptr; + String &String::operator=(const String &other) + { + if (this != &other) { + if (!isOnStack()) + delete[] data.ptr; - copy(other); + copy(other); } return *this; -} + } -String& String::operator+=(const String& other) { + String &String::operator+=(const String &other) + { const size_type my_old_size = size(); const size_type other_size = other.size(); const size_type total_size = my_old_size + other_size; - if(isOnStack()) { - if(total_size < len) { - // append to the current stack space - memcpy(buf + my_old_size, other.c_str(), other_size + 1); - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - setLast(last - total_size); - } else { - // alloc new chunk - char* temp = new char[total_size + 1]; - // copy current data to new location before writing in the union - memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed - // update data in union - setOnHeap(); - data.size = total_size; - data.capacity = data.size + 1; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } - } else { - if(data.capacity > total_size) { - // append to the current heap block - data.size = total_size; - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } else { - // resize - data.capacity *= 2; - if(data.capacity <= total_size) - data.capacity = total_size + 1; - // alloc new chunk - char* temp = new char[data.capacity]; - // copy current data to new location before releasing it - memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed - // release old chunk - delete[] data.ptr; - // update the rest of the union members - data.size = total_size; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } + if (isOnStack()) { + if (total_size < len) { + // append to the current stack space + memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + setLast(last - total_size); + } + else { + // alloc new chunk + char *temp = new char[total_size + 1]; + // copy current data to new location before writing in the union + memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed + // update data in union + setOnHeap(); + data.size = total_size; + data.capacity = data.size + 1; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } + else { + if (data.capacity > total_size) { + // append to the current heap block + data.size = total_size; + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + else { + // resize + data.capacity *= 2; + if (data.capacity <= total_size) + data.capacity = total_size + 1; + // alloc new chunk + char *temp = new char[data.capacity]; + // copy current data to new location before releasing it + memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed + // release old chunk + delete[] data.ptr; + // update the rest of the union members + data.size = total_size; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } } return *this; -} + } -String::String(String&& other) noexcept { + String::String(String &&other) noexcept + { memcpy(buf, other.buf, len); other.buf[0] = '\0'; other.setLast(); -} + } -String& String::operator=(String&& other) noexcept { - if(this != &other) { - if(!isOnStack()) - delete[] data.ptr; - memcpy(buf, other.buf, len); - other.buf[0] = '\0'; - other.setLast(); + String &String::operator=(String &&other) noexcept + { + if (this != &other) { + if (!isOnStack()) + delete[] data.ptr; + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); } return *this; -} + } -char String::operator[](size_type i) const { - return const_cast(this)->operator[](i); -} + char String::operator[](size_type i) const { return const_cast(this)->operator[](i); } -char& String::operator[](size_type i) { - if(isOnStack()) - return reinterpret_cast(buf)[i]; + char &String::operator[](size_type i) + { + if (isOnStack()) + return reinterpret_cast(buf)[i]; return data.ptr[i]; -} + } -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") -String::size_type String::size() const { - if(isOnStack()) - return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") + String::size_type String::size() const + { + if (isOnStack()) + return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 return data.size; -} -DOCTEST_GCC_SUPPRESS_WARNING_POP + } + DOCTEST_GCC_SUPPRESS_WARNING_POP -String::size_type String::capacity() const { - if(isOnStack()) - return len; + String::size_type String::capacity() const + { + if (isOnStack()) + return len; return data.capacity; -} + } -String String::substr(size_type pos, size_type cnt) && { - cnt = std::min(cnt, size() - 1 - pos); - char* cptr = c_str(); + String String::substr(size_type pos, size_type cnt) && + { + cnt = std::min(cnt, size() - 1 - pos); + char *cptr = c_str(); memmove(cptr, cptr + pos, cnt); setSize(cnt); return std::move(*this); -} + } -String String::substr(size_type pos, size_type cnt) const & { + String String::substr(size_type pos, size_type cnt) const & + { cnt = std::min(cnt, size() - 1 - pos); - return String{ c_str() + pos, cnt }; -} - -String::size_type String::find(char ch, size_type pos) const { - const char* begin = c_str(); - const char* end = begin + size(); - const char* it = begin + pos; - for (; it < end && *it != ch; it++); - if (it < end) { return static_cast(it - begin); } - else { return npos; } -} - -String::size_type String::rfind(char ch, size_type pos) const { - const char* begin = c_str(); - const char* it = begin + std::min(pos, size() - 1); - for (; it >= begin && *it != ch; it--); - if (it >= begin) { return static_cast(it - begin); } - else { return npos; } -} + return String{c_str() + pos, cnt}; + } + + String::size_type String::find(char ch, size_type pos) const + { + const char *begin = c_str(); + const char *end = begin + size(); + const char *it = begin + pos; + for (; it < end && *it != ch; it++) + ; + if (it < end) { + return static_cast(it - begin); + } + else { + return npos; + } + } + + String::size_type String::rfind(char ch, size_type pos) const + { + const char *begin = c_str(); + const char *it = begin + std::min(pos, size() - 1); + for (; it >= begin && *it != ch; it--) + ; + if (it >= begin) { + return static_cast(it - begin); + } + else { + return npos; + } + } -int String::compare(const char* other, bool no_case) const { - if(no_case) - return doctest::stricmp(c_str(), other); + int String::compare(const char *other, bool no_case) const + { + if (no_case) + return doctest::stricmp(c_str(), other); return std::strcmp(c_str(), other); -} + } -int String::compare(const String& other, bool no_case) const { + int String::compare(const String &other, bool no_case) const + { return compare(other.c_str(), no_case); -} + } -String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } + String operator+(const String &lhs, const String &rhs) { return String(lhs) += rhs; } -bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } -bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } -bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } -bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } -bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } -bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } + bool operator==(const String &lhs, const String &rhs) { return lhs.compare(rhs) == 0; } + bool operator!=(const String &lhs, const String &rhs) { return lhs.compare(rhs) != 0; } + bool operator<(const String &lhs, const String &rhs) { return lhs.compare(rhs) < 0; } + bool operator>(const String &lhs, const String &rhs) { return lhs.compare(rhs) > 0; } + bool operator<=(const String &lhs, const String &rhs) + { + return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; + } + bool operator>=(const String &lhs, const String &rhs) + { + return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; + } -std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } + std::ostream &operator<<(std::ostream &s, const String &in) { return s << in.c_str(); } -Contains::Contains(const String& str) : string(str) { } + Contains::Contains(const String &str) : string(str) {} -bool Contains::checkWith(const String& other) const { + bool Contains::checkWith(const String &other) const + { return strstr(other.c_str(), string.c_str()) != nullptr; -} + } -String toString(const Contains& in) { - return "Contains( " + in.string + " )"; -} + String toString(const Contains &in) { return "Contains( " + in.string + " )"; } -bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } -bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } -bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } -bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + bool operator==(const String &lhs, const Contains &rhs) { return rhs.checkWith(lhs); } + bool operator==(const Contains &lhs, const String &rhs) { return lhs.checkWith(rhs); } + bool operator!=(const String &lhs, const Contains &rhs) { return !rhs.checkWith(lhs); } + bool operator!=(const Contains &lhs, const String &rhs) { return !lhs.checkWith(rhs); } -namespace { - void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) -} // namespace + namespace { + void color_to_stream(std::ostream &, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) + } // namespace -namespace Color { - std::ostream& operator<<(std::ostream& s, Color::Enum code) { - color_to_stream(s, code); - return s; + namespace Color { + std::ostream &operator<<(std::ostream &s, Color::Enum code) + { + color_to_stream(s, code); + return s; } -} // namespace Color + } // namespace Color -// clang-format off + // clang-format off const char* assertString(assertType::Enum at) { DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type @@ -3866,181 +4222,191 @@ const char* assertString(assertType::Enum at) { } DOCTEST_MSVC_SUPPRESS_WARNING_POP } -// clang-format on - -const char* failureString(assertType::Enum at) { - if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional - return "WARNING"; - if(at & assertType::is_check) //!OCLINT bitwise operator in conditional - return "ERROR"; - if(at & assertType::is_require) //!OCLINT bitwise operator in conditional - return "FATAL ERROR"; + // clang-format on + + const char *failureString(assertType::Enum at) + { + if (at & assertType::is_warn) //! OCLINT bitwise operator in conditional + return "WARNING"; + if (at & assertType::is_check) //! OCLINT bitwise operator in conditional + return "ERROR"; + if (at & assertType::is_require) //! OCLINT bitwise operator in conditional + return "FATAL ERROR"; return ""; -} + } -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -// depending on the current options this will remove the path of filenames -const char* skipPathFromFilename(const char* file) { + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") + // depending on the current options this will remove the path of filenames + const char *skipPathFromFilename(const char *file) + { #ifndef DOCTEST_CONFIG_DISABLE - if(getContextOptions()->no_path_in_filenames) { - auto back = std::strrchr(file, '\\'); - auto forward = std::strrchr(file, '/'); - if(back || forward) { - if(back > forward) - forward = back; - return forward + 1; - } + if (getContextOptions()->no_path_in_filenames) { + auto back = std::strrchr(file, '\\'); + auto forward = std::strrchr(file, '/'); + if (back || forward) { + if (back > forward) + forward = back; + return forward + 1; + } } #endif // DOCTEST_CONFIG_DISABLE return file; -} -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -bool SubcaseSignature::operator==(const SubcaseSignature& other) const { - return m_line == other.m_line - && std::strcmp(m_file, other.m_file) == 0 - && m_name == other.m_name; -} - -bool SubcaseSignature::operator<(const SubcaseSignature& other) const { - if(m_line != other.m_line) - return m_line < other.m_line; - if(std::strcmp(m_file, other.m_file) != 0) - return std::strcmp(m_file, other.m_file) < 0; + } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + + bool SubcaseSignature::operator==(const SubcaseSignature &other) const + { + return m_line == other.m_line && std::strcmp(m_file, other.m_file) == 0 && + m_name == other.m_name; + } + + bool SubcaseSignature::operator<(const SubcaseSignature &other) const + { + if (m_line != other.m_line) + return m_line < other.m_line; + if (std::strcmp(m_file, other.m_file) != 0) + return std::strcmp(m_file, other.m_file) < 0; return m_name.compare(other.m_name) < 0; -} + } -DOCTEST_DEFINE_INTERFACE(IContextScope) + DOCTEST_DEFINE_INTERFACE(IContextScope) -namespace detail { - void filldata::fill(std::ostream* stream, const void* in) { - if (in) { *stream << in; } - else { *stream << "nullptr"; } + namespace detail { + void filldata::fill(std::ostream *stream, const void *in) + { + if (in) { + *stream << in; + } + else { + *stream << "nullptr"; + } } - template - String toStreamLit(T t) { - std::ostream* os = tlssPush(); - os->operator<<(t); - return tlssPop(); + template String toStreamLit(T t) + { + std::ostream *os = tlssPush(); + os->operator<<(t); + return tlssPop(); } -} + } // namespace detail #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } + String toString(const char *in) { return String("\"") + (in ? in : "{null string}") + "\""; } #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -String toString(const std::string& in) { return in.c_str(); } + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + String toString(const std::string &in) { return in.c_str(); } #endif // VS 2019 -String toString(String in) { return in; } + String toString(String in) { return in; } -String toString(std::nullptr_t) { return "nullptr"; } + String toString(std::nullptr_t) { return "nullptr"; } -String toString(bool in) { return in ? "true" : "false"; } + String toString(bool in) { return in ? "true" : "false"; } -String toString(float in) { return toStreamLit(in); } -String toString(double in) { return toStreamLit(in); } -String toString(double long in) { return toStreamLit(in); } + String toString(float in) { return toStreamLit(in); } + String toString(double in) { return toStreamLit(in); } + String toString(double long in) { return toStreamLit(in); } -String toString(char in) { return toStreamLit(static_cast(in)); } -String toString(char signed in) { return toStreamLit(static_cast(in)); } -String toString(char unsigned in) { return toStreamLit(static_cast(in)); } -String toString(short in) { return toStreamLit(in); } -String toString(short unsigned in) { return toStreamLit(in); } -String toString(signed in) { return toStreamLit(in); } -String toString(unsigned in) { return toStreamLit(in); } -String toString(long in) { return toStreamLit(in); } -String toString(long unsigned in) { return toStreamLit(in); } -String toString(long long in) { return toStreamLit(in); } -String toString(long long unsigned in) { return toStreamLit(in); } + String toString(char in) { return toStreamLit(static_cast(in)); } + String toString(char signed in) { return toStreamLit(static_cast(in)); } + String toString(char unsigned in) { return toStreamLit(static_cast(in)); } + String toString(short in) { return toStreamLit(in); } + String toString(short unsigned in) { return toStreamLit(in); } + String toString(signed in) { return toStreamLit(in); } + String toString(unsigned in) { return toStreamLit(in); } + String toString(long in) { return toStreamLit(in); } + String toString(long unsigned in) { return toStreamLit(in); } + String toString(long long in) { return toStreamLit(in); } + String toString(long long unsigned in) { return toStreamLit(in); } -Approx::Approx(double value) - : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) - , m_scale(1.0) - , m_value(value) {} + Approx::Approx(double value) + : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100), m_scale(1.0), + m_value(value) + { + } -Approx Approx::operator()(double value) const { + Approx Approx::operator()(double value) const + { Approx approx(value); approx.epsilon(m_epsilon); approx.scale(m_scale); return approx; -} + } -Approx& Approx::epsilon(double newEpsilon) { + Approx &Approx::epsilon(double newEpsilon) + { m_epsilon = newEpsilon; return *this; -} -Approx& Approx::scale(double newScale) { + } + Approx &Approx::scale(double newScale) + { m_scale = newScale; return *this; -} + } -bool operator==(double lhs, const Approx& rhs) { + bool operator==(double lhs, const Approx &rhs) + { // Thanks to Richard Harris for his help refining this formula return std::fabs(lhs - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); -} -bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } -bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } -bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); } -bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; } -bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } -bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; } -bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } -bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; } -bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } -bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; } -bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } - -String toString(const Approx& in) { - return "Approx( " + doctest::toString(in.m_value) + " )"; -} -const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) -template -IsNaN::operator bool() const { - return std::isnan(value) ^ flipped; -} -DOCTEST_MSVC_SUPPRESS_WARNING_POP -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template -String toString(IsNaN in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; } -String toString(IsNaN in) { return toString(in); } -String toString(IsNaN in) { return toString(in); } -String toString(IsNaN in) { return toString(in); } + } + bool operator==(const Approx &lhs, double rhs) { return operator==(rhs, lhs); } + bool operator!=(double lhs, const Approx &rhs) { return !operator==(lhs, rhs); } + bool operator!=(const Approx &lhs, double rhs) { return !operator==(rhs, lhs); } + bool operator<=(double lhs, const Approx &rhs) { return lhs < rhs.m_value || lhs == rhs; } + bool operator<=(const Approx &lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } + bool operator>=(double lhs, const Approx &rhs) { return lhs > rhs.m_value || lhs == rhs; } + bool operator>=(const Approx &lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } + bool operator<(double lhs, const Approx &rhs) { return lhs < rhs.m_value && lhs != rhs; } + bool operator<(const Approx &lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } + bool operator>(double lhs, const Approx &rhs) { return lhs > rhs.m_value && lhs != rhs; } + bool operator>(const Approx &lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } + + String toString(const Approx &in) { return "Approx( " + doctest::toString(in.m_value) + " )"; } + const ContextOptions *getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) + template IsNaN::operator bool() const { return std::isnan(value) ^ flipped; } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + template struct DOCTEST_INTERFACE_DEF IsNaN; + template struct DOCTEST_INTERFACE_DEF IsNaN; + template struct DOCTEST_INTERFACE_DEF IsNaN; + template String toString(IsNaN in) + { + return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; + } + String toString(IsNaN in) { return toString(in); } + String toString(IsNaN in) { return toString(in); } + String toString(IsNaN in) { return toString(in); } } // namespace doctest #ifdef DOCTEST_CONFIG_DISABLE namespace doctest { -Context::Context(int, const char* const*) {} -Context::~Context() = default; -void Context::applyCommandLine(int, const char* const*) {} -void Context::addFilter(const char*, const char*) {} -void Context::clearFilters() {} -void Context::setOption(const char*, bool) {} -void Context::setOption(const char*, int) {} -void Context::setOption(const char*, const char*) {} -bool Context::shouldExit() { return false; } -void Context::setAsDefaultForAssertsOutOfTestCases() {} -void Context::setAssertHandler(detail::assert_handler) {} -void Context::setCout(std::ostream*) {} -int Context::run() { return 0; } - -int IReporter::get_num_active_contexts() { return 0; } -const IContextScope* const* IReporter::get_active_contexts() { return nullptr; } -int IReporter::get_num_stringified_contexts() { return 0; } -const String* IReporter::get_stringified_contexts() { return nullptr; } - -int registerReporter(const char*, int, IReporter*) { return 0; } + Context::Context(int, const char *const *) {} + Context::~Context() = default; + void Context::applyCommandLine(int, const char *const *) {} + void Context::addFilter(const char *, const char *) {} + void Context::clearFilters() {} + void Context::setOption(const char *, bool) {} + void Context::setOption(const char *, int) {} + void Context::setOption(const char *, const char *) {} + bool Context::shouldExit() { return false; } + void Context::setAsDefaultForAssertsOutOfTestCases() {} + void Context::setAssertHandler(detail::assert_handler) {} + void Context::setCout(std::ostream *) {} + int Context::run() { return 0; } + + int IReporter::get_num_active_contexts() { return 0; } + const IContextScope *const *IReporter::get_active_contexts() { return nullptr; } + int IReporter::get_num_stringified_contexts() { return 0; } + const String *IReporter::get_stringified_contexts() { return nullptr; } + + int registerReporter(const char *, int, IReporter *) { return 0; } } // namespace doctest #else // DOCTEST_CONFIG_DISABLE @@ -4056,220 +4422,244 @@ int registerReporter(const char*, int, IReporter*) { return 0; } #endif // DOCTEST_CONFIG_COLORS_NONE namespace doctest_detail_test_suite_ns { -// holds the current test suite -doctest::detail::TestSuite& getCurrentTestSuite() { + // holds the current test suite + doctest::detail::TestSuite &getCurrentTestSuite() + { static doctest::detail::TestSuite data{}; return data; -} + } } // namespace doctest_detail_test_suite_ns namespace doctest { -namespace { + namespace { // the int (priority) is part of the key for automatic sorting - sadly one can register a - // reporter with a duplicate name and a different priority but hopefully that won't happen often :| + // reporter with a duplicate name and a different priority but hopefully that won't happen often + // :| using reporterMap = std::map, reporterCreatorFunc>; - reporterMap& getReporters() { - static reporterMap data; - return data; + reporterMap &getReporters() + { + static reporterMap data; + return data; } - reporterMap& getListeners() { - static reporterMap data; - return data; + reporterMap &getListeners() + { + static reporterMap data; + return data; } -} // namespace -namespace detail { + } // namespace + namespace detail { #define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ - for(auto& curr_rep : g_cs->reporters_currently_used) \ - curr_rep->function(__VA_ARGS__) + for (auto &curr_rep : g_cs->reporters_currently_used) \ + curr_rep->function(__VA_ARGS__) - bool checkIfShouldThrow(assertType::Enum at) { - if(at & assertType::is_require) //!OCLINT bitwise operator in conditional - return true; + bool checkIfShouldThrow(assertType::Enum at) + { + if (at & assertType::is_require) //! OCLINT bitwise operator in conditional + return true; - if((at & assertType::is_check) //!OCLINT bitwise operator in conditional - && getContextOptions()->abort_after > 0 && - (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= - getContextOptions()->abort_after) - return true; + if ((at & assertType::is_check) //! OCLINT bitwise operator in conditional + && getContextOptions()->abort_after > 0 && + (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= + getContextOptions()->abort_after) + return true; - return false; + return false; } #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_NORETURN void throwException() { - g_cs->shouldLogCurrentException = false; - throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) + DOCTEST_NORETURN void throwException() + { + g_cs->shouldLogCurrentException = false; + throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) } -#else // DOCTEST_CONFIG_NO_EXCEPTIONS +#else // DOCTEST_CONFIG_NO_EXCEPTIONS void throwException() {} #endif // DOCTEST_CONFIG_NO_EXCEPTIONS -} // namespace detail + } // namespace detail -namespace { + namespace { using namespace detail; // matching of a string against a wildcard mask (case sensitivity configurable) taken from // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing - int wildcmp(const char* str, const char* wild, bool caseSensitive) { - const char* cp = str; - const char* mp = wild; - - while((*str) && (*wild != '*')) { - if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && - (*wild != '?')) { - return 0; - } - wild++; - str++; + int wildcmp(const char *str, const char *wild, bool caseSensitive) + { + const char *cp = str; + const char *mp = wild; + + while ((*str) && (*wild != '*')) { + if ((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && + (*wild != '?')) { + return 0; + } + wild++; + str++; + } + + while (*str) { + if (*wild == '*') { + if (!*++wild) { + return 1; + } + mp = wild; + cp = str + 1; + } + else if ((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || + (*wild == '?')) { + wild++; + str++; } - - while(*str) { - if(*wild == '*') { - if(!*++wild) { - return 1; - } - mp = wild; - cp = str + 1; - } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || - (*wild == '?')) { - wild++; - str++; - } else { - wild = mp; //!OCLINT parameter reassignment - str = cp++; //!OCLINT parameter reassignment - } + else { + wild = mp; //! OCLINT parameter reassignment + str = cp++; //! OCLINT parameter reassignment } + } - while(*wild == '*') { - wild++; - } - return !*wild; + while (*wild == '*') { + wild++; + } + return !*wild; } // checks if the name matches any of the filters (and can be configured what to do when empty) - bool matchesAny(const char* name, const std::vector& filters, bool matchEmpty, - bool caseSensitive) { - if (filters.empty() && matchEmpty) - return true; - for (auto& curr : filters) - if (wildcmp(name, curr.c_str(), caseSensitive)) - return true; - return false; + bool matchesAny(const char *name, const std::vector &filters, bool matchEmpty, + bool caseSensitive) + { + if (filters.empty() && matchEmpty) + return true; + for (auto &curr : filters) + if (wildcmp(name, curr.c_str(), caseSensitive)) + return true; + return false; } DOCTEST_NO_SANITIZE_INTEGER - unsigned long long hash(unsigned long long a, unsigned long long b) { - return (a << 5) + b; - } + unsigned long long hash(unsigned long long a, unsigned long long b) { return (a << 5) + b; } // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html DOCTEST_NO_SANITIZE_INTEGER - unsigned long long hash(const char* str) { - unsigned long long hash = 5381; - char c; - while ((c = *str++)) - hash = ((hash << 5) + hash) + c; // hash * 33 + c - return hash; + unsigned long long hash(const char *str) + { + unsigned long long hash = 5381; + char c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + return hash; } - unsigned long long hash(const SubcaseSignature& sig) { - return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); + unsigned long long hash(const SubcaseSignature &sig) + { + return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); } - unsigned long long hash(const std::vector& sigs, size_t count) { - unsigned long long running = 0; - auto end = sigs.begin() + count; - for (auto it = sigs.begin(); it != end; it++) { - running = hash(running, hash(*it)); - } - return running; + unsigned long long hash(const std::vector &sigs, size_t count) + { + unsigned long long running = 0; + auto end = sigs.begin() + count; + for (auto it = sigs.begin(); it != end; it++) { + running = hash(running, hash(*it)); + } + return running; } - unsigned long long hash(const std::vector& sigs) { - unsigned long long running = 0; - for (const SubcaseSignature& sig : sigs) { - running = hash(running, hash(sig)); - } - return running; + unsigned long long hash(const std::vector &sigs) + { + unsigned long long running = 0; + for (const SubcaseSignature &sig : sigs) { + running = hash(running, hash(sig)); + } + return running; } -} // namespace -namespace detail { - bool Subcase::checkFilters() { - if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { - if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) - return true; - if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) - return true; - } - return false; + } // namespace + namespace detail { + bool Subcase::checkFilters() + { + if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { + if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) + return true; + if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) + return true; + } + return false; } - Subcase::Subcase(const String& name, const char* file, int line) - : m_signature({name, file, line}) { - if (!g_cs->reachedLeaf) { - if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() - || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { - // Going down. - if (checkFilters()) { return; } - - g_cs->subcaseStack.push_back(m_signature); - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } - } else { - if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { - // This subcase is reentered via control flow. - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth - && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) - == g_cs->fullyTraversedSubcases.end()) { - if (checkFilters()) { return; } - // This subcase is part of the one to be executed next. - g_cs->nextSubcaseStack.clear(); - g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), - g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); - g_cs->nextSubcaseStack.push_back(m_signature); - } - } + Subcase::Subcase(const String &name, const char *file, int line) + : m_signature({name, file, line}) + { + if (!g_cs->reachedLeaf) { + if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() || + g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { + // Going down. + if (checkFilters()) { + return; + } + + g_cs->subcaseStack.push_back(m_signature); + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + } + else { + if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { + // This subcase is reentered via control flow. + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth && + g_cs->fullyTraversedSubcases.find(hash( + hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) == + g_cs->fullyTraversedSubcases.end()) { + if (checkFilters()) { + return; + } + // This subcase is part of the one to be executed next. + g_cs->nextSubcaseStack.clear(); + g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), g_cs->subcaseStack.begin(), + g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); + g_cs->nextSubcaseStack.push_back(m_signature); + } + } } DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - Subcase::~Subcase() { - if (m_entered) { - g_cs->currentSubcaseDepth--; - - if (!g_cs->reachedLeaf) { - // Leaf. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - g_cs->nextSubcaseStack.clear(); - g_cs->reachedLeaf = true; - } else if (g_cs->nextSubcaseStack.empty()) { - // All children are finished. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - } + Subcase::~Subcase() + { + if (m_entered) { + g_cs->currentSubcaseDepth--; + + if (!g_cs->reachedLeaf) { + // Leaf. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + g_cs->nextSubcaseStack.clear(); + g_cs->reachedLeaf = true; + } + else if (g_cs->nextSubcaseStack.empty()) { + // All children are finished. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + } -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if(std::uncaught_exceptions() > 0 +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && \ + (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if (std::uncaught_exceptions() > 0 #else - if(std::uncaught_exception() + if (std::uncaught_exception() #endif - && g_cs->shouldLogCurrentException) { - DOCTEST_ITERATE_THROUGH_REPORTERS( - test_case_exception, {"exception thrown in subcase - will translate later " - "when the whole test case has been exited (cannot " - "translate while there is an active exception)", - false}); - g_cs->shouldLogCurrentException = false; - } - - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + && g_cs->shouldLogCurrentException) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + {"exception thrown in subcase - will translate later " + "when the whole test case has been exited (cannot " + "translate while there is an active exception)", + false}); + g_cs->shouldLogCurrentException = false; } + + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } } DOCTEST_CLANG_SUPPRESS_WARNING_POP @@ -4278,128 +4668,135 @@ namespace detail { Subcase::operator bool() const { return m_entered; } - Result::Result(bool passed, const String& decomposition) - : m_passed(passed) - , m_decomp(decomposition) {} - - ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) - : m_at(at) {} - - TestSuite& TestSuite::operator*(const char* in) { - m_test_suite = in; - return *this; + Result::Result(bool passed, const String &decomposition) + : m_passed(passed), m_decomp(decomposition) + { } - TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type, int template_id) { - m_file = file; - m_line = line; - m_name = nullptr; // will be later overridden in operator* - m_test_suite = test_suite.m_test_suite; - m_description = test_suite.m_description; - m_skip = test_suite.m_skip; - m_no_breaks = test_suite.m_no_breaks; - m_no_output = test_suite.m_no_output; - m_may_fail = test_suite.m_may_fail; - m_should_fail = test_suite.m_should_fail; - m_expected_failures = test_suite.m_expected_failures; - m_timeout = test_suite.m_timeout; + ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) : m_at(at) {} - m_test = test; - m_type = type; - m_template_id = template_id; + TestSuite &TestSuite::operator*(const char *in) + { + m_test_suite = in; + return *this; } - TestCase::TestCase(const TestCase& other) - : TestCaseData() { - *this = other; + TestCase::TestCase(funcType test, const char *file, unsigned line, const TestSuite &test_suite, + const String &type, int template_id) + { + m_file = file; + m_line = line; + m_name = nullptr; // will be later overridden in operator* + m_test_suite = test_suite.m_test_suite; + m_description = test_suite.m_description; + m_skip = test_suite.m_skip; + m_no_breaks = test_suite.m_no_breaks; + m_no_output = test_suite.m_no_output; + m_may_fail = test_suite.m_may_fail; + m_should_fail = test_suite.m_should_fail; + m_expected_failures = test_suite.m_expected_failures; + m_timeout = test_suite.m_timeout; + + m_test = test; + m_type = type; + m_template_id = template_id; } + TestCase::TestCase(const TestCase &other) : TestCaseData() { *this = other; } + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& TestCase::operator=(const TestCase& other) { - TestCaseData::operator=(other); - m_test = other.m_test; - m_type = other.m_type; - m_template_id = other.m_template_id; - m_full_name = other.m_full_name; - - if(m_template_id != -1) - m_name = m_full_name.c_str(); - return *this; + TestCase &TestCase::operator=(const TestCase &other) + { + TestCaseData::operator=(other); + m_test = other.m_test; + m_type = other.m_type; + m_template_id = other.m_template_id; + m_full_name = other.m_full_name; + + if (m_template_id != -1) + m_name = m_full_name.c_str(); + return *this; } DOCTEST_MSVC_SUPPRESS_WARNING_POP - TestCase& TestCase::operator*(const char* in) { - m_name = in; - // make a new name with an appended type for templated test case - if(m_template_id != -1) { - m_full_name = String(m_name) + "<" + m_type + ">"; - // redirect the name to point to the newly constructed full name - m_name = m_full_name.c_str(); - } - return *this; + TestCase &TestCase::operator*(const char *in) + { + m_name = in; + // make a new name with an appended type for templated test case + if (m_template_id != -1) { + m_full_name = String(m_name) + "<" + m_type + ">"; + // redirect the name to point to the newly constructed full name + m_name = m_full_name.c_str(); + } + return *this; } - bool TestCase::operator<(const TestCase& other) const { - // this will be used only to differentiate between test cases - not relevant for sorting - if(m_line != other.m_line) - return m_line < other.m_line; - const int name_cmp = strcmp(m_name, other.m_name); - if(name_cmp != 0) - return name_cmp < 0; - const int file_cmp = m_file.compare(other.m_file); - if(file_cmp != 0) - return file_cmp < 0; - return m_template_id < other.m_template_id; + bool TestCase::operator<(const TestCase &other) const + { + // this will be used only to differentiate between test cases - not relevant for sorting + if (m_line != other.m_line) + return m_line < other.m_line; + const int name_cmp = strcmp(m_name, other.m_name); + if (name_cmp != 0) + return name_cmp < 0; + const int file_cmp = m_file.compare(other.m_file); + if (file_cmp != 0) + return file_cmp < 0; + return m_template_id < other.m_template_id; } // all the registered tests - std::set& getRegisteredTests() { - static std::set data; - return data; + std::set &getRegisteredTests() + { + static std::set data; + return data; } -} // namespace detail -namespace { + } // namespace detail + namespace { using namespace detail; // for sorting tests by file/line - bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { - // this is needed because MSVC gives different case for drive letters - // for __FILE__ when evaluated in a header and a source file - const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); - if(res != 0) - return res < 0; - if(lhs->m_line != rhs->m_line) - return lhs->m_line < rhs->m_line; - return lhs->m_template_id < rhs->m_template_id; + bool fileOrderComparator(const TestCase *lhs, const TestCase *rhs) + { + // this is needed because MSVC gives different case for drive letters + // for __FILE__ when evaluated in a header and a source file + const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); + if (res != 0) + return res < 0; + if (lhs->m_line != rhs->m_line) + return lhs->m_line < rhs->m_line; + return lhs->m_template_id < rhs->m_template_id; } // for sorting tests by suite/file/line - bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) { - const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); - if(res != 0) - return res < 0; - return fileOrderComparator(lhs, rhs); + bool suiteOrderComparator(const TestCase *lhs, const TestCase *rhs) + { + const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); + if (res != 0) + return res < 0; + return fileOrderComparator(lhs, rhs); } // for sorting tests by name/suite/file/line - bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) { - const int res = std::strcmp(lhs->m_name, rhs->m_name); - if(res != 0) - return res < 0; - return suiteOrderComparator(lhs, rhs); + bool nameOrderComparator(const TestCase *lhs, const TestCase *rhs) + { + const int res = std::strcmp(lhs->m_name, rhs->m_name); + if (res != 0) + return res < 0; + return suiteOrderComparator(lhs, rhs); } DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - void color_to_stream(std::ostream& s, Color::Enum code) { - static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS - static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE + void color_to_stream(std::ostream &s, Color::Enum code) + { + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE #ifdef DOCTEST_CONFIG_COLORS_ANSI - if(g_no_colors || - (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) - return; + if (g_no_colors || + (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) + return; - auto col = ""; - // clang-format off + auto col = ""; + // clang-format off switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement case Color::Red: col = "[0;31m"; break; case Color::Green: col = "[0;32m"; break; @@ -4416,34 +4813,36 @@ namespace { case Color::White: default: col = "[0m"; } - // clang-format on - s << "\033" << col; + // clang-format on + s << "\033" << col; #endif // DOCTEST_CONFIG_COLORS_ANSI #ifdef DOCTEST_CONFIG_COLORS_WINDOWS - if(g_no_colors || - (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) - return; + if (g_no_colors || + (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) + return; - static struct ConsoleHelper { - HANDLE stdoutHandle; - WORD origFgAttrs; - WORD origBgAttrs; - - ConsoleHelper() { - stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); - origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | - BACKGROUND_BLUE | BACKGROUND_INTENSITY); - origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | - FOREGROUND_BLUE | FOREGROUND_INTENSITY); - } - } ch; + static struct ConsoleHelper + { + HANDLE stdoutHandle; + WORD origFgAttrs; + WORD origBgAttrs; + + ConsoleHelper() + { + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + } ch; #define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) - // clang-format off + // clang-format off switch (code) { case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; @@ -4460,24 +4859,26 @@ namespace { case Color::Bright: // invalid default: DOCTEST_SET_ATTR(ch.origFgAttrs); } - // clang-format on + // clang-format on #endif // DOCTEST_CONFIG_COLORS_WINDOWS } DOCTEST_CLANG_SUPPRESS_WARNING_POP - std::vector& getExceptionTranslators() { - static std::vector data; - return data; + std::vector &getExceptionTranslators() + { + static std::vector data; + return data; } - String translateActiveException() { + String translateActiveException() + { #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - String res; - auto& translators = getExceptionTranslators(); - for(auto& curr : translators) - if(curr->translate(res)) - return res; - // clang-format off + String res; + auto &translators = getExceptionTranslators(); + for (auto &curr : translators) + if (curr->translate(res)) + return res; + // clang-format off DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") try { throw; @@ -4493,74 +4894,80 @@ namespace { DOCTEST_GCC_SUPPRESS_WARNING_POP // clang-format on #else // DOCTEST_CONFIG_NO_EXCEPTIONS - return ""; + return ""; #endif // DOCTEST_CONFIG_NO_EXCEPTIONS } -} // namespace + } // namespace -namespace detail { + namespace detail { // used by the macros for registering tests - int regTest(const TestCase& tc) { - getRegisteredTests().insert(tc); - return 0; + int regTest(const TestCase &tc) + { + getRegisteredTests().insert(tc); + return 0; } // sets the current test suite - int setTestSuite(const TestSuite& ts) { - doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; - return 0; + int setTestSuite(const TestSuite &ts) + { + doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; + return 0; } #ifdef DOCTEST_IS_DEBUGGER_ACTIVE bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } #else // DOCTEST_IS_DEBUGGER_ACTIVE #ifdef DOCTEST_PLATFORM_LINUX - class ErrnoGuard { + class ErrnoGuard + { public: - ErrnoGuard() : m_oldErrno(errno) {} - ~ErrnoGuard() { errno = m_oldErrno; } + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: - int m_oldErrno; + int m_oldErrno; }; // See the comments in Catch2 for the reasoning behind this implementation: // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 - bool isDebuggerActive() { - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for(std::string line; std::getline(in, line);) { - static const int PREFIX_LEN = 11; - if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - return false; + bool isDebuggerActive() + { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for (std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if (line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; } #elif defined(DOCTEST_PLATFORM_MAC) // The following function is taken directly from the following technical note: // https://developer.apple.com/library/archive/qa/qa1361/_index.html // Returns true if the current process is being debugged (either // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive() { - int mib[4]; - kinfo_proc info; - size_t size; - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - info.kp_proc.p_flag = 0; - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - // Call sysctl. - size = sizeof(info); - if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { - std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; - return false; - } - // We're being debugged if the P_TRACED flag is set. - return ((info.kp_proc.p_flag & P_TRACED) != 0); + bool isDebuggerActive() + { + int mib[4]; + kinfo_proc info; + size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + // Call sysctl. + size = sizeof(info); + if (sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { + std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; + return false; + } + // We're being debugged if the P_TRACED flag is set. + return ((info.kp_proc.p_flag & P_TRACED) != 0); } #elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } @@ -4569,24 +4976,24 @@ namespace detail { #endif // Platform #endif // DOCTEST_IS_DEBUGGER_ACTIVE - void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { - if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == - getExceptionTranslators().end()) - getExceptionTranslators().push_back(et); + void registerExceptionTranslatorImpl(const IExceptionTranslator *et) + { + if (std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == + getExceptionTranslators().end()) + getExceptionTranslators().push_back(et); } - DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() + DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() - ContextScopeBase::ContextScopeBase() { - g_infoContexts.push_back(this); - } + ContextScopeBase::ContextScopeBase() { g_infoContexts.push_back(this); } - ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept { - if (other.need_to_destroy) { - other.destroy(); - } - other.need_to_destroy = false; - g_infoContexts.push_back(this); + ContextScopeBase::ContextScopeBase(ContextScopeBase &&other) noexcept + { + if (other.need_to_destroy) { + other.destroy(); + } + other.need_to_destroy = false; + g_infoContexts.push_back(this); } DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 @@ -4596,172 +5003,176 @@ namespace detail { // destroy cannot be inlined into the destructor because that would mean calling stringify after // ContextScope has been destroyed (base class destructors run after derived class destructors). // Instead, ContextScope calls this method directly from its destructor. - void ContextScopeBase::destroy() { -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if(std::uncaught_exceptions() > 0) { + void ContextScopeBase::destroy() + { +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && \ + (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if (std::uncaught_exceptions() > 0) { #else - if(std::uncaught_exception()) { + if (std::uncaught_exception()) { #endif - std::ostringstream s; - this->stringify(&s); - g_cs->stringifiedContexts.push_back(s.str().c_str()); - } - g_infoContexts.pop_back(); + std::ostringstream s; + this->stringify(&s); + g_cs->stringifiedContexts.push_back(s.str().c_str()); + } + g_infoContexts.pop_back(); } DOCTEST_CLANG_SUPPRESS_WARNING_POP DOCTEST_GCC_SUPPRESS_WARNING_POP DOCTEST_MSVC_SUPPRESS_WARNING_POP -} // namespace detail -namespace { + } // namespace detail + namespace { using namespace detail; #if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) struct FatalConditionHandler { - static void reset() {} - static void allocateAltStackMem() {} - static void freeAltStackMem() {} + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} }; #else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH - void reportFatal(const std::string&); + void reportFatal(const std::string &); #ifdef DOCTEST_PLATFORM_WINDOWS struct SignalDefs { - DWORD id; - const char* name; + DWORD id; + const char *name; }; // There is no 1-1 mapping between signals and windows exceptions. // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. SignalDefs signalDefs[] = { - {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), - "SIGILL - Illegal instruction signal"}, - {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, - {static_cast(EXCEPTION_ACCESS_VIOLATION), - "SIGSEGV - Segmentation violation signal"}, - {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, + {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal"}, + {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal"}, + {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, }; struct FatalConditionHandler { - static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { - // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the - // console just once no matter how many threads have crashed. - DOCTEST_DECLARE_STATIC_MUTEX(mutex) - static bool execute = true; - { - DOCTEST_LOCK_MUTEX(mutex) - if(execute) { - bool reported = false; - for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - reported = true; - break; - } - } - if(reported == false) - reportFatal("Unhandled SEH exception caught"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - } - execute = false; + static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) + { + // Multiple threads may enter this filter/handler at once. We want the error message to be + // printed on the console just once no matter how many threads have crashed. + DOCTEST_DECLARE_STATIC_MUTEX(mutex) + static bool execute = true; + { + DOCTEST_LOCK_MUTEX(mutex) + if (execute) { + bool reported = false; + for (size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } } + if (reported == false) + reportFatal("Unhandled SEH exception caught"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + } + execute = false; + } + std::exit(EXIT_FAILURE); + } + + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + + FatalConditionHandler() + { + isSet = true; + // 32k seems enough for doctest to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + // Register an unhandled exception filter + previousTop = SetUnhandledExceptionFilter(handleException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() DOCTEST_NOEXCEPT { + reportFatal("Terminate handler called"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called + // as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { + if (signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); std::exit(EXIT_FAILURE); - } - - static void allocateAltStackMem() {} - static void freeAltStackMem() {} - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for doctest to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - // Register an unhandled exception filter - previousTop = SetUnhandledExceptionFilter(handleException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - - // On Windows uncaught exceptions from another thread, exceptions from - // destructors, or calls to std::terminate are not a SEH exception - - // The terminal handler gets called when: - // - std::terminate is called FROM THE TEST RUNNER THREAD - // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD - original_terminate_handler = std::get_terminate(); - std::set_terminate([]() DOCTEST_NOEXCEPT { - reportFatal("Terminate handler called"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well - }); - - // SIGABRT is raised when: - // - std::terminate is called FROM A DIFFERENT THREAD - // - an exception is thrown from a destructor FROM A DIFFERENT THREAD - // - an uncaught exception is thrown FROM A DIFFERENT THREAD - prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { - if(signal == SIGABRT) { - reportFatal("SIGABRT - Abort (abnormal termination) signal"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); - } - }); - - // The following settings are taken from google test, and more - // specifically from UnitTest::Run() inside of gtest.cc - - // the user does not want to see pop-up dialogs about crashes - prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | - SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); - // This forces the abort message to go to stderr in all circumstances. - prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); - // In the debug version, Visual Studio pops up a separate dialog - // offering a choice to debug the aborted program - we want to disable that. - prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - // In debug mode, the Windows CRT can crash with an assertion over invalid - // input (e.g. passing an invalid file descriptor). The default handling - // for these assertions is to pop up a dialog and wait for user input. - // Instead ask the CRT to dump such assertions to stderr non-interactively. - prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - } - - static void reset() { - if(isSet) { - // Unregister handler and restore the old guarantee - SetUnhandledExceptionFilter(previousTop); - SetThreadStackGuarantee(&guaranteeSize); - std::set_terminate(original_terminate_handler); - std::signal(SIGABRT, prev_sigabrt_handler); - SetErrorMode(prev_error_mode_1); - _set_error_mode(prev_error_mode_2); - _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); - static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); - isSet = false; - } - } - - ~FatalConditionHandler() { reset(); } + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } + + static void reset() + { + if (isSet) { + // Unregister handler and restore the old guarantee + SetUnhandledExceptionFilter(previousTop); + SetThreadStackGuarantee(&guaranteeSize); + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); + static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); + isSet = false; + } + } + + ~FatalConditionHandler() { reset(); } private: - static UINT prev_error_mode_1; - static int prev_error_mode_2; - static unsigned int prev_abort_behavior; - static int prev_report_mode; - static _HFILE prev_report_file; - static void (DOCTEST_CDECL *prev_sigabrt_handler)(int); - static std::terminate_handler original_terminate_handler; - static bool isSet; - static ULONG guaranteeSize; - static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void(DOCTEST_CDECL *prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; + static bool isSet; + static ULONG guaranteeSize; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; }; UINT FatalConditionHandler::prev_error_mode_1; @@ -4769,18 +5180,18 @@ namespace { unsigned int FatalConditionHandler::prev_abort_behavior; int FatalConditionHandler::prev_report_mode; _HFILE FatalConditionHandler::prev_report_file; - void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); - std::terminate_handler FatalConditionHandler::original_terminate_handler; - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; + void(DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; + bool FatalConditionHandler::isSet = false; + ULONG FatalConditionHandler::guaranteeSize = 0; + LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; #else // DOCTEST_PLATFORM_WINDOWS struct SignalDefs { - int id; - const char* name; + int id; + const char *name; }; SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"}, {SIGILL, "SIGILL - Illegal instruction signal"}, @@ -4791,75 +5202,74 @@ namespace { struct FatalConditionHandler { - static bool isSet; - static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; - static stack_t oldSigStack; - static size_t altStackSize; - static char* altStackMem; - - static void handleSignal(int sig) { - const char* name = ""; - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - SignalDefs& def = signalDefs[i]; - if(sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise(sig); - } - - static void allocateAltStackMem() { - altStackMem = new char[altStackSize]; - } + static bool isSet; + static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; + static stack_t oldSigStack; + static size_t altStackSize; + static char *altStackMem; + + static void handleSignal(int sig) + { + const char *name = ""; + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + SignalDefs &def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise(sig); + } + + static void allocateAltStackMem() { altStackMem = new char[altStackSize]; } + + static void freeAltStackMem() { delete[] altStackMem; } + + FatalConditionHandler() + { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = altStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {}; + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + ~FatalConditionHandler() { reset(); } + static void reset() + { + if (isSet) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + }; - static void freeAltStackMem() { - delete[] altStackMem; - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = altStackSize; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = {}; - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { reset(); } - static void reset() { - if(isSet) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; + bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; + stack_t FatalConditionHandler::oldSigStack = {}; size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; - char* FatalConditionHandler::altStackMem = nullptr; + char *FatalConditionHandler::altStackMem = nullptr; #endif // DOCTEST_PLATFORM_WINDOWS #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH -} // namespace + } // namespace -namespace { + namespace { using namespace detail; #ifdef DOCTEST_PLATFORM_WINDOWS @@ -4869,161 +5279,186 @@ namespace { #define DOCTEST_OUTPUT_DEBUG_STRING(text) #endif // Platform - void addAssert(assertType::Enum at) { - if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional - g_cs->numAssertsCurrentTest_atomic++; + void addAssert(assertType::Enum at) + { + if ((at & assertType::is_warn) == 0) //! OCLINT bitwise operator in conditional + g_cs->numAssertsCurrentTest_atomic++; } - void addFailedAssert(assertType::Enum at) { - if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional - g_cs->numAssertsFailedCurrentTest_atomic++; + void addFailedAssert(assertType::Enum at) + { + if ((at & assertType::is_warn) == 0) //! OCLINT bitwise operator in conditional + g_cs->numAssertsFailedCurrentTest_atomic++; } #if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) - void reportFatal(const std::string& message) { - g_cs->failure_flags |= TestCaseFailureReason::Crash; + void reportFatal(const std::string &message) + { + g_cs->failure_flags |= TestCaseFailureReason::Crash; - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); - while (g_cs->subcaseStack.size()) { - g_cs->subcaseStack.pop_back(); - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); - } + while (g_cs->subcaseStack.size()) { + g_cs->subcaseStack.pop_back(); + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } - g_cs->finalizeTestCaseData(); + g_cs->finalizeTestCaseData(); - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); } #endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH -} // namespace - -AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string) - : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), - m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), - m_exception_string(exception_string) { + } // namespace + + AssertData::AssertData(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const StringContains &exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) + { #if DOCTEST_MSVC if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC - ++m_expr; + ++m_expr; #endif // MSVC -} - -namespace detail { - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const String& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) { } + } - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) { } - - void ResultBuilder::setResult(const Result& res) { - m_decomp = res.m_decomp; - m_failed = !res.m_passed; + namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const String &exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) + { } - void ResultBuilder::translateException() { - m_threw = true; - m_exception = translateActiveException(); + ResultBuilder::ResultBuilder(assertType::Enum at, const char *file, int line, const char *expr, + const char *exception_type, const Contains &exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) + { } - bool ResultBuilder::log() { - if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - m_failed = !m_threw; - } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT - m_failed = !m_threw_as || !m_exception_string.check(m_exception); - } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - m_failed = !m_threw_as; - } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - m_failed = !m_exception_string.check(m_exception); - } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - m_failed = m_threw; - } - - if(m_exception.size()) - m_exception = "\"" + m_exception + "\""; - - if(is_running_in_test) { - addAssert(m_at); - DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); - - if(m_failed) - addFailedAssert(m_at); - } else if(m_failed) { - failed_out_of_a_testing_context(*this); - } + void ResultBuilder::setResult(const Result &res) + { + m_decomp = res.m_decomp; + m_failed = !res.m_passed; + } - return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && - (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + void ResultBuilder::translateException() + { + m_threw = true; + m_exception = translateActiveException(); } - void ResultBuilder::react() const { - if(m_failed && checkIfShouldThrow(m_at)) - throwException(); + bool ResultBuilder::log() + { + if (m_at & assertType::is_throws) { //! OCLINT bitwise operator in conditional + m_failed = !m_threw; + } + else if ((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //! OCLINT + m_failed = !m_threw_as || !m_exception_string.check(m_exception); + } + else if (m_at & assertType::is_throws_as) { //! OCLINT bitwise operator in conditional + m_failed = !m_threw_as; + } + else if (m_at & assertType::is_throws_with) { //! OCLINT bitwise operator in conditional + m_failed = !m_exception_string.check(m_exception); + } + else if (m_at & assertType::is_nothrow) { //! OCLINT bitwise operator in conditional + m_failed = m_threw; + } + + if (m_exception.size()) + m_exception = "\"" + m_exception + "\""; + + if (is_running_in_test) { + addAssert(m_at); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); + + if (m_failed) + addFailedAssert(m_at); + } + else if (m_failed) { + failed_out_of_a_testing_context(*this); + } + + return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && + (g_cs->currentTest == nullptr || + !g_cs->currentTest->m_no_breaks); // break into debugger } - void failed_out_of_a_testing_context(const AssertData& ad) { - if(g_cs->ah) - g_cs->ah(ad); - else - std::abort(); + void ResultBuilder::react() const + { + if (m_failed && checkIfShouldThrow(m_at)) + throwException(); } - bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, - const Result& result) { - bool failed = !result.m_passed; + void failed_out_of_a_testing_context(const AssertData &ad) + { + if (g_cs->ah) + g_cs->ah(ad); + else + std::abort(); + } - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); - DOCTEST_ASSERT_IN_TESTS(result.m_decomp); - return !failed; + bool decomp_assert(assertType::Enum at, const char *file, int line, const char *expr, + const Result &result) + { + bool failed = !result.m_passed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); + DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + return !failed; } - MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { - m_stream = tlssPush(); - m_file = file; - m_line = line; - m_severity = severity; + MessageBuilder::MessageBuilder(const char *file, int line, assertType::Enum severity) + { + m_stream = tlssPush(); + m_file = file; + m_line = line; + m_severity = severity; } - MessageBuilder::~MessageBuilder() { - if (!logged) - tlssPop(); + MessageBuilder::~MessageBuilder() + { + if (!logged) + tlssPop(); } DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) - bool MessageBuilder::log() { - if (!logged) { - m_string = tlssPop(); - logged = true; - } + bool MessageBuilder::log() + { + if (!logged) { + m_string = tlssPop(); + logged = true; + } - DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); - const bool isWarn = m_severity & assertType::is_warn; + const bool isWarn = m_severity & assertType::is_warn; - // warn is just a message in this context so we don't treat it as an assert - if(!isWarn) { - addAssert(m_severity); - addFailedAssert(m_severity); - } + // warn is just a message in this context so we don't treat it as an assert + if (!isWarn) { + addAssert(m_severity); + addFailedAssert(m_severity); + } - return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && - (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && + (g_cs->currentTest == nullptr || + !g_cs->currentTest->m_no_breaks); // break into debugger } - void MessageBuilder::react() { - if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional - throwException(); + void MessageBuilder::react() + { + if (m_severity & assertType::is_require) //! OCLINT bitwise operator in conditional + throwException(); } -} // namespace detail -namespace { + } // namespace detail + namespace { using namespace detail; // clang-format off @@ -5414,291 +5849,303 @@ namespace { struct XmlReporter : public IReporter { - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - XmlReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) {} - - void log_contexts() { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - std::stringstream ss; - for(int i = 0; i < num_contexts; ++i) { - contexts[i]->stringify(&ss); - xml.scopedElement("Info").writeText(ss.str()); - ss.str(""); - } - } - } - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - void test_case_start_impl(const TestCaseData& in) { - bool open_ts_tag = false; - if(tc != nullptr) { // we have already opened a test suite - if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { - xml.endElement(); - open_ts_tag = true; - } - } - else { - open_ts_tag = true; // first test case ==> first test suite - } - - if(open_ts_tag) { - xml.startElement("TestSuite"); - xml.writeAttribute("name", in.m_test_suite); - } - - tc = ∈ - xml.startElement("TestCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) - .writeAttribute("line", line(in.m_line)) - .writeAttribute("description", in.m_description); - - if(Approx(in.m_timeout) != 0) - xml.writeAttribute("timeout", in.m_timeout); - if(in.m_may_fail) - xml.writeAttribute("may_fail", true); - if(in.m_should_fail) - xml.writeAttribute("should_fail", true); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override { - test_run_start(); - if(opt.list_reporters) { - for(auto& curr : getListeners()) - xml.scopedElement("Listener") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - for(auto& curr : getReporters()) - xml.scopedElement("Reporter") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - } else if(opt.count || opt.list_test_cases) { - for(unsigned i = 0; i < in.num_data; ++i) { - xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) - .writeAttribute("testsuite", in.data[i]->m_test_suite) - .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) - .writeAttribute("line", line(in.data[i]->m_line)) - .writeAttribute("skipped", in.data[i]->m_skip); - } - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - } else if(opt.list_test_suites) { - for(unsigned i = 0; i < in.num_data; ++i) - xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - xml.scopedElement("OverallResultsTestSuites") - .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); - } + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions &opt; + const TestCaseData *tc = nullptr; + + XmlReporter(const ContextOptions &co) : xml(*co.cout), opt(co) {} + + void log_contexts() + { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + std::stringstream ss; + for (int i = 0; i < num_contexts; ++i) { + contexts[i]->stringify(&ss); + xml.scopedElement("Info").writeText(ss.str()); + ss.str(""); + } + } + } + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + void test_case_start_impl(const TestCaseData &in) + { + bool open_ts_tag = false; + if (tc != nullptr) { // we have already opened a test suite + if (std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { xml.endElement(); + open_ts_tag = true; + } } - - void test_run_start() override { - xml.writeDeclaration(); - - // remove .exe extension - mainly to have the same output on UNIX and Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); + else { + open_ts_tag = true; // first test case ==> first test suite + } + + if (open_ts_tag) { + xml.startElement("TestSuite"); + xml.writeAttribute("name", in.m_test_suite); + } + + tc = ∈ + xml.startElement("TestCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) + .writeAttribute("line", line(in.m_line)) + .writeAttribute("description", in.m_description); + + if (Approx(in.m_timeout) != 0) + xml.writeAttribute("timeout", in.m_timeout); + if (in.m_may_fail) + xml.writeAttribute("may_fail", true); + if (in.m_should_fail) + xml.writeAttribute("should_fail", true); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData &in) override + { + test_run_start(); + if (opt.list_reporters) { + for (auto &curr : getListeners()) + xml.scopedElement("Listener") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + for (auto &curr : getReporters()) + xml.scopedElement("Reporter") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + } + else if (opt.count || opt.list_test_cases) { + for (unsigned i = 0; i < in.num_data; ++i) { + xml.scopedElement("TestCase") + .writeAttribute("name", in.data[i]->m_name) + .writeAttribute("testsuite", in.data[i]->m_test_suite) + .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) + .writeAttribute("line", line(in.data[i]->m_line)) + .writeAttribute("skipped", in.data[i]->m_skip); + } + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + } + else if (opt.list_test_suites) { + for (unsigned i = 0; i < in.num_data; ++i) + xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + xml.scopedElement("OverallResultsTestSuites") + .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); + } + xml.endElement(); + } + + void test_run_start() override + { + xml.writeDeclaration(); + + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); #ifdef DOCTEST_PLATFORM_WINDOWS - if(binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); + if (binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); #endif // DOCTEST_PLATFORM_WINDOWS - xml.startElement("doctest").writeAttribute("binary", binary_name); - if(opt.no_version == false) - xml.writeAttribute("version", DOCTEST_VERSION_STR); - - // only the consequential ones (TODO: filters) - xml.scopedElement("Options") - .writeAttribute("order_by", opt.order_by.c_str()) - .writeAttribute("rand_seed", opt.rand_seed) - .writeAttribute("first", opt.first) - .writeAttribute("last", opt.last) - .writeAttribute("abort_after", opt.abort_after) - .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) - .writeAttribute("case_sensitive", opt.case_sensitive) - .writeAttribute("no_throw", opt.no_throw) - .writeAttribute("no_skip", opt.no_skip); - } - - void test_run_end(const TestRunStats& p) override { - if(tc) // the TestSuite tag - only if there has been at least 1 test case - xml.endElement(); - - xml.scopedElement("OverallResultsAsserts") - .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) - .writeAttribute("failures", p.numAssertsFailed); - - xml.startElement("OverallResultsTestCases") - .writeAttribute("successes", - p.numTestCasesPassingFilters - p.numTestCasesFailed) - .writeAttribute("failures", p.numTestCasesFailed); - if(opt.no_skipped_summary == false) - xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); - xml.endElement(); - - xml.endElement(); - } - - void test_case_start(const TestCaseData& in) override { - test_case_start_impl(in); - xml.ensureTagClosed(); - } - - void test_case_reenter(const TestCaseData&) override {} - - void test_case_end(const CurrentTestCaseStats& st) override { - xml.startElement("OverallResultsAsserts") - .writeAttribute("successes", - st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) - .writeAttribute("failures", st.numAssertsFailedCurrentTest) - .writeAttribute("test_case_success", st.testCaseSuccess); - if(opt.duration) - xml.writeAttribute("duration", st.seconds); - if(tc->m_expected_failures) - xml.writeAttribute("expected_failures", tc->m_expected_failures); - xml.endElement(); - - xml.endElement(); - } - - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - - xml.scopedElement("Exception") - .writeAttribute("crash", e.is_crash) - .writeText(e.error_string.c_str()); - } - - void subcase_start(const SubcaseSignature& in) override { - xml.startElement("SubCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file)) - .writeAttribute("line", line(in.m_line)); - xml.ensureTagClosed(); - } - - void subcase_end() override { xml.endElement(); } - - void log_assert(const AssertData& rb) override { - if(!rb.m_failed && !opt.success) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Expression") - .writeAttribute("success", !rb.m_failed) - .writeAttribute("type", assertString(rb.m_at)) - .writeAttribute("filename", skipPathFromFilename(rb.m_file)) - .writeAttribute("line", line(rb.m_line)); - - xml.scopedElement("Original").writeText(rb.m_expr); - - if(rb.m_threw) - xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); - - if(rb.m_at & assertType::is_throws_as) - xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); - if(rb.m_at & assertType::is_throws_with) - xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); - if((rb.m_at & assertType::is_normal) && !rb.m_threw) - xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void log_message(const MessageData& mb) override { - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Message") - .writeAttribute("type", failureString(mb.m_severity)) - .writeAttribute("filename", skipPathFromFilename(mb.m_file)) - .writeAttribute("line", line(mb.m_line)); - - xml.scopedElement("Text").writeText(mb.m_string.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void test_case_skipped(const TestCaseData& in) override { - if(opt.no_skipped_summary == false) { - test_case_start_impl(in); - xml.writeAttribute("skipped", "true"); - xml.endElement(); - } - } + xml.startElement("doctest").writeAttribute("binary", binary_name); + if (opt.no_version == false) + xml.writeAttribute("version", DOCTEST_VERSION_STR); + + // only the consequential ones (TODO: filters) + xml.scopedElement("Options") + .writeAttribute("order_by", opt.order_by.c_str()) + .writeAttribute("rand_seed", opt.rand_seed) + .writeAttribute("first", opt.first) + .writeAttribute("last", opt.last) + .writeAttribute("abort_after", opt.abort_after) + .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) + .writeAttribute("case_sensitive", opt.case_sensitive) + .writeAttribute("no_throw", opt.no_throw) + .writeAttribute("no_skip", opt.no_skip); + } + + void test_run_end(const TestRunStats &p) override + { + if (tc) // the TestSuite tag - only if there has been at least 1 test case + xml.endElement(); + + xml.scopedElement("OverallResultsAsserts") + .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) + .writeAttribute("failures", p.numAssertsFailed); + + xml.startElement("OverallResultsTestCases") + .writeAttribute("successes", p.numTestCasesPassingFilters - p.numTestCasesFailed) + .writeAttribute("failures", p.numTestCasesFailed); + if (opt.no_skipped_summary == false) + xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); + xml.endElement(); + + xml.endElement(); + } + + void test_case_start(const TestCaseData &in) override + { + test_case_start_impl(in); + xml.ensureTagClosed(); + } + + void test_case_reenter(const TestCaseData &) override {} + + void test_case_end(const CurrentTestCaseStats &st) override + { + xml.startElement("OverallResultsAsserts") + .writeAttribute("successes", st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) + .writeAttribute("failures", st.numAssertsFailedCurrentTest) + .writeAttribute("test_case_success", st.testCaseSuccess); + if (opt.duration) + xml.writeAttribute("duration", st.seconds); + if (tc->m_expected_failures) + xml.writeAttribute("expected_failures", tc->m_expected_failures); + xml.endElement(); + + xml.endElement(); + } + + void test_case_exception(const TestCaseException &e) override + { + DOCTEST_LOCK_MUTEX(mutex) + + xml.scopedElement("Exception") + .writeAttribute("crash", e.is_crash) + .writeText(e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature &in) override + { + xml.startElement("SubCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file)) + .writeAttribute("line", line(in.m_line)); + xml.ensureTagClosed(); + } + + void subcase_end() override { xml.endElement(); } + + void log_assert(const AssertData &rb) override + { + if (!rb.m_failed && !opt.success) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Expression") + .writeAttribute("success", !rb.m_failed) + .writeAttribute("type", assertString(rb.m_at)) + .writeAttribute("filename", skipPathFromFilename(rb.m_file)) + .writeAttribute("line", line(rb.m_line)); + + xml.scopedElement("Original").writeText(rb.m_expr); + + if (rb.m_threw) + xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); + + if (rb.m_at & assertType::is_throws_as) + xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); + if (rb.m_at & assertType::is_throws_with) + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); + if ((rb.m_at & assertType::is_normal) && !rb.m_threw) + xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void log_message(const MessageData &mb) override + { + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Message") + .writeAttribute("type", failureString(mb.m_severity)) + .writeAttribute("filename", skipPathFromFilename(mb.m_file)) + .writeAttribute("line", line(mb.m_line)); + + xml.scopedElement("Text").writeText(mb.m_string.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void test_case_skipped(const TestCaseData &in) override + { + if (opt.no_skipped_summary == false) { + test_case_start_impl(in); + xml.writeAttribute("skipped", "true"); + xml.endElement(); + } + } }; DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); - void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { - if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == - 0) //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " - << Color::None; - - if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; - } else if((rb.m_at & assertType::is_throws_as) && - (rb.m_at & assertType::is_throws_with)) { //!OCLINT - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() - << "\", " << rb.m_exception_type << " ) " << Color::None; - if(rb.m_threw) { - if(!rb.m_failed) { - s << "threw as expected!\n"; - } else { - s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; - } - } else { - s << "did NOT throw at all!\n"; - } - } else if(rb.m_at & - assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " - << rb.m_exception_type << " ) " << Color::None - << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & - assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() - << "\" ) " << Color::None - << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan - << rb.m_exception << "\n"; - } else { - s << (rb.m_threw ? "THREW exception: " : - (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); - if(rb.m_threw) - s << rb.m_exception << "\n"; - else - s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + void fulltext_log_assert_to_stream(std::ostream &s, const AssertData &rb) + { + if ((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == + 0) //! OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " << Color::None; + + if (rb.m_at & assertType::is_throws) { //! OCLINT bitwise operator in conditional + s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } + else if ((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //! OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() << "\", " << rb.m_exception_type << " ) " << Color::None; + if (rb.m_threw) { + if (!rb.m_failed) { + s << "threw as expected!\n"; + } + else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } } + else { + s << "did NOT throw at all!\n"; + } + } + else if (rb.m_at & assertType::is_throws_as) { //! OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " + << rb.m_exception_type << " ) " << Color::None + << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : "threw a DIFFERENT exception: ") + : "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } + else if (rb.m_at & assertType::is_throws_with) { //! OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() << "\" ) " << Color::None + << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : "threw a DIFFERENT exception: ") + : "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } + else if (rb.m_at & assertType::is_nothrow) { //! OCLINT bitwise operator in conditional + s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan << rb.m_exception + << "\n"; + } + else { + s << (rb.m_threw ? "THREW exception: " + : (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); + if (rb.m_threw) + s << rb.m_exception << "\n"; + else + s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + } } // TODO: @@ -5708,375 +6155,401 @@ namespace { // - more attributes in tags struct JUnitReporter : public IReporter { - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - Timer timer; - std::vector deepestSubcaseStackNames; - - struct JUnitTestCaseData + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + Timer timer; + std::vector deepestSubcaseStackNames; + + struct JUnitTestCaseData + { + static std::string getCurrentTimestamp() { - static std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - - std::tm timeInfo; -#ifdef DOCTEST_PLATFORM_WINDOWS - gmtime_s(&timeInfo, &rawtime); -#else // DOCTEST_PLATFORM_WINDOWS - gmtime_r(&rawtime, &timeInfo); -#endif // DOCTEST_PLATFORM_WINDOWS - - char timeStamp[timeStampSize]; - const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); - return std::string(timeStamp); - } - - struct JUnitTestMessage - { - JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) - : message(_message), type(_type), details(_details) {} - - JUnitTestMessage(const std::string& _message, const std::string& _details) - : message(_message), type(), details(_details) {} - - std::string message, type, details; - }; - - struct JUnitTestCase - { - JUnitTestCase(const std::string& _classname, const std::string& _name) - : classname(_classname), name(_name), time(0), failures() {} - - std::string classname, name; - double time; - std::vector failures, errors; - }; - - void add(const std::string& classname, const std::string& name) { - testcases.emplace_back(classname, name); - } - - void appendSubcaseNamesToLastTestcase(std::vector nameStack) { - for(auto& curr: nameStack) - if(curr.size()) - testcases.back().name += std::string("/") + curr.c_str(); - } - - void addTime(double time) { - if(time < 1e-4) - time = 0; - testcases.back().time = time; - totalSeconds += time; - } + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - void addFailure(const std::string& message, const std::string& type, const std::string& details) { - testcases.back().failures.emplace_back(message, type, details); - ++totalFailures; - } - - void addError(const std::string& message, const std::string& details) { - testcases.back().errors.emplace_back(message, details); - ++totalErrors; - } - - std::vector testcases; - double totalSeconds = 0; - int totalErrors = 0, totalFailures = 0; - }; - - JUnitTestCaseData testCaseData; - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - JUnitReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) {} - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData&) override { - xml.writeDeclaration(); - } - - void test_run_start() override { - xml.writeDeclaration(); - } - - void test_run_end(const TestRunStats& p) override { - // remove .exe extension - mainly to have the same output on UNIX and Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); + std::tm timeInfo; #ifdef DOCTEST_PLATFORM_WINDOWS - if(binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); #endif // DOCTEST_PLATFORM_WINDOWS - xml.startElement("testsuites"); - xml.startElement("testsuite").writeAttribute("name", binary_name) - .writeAttribute("errors", testCaseData.totalErrors) - .writeAttribute("failures", testCaseData.totalFailures) - .writeAttribute("tests", p.numAsserts); - if(opt.no_time_in_output == false) { - xml.writeAttribute("time", testCaseData.totalSeconds); - xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); - } - if(opt.no_version == false) - xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); - - for(const auto& testCase : testCaseData.testcases) { - xml.startElement("testcase") - .writeAttribute("classname", testCase.classname) - .writeAttribute("name", testCase.name); - if(opt.no_time_in_output == false) - xml.writeAttribute("time", testCase.time); - // This is not ideal, but it should be enough to mimic gtest's junit output. - xml.writeAttribute("status", "run"); - - for(const auto& failure : testCase.failures) { - xml.scopedElement("failure") - .writeAttribute("message", failure.message) - .writeAttribute("type", failure.type) - .writeText(failure.details, false); - } - for(const auto& error : testCase.errors) { - xml.scopedElement("error") - .writeAttribute("message", error.message) - .writeText(error.details); - } + char timeStamp[timeStampSize]; + const char *const fmt = "%Y-%m-%dT%H:%M:%SZ"; - xml.endElement(); - } - xml.endElement(); - xml.endElement(); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + return std::string(timeStamp); } - void test_case_start(const TestCaseData& in) override { - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); - timer.start(); - } + struct JUnitTestMessage + { + JUnitTestMessage(const std::string &_message, const std::string &_type, + const std::string &_details) + : message(_message), type(_type), details(_details) + { + } + + JUnitTestMessage(const std::string &_message, const std::string &_details) + : message(_message), type(), details(_details) + { + } + + std::string message, type, details; + }; - void test_case_reenter(const TestCaseData& in) override { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); + struct JUnitTestCase + { + JUnitTestCase(const std::string &_classname, const std::string &_name) + : classname(_classname), name(_name), time(0), failures() + { + } + + std::string classname, name; + double time; + std::vector failures, errors; + }; - timer.start(); - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + void add(const std::string &classname, const std::string &name) + { + testcases.emplace_back(classname, name); } - void test_case_end(const CurrentTestCaseStats&) override { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); + void appendSubcaseNamesToLastTestcase(std::vector nameStack) + { + for (auto &curr : nameStack) + if (curr.size()) + testcases.back().name += std::string("/") + curr.c_str(); } - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - testCaseData.addError("exception", e.error_string.c_str()); + void addTime(double time) + { + if (time < 1e-4) + time = 0; + testcases.back().time = time; + totalSeconds += time; } - void subcase_start(const SubcaseSignature& in) override { - deepestSubcaseStackNames.push_back(in.m_name); + void addFailure(const std::string &message, const std::string &type, + const std::string &details) + { + testcases.back().failures.emplace_back(message, type, details); + ++totalFailures; } - void subcase_end() override {} - - void log_assert(const AssertData& rb) override { - if(!rb.m_failed) // report only failures & ignore the `success` option - return; - - DOCTEST_LOCK_MUTEX(mutex) - - std::ostringstream os; - os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; - - fulltext_log_assert_to_stream(os, rb); - log_contexts(os); - testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + void addError(const std::string &message, const std::string &details) + { + testcases.back().errors.emplace_back(message, details); + ++totalErrors; } - void log_message(const MessageData& mb) override { - if(mb.m_severity & assertType::is_warn) // report only failures - return; + std::vector testcases; + double totalSeconds = 0; + int totalErrors = 0, totalFailures = 0; + }; - DOCTEST_LOCK_MUTEX(mutex) + JUnitTestCaseData testCaseData; - std::ostringstream os; - os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + // caching pointers/references to objects of these types - safe to do + const ContextOptions &opt; + const TestCaseData *tc = nullptr; - os << mb.m_string.c_str() << "\n"; - log_contexts(os); + JUnitReporter(const ContextOptions &co) : xml(*co.cout), opt(co) {} - testCaseData.addFailure(mb.m_string.c_str(), - mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str()); - } + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - void test_case_skipped(const TestCaseData&) override {} + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= - void log_contexts(std::ostringstream& s) { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); + void report_query(const QueryData &) override { xml.writeDeclaration(); } - s << " logged: "; - for(int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << std::endl; - } - } - } + void test_run_start() override { xml.writeDeclaration(); } + + void test_run_end(const TestRunStats &p) override + { + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if (binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + xml.startElement("testsuites"); + xml.startElement("testsuite") + .writeAttribute("name", binary_name) + .writeAttribute("errors", testCaseData.totalErrors) + .writeAttribute("failures", testCaseData.totalFailures) + .writeAttribute("tests", p.numAsserts); + if (opt.no_time_in_output == false) { + xml.writeAttribute("time", testCaseData.totalSeconds); + xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); + } + if (opt.no_version == false) + xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); + + for (const auto &testCase : testCaseData.testcases) { + xml.startElement("testcase") + .writeAttribute("classname", testCase.classname) + .writeAttribute("name", testCase.name); + if (opt.no_time_in_output == false) + xml.writeAttribute("time", testCase.time); + // This is not ideal, but it should be enough to mimic gtest's junit output. + xml.writeAttribute("status", "run"); + + for (const auto &failure : testCase.failures) { + xml.scopedElement("failure") + .writeAttribute("message", failure.message) + .writeAttribute("type", failure.type) + .writeText(failure.details, false); + } + + for (const auto &error : testCase.errors) { + xml.scopedElement("error") + .writeAttribute("message", error.message) + .writeText(error.details); + } + + xml.endElement(); + } + xml.endElement(); + xml.endElement(); + } + + void test_case_start(const TestCaseData &in) override + { + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + timer.start(); + } + + void test_case_reenter(const TestCaseData &in) override + { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + + timer.start(); + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + } + + void test_case_end(const CurrentTestCaseStats &) override + { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + } + + void test_case_exception(const TestCaseException &e) override + { + DOCTEST_LOCK_MUTEX(mutex) + testCaseData.addError("exception", e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature &in) override + { + deepestSubcaseStackNames.push_back(in.m_name); + } + + void subcase_end() override {} + + void log_assert(const AssertData &rb) override + { + if (!rb.m_failed) // report only failures & ignore the `success` option + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") << line(rb.m_line) + << (opt.gnu_file_line ? ":" : "):") << std::endl; + + fulltext_log_assert_to_stream(os, rb); + log_contexts(os); + testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + } + + void log_message(const MessageData &mb) override + { + if (mb.m_severity & assertType::is_warn) // report only failures + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") << line(mb.m_line) + << (opt.gnu_file_line ? ":" : "):") << std::endl; + + os << mb.m_string.c_str() << "\n"; + log_contexts(os); + + testCaseData.addFailure(mb.m_string.c_str(), + mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", + os.str()); + } + + void test_case_skipped(const TestCaseData &) override {} + + void log_contexts(std::ostringstream &s) + { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for (int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } }; DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); struct Whitespace { - int nrSpaces; - explicit Whitespace(int nr) - : nrSpaces(nr) {} + int nrSpaces; + explicit Whitespace(int nr) : nrSpaces(nr) {} }; - std::ostream& operator<<(std::ostream& out, const Whitespace& ws) { - if(ws.nrSpaces != 0) - out << std::setw(ws.nrSpaces) << ' '; - return out; + std::ostream &operator<<(std::ostream &out, const Whitespace &ws) + { + if (ws.nrSpaces != 0) + out << std::setw(ws.nrSpaces) << ' '; + return out; } struct ConsoleReporter : public IReporter { - std::ostream& s; - bool hasLoggedCurrentTestStart; - std::vector subcasesStack; - size_t currentSubcaseLevel; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc; - - ConsoleReporter(const ContextOptions& co) - : s(*co.cout) - , opt(co) {} - - ConsoleReporter(const ContextOptions& co, std::ostream& ostr) - : s(ostr) - , opt(co) {} - - // ========================================================================================= - // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE - // ========================================================================================= - - void separator_to_stream() { - s << Color::Yellow - << "===============================================================================" - "\n"; - } - - const char* getSuccessOrFailString(bool success, assertType::Enum at, - const char* success_str) { - if(success) - return success_str; - return failureString(at); - } - - Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) { - return success ? Color::BrightGreen : - (at & assertType::is_warn) ? Color::Yellow : Color::Red; - } - - void successOrFailColoredStringToStream(bool success, assertType::Enum at, - const char* success_str = "SUCCESS") { - s << getSuccessOrFailColor(success, at) - << getSuccessOrFailString(success, at, success_str) << ": "; - } - - void log_contexts() { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - - s << Color::None << " logged: "; - for(int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << "\n"; - } - } - - s << "\n"; - } - - // this was requested to be made virtual so users could override it - virtual void file_line_to_stream(const char* file, int line, - const char* tail = "") { - s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") - << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option - << (opt.gnu_file_line ? ":" : "):") << tail; - } - - void logTestStart() { - if(hasLoggedCurrentTestStart) - return; - - separator_to_stream(); - file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); - if(tc->m_description) - s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; - if(tc->m_test_suite && tc->m_test_suite[0] != '\0') - s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; - if(strncmp(tc->m_name, " Scenario:", 11) != 0) - s << Color::Yellow << "TEST CASE: "; - s << Color::None << tc->m_name << "\n"; - - for(size_t i = 0; i < currentSubcaseLevel; ++i) { - if(subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - - if(currentSubcaseLevel != subcasesStack.size()) { - s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; - for(size_t i = 0; i < subcasesStack.size(); ++i) { - if(subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - } - + std::ostream &s; + bool hasLoggedCurrentTestStart; + std::vector subcasesStack; + size_t currentSubcaseLevel; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions &opt; + const TestCaseData *tc; + + ConsoleReporter(const ContextOptions &co) : s(*co.cout), opt(co) {} + + ConsoleReporter(const ContextOptions &co, std::ostream &ostr) : s(ostr), opt(co) {} + + // ========================================================================================= + // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE + // ========================================================================================= + + void separator_to_stream() + { + s << Color::Yellow + << "===============================================================================" + "\n"; + } + + const char *getSuccessOrFailString(bool success, assertType::Enum at, const char *success_str) + { + if (success) + return success_str; + return failureString(at); + } + + Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) + { + return success ? Color::BrightGreen + : (at & assertType::is_warn) ? Color::Yellow + : Color::Red; + } + + void successOrFailColoredStringToStream(bool success, assertType::Enum at, + const char *success_str = "SUCCESS") + { + s << getSuccessOrFailColor(success, at) << getSuccessOrFailString(success, at, success_str) + << ": "; + } + + void log_contexts() + { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + + s << Color::None << " logged: "; + for (int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); s << "\n"; - - hasLoggedCurrentTestStart = true; - } - - void printVersion() { - if(opt.no_version == false) - s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" - << DOCTEST_VERSION_STR << "\"\n"; - } - - void printIntro() { - if(opt.no_intro == false) { - printVersion(); - s << Color::Cyan << "[doctest] " << Color::None - << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; - } - } - - void printHelp() { - int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); - printVersion(); - // clang-format off + } + } + + s << "\n"; + } + + // this was requested to be made virtual so users could override it + virtual void file_line_to_stream(const char *file, int line, const char *tail = "") + { + s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") + << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option + << (opt.gnu_file_line ? ":" : "):") << tail; + } + + void logTestStart() + { + if (hasLoggedCurrentTestStart) + return; + + separator_to_stream(); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); + if (tc->m_description) + s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; + if (tc->m_test_suite && tc->m_test_suite[0] != '\0') + s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; + if (strncmp(tc->m_name, " Scenario:", 11) != 0) + s << Color::Yellow << "TEST CASE: "; + s << Color::None << tc->m_name << "\n"; + + for (size_t i = 0; i < currentSubcaseLevel; ++i) { + if (subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + + if (currentSubcaseLevel != subcasesStack.size()) { + s << Color::Yellow + << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" + << Color::None; + for (size_t i = 0; i < subcasesStack.size(); ++i) { + if (subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + } + + s << "\n"; + + hasLoggedCurrentTestStart = true; + } + + void printVersion() + { + if (opt.no_version == false) + s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" + << DOCTEST_VERSION_STR << "\"\n"; + } + + void printIntro() + { + if (opt.no_intro == false) { + printVersion(); + s << Color::Cyan << "[doctest] " << Color::None + << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + } + } + + void printHelp() + { + int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); + printVersion(); + // clang-format off s << Color::Cyan << "[doctest]\n" << Color::None; s << Color::Cyan << "[doctest] " << Color::None; s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; @@ -6184,228 +6657,255 @@ namespace { s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n"; // ================================================================================== << 79 - // clang-format on - - s << Color::Cyan << "\n[doctest] " << Color::None; - s << "for more information visit the project documentation\n\n"; - } - - void printRegisteredReporters() { - printVersion(); - auto printReporters = [this] (const reporterMap& reporters, const char* type) { - if(reporters.size()) { - s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; - for(auto& curr : reporters) - s << "priority: " << std::setw(5) << curr.first.first - << " name: " << curr.first.second << "\n"; - } - }; - printReporters(getListeners(), "listeners"); - printReporters(getReporters(), "reporters"); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override { - if(opt.version) { - printVersion(); - } else if(opt.help) { - printHelp(); - } else if(opt.list_reporters) { - printRegisteredReporters(); - } else if(opt.count || opt.list_test_cases) { - if(opt.list_test_cases) { - s << Color::Cyan << "[doctest] " << Color::None - << "listing all test case names\n"; - separator_to_stream(); - } - - for(unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_name << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - - } else if(opt.list_test_suites) { - s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; - separator_to_stream(); - - for(unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_test_suite << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "test suites with unskipped test cases passing the current filters: " - << g_cs->numTestSuitesPassingFilters << "\n"; - } - } - - void test_run_start() override { - if(!opt.minimal) - printIntro(); - } - - void test_run_end(const TestRunStats& p) override { - if(opt.minimal && p.numTestCasesFailed == 0) - return; - - separator_to_stream(); - s << std::dec; - - auto totwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); - auto passwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); - auto failwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); - const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; - s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) - << p.numTestCasesPassingFilters << " | " - << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : - Color::Green) - << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" - << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) - << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; - if(opt.no_skipped_summary == false) { - const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; - s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped - << " skipped" << Color::None; - } - s << "\n"; - s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) - << p.numAsserts << " | " - << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None - << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) - << p.numAssertsFailed << " failed" << Color::None << " |\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) - << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; - } - - void test_case_start(const TestCaseData& in) override { - hasLoggedCurrentTestStart = false; - tc = ∈ - subcasesStack.clear(); - currentSubcaseLevel = 0; - } - - void test_case_reenter(const TestCaseData&) override { - subcasesStack.clear(); - } + // clang-format on - void test_case_end(const CurrentTestCaseStats& st) override { - if(tc->m_no_output) - return; - - // log the preamble of the test case only if there is something - // else to print - something other than that an assert has failed - if(opt.duration || - (st.failure_flags && st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) - logTestStart(); - - if(opt.duration) - s << Color::None << std::setprecision(6) << std::fixed << st.seconds - << " s: " << tc->m_name << "\n"; - - if(st.failure_flags & TestCaseFailureReason::Timeout) - s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) - << std::fixed << tc->m_timeout << "!\n"; - - if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { - s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; - } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { - s << Color::Yellow << "Failed as expected so marking it as not failed\n"; - } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { - s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; - } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { - s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures - << " times so marking it as failed!\n"; - } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { - s << Color::Yellow << "Failed exactly " << tc->m_expected_failures - << " times as expected so marking it as not failed!\n"; - } - if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { - s << Color::Red << "Aborting - too many failed asserts!\n"; - } - s << Color::None; // lgtm [cpp/useless-expression] - } + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "for more information visit the project documentation\n\n"; + } + + void printRegisteredReporters() + { + printVersion(); + auto printReporters = [this](const reporterMap &reporters, const char *type) { + if (reporters.size()) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type + << "\n"; + for (auto &curr : reporters) + s << "priority: " << std::setw(5) << curr.first.first + << " name: " << curr.first.second << "\n"; + } + }; + printReporters(getListeners(), "listeners"); + printReporters(getReporters(), "reporters"); + } - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - if(tc->m_no_output) - return; - - logTestStart(); - - file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); - successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : - assertType::is_check); - s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") - << Color::Cyan << e.error_string << "\n"; - - int num_stringified_contexts = get_num_stringified_contexts(); - if(num_stringified_contexts) { - auto stringified_contexts = get_stringified_contexts(); - s << Color::None << " logged: "; - for(int i = num_stringified_contexts; i > 0; --i) { - s << (i == num_stringified_contexts ? "" : " ") - << stringified_contexts[i - 1] << "\n"; - } - } - s << "\n" << Color::None; - } + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= - void subcase_start(const SubcaseSignature& subc) override { - subcasesStack.push_back(subc); - ++currentSubcaseLevel; - hasLoggedCurrentTestStart = false; + void report_query(const QueryData &in) override + { + if (opt.version) { + printVersion(); } - - void subcase_end() override { - --currentSubcaseLevel; - hasLoggedCurrentTestStart = false; + else if (opt.help) { + printHelp(); } - - void log_assert(const AssertData& rb) override { - if((!rb.m_failed && !opt.success) || tc->m_no_output) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - logTestStart(); - - file_line_to_stream(rb.m_file, rb.m_line, " "); - successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); - - fulltext_log_assert_to_stream(s, rb); - - log_contexts(); + else if (opt.list_reporters) { + printRegisteredReporters(); } + else if (opt.count || opt.list_test_cases) { + if (opt.list_test_cases) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test case names\n"; + separator_to_stream(); + } + + for (unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_name << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + } + else if (opt.list_test_suites) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; + separator_to_stream(); + + for (unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_test_suite << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "test suites with unskipped test cases passing the current filters: " + << g_cs->numTestSuitesPassingFilters << "\n"; + } + } + + void test_run_start() override + { + if (!opt.minimal) + printIntro(); + } + + void test_run_end(const TestRunStats &p) override + { + if (opt.minimal && p.numTestCasesFailed == 0) + return; + + separator_to_stream(); + s << std::dec; + + auto totwidth = + int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, + static_cast(p.numAsserts))) + + 1))); + auto passwidth = + int(std::ceil(log10(static_cast(std::max( + p.numTestCasesPassingFilters - p.numTestCasesFailed, + static_cast(p.numAsserts - p.numAssertsFailed))) + + 1))); + auto failwidth = int( + std::ceil(log10(static_cast(std::max( + p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + + 1))); + const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) + << p.numTestCasesPassingFilters << " | " + << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed + << " passed" << Color::None << " | " + << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numTestCasesFailed << " failed" << Color::None << " |"; + if (opt.no_skipped_summary == false) { + const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped << " skipped" + << Color::None; + } + s << "\n"; + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) + << p.numAsserts << " | " + << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numAssertsFailed << " failed" << Color::None << " |\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) + << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; + } + + void test_case_start(const TestCaseData &in) override + { + hasLoggedCurrentTestStart = false; + tc = ∈ + subcasesStack.clear(); + currentSubcaseLevel = 0; + } + + void test_case_reenter(const TestCaseData &) override { subcasesStack.clear(); } + + void test_case_end(const CurrentTestCaseStats &st) override + { + if (tc->m_no_output) + return; + + // log the preamble of the test case only if there is something + // else to print - something other than that an assert has failed + if (opt.duration || + (st.failure_flags && + st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) + logTestStart(); + + if (opt.duration) + s << Color::None << std::setprecision(6) << std::fixed << st.seconds + << " s: " << tc->m_name << "\n"; + + if (st.failure_flags & TestCaseFailureReason::Timeout) + s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) + << std::fixed << tc->m_timeout << "!\n"; + + if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { + s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; + } + else if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { + s << Color::Yellow << "Failed as expected so marking it as not failed\n"; + } + else if (st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { + s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; + } + else if (st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { + s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures + << " times so marking it as failed!\n"; + } + else if (st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { + s << Color::Yellow << "Failed exactly " << tc->m_expected_failures + << " times as expected so marking it as not failed!\n"; + } + if (st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { + s << Color::Red << "Aborting - too many failed asserts!\n"; + } + s << Color::None; // lgtm [cpp/useless-expression] + } + + void test_case_exception(const TestCaseException &e) override + { + DOCTEST_LOCK_MUTEX(mutex) + if (tc->m_no_output) + return; + + logTestStart(); + + file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); + successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require + : assertType::is_check); + s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") + << Color::Cyan << e.error_string << "\n"; + + int num_stringified_contexts = get_num_stringified_contexts(); + if (num_stringified_contexts) { + auto stringified_contexts = get_stringified_contexts(); + s << Color::None << " logged: "; + for (int i = num_stringified_contexts; i > 0; --i) { + s << (i == num_stringified_contexts ? "" : " ") << stringified_contexts[i - 1] + << "\n"; + } + } + s << "\n" << Color::None; + } + + void subcase_start(const SubcaseSignature &subc) override + { + subcasesStack.push_back(subc); + ++currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void subcase_end() override + { + --currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void log_assert(const AssertData &rb) override + { + if ((!rb.m_failed && !opt.success) || tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(rb.m_file, rb.m_line, " "); + successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); + + fulltext_log_assert_to_stream(s, rb); - void log_message(const MessageData& mb) override { - if(tc->m_no_output) - return; + log_contexts(); + } - DOCTEST_LOCK_MUTEX(mutex) + void log_message(const MessageData &mb) override + { + if (tc->m_no_output) + return; - logTestStart(); + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); - file_line_to_stream(mb.m_file, mb.m_line, " "); - s << getSuccessOrFailColor(false, mb.m_severity) - << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, - "MESSAGE") << ": "; - s << Color::None << mb.m_string << "\n"; - log_contexts(); - } + file_line_to_stream(mb.m_file, mb.m_line, " "); + s << getSuccessOrFailColor(false, mb.m_severity) + << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, "MESSAGE") + << ": "; + s << Color::None << mb.m_string << "\n"; + log_contexts(); + } - void test_case_skipped(const TestCaseData&) override {} + void test_case_skipped(const TestCaseData &) override {} }; DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); @@ -6413,201 +6913,211 @@ namespace { #ifdef DOCTEST_PLATFORM_WINDOWS struct DebugOutputWindowReporter : public ConsoleReporter { - DOCTEST_THREAD_LOCAL static std::ostringstream oss; + DOCTEST_THREAD_LOCAL static std::ostringstream oss; - DebugOutputWindowReporter(const ContextOptions& co) - : ConsoleReporter(co, oss) {} + DebugOutputWindowReporter(const ContextOptions &co) : ConsoleReporter(co, oss) {} #define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ - void func(type arg) override { \ - bool with_col = g_no_colors; \ - g_no_colors = false; \ - ConsoleReporter::func(arg); \ - if(oss.tellp() != std::streampos{}) { \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ - } \ - g_no_colors = with_col; \ - } - - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) + void func(type arg) override \ + { \ + bool with_col = g_no_colors; \ + g_no_colors = false; \ + ConsoleReporter::func(arg); \ + if (oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ + g_no_colors = with_col; \ + } + + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData &, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData &, in) }; DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; #endif // DOCTEST_PLATFORM_WINDOWS // the implementation of parseOption() - bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { - // going from the end to the beginning and stopping on the first occurrence from the end - for(int i = argc; i > 0; --i) { - auto index = i - 1; - auto temp = std::strstr(argv[index], pattern); - if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue - // eliminate matches in which the chars before the option are not '-' - bool noBadCharsFound = true; - auto curr = argv[index]; - while(curr != temp) { - if(*curr++ != '-') { - noBadCharsFound = false; - break; - } - } - if(noBadCharsFound && argv[index][0] == '-') { - if(value) { - // parsing the value of an option - temp += strlen(pattern); - const unsigned len = strlen(temp); - if(len) { - *value = temp; - return true; - } - } else { - // just a flag - no value - return true; - } - } + bool parseOptionImpl(int argc, const char *const *argv, const char *pattern, String *value) + { + // going from the end to the beginning and stopping on the first occurrence from the end + for (int i = argc; i > 0; --i) { + auto index = i - 1; + auto temp = std::strstr(argv[index], pattern); + if (temp && + (value || strlen(temp) == strlen(pattern))) { //! OCLINT prefer early exits and continue + // eliminate matches in which the chars before the option are not '-' + bool noBadCharsFound = true; + auto curr = argv[index]; + while (curr != temp) { + if (*curr++ != '-') { + noBadCharsFound = false; + break; + } + } + if (noBadCharsFound && argv[index][0] == '-') { + if (value) { + // parsing the value of an option + temp += strlen(pattern); + const unsigned len = strlen(temp); + if (len) { + *value = temp; + return true; + } + } + else { + // just a flag - no value + return true; } + } } - return false; + } + return false; } // parses an option and returns the string after the '=' character - bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, - const String& defaultVal = String()) { - if(value) - *value = defaultVal; + bool parseOption(int argc, const char *const *argv, const char *pattern, + String *value = nullptr, const String &defaultVal = String()) + { + if (value) + *value = defaultVal; #ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - // offset (normally 3 for "dt-") to skip prefix - if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) - return true; + // offset (normally 3 for "dt-") to skip prefix + if (parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) + return true; #endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - return parseOptionImpl(argc, argv, pattern, value); + return parseOptionImpl(argc, argv, pattern, value); } // locates a flag on the command line - bool parseFlag(int argc, const char* const* argv, const char* pattern) { - return parseOption(argc, argv, pattern); + bool parseFlag(int argc, const char *const *argv, const char *pattern) + { + return parseOption(argc, argv, pattern); } // parses a comma separated list of words after a pattern in one of the arguments in argv - bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, - std::vector& res) { - String filtersString; - if(parseOption(argc, argv, pattern, &filtersString)) { - // tokenize with "," as a separator, unless escaped with backslash - std::ostringstream s; - auto flush = [&s, &res]() { - auto string = s.str(); - if(string.size() > 0) { - res.push_back(string.c_str()); - } - s.str(""); - }; - - bool seenBackslash = false; - const char* current = filtersString.c_str(); - const char* end = current + strlen(current); - while(current != end) { - char character = *current++; - if(seenBackslash) { - seenBackslash = false; - if(character == ',' || character == '\\') { - s.put(character); - continue; - } - s.put('\\'); - } - if(character == '\\') { - seenBackslash = true; - } else if(character == ',') { - flush(); - } else { - s.put(character); - } - } + bool parseCommaSepArgs(int argc, const char *const *argv, const char *pattern, + std::vector &res) + { + String filtersString; + if (parseOption(argc, argv, pattern, &filtersString)) { + // tokenize with "," as a separator, unless escaped with backslash + std::ostringstream s; + auto flush = [&s, &res]() { + auto string = s.str(); + if (string.size() > 0) { + res.push_back(string.c_str()); + } + s.str(""); + }; - if(seenBackslash) { - s.put('\\'); + bool seenBackslash = false; + const char *current = filtersString.c_str(); + const char *end = current + strlen(current); + while (current != end) { + char character = *current++; + if (seenBackslash) { + seenBackslash = false; + if (character == ',' || character == '\\') { + s.put(character); + continue; } + s.put('\\'); + } + if (character == '\\') { + seenBackslash = true; + } + else if (character == ',') { flush(); - return true; + } + else { + s.put(character); + } } - return false; + + if (seenBackslash) { + s.put('\\'); + } + flush(); + return true; + } + return false; } - enum optionType - { - option_bool, - option_int - }; + enum optionType { option_bool, option_int }; // parses an int/bool option from the command line - bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, - int& res) { - String parsedValue; - if(!parseOption(argc, argv, pattern, &parsedValue)) - return false; - - if(type) { - // integer - // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse... - int theInt = std::atoi(parsedValue.c_str()); - if (theInt != 0) { - res = theInt; //!OCLINT parameter reassignment - return true; - } - } else { - // boolean - const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1 - const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1 - - // if the value matches any of the positive/negative possibilities - for (unsigned i = 0; i < 4; i++) { - if (parsedValue.compare(positive[i], true) == 0) { - res = 1; //!OCLINT parameter reassignment - return true; - } - if (parsedValue.compare(negative[i], true) == 0) { - res = 0; //!OCLINT parameter reassignment - return true; - } - } - } + bool parseIntOption(int argc, const char *const *argv, const char *pattern, optionType type, + int &res) + { + String parsedValue; + if (!parseOption(argc, argv, pattern, &parsedValue)) return false; + + if (type) { + // integer + // TODO: change this to use std::stoi or something else! currently it uses undefined + // behavior - assumes '0' on failed parse... + int theInt = std::atoi(parsedValue.c_str()); + if (theInt != 0) { + res = theInt; //! OCLINT parameter reassignment + return true; + } + } + else { + // boolean + const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1 + const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1 + + // if the value matches any of the positive/negative possibilities + for (unsigned i = 0; i < 4; i++) { + if (parsedValue.compare(positive[i], true) == 0) { + res = 1; //! OCLINT parameter reassignment + return true; + } + if (parsedValue.compare(negative[i], true) == 0) { + res = 0; //! OCLINT parameter reassignment + return true; + } + } + } + return false; } -} // namespace + } // namespace -Context::Context(int argc, const char* const* argv) - : p(new detail::ContextState) { + Context::Context(int argc, const char *const *argv) : p(new detail::ContextState) + { parseArgs(argc, argv, true); - if(argc) - p->binary_name = argv[0]; -} - -Context::~Context() { - if(g_cs == p) - g_cs = nullptr; + if (argc) + p->binary_name = argv[0]; + } + + Context::~Context() + { + if (g_cs == p) + g_cs = nullptr; delete p; -} + } -void Context::applyCommandLine(int argc, const char* const* argv) { + void Context::applyCommandLine(int argc, const char *const *argv) + { parseArgs(argc, argv); - if(argc) - p->binary_name = argv[0]; -} + if (argc) + p->binary_name = argv[0]; + } -// parses args -void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { + // parses args + void Context::parseArgs(int argc, const char *const *argv, bool withDefaults) + { using namespace detail; // clang-format off @@ -6635,27 +7145,27 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { String strRes; #define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ - if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ - parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ - p->var = static_cast(intRes); \ - else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ - p->var = true; \ - else if(withDefaults) \ - p->var = default + if (parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ + p->var = static_cast(intRes); \ + else if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ + p->var = true; \ + else if (withDefaults) \ + p->var = default #define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ - if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ - parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ - p->var = intRes; \ - else if(withDefaults) \ - p->var = default + if (parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ + p->var = intRes; \ + else if (withDefaults) \ + p->var = default #define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ - if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ - parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ - withDefaults) \ - p->var = strRes + if (parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ + parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ + withDefaults) \ + p->var = strRes // clang-format off DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); @@ -6691,110 +7201,116 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); // clang-format on - if(withDefaults) { - p->help = false; - p->version = false; - p->count = false; - p->list_test_cases = false; - p->list_test_suites = false; - p->list_reporters = false; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { - p->help = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { - p->version = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { - p->count = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { - p->list_test_cases = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { - p->list_test_suites = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { - p->list_reporters = true; - p->exit = true; + if (withDefaults) { + p->help = false; + p->version = false; + p->count = false; + p->list_test_cases = false; + p->list_test_suites = false; + p->list_reporters = false; } -} + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { + p->help = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { + p->version = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { + p->count = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { + p->list_test_cases = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { + p->list_test_suites = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { + p->list_reporters = true; + p->exit = true; + } + } -// allows the user to add procedurally to the filters from the command line -void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } + // allows the user to add procedurally to the filters from the command line + void Context::addFilter(const char *filter, const char *value) { setOption(filter, value); } -// allows the user to clear all filters from the command line -void Context::clearFilters() { - for(auto& curr : p->filters) - curr.clear(); -} + // allows the user to clear all filters from the command line + void Context::clearFilters() + { + for (auto &curr : p->filters) + curr.clear(); + } -// allows the user to override procedurally the bool options from the command line -void Context::setOption(const char* option, bool value) { + // allows the user to override procedurally the bool options from the command line + void Context::setOption(const char *option, bool value) + { setOption(option, value ? "true" : "false"); -} + } -// allows the user to override procedurally the int options from the command line -void Context::setOption(const char* option, int value) { + // allows the user to override procedurally the int options from the command line + void Context::setOption(const char *option, int value) + { setOption(option, toString(value).c_str()); -} + } -// allows the user to override procedurally the string options from the command line -void Context::setOption(const char* option, const char* value) { + // allows the user to override procedurally the string options from the command line + void Context::setOption(const char *option, const char *value) + { auto argv = String("-") + option + "=" + value; auto lvalue = argv.c_str(); parseArgs(1, &lvalue); -} + } -// users should query this in their main() and exit the program if true -bool Context::shouldExit() { return p->exit; } + // users should query this in their main() and exit the program if true + bool Context::shouldExit() { return p->exit; } -void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } + void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } -void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } + void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } -void Context::setCout(std::ostream* out) { p->cout = out; } + void Context::setCout(std::ostream *out) { p->cout = out; } -static class DiscardOStream : public std::ostream -{ -private: + static class DiscardOStream : public std::ostream + { + private: class : public std::streambuf { private: - // allowing some buffering decreases the amount of calls to overflow - char buf[1024]; + // allowing some buffering decreases the amount of calls to overflow + char buf[1024]; protected: - std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } + std::streamsize xsputn(const char_type *, std::streamsize count) override { return count; } - int_type overflow(int_type ch) override { - setp(std::begin(buf), std::end(buf)); - return traits_type::not_eof(ch); - } + int_type overflow(int_type ch) override + { + setp(std::begin(buf), std::end(buf)); + return traits_type::not_eof(ch); + } } discardBuf; -public: - DiscardOStream() - : std::ostream(&discardBuf) {} -} discardOut; + public: + DiscardOStream() : std::ostream(&discardBuf) {} + } discardOut; -// the main function that does all the filtering and test running -int Context::run() { + // the main function that does all the filtering and test running + int Context::run() + { using namespace detail; - // save the old context state in case such was setup - for using asserts out of a testing context + // save the old context state in case such was setup - for using asserts out of a testing + // context auto old_cs = g_cs; // this is the current contest g_cs = p; @@ -6804,277 +7320,291 @@ int Context::run() { p->resetRunData(); std::fstream fstr; - if(p->cout == nullptr) { - if(p->quiet) { - p->cout = &discardOut; - } else if(p->out.size()) { - // to a file if specified - fstr.open(p->out.c_str(), std::fstream::out); - p->cout = &fstr; - } else { + if (p->cout == nullptr) { + if (p->quiet) { + p->cout = &discardOut; + } + else if (p->out.size()) { + // to a file if specified + fstr.open(p->out.c_str(), std::fstream::out); + p->cout = &fstr; + } + else { #ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - // stdout by default - p->cout = &std::cout; -#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - return EXIT_FAILURE; + // stdout by default + p->cout = &std::cout; +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + return EXIT_FAILURE; #endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - } + } } FatalConditionHandler::allocateAltStackMem(); auto cleanup_and_return = [&]() { - FatalConditionHandler::freeAltStackMem(); + FatalConditionHandler::freeAltStackMem(); - if(fstr.is_open()) - fstr.close(); + if (fstr.is_open()) + fstr.close(); - // restore context - g_cs = old_cs; - is_running_in_test = false; + // restore context + g_cs = old_cs; + is_running_in_test = false; - // we have to free the reporters which were allocated when the run started - for(auto& curr : p->reporters_currently_used) - delete curr; - p->reporters_currently_used.clear(); + // we have to free the reporters which were allocated when the run started + for (auto &curr : p->reporters_currently_used) + delete curr; + p->reporters_currently_used.clear(); - if(p->numTestCasesFailed && !p->no_exitcode) - return EXIT_FAILURE; - return EXIT_SUCCESS; + if (p->numTestCasesFailed && !p->no_exitcode) + return EXIT_FAILURE; + return EXIT_SUCCESS; }; // setup default reporter if none is given through the command line - if(p->filters[8].empty()) - p->filters[8].push_back("console"); + if (p->filters[8].empty()) + p->filters[8].push_back("console"); // check to see if any of the registered reporters has been selected - for(auto& curr : getReporters()) { - if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) - p->reporters_currently_used.push_back(curr.second(*g_cs)); + for (auto &curr : getReporters()) { + if (matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) + p->reporters_currently_used.push_back(curr.second(*g_cs)); } // TODO: check if there is nothing in reporters_currently_used // prepend all listeners - for(auto& curr : getListeners()) - p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); + for (auto &curr : getListeners()) + p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); #ifdef DOCTEST_PLATFORM_WINDOWS - if(isDebuggerActive() && p->no_debug_output == false) - p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); + if (isDebuggerActive() && p->no_debug_output == false) + p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); #endif // DOCTEST_PLATFORM_WINDOWS // handle version, help and no_run - if(p->no_run || p->version || p->help || p->list_reporters) { - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); + if (p->no_run || p->version || p->help || p->list_reporters) { + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); - return cleanup_and_return(); + return cleanup_and_return(); } - std::vector testArray; - for(auto& curr : getRegisteredTests()) - testArray.push_back(&curr); + std::vector testArray; + for (auto &curr : getRegisteredTests()) + testArray.push_back(&curr); p->numTestCases = testArray.size(); // sort the collected records - if(!testArray.empty()) { - if(p->order_by.compare("file", true) == 0) { - std::sort(testArray.begin(), testArray.end(), fileOrderComparator); - } else if(p->order_by.compare("suite", true) == 0) { - std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); - } else if(p->order_by.compare("name", true) == 0) { - std::sort(testArray.begin(), testArray.end(), nameOrderComparator); - } else if(p->order_by.compare("rand", true) == 0) { - std::srand(p->rand_seed); - - // random_shuffle implementation - const auto first = &testArray[0]; - for(size_t i = testArray.size() - 1; i > 0; --i) { - int idxToSwap = std::rand() % (i + 1); - - const auto temp = first[i]; - - first[i] = first[idxToSwap]; - first[idxToSwap] = temp; - } - } else if(p->order_by.compare("none", true) == 0) { - // means no sorting - beneficial for death tests which call into the executable - // with a specific test case in mind - we don't want to slow down the startup times - } + if (!testArray.empty()) { + if (p->order_by.compare("file", true) == 0) { + std::sort(testArray.begin(), testArray.end(), fileOrderComparator); + } + else if (p->order_by.compare("suite", true) == 0) { + std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); + } + else if (p->order_by.compare("name", true) == 0) { + std::sort(testArray.begin(), testArray.end(), nameOrderComparator); + } + else if (p->order_by.compare("rand", true) == 0) { + std::srand(p->rand_seed); + + // random_shuffle implementation + const auto first = &testArray[0]; + for (size_t i = testArray.size() - 1; i > 0; --i) { + int idxToSwap = std::rand() % (i + 1); + + const auto temp = first[i]; + + first[i] = first[idxToSwap]; + first[idxToSwap] = temp; + } + } + else if (p->order_by.compare("none", true) == 0) { + // means no sorting - beneficial for death tests which call into the executable + // with a specific test case in mind - we don't want to slow down the startup times + } } std::set testSuitesPassingFilt; - bool query_mode = p->count || p->list_test_cases || p->list_test_suites; - std::vector queryResults; + bool query_mode = p->count || p->list_test_cases || p->list_test_suites; + std::vector queryResults; - if(!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); + if (!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); // invoke the registered functions if they match the filter criteria (or just count them) - for(auto& curr : testArray) { - const auto& tc = *curr; - - bool skip_me = false; - if(tc.m_skip && !p->no_skip) - skip_me = true; - - if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) - skip_me = true; - if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) - skip_me = true; - if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) - skip_me = true; - - if(!skip_me) - p->numTestCasesPassingFilters++; - - // skip the test if it is not in the execution range - if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || - (p->first > p->numTestCasesPassingFilters)) - skip_me = true; - - if(skip_me) { - if(!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); - continue; - } - - // do not execute the test if we are to only count the number of filter passing tests - if(p->count) - continue; - - // print the name of the test and don't execute it - if(p->list_test_cases) { - queryResults.push_back(&tc); - continue; - } - - // print the name of the test suite if not done already and don't execute it - if(p->list_test_suites) { - if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { - queryResults.push_back(&tc); - testSuitesPassingFilt.insert(tc.m_test_suite); - p->numTestSuitesPassingFilters++; - } - continue; - } - - // execute the test if it passes all the filtering - { - p->currentTest = &tc; - - p->failure_flags = TestCaseFailureReason::None; - p->seconds = 0; - - // reset atomic counters - p->numAssertsFailedCurrentTest_atomic = 0; - p->numAssertsCurrentTest_atomic = 0; - - p->fullyTraversedSubcases.clear(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); - - p->timer.start(); - - bool run_test = true; - - do { - // reset some of the fields for subcases (except for the set of fully passed ones) - p->reachedLeaf = false; - // May not be empty if previous subcase exited via exception. - p->subcaseStack.clear(); - p->currentSubcaseDepth = 0; - - p->shouldLogCurrentException = true; - - // reset stuff for logging with INFO() - p->stringifiedContexts.clear(); + for (auto &curr : testArray) { + const auto &tc = *curr; + + bool skip_me = false; + if (tc.m_skip && !p->no_skip) + skip_me = true; + + if (!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) + skip_me = true; + if (!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) + skip_me = true; + if (!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) + skip_me = true; + + if (!skip_me) + p->numTestCasesPassingFilters++; + + // skip the test if it is not in the execution range + if ((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || + (p->first > p->numTestCasesPassingFilters)) + skip_me = true; + + if (skip_me) { + if (!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); + continue; + } + + // do not execute the test if we are to only count the number of filter passing tests + if (p->count) + continue; + + // print the name of the test and don't execute it + if (p->list_test_cases) { + queryResults.push_back(&tc); + continue; + } + + // print the name of the test suite if not done already and don't execute it + if (p->list_test_suites) { + if ((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { + queryResults.push_back(&tc); + testSuitesPassingFilt.insert(tc.m_test_suite); + p->numTestSuitesPassingFilters++; + } + continue; + } + + // execute the test if it passes all the filtering + { + p->currentTest = &tc; + + p->failure_flags = TestCaseFailureReason::None; + p->seconds = 0; + + // reset atomic counters + p->numAssertsFailedCurrentTest_atomic = 0; + p->numAssertsCurrentTest_atomic = 0; + + p->fullyTraversedSubcases.clear(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); + + p->timer.start(); + + bool run_test = true; + + do { + // reset some of the fields for subcases (except for the set of fully passed ones) + p->reachedLeaf = false; + // May not be empty if previous subcase exited via exception. + p->subcaseStack.clear(); + p->currentSubcaseDepth = 0; + + p->shouldLogCurrentException = true; + + // reset stuff for logging with INFO() + p->stringifiedContexts.clear(); #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { + try { #endif // DOCTEST_CONFIG_NO_EXCEPTIONS -// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable - FatalConditionHandler fatalConditionHandler; // Handle signals - // execute the test - tc.m_test(); - fatalConditionHandler.reset(); -DOCTEST_MSVC_SUPPRESS_WARNING_POP + // MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static + // method) + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable + FatalConditionHandler fatalConditionHandler; // Handle signals + // execute the test + tc.m_test(); + fatalConditionHandler.reset(); + DOCTEST_MSVC_SUPPRESS_WARNING_POP #ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - } catch(const TestFailureException&) { - p->failure_flags |= TestCaseFailureReason::AssertFailure; - } catch(...) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, - {translateActiveException(), false}); - p->failure_flags |= TestCaseFailureReason::Exception; - } + } + catch (const TestFailureException &) { + p->failure_flags |= TestCaseFailureReason::AssertFailure; + } + catch (...) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + {translateActiveException(), false}); + p->failure_flags |= TestCaseFailureReason::Exception; + } #endif // DOCTEST_CONFIG_NO_EXCEPTIONS - // exit this loop if enough assertions have failed - even if there are more subcases - if(p->abort_after > 0 && - p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { - run_test = false; - p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; - } + // exit this loop if enough assertions have failed - even if there are more subcases + if (p->abort_after > 0 && + p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { + run_test = false; + p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; + } - if(!p->nextSubcaseStack.empty() && run_test) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); - if(p->nextSubcaseStack.empty()) - run_test = false; - } while(run_test); + if (!p->nextSubcaseStack.empty() && run_test) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); + if (p->nextSubcaseStack.empty()) + run_test = false; + } while (run_test); - p->finalizeTestCaseData(); + p->finalizeTestCaseData(); - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - p->currentTest = nullptr; + p->currentTest = nullptr; - // stop executing tests if enough assertions have failed - if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) - break; - } + // stop executing tests if enough assertions have failed + if (p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) + break; + } } - if(!query_mode) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); - } else { - QueryData qdata; - qdata.run_stats = g_cs; - qdata.data = queryResults.data(); - qdata.num_data = unsigned(queryResults.size()); - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); + if (!query_mode) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } + else { + QueryData qdata; + qdata.run_stats = g_cs; + qdata.data = queryResults.data(); + qdata.num_data = unsigned(queryResults.size()); + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); } return cleanup_and_return(); -} + } -DOCTEST_DEFINE_INTERFACE(IReporter) + DOCTEST_DEFINE_INTERFACE(IReporter) -int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } -const IContextScope* const* IReporter::get_active_contexts() { + int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } + const IContextScope *const *IReporter::get_active_contexts() + { return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; -} + } -int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } -const String* IReporter::get_stringified_contexts() { + int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } + const String *IReporter::get_stringified_contexts() + { return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr; -} + } -namespace detail { - void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { - if(isReporter) - getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); - else - getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + namespace detail { + void registerReporterImpl(const char *name, int priority, reporterCreatorFunc c, + bool isReporter) + { + if (isReporter) + getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + else + getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); } -} // namespace detail + } // namespace detail } // namespace doctest @@ -7082,7 +7612,7 @@ namespace detail { #ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182 -int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } +int main(int argc, char **argv) { return doctest::Context(argc, argv).run(); } DOCTEST_MSVC_SUPPRESS_WARNING_POP #endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN @@ -7104,3 +7634,5 @@ DOCTEST_SUPPRESS_COMMON_WARNINGS_POP #undef NOMINMAX #undef DOCTEST_UNDEF_NOMINMAX #endif // DOCTEST_UNDEF_NOMINMAX + +// NOLINTEND diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C index f0f9bd6a8d..06416b377e 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.C @@ -74,7 +74,7 @@ // Static internal helper functions // ======================================================================== namespace { - static bool sixty_four_bit_message_output = false; + bool sixty_four_bit_message_output = false; std::vector exodus_types({EX_GLOBAL, EX_BLOB, EX_ASSEMBLY, EX_NODE_BLOCK, EX_EDGE_BLOCK, EX_FACE_BLOCK, EX_ELEM_BLOCK, @@ -110,7 +110,7 @@ namespace { { // Walk the tree without cyclic dependency if (assemblyIndex < m_assemblies.size()) { - if (m_visitedAssemblies[assemblyIndex] == false) { + if (!m_visitedAssemblies[assemblyIndex]) { m_visitedAssemblies[assemblyIndex] = true; const auto &assembly = m_assemblies[assemblyIndex]; @@ -557,7 +557,7 @@ namespace Ioex { ex_put_qa(get_file_pointer(), num_qa_records + 1, nullptr); } else { - auto *qa = new qa_element[num_qa_records + 1]; + std::vector qa(num_qa_records + 1); for (size_t i = 0; i < num_qa_records + 1; i++) { for (int j = 0; j < 4; j++) { qa[i].qa_record[0][j] = new char[MAX_STR_LENGTH + 1]; @@ -600,7 +600,6 @@ namespace Ioex { delete[] qa[i].qa_record[0][j]; } } - delete[] qa; } } @@ -1522,7 +1521,7 @@ namespace Ioex { #if GLOBALS_ARE_TRANSIENT int field_count = add_results_fields(get_region()); #else - int field_count = add_reduction_results_fields(get_region()); + int field_count = add_reduction_results_fields(get_region()); #endif m_reductionValues[EX_GLOBAL][0].resize(field_count); add_mesh_reduction_fields(0, get_region()); diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h index 69df1d055c..9d27bb031c 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_BaseDatabaseIO.h @@ -130,7 +130,6 @@ namespace Ioex { int int_byte_size_db() const override; void set_int_byte_size_api(Ioss::DataSize size) const override; - protected: int64_t get_field_internal(const Ioss::Region *reg, const Ioss::Field &field, void *data, size_t data_size) const override = 0; int64_t get_field_internal(const Ioss::NodeBlock *nb, const Ioss::Field &field, void *data, @@ -264,8 +263,6 @@ namespace Ioex { void flush_database__() const override; void finalize_write(int state, double sim_time); - // Private member data... - protected: mutable int m_exodusFilePtr{-1}; // If using links to file-per-state, the file pointer for "base" file. mutable int m_exodusBasePtr{-1}; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C index 0be687e9a2..f2d16b8b3f 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_DatabaseIO.C @@ -608,7 +608,7 @@ namespace Ioex { char *qa_record[1][4]; }; - auto qa = new qa_element[num_qa]; + std::vector qa(num_qa); for (int i = 0; i < num_qa; i++) { for (int j = 0; j < 4; j++) { qa[i].qa_record[0][j] = new char[MAX_STR_LENGTH + 1]; @@ -625,7 +625,6 @@ namespace Ioex { delete[] qa[i].qa_record[0][j]; } } - delete[] qa; } // Get information records from database and add to informationRecords... @@ -843,10 +842,10 @@ namespace Ioex { if (nemesis_file) { // A nemesis file typically separates nodes into multiple // communication sets by processor. (each set specifies - // nodes/elements that communicate with only a single processor). - // For Sierra, we want a single node commun. map and a single - // element commun. map specifying all communications so we combine - // all sets into a single set. + // nodes/elements that communicate with only a single + // processor). For Sierra, we want a single node communication + // map and a single element communication map specifying all + // communications so we combine all sets into a single set. if (int_byte_size_api() == 4) { int gn, ge, geb, gns, gss; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C index ee4793e6e3..98e21da560 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.C @@ -885,11 +885,6 @@ namespace Ioex { template void DecompositionData::get_block_connectivity(int filePtr, int64_t *data, int64_t id, size_t blk_seq, size_t nnpe) const; - - template std::vector DecompositionData::get_all_block_connectivity(int filePtr, - int *data) const; - template std::vector - DecompositionData::get_all_block_connectivity(int filePtr, int64_t *data) const; #endif /// relates DecompositionData::get_block_connectivity template @@ -919,164 +914,6 @@ namespace Ioex { } } - template - std::vector DecompositionData::get_all_block_connectivity_file_offset() const - { - std::vector conn_offset(el_blocks.size() + 1, 0); - - for (size_t blk_seq = 0; blk_seq < el_blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &blk = el_blocks[blk_seq]; - - // Determine number of file decomp elements are in this block and the offset into the block. - size_t count = get_block_element_count(blk_seq); - - int npe = blk.nodesPerEntity; - conn_offset[blk_seq + 1] = count * npe; - } - - for (size_t i = 1; i <= el_blocks.size(); ++i) { - conn_offset[i] += conn_offset[i - 1]; - } - - return conn_offset; - } - - template - std::vector DecompositionData::get_all_block_file_offset_impl( - const std::vector &block_component_count) const - { - std::vector offset(el_blocks.size() + 1, 0); - - for (size_t blk_seq = 0; blk_seq < el_blocks.size(); blk_seq++) { - // Determine number of file decomp elements are in this block and the offset into the block. - size_t count = get_block_element_count(blk_seq); - - offset[blk_seq + 1] = count * block_component_count[blk_seq]; - } - - for (size_t i = 1; i <= el_blocks.size(); ++i) { - offset[i] += offset[i - 1]; - } - - return offset; - } - - template - std::vector DecompositionData::get_all_block_connectivity(int filePtr, - INT *data) const - { - m_decomposition.show_progress(__func__); - - std::vector retval; - std::vector file_conn_offset = get_all_block_connectivity_file_offset(); - - if (m_decomposition.m_method == "LINEAR") { - for (size_t blk_seq = 0; blk_seq < el_blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &blk = el_blocks[blk_seq]; - int64_t id = blk.id(); - size_t offset = get_block_element_offset(blk_seq); - size_t count = get_block_element_count(blk_seq); - - ex_get_partial_conn(filePtr, EX_ELEM_BLOCK, id, offset + 1, count, - &data[file_conn_offset[blk_seq]], nullptr, nullptr); - } - - retval = file_conn_offset; - } - else { - std::vector file_conn(file_conn_offset[el_blocks.size()]); - std::vector block_component_count(el_blocks.size(), 0); - - for (size_t blk_seq = 0; blk_seq < el_blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &blk = el_blocks[blk_seq]; - int64_t id = blk.id(); - size_t offset = get_block_element_offset(blk_seq); - size_t count = get_block_element_count(blk_seq); - - block_component_count[blk_seq] = blk.nodesPerEntity; - ex_get_partial_conn(filePtr, EX_ELEM_BLOCK, id, offset + 1, count, - &file_conn[file_conn_offset[blk_seq]], nullptr, nullptr); - } - - retval = m_decomposition.communicate_all_block_data(file_conn.data(), data, el_blocks, - file_conn_offset, block_component_count); - } - - size_t length = retval[el_blocks.size()]; - - for (size_t i = 0; i < length; i++) { - data[i] = node_global_to_local(data[i]); - } - - return retval; - } - - template - void DecompositionData::get_all_block_field_impl( - int filePtr, void *iossData, size_t step, const std::vector &block_data) const - { - m_decomposition.show_progress(__func__); - - double *data = reinterpret_cast(iossData); - size_t num_blocks = el_blocks.size(); - - std::vector block_component_count(num_blocks); - for (size_t blk_seq = 0; blk_seq < num_blocks; blk_seq++) { - block_component_count[blk_seq] = block_data[blk_seq].comp_count; - } - - std::vector file_conn_offset = get_all_block_file_offset_impl(block_component_count); - - m_decomposition.show_progress("\tex_get_partial_var (elem)"); - - if (m_decomposition.m_method == "LINEAR") { - - for (size_t blk_seq = 0; blk_seq < el_blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &blk = el_blocks[blk_seq]; - int64_t id = blk.id(); - size_t offset = get_block_element_offset(blk_seq); - size_t count = get_block_element_count(blk_seq); - - for (size_t comp = 0; comp < block_data[blk_seq].comp_count; comp++) { - size_t var_index = block_data[blk_seq].var_index[comp]; - size_t file_index = file_conn_offset[blk_seq] + count * comp; - - int ierr = ex_get_partial_var(filePtr, step, EX_ELEM_BLOCK, var_index, id, offset + 1, - count, &data[file_index]); - - if (ierr < 0) { - Ioex::exodus_error(filePtr, __LINE__, __func__, __FILE__); - } - } - } - } - else { - std::vector file_data(file_conn_offset[num_blocks]); - - for (size_t blk_seq = 0; blk_seq < el_blocks.size(); blk_seq++) { - const Ioss::BlockDecompositionData &blk = el_blocks[blk_seq]; - int64_t id = blk.id(); - size_t offset = get_block_element_offset(blk_seq); - size_t count = get_block_element_count(blk_seq); - - for (size_t comp = 0; comp < block_data[blk_seq].comp_count; comp++) { - size_t var_index = block_data[blk_seq].var_index[comp]; - size_t file_index = file_conn_offset[blk_seq] + count * comp; - - int ierr = ex_get_partial_var(filePtr, step, EX_ELEM_BLOCK, var_index, id, offset + 1, - count, &file_data[file_index]); - - if (ierr < 0) { - Ioex::exodus_error(filePtr, __LINE__, __func__, __FILE__); - } - } - } - - m_decomposition.communicate_all_block_data(file_data.data(), data, el_blocks, - file_conn_offset, block_component_count); - } - } - template int DecompositionData::get_var(int filePtr, int step, ex_entity_type type, int var_index, ex_entity_id id, int64_t num_entity, @@ -1283,83 +1120,6 @@ namespace Ioex { } } - size_t DecompositionDataBase::get_all_block_connectivity_size() const - { - size_t connSize = Ioss::get_all_block_connectivity_ioss_offset_size(el_blocks); - return connSize; - } - - std::vector - DecompositionDataBase::get_all_block_offset(const std::vector &block_component_count) const - { - std::vector offset = Ioss::get_all_block_ioss_offset(el_blocks, block_component_count); - return offset; - } - - std::vector DecompositionDataBase::get_all_block_connectivity_component_count() const - { - std::vector component_count = - Ioss::get_all_block_connectivity_ioss_component_count(el_blocks); - return component_count; - } - - std::vector DecompositionDataBase::get_all_block_file_offset( - const std::vector &block_component_count) const - { - std::vector offset; - - if (int_size() == sizeof(int)) { - const DecompositionData *this32 = dynamic_cast *>(this); - Ioss::Utils::check_dynamic_cast(this32); - offset = this32->get_all_block_file_offset_impl(block_component_count); - } - else { - const DecompositionData *this64 = - dynamic_cast *>(this); - Ioss::Utils::check_dynamic_cast(this64); - offset = this64->get_all_block_file_offset_impl(block_component_count); - } - - return offset; - } - - std::vector DecompositionDataBase::get_all_block_connectivity(int filePtr, - void *data) const - { - std::vector offset; - - if (int_size() == sizeof(int)) { - const DecompositionData *this32 = dynamic_cast *>(this); - Ioss::Utils::check_dynamic_cast(this32); - offset = this32->get_all_block_connectivity(filePtr, reinterpret_cast(data)); - } - else { - const DecompositionData *this64 = - dynamic_cast *>(this); - Ioss::Utils::check_dynamic_cast(this64); - offset = this64->get_all_block_connectivity(filePtr, reinterpret_cast(data)); - } - - return offset; - } - - void - DecompositionDataBase::get_all_block_field(int filePtr, void *data, size_t step, - const std::vector &block_data) const - { - if (int_size() == sizeof(int)) { - const DecompositionData *this32 = dynamic_cast *>(this); - Ioss::Utils::check_dynamic_cast(this32); - this32->get_all_block_field_impl(filePtr, data, step, block_data); - } - else { - const DecompositionData *this64 = - dynamic_cast *>(this); - Ioss::Utils::check_dynamic_cast(this64); - this64->get_all_block_field_impl(filePtr, data, step, block_data); - } - } - const Ioss::SetDecompositionData &DecompositionDataBase::get_decomp_set(ex_entity_type type, ex_entity_id id) const { @@ -2174,6 +1934,261 @@ namespace Ioex { } } } + + ElementBlockBatchReader::ElementBlockBatchReader(const DecompositionDataBase *decompDB) + : m_decompositionDB(decompDB), m_batchOffset(decompDB->el_blocks) + { + } + + size_t + ElementBlockBatchReader::get_connectivity_size(const std::vector &blockSubsetIndex) const + { + size_t connSize = m_batchOffset.get_connectivity_ioss_offset_size(blockSubsetIndex); + return connSize; + } + + template + std::vector ElementBlockBatchReader::get_connectivity_file_offset( + const std::vector &blockSubsetIndex) const + { + const DecompositionData *decompData = + dynamic_cast *>(m_decompositionDB); + Ioss::Utils::check_dynamic_cast(decompData); + + std::vector offset(blockSubsetIndex.size() + 1, 0); + + for (size_t i = 0; i < blockSubsetIndex.size(); i++) { + int64_t blk_seq = blockSubsetIndex[i]; + const Ioss::BlockDecompositionData &blk = m_decompositionDB->el_blocks[blk_seq]; + + // Determine number of file decomp elements are in this block and the offset into the block. + size_t count = decompData->get_block_element_count(blk_seq); + + int npe = blk.nodesPerEntity; + offset[i + 1] = count * npe; + } + + for (size_t i = 1; i <= blockSubsetIndex.size(); ++i) { + offset[i] += offset[i - 1]; + } + + return offset; + } + + template + std::vector ElementBlockBatchReader::get_connectivity_impl( + int filePtr, const std::vector &blockSubsetIndex, void *data) const + { + const DecompositionData *decompData = + dynamic_cast *>(m_decompositionDB); + Ioss::Utils::check_dynamic_cast(decompData); + + decompData->m_decomposition.show_progress(__func__); + + INT *connData = reinterpret_cast(data); + + std::vector retval; + std::vector fileConnOffset = get_connectivity_file_offset(blockSubsetIndex); + + if (decompData->m_decomposition.m_method == "LINEAR") { + for (size_t i = 0; i < blockSubsetIndex.size(); i++) { + int64_t blk_seq = blockSubsetIndex[i]; + const Ioss::BlockDecompositionData &blk = m_decompositionDB->el_blocks[blk_seq]; + int64_t id = blk.id(); + size_t offset = decompData->get_block_element_offset(blk_seq); + size_t count = decompData->get_block_element_count(blk_seq); + + ex_get_partial_conn(filePtr, EX_ELEM_BLOCK, id, offset + 1, count, + &connData[fileConnOffset[i]], nullptr, nullptr); + } + + retval = fileConnOffset; + } + else { + std::vector file_conn(fileConnOffset[blockSubsetIndex.size()]); + std::vector blockComponentCount(blockSubsetIndex.size(), 0); + + for (size_t i = 0; i < blockSubsetIndex.size(); i++) { + int64_t blk_seq = blockSubsetIndex[i]; + const Ioss::BlockDecompositionData &blk = m_decompositionDB->el_blocks[blk_seq]; + int64_t id = blk.id(); + size_t offset = decompData->get_block_element_offset(blk_seq); + size_t count = decompData->get_block_element_count(blk_seq); + + blockComponentCount[i] = blk.nodesPerEntity; + ex_get_partial_conn(filePtr, EX_ELEM_BLOCK, id, offset + 1, count, + &file_conn[fileConnOffset[i]], nullptr, nullptr); + } + + retval = decompData->m_decomposition.communicate_entity_data( + file_conn.data(), connData, m_decompositionDB->el_blocks, blockSubsetIndex, + fileConnOffset, blockComponentCount); + } + + size_t length = retval[blockSubsetIndex.size()]; + + for (size_t i = 0; i < length; i++) { + connData[i] = decompData->node_global_to_local(connData[i]); + } + + return retval; + } + + std::vector ElementBlockBatchReader::get_connectivity( + int filePtr, const std::vector &blockSubsetIndex, void *data) const + { + std::vector offset; + + if (m_decompositionDB->int_size() == sizeof(int)) { + offset = get_connectivity_impl(filePtr, blockSubsetIndex, data); + } + else { + offset = get_connectivity_impl(filePtr, blockSubsetIndex, data); + } + + return offset; + } + + std::vector + ElementBlockBatchReader::get_offset(const std::vector &blockSubsetIndex, + const std::vector &blockComponentCount) const + { + std::vector offset = + m_batchOffset.get_ioss_offset(blockSubsetIndex, blockComponentCount); + return offset; + } + + std::vector ElementBlockBatchReader::get_connectivity_component_count( + const std::vector &blockSubsetIndex) const + { + std::vector componentCount = + m_batchOffset.get_connectivity_ioss_component_count(blockSubsetIndex); + return componentCount; + } + + template + std::vector + ElementBlockBatchReader::get_file_offset(const std::vector &blockSubsetIndex, + const std::vector &blockComponentCount) const + { + const DecompositionData *decompData = + dynamic_cast *>(m_decompositionDB); + Ioss::Utils::check_dynamic_cast(decompData); + + std::vector offset(blockSubsetIndex.size() + 1, 0); + + for (size_t i = 0; i < blockSubsetIndex.size(); i++) { + int64_t blk_seq = blockSubsetIndex[i]; + + // Determine number of file decomp elements are in this block and the offset into the block. + size_t count = decompData->get_block_element_count(blk_seq); + + offset[i + 1] = count * blockComponentCount[i]; + } + + for (size_t i = 1; i <= blockSubsetIndex.size(); ++i) { + offset[i] += offset[i - 1]; + } + + return offset; + } + + void ElementBlockBatchReader::get_field_data(int filePtr, void *data, + const std::vector &blockSubsetIndex, + size_t step, + const std::vector &block_data) const + { + if (m_decompositionDB->int_size() == sizeof(int)) { + get_field_data_impl(filePtr, data, blockSubsetIndex, step, block_data); + } + else { + get_field_data_impl(filePtr, data, blockSubsetIndex, step, block_data); + } + } + + std::vector ElementBlockBatchReader::get_block_component_count( + const std::vector &blockSubsetIndex, + const std::vector &blockFieldData) const + { + size_t num_blocks = blockSubsetIndex.size(); + std::vector blockComponentCount(num_blocks); + + for (size_t blk_seq = 0; blk_seq < blockSubsetIndex.size(); blk_seq++) { + blockComponentCount[blk_seq] = blockFieldData[blk_seq].comp_count; + } + + return blockComponentCount; + } + + template + void ElementBlockBatchReader::load_field_data(int filePtr, double *fileData, + const std::vector &blockSubsetIndex, + size_t step, + const std::vector &blockFieldData, + const std::vector &blockComponentCount, + const std::vector &fileConnOffset) const + { + const DecompositionData *decompData = + dynamic_cast *>(m_decompositionDB); + Ioss::Utils::check_dynamic_cast(decompData); + + decompData->m_decomposition.show_progress("\tex_get_partial_var (elem)"); + + for (size_t i = 0; i < blockSubsetIndex.size(); i++) { + int64_t blk_seq = blockSubsetIndex[i]; + const Ioss::BlockDecompositionData &blk = decompData->el_blocks[blk_seq]; + int64_t id = blk.id(); + size_t offset = decompData->get_block_element_offset(blk_seq); + size_t count = decompData->get_block_element_count(blk_seq); + + for (size_t comp = 0; comp < blockFieldData[i].comp_count; comp++) { + size_t var_index = blockFieldData[i].var_index[comp]; + size_t file_index = fileConnOffset[i] + count * comp; + + int ierr = ex_get_partial_var(filePtr, step, EX_ELEM_BLOCK, var_index, id, offset + 1, + count, &fileData[file_index]); + + if (ierr < 0) { + Ioex::exodus_error(filePtr, __LINE__, __func__, __FILE__); + } + } + } + } + + template + void ElementBlockBatchReader::get_field_data_impl( + int filePtr, void *iossData, const std::vector &blockSubsetIndex, size_t step, + const std::vector &blockFieldData) const + { + const DecompositionData *decompData = + dynamic_cast *>(m_decompositionDB); + Ioss::Utils::check_dynamic_cast(decompData); + + decompData->m_decomposition.show_progress(__func__); + + double *data = reinterpret_cast(iossData); + + std::vector blockComponentCount = + get_block_component_count(blockSubsetIndex, blockFieldData); + std::vector fileConnOffset = + get_file_offset(blockSubsetIndex, blockComponentCount); + + if (decompData->m_decomposition.m_method == "LINEAR") { + load_field_data(filePtr, data, blockSubsetIndex, step, blockFieldData, + blockComponentCount, fileConnOffset); + } + else { + size_t numBlocks = blockSubsetIndex.size(); + std::vector fileData(fileConnOffset[numBlocks]); + load_field_data(filePtr, fileData.data(), blockSubsetIndex, step, blockFieldData, + blockComponentCount, fileConnOffset); + + decompData->m_decomposition.communicate_entity_data(fileData.data(), data, + decompData->el_blocks, blockSubsetIndex, + fileConnOffset, blockComponentCount); + } + } + } // namespace Ioex #else IOSS_MAYBE_UNUSED const char ioss_exodus_decomposition_data_unused_symbol_dummy = '\0'; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h index e5e2265ee3..72c429fb40 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_DecompositionData.h @@ -28,7 +28,8 @@ namespace Ioss { class Field; -} + class ElementBlock; +} // namespace Ioss namespace Ioex { struct IOEX_EXPORT BlockFieldData { @@ -86,17 +87,6 @@ namespace Ioex { void get_block_connectivity(int filePtr, void *data, int64_t id, size_t blk_seq, size_t nnpe) const; - std::vector get_all_block_connectivity(int filePtr, void *data) const; - size_t get_all_block_connectivity_size() const; - std::vector get_all_block_connectivity_component_count() const; - - std::vector get_all_block_offset(const std::vector &block_component_count) const; - std::vector - get_all_block_file_offset(const std::vector &block_component_count) const; - - void get_all_block_field(int filePtr, void *data, size_t step, - const std::vector &block_data) const; - void read_elem_proc_map(int filePtr, void *data) const; void get_node_entity_proc_data(void *entity_proc, const Ioss::MapContainer &node_map, @@ -169,14 +159,6 @@ namespace Ioex { void get_block_connectivity(int filePtr, INT *data, int64_t id, size_t blk_seq, size_t nnpe) const; - std::vector get_all_block_connectivity(int filePtr, INT *data) const; - - void get_all_block_field_impl(int filePtr, void *data, size_t step, - const std::vector &block_data) const; - - std::vector - get_all_block_file_offset_impl(const std::vector &block_component_count) const; - size_t get_commset_node_size() const { return m_decomposition.m_nodeCommMap.size() / 2; } int get_attr(int filePtr, ex_entity_type obj_type, ex_entity_id id, size_t attr_count, @@ -202,9 +184,20 @@ namespace Ioex { std::vector &global_implicit_map, Ioss::Map &node_map, int64_t *locally_owned_count, int64_t *processor_offset); - private: - std::vector get_all_block_connectivity_file_offset() const; + // global_index is 1-based index into global list of nodes [1..global_node_count] + // return value is 1-based index into local list of nodes on this + // processor (ioss-decomposition) + size_t node_global_to_local(size_t global_index) const + { + return m_decomposition.node_global_to_local(global_index); + } + + size_t elem_global_to_local(size_t global_index) const + { + return m_decomposition.elem_global_to_local(global_index); + } + private: #if !defined(NO_ZOLTAN_SUPPORT) void zoltan_decompose(const std::string &method); #endif @@ -262,19 +255,6 @@ namespace Ioex { return m_decomposition.i_own_elem(elem); } - // global_index is 1-based index into global list of nodes [1..global_node_count] - // return value is 1-based index into local list of nodes on this - // processor (ioss-decomposition) - size_t node_global_to_local(size_t global_index) const - { - return m_decomposition.node_global_to_local(global_index); - } - - size_t elem_global_to_local(size_t global_index) const - { - return m_decomposition.elem_global_to_local(global_index); - } - void build_global_to_local_elem_map() { m_decomposition.build_global_to_local_elem_map(); } void get_element_block_communication() @@ -306,5 +286,60 @@ namespace Ioex { public: Ioss::Decomposition m_decomposition; }; + + class IOEX_EXPORT ElementBlockBatchReader + { + public: + ElementBlockBatchReader(const DecompositionDataBase *decompDB); + ~ElementBlockBatchReader() = default; + + size_t get_connectivity_size(const std::vector &blocks_subset_index) const; + + std::vector get_connectivity(int filePtr, + const std::vector &blocks_subset_index, + void *data) const; + + std::vector get_offset(const std::vector &blocks_subset_index, + const std::vector &block_component_count) const; + + void get_field_data(int filePtr, void *data, const std::vector &blocks_subset_index, + size_t step, const std::vector &block_data) const; + + private: + const DecompositionDataBase *m_decompositionDB{nullptr}; + Ioss::ElementBlockBatchOffset m_batchOffset; + + template + std::vector get_connectivity_impl(int filePtr, + const std::vector &blocks_subset_index, + void *data) const; + + template + void get_field_data_impl(int filePtr, void *iossData, + const std::vector &blocks_subset_index, size_t step, + const std::vector &block_data) const; + + template + std::vector + get_connectivity_file_offset(const std::vector &blocks_subset_index) const; + + template + std::vector get_file_offset(const std::vector &blocks_subset_index, + const std::vector &block_component_count) const; + + std::vector + get_connectivity_component_count(const std::vector &blocks_subset_index) const; + + std::vector + get_block_component_count(const std::vector &blockSubsetIndex, + const std::vector &blockFieldData) const; + + template + void load_field_data(int filePtr, double *fileData, + const std::vector &blockSubsetIndex, size_t step, + const std::vector &blockFieldData, + const std::vector &blockComponentCount, + const std::vector &fileConnOffset) const; + }; } // namespace Ioex #endif diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C index efd486274e..d900548a11 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -13,7 +13,6 @@ extern "C" { #include } -#include // for assert #include // for size_t #include // for nullptr #include // for exit, EXIT_FAILURE @@ -39,6 +38,7 @@ extern "C" { #include "Ioss_Region.h" #include "Ioss_SideBlock.h" #include "Ioss_SideSet.h" +#include "Ioss_SmartAssert.h" #include "Ioss_Utils.h" #include "Ioss_VariableType.h" @@ -118,7 +118,7 @@ Assembly::Assembly(const Ioss::Assembly &other) const auto &members = other.get_members(); for (const auto &member : members) { - assert(member->property_exists("id")); + SMART_ASSERT(member->property_exists("id")); memberIdList.push_back(member->get_property("id").get_int()); } } @@ -367,8 +367,7 @@ SideSet::SideSet(const Ioss::SideSet &other) } Internals::Internals(int exoid, int maximum_name_length, const Ioss::ParallelUtils &util) - : exodusFilePtr(exoid), nodeMapVarID(), elementMapVarID(), - maximumNameLength(maximum_name_length), parallelUtil(util) + : exodusFilePtr(exoid), maximumNameLength(maximum_name_length), parallelUtil(util) { } @@ -586,11 +585,10 @@ int Internals::initialize_state_file(Mesh &mesh, const ex_var_params &var_params } } - int varid; - int dim[1]; - dim[0] = timedim; - if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, dim, - &varid)) != NC_NOERR) { + int varid; + std::array dim{timedim}; + if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, + dim.data(), &varid)) != NC_NOERR) { std::string errmsg = fmt::format( "Error: failed to define whole time step variable in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); @@ -1086,8 +1084,8 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // For use later as a consistency check, define the number of processors and // the current processor id as an attribute of the file... if (comm.outputNemesis && comm.processorCount > 1) { - int ltempsv[] = {comm.processorCount, comm.processorId}; - status = nc_put_att_int(rootid, NC_GLOBAL, "processor_info", NC_INT, 2, ltempsv); + std::array ltempsv{comm.processorCount, comm.processorId}; + status = nc_put_att_int(rootid, NC_GLOBAL, "processor_info", NC_INT, 2, ltempsv.data()); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format( @@ -1158,9 +1156,8 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) return (EX_FATAL); } - int dim[1]; - dim[0] = timedim; - if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, dim, + std::array dim{timedim}; + if ((status = nc_def_var(exodusFilePtr, VAR_WHOLE_TIME, nc_flt_code(exodusFilePtr), 1, dim.data(), &varid)) != NC_NOERR) { std::string errmsg = fmt::format( "Error: failed to define whole time step variable in file id {}", exodusFilePtr); @@ -1187,8 +1184,8 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // Define the node map here to avoid a later redefine call if (mesh.use_node_map) { - int dims1[] = {numnoddim}; - status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims1, &varid); + std::array dims1{numnoddim}; + status = nc_def_var(exodusFilePtr, VAR_NODE_NUM_MAP, map_type, 1, dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1221,8 +1218,9 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) return (EX_FATAL); } - int dims[] = {numnoddim, numattrdim}; - status = nc_def_var(exodusFilePtr, VAR_NATTRIB, nc_flt_code(exodusFilePtr), 2, dims, &varid); + std::array dims{numnoddim, numattrdim}; + status = + nc_def_var(exodusFilePtr, VAR_NATTRIB, nc_flt_code(exodusFilePtr), 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -1237,7 +1235,7 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) dims[0] = numattrdim; dims[1] = namestrdim; - status = nc_def_var(exodusFilePtr, VAR_NAME_NATTRIB, NC_CHAR, 2, dims, &varid); + status = nc_def_var(exodusFilePtr, VAR_NAME_NATTRIB, NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -1268,9 +1266,9 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // Define the element map here to avoid a later redefine call if (mesh.use_elem_map) { - int dims[] = {numelemdim}; - varid = 0; - status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numelemdim}; + varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ELEM_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1307,9 +1305,9 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // Define the face map here to avoid a later redefine call if (mesh.use_face_map) { - int dims[] = {numfacedim}; - varid = 0; - status = nc_def_var(exodusFilePtr, VAR_FACE_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numfacedim}; + varid = 0; + status = nc_def_var(exodusFilePtr, VAR_FACE_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1346,9 +1344,9 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // Define the edge map here to avoid a later redefine call if (mesh.use_edge_map) { - int dims[1] = {numedgedim}; - varid = 0; - status = nc_def_var(exodusFilePtr, VAR_EDGE_NUM_MAP, map_type, 1, dims, &varid); + std::array dims{numedgedim}; + varid = 0; + status = nc_def_var(exodusFilePtr, VAR_EDGE_NUM_MAP, map_type, 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -1506,11 +1504,11 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // dimension since the vector of global element block IDs is sized // by this quantity. { - const char *vars[] = {VAR_ELBLK_IDS_GLOBAL, VAR_ELBLK_CNT_GLOBAL, nullptr}; - const nc_type types[] = {ids_type, bulk_type}; + std::array vars{VAR_ELBLK_IDS_GLOBAL, VAR_ELBLK_CNT_GLOBAL, nullptr}; + const std::array types{ids_type, bulk_type}; status = define_variables(exodusFilePtr, static_cast(comm.globalElementBlocks), - DIM_NUM_ELBLK_GLOBAL, vars, types); + DIM_NUM_ELBLK_GLOBAL, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } @@ -1520,12 +1518,12 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // dimension since the vector of global element block IDs is sized // by this quantity. { - const char *vars[] = {VAR_NS_IDS_GLOBAL, VAR_NS_NODE_CNT_GLOBAL, VAR_NS_DF_CNT_GLOBAL, - nullptr}; - const nc_type types[] = {ids_type, bulk_type, bulk_type}; + std::array vars{VAR_NS_IDS_GLOBAL, VAR_NS_NODE_CNT_GLOBAL, + VAR_NS_DF_CNT_GLOBAL, nullptr}; + const std::array types{ids_type, bulk_type, bulk_type}; status = define_variables(exodusFilePtr, static_cast(comm.globalNodeSets), - DIM_NUM_NS_GLOBAL, vars, types); + DIM_NUM_NS_GLOBAL, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } @@ -1535,12 +1533,12 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) // dimension since the vector of global element block IDs is sized // by this quantity. { - const char *vars[] = {VAR_SS_IDS_GLOBAL, VAR_SS_SIDE_CNT_GLOBAL, VAR_SS_DF_CNT_GLOBAL, - nullptr}; - const nc_type types[] = {ids_type, bulk_type, bulk_type}; + std::array vars{VAR_SS_IDS_GLOBAL, VAR_SS_SIDE_CNT_GLOBAL, + VAR_SS_DF_CNT_GLOBAL, nullptr}; + const std::array types{ids_type, bulk_type, bulk_type}; status = define_variables(exodusFilePtr, static_cast(comm.globalSideSets), - DIM_NUM_SS_GLOBAL, vars, types); + DIM_NUM_SS_GLOBAL, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } @@ -1627,21 +1625,22 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) } { - const char *vars[] = {VAR_N_COMM_IDS, VAR_N_COMM_STAT, VAR_N_COMM_DATA_IDX, nullptr}; - const nc_type types[] = {ids_type, NC_INT, bulk_type}; + std::array vars{VAR_N_COMM_IDS, VAR_N_COMM_STAT, VAR_N_COMM_DATA_IDX, + nullptr}; + const std::array types{ids_type, NC_INT, bulk_type}; status = define_variables(exodusFilePtr, static_cast(comm.nodeMap.size()), - DIM_NUM_N_CMAPS, vars, types); + DIM_NUM_N_CMAPS, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } } { - const char *vars[] = {VAR_N_COMM_NIDS, VAR_N_COMM_PROC, nullptr}; - const nc_type types[] = {ids_type, NC_INT}; + std::array vars{VAR_N_COMM_NIDS, VAR_N_COMM_PROC, nullptr}; + const std::array types{ids_type, NC_INT}; // Add dimensions for all of the nodal communication maps - status = define_variables(exodusFilePtr, ncnt_cmap, DIM_NCNT_CMAP, vars, types); + status = define_variables(exodusFilePtr, ncnt_cmap, DIM_NCNT_CMAP, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } @@ -1655,19 +1654,22 @@ int Internals::put_metadata(const Mesh &mesh, const CommunicationMetaData &comm) if (mesh.full_nemesis_data) { { - const char *vars[] = {VAR_E_COMM_IDS, VAR_E_COMM_STAT, VAR_E_COMM_DATA_IDX, nullptr}; - const nc_type types[] = {ids_type, NC_INT, bulk_type}; + std::array vars{VAR_E_COMM_IDS, VAR_E_COMM_STAT, VAR_E_COMM_DATA_IDX, + nullptr}; + const std::array types{ids_type, NC_INT, bulk_type}; status = define_variables(exodusFilePtr, static_cast(comm.elementMap.size()), - DIM_NUM_E_CMAPS, vars, types); + DIM_NUM_E_CMAPS, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } } { - const char *vars[] = {VAR_E_COMM_EIDS, VAR_E_COMM_PROC, VAR_E_COMM_SIDS, nullptr}; - const nc_type types[] = {ids_type, NC_INT, bulk_type}; - status = define_variables(exodusFilePtr, ecnt_cmap, DIM_ECNT_CMAP, vars, types); + std::array vars{VAR_E_COMM_EIDS, VAR_E_COMM_PROC, VAR_E_COMM_SIDS, + nullptr}; + const std::array types{ids_type, NC_INT, bulk_type}; + status = + define_variables(exodusFilePtr, ecnt_cmap, DIM_ECNT_CMAP, vars.data(), types.data()); if (status != EX_NOERR) { return (EX_FATAL); } @@ -1709,10 +1711,10 @@ int Internals::put_metadata(const std::vector &assemblies) } /* create variable array in which to store the entry lists */ - int entlst_id; - int dims[1] = {dimid}; - if ((status = nc_def_var(exodusFilePtr, VAR_ENTITY_ASSEMBLY(assembly.id), int_type, 1, dims, - &entlst_id)) != NC_NOERR) { + int entlst_id; + std::array dims{dimid}; + if ((status = nc_def_var(exodusFilePtr, VAR_ENTITY_ASSEMBLY(assembly.id), int_type, 1, + dims.data(), &entlst_id)) != NC_NOERR) { std::string errmsg = fmt::format( "Error: failed to define entity assembly variable in file id {}", exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); @@ -1811,10 +1813,10 @@ int Internals::put_metadata(const std::vector &blobs) // create a variable just as a way to have a blob and its attributes; values not used for // anything - int dims[] = {n1dim}; - int entlst; - if ((status = nc_def_var(exodusFilePtr, VAR_ENTITY_BLOB(blob.id), NC_INT, 1, dims, &entlst)) != - NC_NOERR) { + std::array dims{n1dim}; + int entlst; + if ((status = nc_def_var(exodusFilePtr, VAR_ENTITY_BLOB(blob.id), NC_INT, 1, dims.data(), + &entlst)) != NC_NOERR) { std::string errmsg = fmt::format("Error: failed to create entity for blob {} in file id {}", blob.id, exodusFilePtr); ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); @@ -1889,7 +1891,7 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl return (EX_FATAL); } - assert(blocks.size() == num_elem_blk); + SMART_ASSERT(blocks.size() == num_elem_blk); // Iterate over blocks ... for (size_t iblk = 0; iblk < num_elem_blk; iblk++) { @@ -1939,9 +1941,9 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl // element connectivity array { - int dims[] = {numelbdim, nelnoddim}; - int connid = 0; - status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims, &connid); + std::array dims{numelbdim, nelnoddim}; + int connid = 0; + status = nc_def_var(exodusFilePtr, VAR_CONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format("Error: failed to create connectivity array for block {}" @@ -1981,10 +1983,10 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl } // element->edge connectivity array - int dims[] = {numelbdim, neledgdim}; + std::array dims{numelbdim, neledgdim}; int connid = 0; - status = nc_def_var(exodusFilePtr, VAR_ECONN(iblk + 1), bulk_type, 2, dims, &connid); + status = nc_def_var(exodusFilePtr, VAR_ECONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2012,10 +2014,10 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl } // element->face connectivity array - int dims[] = {numelbdim, nelfacdim}; + std::array dims{numelbdim, nelfacdim}; int connid = 0; - status = nc_def_var(exodusFilePtr, VAR_FCONN(iblk + 1), bulk_type, 2, dims, &connid); + status = nc_def_var(exodusFilePtr, VAR_FCONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2043,10 +2045,10 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl } { - int dims[] = {numelbdim, numattrdim}; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, - dims, &varid); + std::array dims{numelbdim, numattrdim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2074,9 +2076,10 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl { // Attribute name array... - int dims[] = {numattrdim, namestrdim}; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, dims, &varid); + std::array dims{numattrdim, namestrdim}; + int varid = 0; + status = + nc_def_var(exodusFilePtr, VAR_NAME_ATTRIB(iblk + 1), NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2133,7 +2136,7 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl return (EX_FATAL); } - assert(blocks.size() == num_face_blk); + SMART_ASSERT(blocks.size() == num_face_blk); // Iterate over blocks ... for (size_t iblk = 0; iblk < num_face_blk; iblk++) { @@ -2195,10 +2198,10 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl } { - int dims[] = {numelbdim, numattrdim}; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_FATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, - dims, &varid); + std::array dims{numelbdim, numattrdim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_FATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2211,10 +2214,11 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl } { // Attribute name array... - int dims[] = {numattrdim, namestrdim}; - int varid = 0; + std::array dims{numattrdim, namestrdim}; + int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_NAME_FATTRIB(iblk + 1), NC_CHAR, 2, dims, &varid); + status = + nc_def_var(exodusFilePtr, VAR_NAME_FATTRIB(iblk + 1), NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2230,9 +2234,9 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl { // face connectivity array - int dims[] = {numelbdim, nelnoddim}; - int connid = 0; - status = nc_def_var(exodusFilePtr, VAR_FBCONN(iblk + 1), bulk_type, 2, dims, &connid); + std::array dims{numelbdim, nelnoddim}; + int connid = 0; + status = nc_def_var(exodusFilePtr, VAR_FBCONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2296,7 +2300,7 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl return (EX_FATAL); } - assert(blocks.size() == num_edge_blk); + SMART_ASSERT(blocks.size() == num_edge_blk); // Iterate over blocks ... for (size_t iblk = 0; iblk < num_edge_blk; iblk++) { @@ -2358,10 +2362,10 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl return (EX_FATAL); } - int dims[] = {numelbdim, numattrdim}; - int varid = 0; - status = nc_def_var(exodusFilePtr, VAR_EATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, dims, - &varid); + std::array dims{numelbdim, numattrdim}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_EATTRIB(iblk + 1), nc_flt_code(exodusFilePtr), 2, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2376,7 +2380,8 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl dims[0] = numattrdim; dims[1] = namestrdim; - status = nc_def_var(exodusFilePtr, VAR_NAME_EATTRIB(iblk + 1), NC_CHAR, 2, dims, &varid); + status = + nc_def_var(exodusFilePtr, VAR_NAME_EATTRIB(iblk + 1), NC_CHAR, 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2390,11 +2395,11 @@ int Internals::put_metadata(const std::vector &blocks, bool count_onl } // edge connectivity array - int dims[] = {numelbdim, nelnoddim}; + std::array dims{numelbdim, nelnoddim}; int connid = 0; int bulk_type = get_type(exodusFilePtr, EX_BULK_INT64_DB); - status = nc_def_var(exodusFilePtr, VAR_EBCONN(iblk + 1), bulk_type, 2, dims, &connid); + status = nc_def_var(exodusFilePtr, VAR_EBCONN(iblk + 1), bulk_type, 2, dims.data(), &connid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2447,12 +2452,9 @@ int Internals::put_non_define_data(const CommunicationMetaData &comm, bool full_ return (EX_FATAL); } - int nmstat; - size_t start[1]; - if (full_nemesis_data) { - nmstat = comm.nodesInternal == 0 ? 0 : 1; - status = nc_put_var_int(exodusFilePtr, nodeMapVarID[0], &nmstat); + int nmstat = comm.nodesInternal == 0 ? 0 : 1; + status = nc_put_var_int(exodusFilePtr, nodeMapVarID[0], &nmstat); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format( @@ -2522,9 +2524,9 @@ int Internals::put_non_define_data(const CommunicationMetaData &comm, bool full_ long long nl_ncnt_cmap = 0; for (size_t icm = 0; icm < comm.nodeMap.size(); icm++) { - start[0] = icm; - nmstat = comm.nodeMap[icm].entityCount > 0 ? 1 : 0; - status = nc_put_var1_int(exodusFilePtr, n_varid, start, &nmstat); + std::array start{icm}; + int nmstat = comm.nodeMap[icm].entityCount > 0 ? 1 : 0; + status = nc_put_var1_int(exodusFilePtr, n_varid, start.data(), &nmstat); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2545,7 +2547,7 @@ int Internals::put_non_define_data(const CommunicationMetaData &comm, bool full_ ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return (EX_FATAL); } - status = nc_put_var1_longlong(exodusFilePtr, commIndexVar, start, &nl_ncnt_cmap); + status = nc_put_var1_longlong(exodusFilePtr, commIndexVar, start.data(), &nl_ncnt_cmap); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); @@ -2588,10 +2590,10 @@ int Internals::put_non_define_data(const CommunicationMetaData &comm, bool full_ long long nl_ecnt_cmap = 0; // reset this for index for (size_t icm = 0; icm < comm.elementMap.size(); icm++) { - start[0] = icm; - nmstat = comm.elementMap[icm].entityCount > 0 ? 1 : 0; + std::array start{icm}; + auto nmstat = comm.elementMap[icm].entityCount > 0 ? 1 : 0; - status = nc_put_var1_int(exodusFilePtr, e_varid, start, &nmstat); + status = nc_put_var1_int(exodusFilePtr, e_varid, start.data(), &nmstat); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -2612,7 +2614,7 @@ int Internals::put_non_define_data(const CommunicationMetaData &comm, bool full_ ex_err_fn(exodusFilePtr, __func__, errmsg.c_str(), status); return (EX_FATAL); } - status = nc_put_var1_longlong(exodusFilePtr, elemCommIndexVar, start, &nl_ecnt_cmap); + status = nc_put_var1_longlong(exodusFilePtr, elemCommIndexVar, start.data(), &nl_ecnt_cmap); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format( @@ -2697,7 +2699,7 @@ int Internals::put_non_define_data(const std::vector &assemblies) int Internals::put_non_define_data(const std::vector &blocks, bool output_global_data) { - int num_elem_blk = static_cast(blocks.size()); // Verified via assert earlier... + int num_elem_blk = static_cast(blocks.size()); // Verified via SMART_ASSERT earlier... if (num_elem_blk > 0) { // first get id of element block ids array variable @@ -2734,12 +2736,10 @@ int Internals::put_non_define_data(const std::vector &blocks, bool ou return (EX_FATAL); } - size_t start[2]; - size_t count[2]; - std::string text; - count[0] = 1; - start[1] = 0; - count[1] = text.size() + 1; + // TODO: Is this code correct? `text` is never set... + std::string text; + std::array start{0, 0}; + std::array count{1, text.size() + 1}; for (int iblk = 0; iblk < num_elem_blk; iblk++) { if (blocks[iblk].attributeCount > 0 && blocks[iblk].entityCount > 0) { @@ -2755,7 +2755,7 @@ int Internals::put_non_define_data(const std::vector &blocks, bool ou for (int i = 0; i < blocks[iblk].attributeCount; i++) { start[0] = i; - nc_put_vara_text(exodusFilePtr, varid, start, count, text.c_str()); + nc_put_vara_text(exodusFilePtr, varid, start.data(), count.data(), text.c_str()); } } } @@ -2765,7 +2765,7 @@ int Internals::put_non_define_data(const std::vector &blocks, bool ou int Internals::put_non_define_data(const std::vector &blocks) { - int num_face_blk = static_cast(blocks.size()); // Verified via assert earlier... + int num_face_blk = static_cast(blocks.size()); // Verified via SMART_ASSERT earlier... if (num_face_blk > 0) { // first get id of face block ids array variable @@ -2788,12 +2788,10 @@ int Internals::put_non_define_data(const std::vector &blocks) return (EX_FATAL); } - size_t start[2]; - size_t count[2]; - std::string text; - count[0] = 1; - start[1] = 0; - count[1] = text.size() + 1; + // TODO: Is this code correct? `text` is never set... + std::string text; + std::array start{0, 0}; + std::array count{1, text.size() + 1}; for (int iblk = 0; iblk < num_face_blk; iblk++) { if (blocks[iblk].attributeCount > 0 && blocks[iblk].entityCount > 0) { @@ -2809,7 +2807,7 @@ int Internals::put_non_define_data(const std::vector &blocks) for (int i = 0; i < blocks[iblk].attributeCount; i++) { start[0] = i; - nc_put_vara_text(exodusFilePtr, varid, start, count, text.c_str()); + nc_put_vara_text(exodusFilePtr, varid, start.data(), count.data(), text.c_str()); } } } @@ -2819,7 +2817,7 @@ int Internals::put_non_define_data(const std::vector &blocks) int Internals::put_non_define_data(const std::vector &blocks) { - int num_edge_blk = static_cast(blocks.size()); // Verified via assert earlier... + int num_edge_blk = static_cast(blocks.size()); // Verified via SMART_ASSERT earlier... if (num_edge_blk > 0) { // first get id of edge block ids array variable @@ -2842,13 +2840,10 @@ int Internals::put_non_define_data(const std::vector &blocks) return (EX_FATAL); } - size_t start[2]; - size_t count[2]; - std::string text; - count[0] = 1; - start[1] = 0; - count[1] = text.size() + 1; - + // TODO: Is this code correct? `text` is never set... + std::string text; + std::array start{0, 0}; + std::array count{1, text.size() + 1}; for (int iblk = 0; iblk < num_edge_blk; iblk++) { if (blocks[iblk].attributeCount > 0 && blocks[iblk].entityCount > 0) { int varid; @@ -2864,7 +2859,7 @@ int Internals::put_non_define_data(const std::vector &blocks) for (int i = 0; i < blocks[iblk].attributeCount; i++) { start[0] = i; - nc_put_vara_text(exodusFilePtr, varid, start, count, text.c_str()); + nc_put_vara_text(exodusFilePtr, varid, start.data(), count.data(), text.c_str()); } } } @@ -2912,7 +2907,7 @@ int Internals::put_metadata(const std::vector &nodesets, bool count_onl return (EX_FATAL); } - assert(static_cast(nodesets.size()) == num_node_sets); + SMART_ASSERT(static_cast(nodesets.size()) == num_node_sets); for (int i = 0; i < num_node_sets; i++) { @@ -2946,10 +2941,10 @@ int Internals::put_metadata(const std::vector &nodesets, bool count_onl } // define variable to store node set node list here instead of in expns - int dims1[1] = {dimid}; - int varid; - status = - nc_def_var(exodusFilePtr, VAR_NODE_NS(cur_num_node_sets + 1), bulk_type, 1, dims1, &varid); + std::array dims1{dimid}; + int varid; + status = nc_def_var(exodusFilePtr, VAR_NODE_NS(cur_num_node_sets + 1), bulk_type, 1, + dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -2983,7 +2978,7 @@ int Internals::put_metadata(const std::vector &nodesets, bool count_onl } // create variable for distribution factors status = nc_def_var(exodusFilePtr, VAR_FACT_NS(cur_num_node_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims1, &varid); + nc_flt_code(exodusFilePtr), 1, dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3018,9 +3013,9 @@ int Internals::put_metadata(const std::vector &nodesets, bool count_onl } { - int dims[] = {dimid, numattrdim}; - status = nc_def_var(exodusFilePtr, VAR_NSATTRIB(cur_num_node_sets + 1), - nc_flt_code(exodusFilePtr), 2, dims, &varid); + std::array dims{dimid, numattrdim}; + status = nc_def_var(exodusFilePtr, VAR_NSATTRIB(cur_num_node_sets + 1), + nc_flt_code(exodusFilePtr), 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3035,10 +3030,10 @@ int Internals::put_metadata(const std::vector &nodesets, bool count_onl { // Attribute name array... - int dims[] = {numattrdim, namestrdim}; + std::array dims{numattrdim, namestrdim}; status = nc_def_var(exodusFilePtr, VAR_NAME_NSATTRIB(cur_num_node_sets + 1), NC_CHAR, 2, - dims, &varid); + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3084,7 +3079,7 @@ int Internals::put_metadata(const std::vector &edgesets, bool count_onl // inquire how many edge sets are to be stored num_edge_sets = ex_inquire_int(exodusFilePtr, EX_INQ_EDGE_SETS); - assert(static_cast(edgesets.size()) == num_edge_sets); + SMART_ASSERT(static_cast(edgesets.size()) == num_edge_sets); int namestrdim; status = nc_inq_dimid(exodusFilePtr, DIM_STR_NAME, &namestrdim); @@ -3128,10 +3123,10 @@ int Internals::put_metadata(const std::vector &edgesets, bool count_onl } // define variable to store edge set edge list here instead of in expns - int dims1[1] = {dimid}; - int varid; - status = - nc_def_var(exodusFilePtr, VAR_EDGE_ES(cur_num_edge_sets + 1), bulk_type, 1, dims1, &varid); + std::array dims1{dimid}; + int varid; + status = nc_def_var(exodusFilePtr, VAR_EDGE_ES(cur_num_edge_sets + 1), bulk_type, 1, + dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3151,8 +3146,8 @@ int Internals::put_metadata(const std::vector &edgesets, bool count_onl ex__compress_variable(exodusFilePtr, varid, 1); // Orientation variable - status = - nc_def_var(exodusFilePtr, VAR_ORNT_ES(cur_num_edge_sets + 1), bulk_type, 1, dims1, &varid); + status = nc_def_var(exodusFilePtr, VAR_ORNT_ES(cur_num_edge_sets + 1), bulk_type, 1, + dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3186,7 +3181,7 @@ int Internals::put_metadata(const std::vector &edgesets, bool count_onl } // create variable for distribution factors status = nc_def_var(exodusFilePtr, VAR_FACT_ES(cur_num_edge_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims1, &varid); + nc_flt_code(exodusFilePtr), 1, dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3220,9 +3215,9 @@ int Internals::put_metadata(const std::vector &edgesets, bool count_onl } { - int dims[] = {dimid, numattrdim}; - status = nc_def_var(exodusFilePtr, VAR_ESATTRIB(cur_num_edge_sets + 1), - nc_flt_code(exodusFilePtr), 2, dims, &varid); + std::array dims{dimid, numattrdim}; + status = nc_def_var(exodusFilePtr, VAR_ESATTRIB(cur_num_edge_sets + 1), + nc_flt_code(exodusFilePtr), 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3237,10 +3232,10 @@ int Internals::put_metadata(const std::vector &edgesets, bool count_onl { // Attribute name array... - int dims[] = {numattrdim, namestrdim}; + std::array dims{numattrdim, namestrdim}; status = nc_def_var(exodusFilePtr, VAR_NAME_ESATTRIB(cur_num_edge_sets + 1), NC_CHAR, 2, - dims, &varid); + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3286,7 +3281,7 @@ int Internals::put_metadata(const std::vector &facesets, bool count_onl // inquire how many face sets are to be stored num_face_sets = ex_inquire_int(exodusFilePtr, EX_INQ_FACE_SETS); - assert(static_cast(facesets.size()) == num_face_sets); + SMART_ASSERT(static_cast(facesets.size()) == num_face_sets); int namestrdim; status = nc_inq_dimid(exodusFilePtr, DIM_STR_NAME, &namestrdim); @@ -3330,10 +3325,10 @@ int Internals::put_metadata(const std::vector &facesets, bool count_onl } // define variable to store face set face list here instead of in expns - int dims1[1] = {dimid}; - int varid; - status = - nc_def_var(exodusFilePtr, VAR_FACE_FS(cur_num_face_sets + 1), bulk_type, 1, dims1, &varid); + std::array dims1{dimid}; + int varid; + status = nc_def_var(exodusFilePtr, VAR_FACE_FS(cur_num_face_sets + 1), bulk_type, 1, + dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3353,8 +3348,8 @@ int Internals::put_metadata(const std::vector &facesets, bool count_onl ex__compress_variable(exodusFilePtr, varid, 1); // Orientation variable - status = - nc_def_var(exodusFilePtr, VAR_ORNT_FS(cur_num_face_sets + 1), bulk_type, 1, dims1, &varid); + status = nc_def_var(exodusFilePtr, VAR_ORNT_FS(cur_num_face_sets + 1), bulk_type, 1, + dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3388,7 +3383,7 @@ int Internals::put_metadata(const std::vector &facesets, bool count_onl } // create variable for distribution factors status = nc_def_var(exodusFilePtr, VAR_FACT_FS(cur_num_face_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims1, &varid); + nc_flt_code(exodusFilePtr), 1, dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3422,9 +3417,9 @@ int Internals::put_metadata(const std::vector &facesets, bool count_onl } { - int dims[] = {dimid, numattrdim}; - status = nc_def_var(exodusFilePtr, VAR_FSATTRIB(cur_num_face_sets + 1), - nc_flt_code(exodusFilePtr), 2, dims, &varid); + std::array dims{dimid, numattrdim}; + status = nc_def_var(exodusFilePtr, VAR_FSATTRIB(cur_num_face_sets + 1), + nc_flt_code(exodusFilePtr), 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3439,10 +3434,10 @@ int Internals::put_metadata(const std::vector &facesets, bool count_onl { // Attribute name array... - int dims[] = {numattrdim, namestrdim}; + std::array dims{numattrdim, namestrdim}; status = nc_def_var(exodusFilePtr, VAR_NAME_FSATTRIB(cur_num_face_sets + 1), NC_CHAR, 2, - dims, &varid); + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3487,7 +3482,7 @@ int Internals::put_metadata(const std::vector &elemsets, bool count_onl // inquire how many element sets are to be stored num_elem_sets = ex_inquire_int(exodusFilePtr, EX_INQ_ELEM_SETS); - assert(static_cast(elemsets.size()) == num_elem_sets); + SMART_ASSERT(static_cast(elemsets.size()) == num_elem_sets); int namestrdim; status = nc_inq_dimid(exodusFilePtr, DIM_STR_NAME, &namestrdim); @@ -3531,10 +3526,10 @@ int Internals::put_metadata(const std::vector &elemsets, bool count_onl } // define variable to store element set element list here instead of in expns - int dims1[1] = {dimid}; - int varid; + std::array dims1{dimid}; + int varid; status = nc_def_var(exodusFilePtr, VAR_ELEM_ELS(cur_num_elem_sets + 1), - get_type(exodusFilePtr, EX_BULK_INT64_DB), 1, dims1, &varid); + get_type(exodusFilePtr, EX_BULK_INT64_DB), 1, dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); @@ -3569,7 +3564,7 @@ int Internals::put_metadata(const std::vector &elemsets, bool count_onl } // create variable for distribution factors status = nc_def_var(exodusFilePtr, VAR_FACT_ELS(cur_num_elem_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims1, &varid); + nc_flt_code(exodusFilePtr), 1, dims1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3603,9 +3598,9 @@ int Internals::put_metadata(const std::vector &elemsets, bool count_onl } { - int dims[] = {dimid, numattrdim}; - status = nc_def_var(exodusFilePtr, VAR_ESATTRIB(cur_num_elem_sets + 1), - nc_flt_code(exodusFilePtr), 2, dims, &varid); + std::array dims{dimid, numattrdim}; + status = nc_def_var(exodusFilePtr, VAR_ESATTRIB(cur_num_elem_sets + 1), + nc_flt_code(exodusFilePtr), 2, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3620,10 +3615,10 @@ int Internals::put_metadata(const std::vector &elemsets, bool count_onl { // Attribute name array... - int dims[] = {numattrdim, namestrdim}; + std::array dims{numattrdim, namestrdim}; status = nc_def_var(exodusFilePtr, VAR_NAME_ESATTRIB(cur_num_elem_sets + 1), NC_CHAR, 2, - dims, &varid); + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -3803,7 +3798,7 @@ int Internals::put_metadata(const std::vector &sidesets, bool count_onl // inquire how many side sets are to be stored num_side_sets = ex_inquire_int(exodusFilePtr, EX_INQ_SIDE_SETS); - assert(static_cast(sidesets.size()) == num_side_sets); + SMART_ASSERT(static_cast(sidesets.size()) == num_side_sets); for (int i = 0; i < num_side_sets; i++) { @@ -3836,10 +3831,10 @@ int Internals::put_metadata(const std::vector &sidesets, bool count_onl continue; } - int dims[1] = {dimid}; - int varid = 0; - status = - nc_def_var(exodusFilePtr, VAR_ELEM_SS(cur_num_side_sets + 1), bulk_type, 1, dims, &varid); + std::array dims{dimid}; + int varid = 0; + status = nc_def_var(exodusFilePtr, VAR_ELEM_SS(cur_num_side_sets + 1), bulk_type, 1, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3859,8 +3854,8 @@ int Internals::put_metadata(const std::vector &sidesets, bool count_onl ex__compress_variable(exodusFilePtr, varid, 1); // create side list variable for side set - status = - nc_def_var(exodusFilePtr, VAR_SIDE_SS(cur_num_side_sets + 1), bulk_type, 1, dims, &varid); + status = nc_def_var(exodusFilePtr, VAR_SIDE_SS(cur_num_side_sets + 1), bulk_type, 1, + dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -3903,7 +3898,7 @@ int Internals::put_metadata(const std::vector &sidesets, bool count_onl // create distribution factor list variable for side set dims[0] = dimid; status = nc_def_var(exodusFilePtr, VAR_FACT_SS(cur_num_side_sets + 1), - nc_flt_code(exodusFilePtr), 1, dims, &varid); + nc_flt_code(exodusFilePtr), 1, dims.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); if (status == NC_ENAMEINUSE) { @@ -4016,11 +4011,10 @@ namespace { int define_variable(int exodusFilePtr, int64_t size, const char *dim, const char *var, nc_type type) { - int dimid[1]; - int varid; if (size > 0) { - int status = nc_def_dim(exodusFilePtr, dim, size, &dimid[0]); + std::array dimid; + int status = nc_def_dim(exodusFilePtr, dim, size, &dimid[0]); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format("Error: failed to dimension \"{}\" in file id {}", @@ -4029,7 +4023,8 @@ namespace { return (EX_FATAL); } - status = nc_def_var(exodusFilePtr, var, type, 1, dimid, &varid); + int varid; + status = nc_def_var(exodusFilePtr, var, type, 1, dimid.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format("Error: failed to define variable \"{}\" in file ID {}", @@ -4045,11 +4040,9 @@ namespace { int define_variables(int exodusFilePtr, int64_t size, const char *dim, const char *var[], const nc_type *types) { - int dimid[1]; - int varid; - if (size > 0) { - int status = nc_def_dim(exodusFilePtr, dim, size, &dimid[0]); + std::array dimid; + int status = nc_def_dim(exodusFilePtr, dim, size, &dimid[0]); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format("Error: failed to dimension \"{}\" in file id {}", @@ -4060,7 +4053,8 @@ namespace { int i = 0; while (var[i] != nullptr) { - status = nc_def_var(exodusFilePtr, var[i], types[i], 1, dimid, &varid); + int varid; + status = nc_def_var(exodusFilePtr, var[i], types[i], 1, dimid.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format("Error: failed to define variable \"{}\" in file ID {}", @@ -4078,7 +4072,6 @@ namespace { int put_int_array(int exoid, const char *var_type, const std::vector &array) { int var_id; - int status = nc_inq_varid(exoid, var_type, &var_id); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); @@ -4101,7 +4094,6 @@ namespace { int put_int_array(int exoid, const char *var_type, const std::vector &array) { int var_id; - int status = nc_inq_varid(exoid, var_type, &var_id); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); @@ -4124,7 +4116,6 @@ namespace { int put_id_array(int exoid, const char *var_type, const std::vector &ids) { int var_id; - int status = nc_inq_varid(exoid, var_type, &var_id); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); @@ -4169,10 +4160,10 @@ namespace { if (nodes > 0) { // node coordinate arrays -- separate storage... - int dim[] = {node_dim}; + std::array dim{node_dim}; if (dimension > 0) { - int status = - nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, dim, &varid); + int status = nc_def_var(exodusFilePtr, VAR_COORD_X, nc_flt_code(exodusFilePtr), 1, + dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format( @@ -4184,8 +4175,8 @@ namespace { } if (dimension > 1) { - int status = - nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, dim, &varid); + int status = nc_def_var(exodusFilePtr, VAR_COORD_Y, nc_flt_code(exodusFilePtr), 1, + dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format( @@ -4197,8 +4188,8 @@ namespace { } if (dimension > 2) { - int status = - nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, dim, &varid); + int status = nc_def_var(exodusFilePtr, VAR_COORD_Z, nc_flt_code(exodusFilePtr), 1, + dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = fmt::format( @@ -4211,9 +4202,9 @@ namespace { } // coordinate names array - int dim[] = {dim_dim, str_dim}; + std::array dim{dim_dim, str_dim}; - int status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dim, &varid); + int status = nc_def_var(exodusFilePtr, VAR_NAME_COOR, NC_CHAR, 2, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -4254,8 +4245,8 @@ namespace { } // id status array: - int dim1[] = {dimid}; - status = nc_def_var(exoid, stat_var, NC_INT, 1, dim1, &varid); + std::array dim1{dimid}; + status = nc_def_var(exoid, stat_var, NC_INT, 1, dim1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -4270,7 +4261,7 @@ namespace { // id array: int ids_type = get_type(exoid, EX_IDS_INT64_DB); int ids_size = ids_type == NC_INT ? 4 : 8; - status = nc_def_var(exoid, id_var, ids_type, 1, dim1, &varid); + status = nc_def_var(exoid, id_var, ids_type, 1, dim1.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = @@ -4293,8 +4284,8 @@ namespace { } if (name_var != nullptr) { - int dim[] = {dimid, namestrdim}; - status = nc_def_var(exoid, name_var, NC_CHAR, 2, dim, &varid); + std::array dim{dimid, namestrdim}; + status = nc_def_var(exoid, name_var, NC_CHAR, 2, dim.data(), &varid); if (status != NC_NOERR) { ex_opts(EX_VERBOSE); std::string errmsg = diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h index 01a87979a6..cd6671fd22 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Internals.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -409,8 +409,8 @@ namespace Ioex { int max_name_length() const { return maximumNameLength; } int exodusFilePtr{0}; - int nodeMapVarID[3]; - int elementMapVarID[2]; + int nodeMapVarID[3]{}; + int elementMapVarID[2]{}; int commIndexVar{0}; int elemCommIndexVar{0}; int maximumNameLength{32}; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C index 4e7891bf03..b2519351c5 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C @@ -309,18 +309,31 @@ namespace { } template - std::vector get_all_block_field_component_count(const std::string &field_name, - const std::vector &entity_container) + std::vector get_block_to_decomp_map(const std::vector &entity_container) + { + std::vector block_to_decomp(entity_container.size(), 0); + + for (size_t i = 0; i < entity_container.size(); ++i) { + T *entity = entity_container[i]; + block_to_decomp[i] = entity->get_property("iblk").get_int(); + } + + return block_to_decomp; + } + + template + std::vector get_entity_field_component_count(const std::string &field_name, + const std::vector &entity_container) { size_t num_blocks = entity_container.size(); std::vector block_field_component_count(num_blocks, 0); - for (T *entity : entity_container) { + for (size_t i = 0; i < num_blocks; ++i) { + T *entity = entity_container[i]; if (entity->field_exists(field_name)) { - int iblk = entity->get_property("iblk").get_int(); - Ioss::Field field = entity->get_field(field_name); - block_field_component_count[iblk] = field.raw_storage()->component_count(); + Ioss::Field field = entity->get_field(field_name); + block_field_component_count[i] = field.raw_storage()->component_count(); } } @@ -328,8 +341,8 @@ namespace { } template - size_t get_all_block_field_data_size(const std::string &field_name, - const std::vector &entity_container) + size_t get_entity_field_data_size(const std::string &field_name, + const std::vector &entity_container) { size_t total_data_size = 0; for (T *entity : entity_container) { @@ -858,7 +871,7 @@ namespace Ioex { char *qa_record[1][4]; }; - auto qa = new qa_element[num_qa]; + std::vector qa(num_qa); for (int i = 0; i < num_qa; i++) { for (int j = 0; j < 4; j++) { qa[i].qa_record[0][j] = new char[MAX_STR_LENGTH + 1]; @@ -875,7 +888,6 @@ namespace Ioex { delete[] qa[i].qa_record[0][j]; } } - delete[] qa; } // Get information records from database and add to informationRecords... @@ -4962,11 +4974,15 @@ namespace Ioex { } } - std::vector ParallelDatabaseIO::get_all_block_connectivity(const std::string &field_name, - void *data, - size_t data_size) const + std::vector ParallelDatabaseIO::get_entity_connectivity_field_data( + const std::string &field_name, const std::vector &elem_blocks, + void *data, size_t data_size) const { - size_t num_to_get = decomp->get_all_block_connectivity_size(); + std::vector block_to_decomp = get_block_to_decomp_map(elem_blocks); + + ElementBlockBatchReader batchReader(decomp.get()); + + size_t num_to_get = batchReader.get_connectivity_size(block_to_decomp); size_t expected_data_size = num_to_get * decomp->int_size(); if (data_size < expected_data_size) { @@ -4977,7 +4993,8 @@ namespace Ioex { IOSS_ERROR(errmsg); } - std::vector offsets = decomp->get_all_block_connectivity(get_file_pointer(), data); + std::vector offsets = + batchReader.get_connectivity(get_file_pointer(), block_to_decomp, data); if (field_name == "connectivity") { Ioss::Field::BasicType type = @@ -4988,22 +5005,19 @@ namespace Ioex { return offsets; } - std::vector ParallelDatabaseIO::get_all_block_transient_field_data( - const Ioex::VariableNameMap &variables, const std::string &field_name, void *data) const + template + std::vector + ParallelDatabaseIO::get_entity_block_field_data(const Ioex::VariableNameMap &variables, + const std::string &field_name, + const std::vector &entity_container) const { - const Ioss::ElementBlockContainer &elem_blocks = get_region()->get_element_blocks(); - std::vector block_field_component_count = - get_all_block_field_component_count(field_name, elem_blocks); - std::vector ioss_offset = decomp->get_all_block_offset(block_field_component_count); - - size_t num_blocks = elem_blocks.size(); + size_t num_blocks = entity_container.size(); - std::vector block_data(num_blocks); + std::vector block_data(num_blocks); - for (size_t i = 0; i < num_blocks; i++) { - Ioss::ElementBlock *entity = elem_blocks[i]; - int iblk = entity->get_property("iblk").get_int(); - block_data[iblk].id = Ioex::get_id(entity, &ids_); + for (size_t iblk = 0; iblk < num_blocks; ++iblk) { + T *entity = entity_container[iblk]; + block_data[iblk].id = Ioex::get_id(entity, &ids_); if (entity->field_exists(field_name)) { Ioss::Field field = entity->get_field(field_name); @@ -5033,16 +5047,37 @@ namespace Ioex { } } + return block_data; + } + + std::vector ParallelDatabaseIO::get_entity_transient_field_data( + const Ioex::VariableNameMap &variables, const std::string &field_name, + const std::vector &elem_blocks, void *data) const + { + std::vector block_to_decomp = get_block_to_decomp_map(elem_blocks); + + ElementBlockBatchReader batchReader(decomp.get()); + + std::vector block_field_component_count = + get_entity_field_component_count(field_name, elem_blocks); + std::vector ioss_offset = + batchReader.get_offset(block_to_decomp, block_field_component_count); + + size_t num_blocks = elem_blocks.size(); + + std::vector block_data = + get_entity_block_field_data(variables, field_name, elem_blocks); + std::vector temp(ioss_offset[num_blocks]); - decomp->get_all_block_field(get_file_pointer(), temp.data(), get_current_state(), block_data); + batchReader.get_field_data(get_file_pointer(), temp.data(), block_to_decomp, + get_current_state(), block_data); double *rvar = static_cast(data); int *ivar = static_cast(data); int64_t *i64var = static_cast(data); - for (size_t block = 0; block < num_blocks; block++) { - Ioss::ElementBlock *entity = elem_blocks[block]; - int iblk = entity->get_property("iblk").get_int(); + for (size_t iblk = 0; iblk < num_blocks; iblk++) { + Ioss::ElementBlock *entity = elem_blocks[iblk]; size_t comp_count = block_data[iblk].comp_count; if (entity->field_exists(field_name)) { @@ -5093,27 +5128,29 @@ namespace Ioex { return ioss_offset; } - std::vector ParallelDatabaseIO::get_all_block_field_data(const std::string &field_name, - void *data, - size_t data_size) const + std::vector + ParallelDatabaseIO::get_entity_field_data(const std::string &field_name, + const std::vector &elem_blocks, + void *data, size_t data_size) const { if (field_name == "connectivity" || field_name == "connectivity_raw") { - return get_all_block_connectivity(field_name, data, data_size); + return get_entity_connectivity_field_data(field_name, elem_blocks, data, data_size); } - const Ioss::ElementBlockContainer &elem_blocks = get_region()->get_element_blocks(); - size_t expected_data_size = get_all_block_field_data_size(field_name, elem_blocks); + size_t expected_data_size = get_entity_field_data_size(field_name, elem_blocks); if (data_size < expected_data_size) { std::ostringstream errmsg; fmt::print(errmsg, - "ERROR: Connectivity data size {} on region {} is less than expected size {}\n\n", - data_size, get_region()->name(), expected_data_size); + "ERROR: Field {} with data size {} on region {} is less than expected size {}\n\n", + field_name, data_size, get_region()->name(), expected_data_size); IOSS_ERROR(errmsg); } - return get_all_block_transient_field_data(m_variables[EX_ELEM_BLOCK], field_name, data); + return get_entity_transient_field_data(m_variables[EX_ELEM_BLOCK], field_name, elem_blocks, + data); } + } // namespace Ioex #else IOSS_MAYBE_UNUSED const char ioss_exodus_parallel_database_unused_symbol_dummy = '\0'; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.h index fe3c12089e..302980a097 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.h @@ -28,7 +28,8 @@ #include // for vector namespace Ioex { class DecompositionDataBase; -} + struct BlockFieldData; +} // namespace Ioex namespace Ioex { template class DecompositionData; } @@ -74,8 +75,9 @@ namespace Ioex { int get_file_pointer() const override; // Open file and set exodusFilePtr. bool needs_shared_node_information() const override { return true; } - std::vector get_all_block_field_data(const std::string &field_name, void *data, - size_t data_size) const override; + std::vector get_entity_field_data(const std::string &field_name, + const std::vector &elem_blocks, + void *data, size_t data_size) const override; private: void compute_node_status() const; @@ -240,11 +242,20 @@ namespace Ioex { int64_t put_side_field(const Ioss::SideBlock *sd_blk, const Ioss::Field &field, void *data, size_t data_size) const; - std::vector get_all_block_connectivity(const std::string &field_name, void *data, - size_t data_size) const; - std::vector get_all_block_transient_field_data(const Ioex::VariableNameMap &variables, - const std::string &field_name, - void *data) const; + template + std::vector + get_entity_block_field_data(const Ioex::VariableNameMap &variables, + const std::string &field_name, + const std::vector &entity_container) const; + + std::vector + get_entity_connectivity_field_data(const std::string &field_name, + const std::vector &elem_blocks, + void *data, size_t data_size) const; + + std::vector get_entity_transient_field_data( + const Ioex::VariableNameMap &variables, const std::string &field_name, + const std::vector &elem_blocks, void *data) const; // Private member data... mutable std::unique_ptr decomp; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C index ad770e1e4e..b727a14859 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -264,19 +264,19 @@ int64_t Ioex::SuperElement::internal_put_field_data(const Ioss::Field & /* field Ioss::Property Ioex::SuperElement::get_implicit_property(const std::string &the_name) const { if (Ioss::Utils::str_equal(the_name, "numDOF")) { - return Ioss::Property(the_name, static_cast(numDOF)); + return {the_name, static_cast(numDOF)}; } if (Ioss::Utils::str_equal(the_name, "num_nodes")) { - return Ioss::Property(the_name, static_cast(num_nodes)); + return {the_name, static_cast(num_nodes)}; } if (Ioss::Utils::str_equal(the_name, "numEIG")) { - return Ioss::Property(the_name, static_cast(numEIG)); + return {the_name, static_cast(numEIG)}; } if (Ioss::Utils::str_equal(the_name, "num_dim")) { - return Ioss::Property(the_name, static_cast(num_dim)); + return {the_name, static_cast(num_dim)}; } if (Ioss::Utils::str_equal(the_name, "numConstraints")) { - return Ioss::Property(the_name, static_cast(numDOF) - static_cast(numEIG)); + return {the_name, static_cast(numDOF) - static_cast(numEIG)}; } return Ioss::GroupingEntity::get_implicit_property(the_name); diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.h index b335bec976..7461f53e2a 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_SuperElement.h @@ -33,7 +33,7 @@ namespace Ioex { std::string contains_string() const override { return "Element"; } Ioss::EntityType type() const override { return Ioss::SUPERELEMENT; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Ioss::Property get_implicit_property(const std::string &the_name) const override; diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C index d5bcb34be4..972e5b4c19 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.C @@ -18,11 +18,11 @@ #include namespace { - size_t match(const char *name1, const char *name2) + size_t match(const std::string &name1, const std::string &name2) { - size_t l1 = std::strlen(name1); - size_t l2 = std::strlen(name2); - size_t len = l1 < l2 ? l1 : l2; + size_t l1 = name1.size(); + size_t l2 = name2.size(); + size_t len = std::min(l1, l2); for (size_t i = 0; i < len; i++) { if (name1[i] != name2[i]) { while (i > 0 && (isdigit(name1[i - 1]) != 0) && (isdigit(name2[i - 1]) != 0)) { @@ -237,7 +237,7 @@ namespace Ioex { const char *s = substring; const char *t = type.c_str(); - SMART_ASSERT(s != nullptr && t != nullptr); + SMART_ASSERT(s != nullptr); while (*s != '\0' && *t != '\0') { if (*s++ != tolower(*t++)) { return false; @@ -409,14 +409,14 @@ namespace Ioex { // VECTOR_3D). If found, it returns the name. // - static char displace[] = "displacement"; + static const std::string displace = "displacement"; size_t max_span = 0; for (const auto &name : fields) { std::string lc_name(name); Ioss::Utils::fixup_name(lc_name); - size_t span = match(lc_name.c_str(), displace); + size_t span = match(lc_name, displace); if (span > max_span) { const Ioss::VariableType *var_type = block->get_field(name).transformed_storage(); int comp_count = var_type->component_count(); @@ -482,7 +482,7 @@ namespace Ioex { } } db_has_name = true; - return (std::string(buffer.data())); + return {buffer.data()}; } db_has_name = false; return Ioss::Utils::encode_entity_name(basename, id); diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h index 3f4ae91579..61bd2c2ec7 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_Utils.h @@ -106,9 +106,6 @@ namespace Ioex { const std::string &basename, int length, bool &db_has_name); - IOEX_EXPORT void filter_element_list(Ioss::Region *region, Ioss::Int64Vector &elements, - Ioss::Int64Vector &sides, bool remove_omitted_elements); - IOEX_EXPORT bool filter_node_list(Ioss::Int64Vector &nodes, const std::vector &node_connectivity_status); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C index 3a1d10bc0b..090f12b453 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.C @@ -249,7 +249,7 @@ namespace Ioexnl { if (using_parallel_io() && myProcessor != 0) {} else { - auto *qa = new qa_element[num_qa_records + 1]; + std::vector qa(num_qa_records + 1); for (size_t i = 0; i < num_qa_records + 1; i++) { for (int j = 0; j < 4; j++) { qa[i].qa_record[0][j] = new char[MAX_STR_LENGTH + 1]; @@ -287,7 +287,6 @@ namespace Ioexnl { delete[] qa[i].qa_record[0][j]; } } - delete[] qa; } } diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h index 60d39e05e7..9e239ced59 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_BaseDatabaseIO.h @@ -127,7 +127,6 @@ namespace Ioexnl { int int_byte_size_db() const override; void set_int_byte_size_api(Ioss::DataSize size) const override; - protected: IOSS_NOOP_GFI(Ioss::Region) IOSS_NOOP_GFI(Ioss::NodeBlock) IOSS_NOOP_GFI(Ioss::EdgeBlock) @@ -243,8 +242,6 @@ namespace Ioexnl { void flush_database__() const override; void finalize_write(int state, double sim_time); - // Private member data... - protected: mutable int m_exodusFilePtr{-1}; // If using links to file-per-state, the file pointer for "base" file. mutable int m_exodusBasePtr{-1}; diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.h index 8828f672a7..3ccb9020ff 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DatabaseIO.h @@ -114,7 +114,6 @@ namespace Ioexnl { int64_t get_Xset_field_internal(const Ioss::EntitySet *ns, const Ioss::Field &field, void *data, size_t data_size) const; - private: int64_t read_nodal_coordinates(); void read_elements(const Ioss::ElementBlock &block); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C index 7f32d3ed14..2dbf099c97 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.C @@ -20,7 +20,7 @@ #include // for assert #include // for INT_MAX #include -#include // for exit, EXIT_FAILURE +#include // for exit, EXIT_FAILURE #include #include #include // for operator<<, ostringstream, etc diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.h index fd777b911f..1ea33a77d3 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_DecompositionData.h @@ -38,10 +38,10 @@ namespace Ioexnl { DecompositionDataBase(const DecompositionDataBase &) = delete; DecompositionDataBase &operator=(const DecompositionDataBase &) = delete; - virtual ~DecompositionDataBase() = default; - virtual int int_size() const = 0; - virtual size_t ioss_node_count() const = 0; - virtual size_t ioss_elem_count() const = 0; + virtual ~DecompositionDataBase() = default; + virtual int int_size() const = 0; + virtual size_t ioss_node_count() const = 0; + virtual size_t ioss_elem_count() const = 0; virtual int spatial_dimension() const = 0; virtual size_t global_node_count() const = 0; diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.C index d732ead521..a5d44abcc8 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.C @@ -4,8 +4,8 @@ // // See packages/seacas/LICENSE for details -#include // for Ioexnl DatabaseIO -#include // for Ioexnl IOFactory +#include // for Ioexnl DatabaseIO +#include // for Ioexnl IOFactory #if defined(PARALLEL_AWARE_EXODUS) // Defined in exodusII.h #include // for Ioexnl ParallelDatabaseIO @@ -15,7 +15,7 @@ #include // for nullptr #include #include -#include // for string +#include // for string #include "Ioss_CodeTypes.h" // for Ioss_MPI_Comm #include "Ioss_DBUsage.h" // for DatabaseUsage diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.h index 8fb7086698..803f248a50 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_IOFactory.h @@ -10,9 +10,9 @@ #include "Ioss_DatabaseIO.h" // for DatabaseIO #include -#include // for DatabaseUsage -#include // for IOFactory -#include // for string +#include // for DatabaseUsage +#include // for IOFactory +#include // for string namespace Ioss { class PropertyManager; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Internals.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Internals.C index 188da18051..4c59966da9 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Internals.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Internals.C @@ -13,15 +13,15 @@ extern "C" { #include } -#include // for assert -#include // for size_t -#include // for nullptr -#include // for exit, EXIT_FAILURE -#include // for strlen +#include // for assert +#include // for size_t +#include // for nullptr +#include // for exit, EXIT_FAILURE +#include // for strlen #include -#include // for operator<<, etc -#include // for string, operator==, etc -#include // for vector +#include // for operator<<, etc +#include // for string, operator==, etc +#include // for vector #include "Ioss_Assembly.h" #include "Ioss_Blob.h" diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.h index e5af2e1cb7..39b46bd1da 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_ParallelDatabaseIO.h @@ -19,13 +19,13 @@ #include // for less #include // for map, map<>::value_compare #include -#include // for set -#include // for size_t -#include // for int64_t -#include // for string, operator< -#include // for nullptr, time_t -#include // for pair -#include // for vector +#include // for set +#include // for size_t +#include // for int64_t +#include // for string, operator< +#include // for nullptr, time_t +#include // for pair +#include // for vector namespace Ioexnl { class DecompositionDataBase; } diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C index fb690c7882..bc0fcabf91 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -265,19 +265,19 @@ int64_t Ioexnl::SuperElement::internal_put_field_data(const Ioss::Field & /* fie Ioss::Property Ioexnl::SuperElement::get_implicit_property(const std::string &the_name) const { if (Ioss::Utils::str_equal(the_name, "numDOF")) { - return Ioss::Property(the_name, static_cast(numDOF)); + return {the_name, static_cast(numDOF)}; } if (Ioss::Utils::str_equal(the_name, "num_nodes")) { - return Ioss::Property(the_name, static_cast(num_nodes)); + return {the_name, static_cast(num_nodes)}; } if (Ioss::Utils::str_equal(the_name, "numEIG")) { - return Ioss::Property(the_name, static_cast(numEIG)); + return {the_name, static_cast(numEIG)}; } if (Ioss::Utils::str_equal(the_name, "num_dim")) { - return Ioss::Property(the_name, static_cast(num_dim)); + return {the_name, static_cast(num_dim)}; } if (Ioss::Utils::str_equal(the_name, "numConstraints")) { - return Ioss::Property(the_name, static_cast(numDOF) - static_cast(numEIG)); + return {the_name, static_cast(numDOF) - static_cast(numEIG)}; } return Ioss::GroupingEntity::get_implicit_property(the_name); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.h index 6de9abf078..6d3a75035a 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_SuperElement.h @@ -33,7 +33,7 @@ namespace Ioexnl { std::string contains_string() const override { return "Element"; } Ioss::EntityType type() const override { return Ioss::SUPERELEMENT; } - // Handle implicit properties -- These are calcuated from data stored + // Handle implicit properties -- These are calculated from data stored // in the grouping entity instead of having an explicit value assigned. // An example would be 'element_block_count' for a region. Ioss::Property get_implicit_property(const std::string &the_name) const override; diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.C b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.C index fd8d3def9f..0c7af15061 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.C +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.C @@ -19,11 +19,11 @@ #include namespace { - size_t match(const char *name1, const char *name2) + size_t match(const std::string &name1, const std::string &name2) { - size_t l1 = std::strlen(name1); - size_t l2 = std::strlen(name2); - size_t len = l1 < l2 ? l1 : l2; + size_t l1 = name1.size(); + size_t l2 = name2.size(); + size_t len = std::min(l1, l2); for (size_t i = 0; i < len; i++) { if (name1[i] != name2[i]) { while (i > 0 && (isdigit(name1[i - 1]) != 0) && (isdigit(name2[i - 1]) != 0)) { @@ -212,7 +212,7 @@ namespace Ioexnl { const char *s = substring; const char *t = type.c_str(); - SMART_ASSERT(s != nullptr && t != nullptr); + SMART_ASSERT(s != nullptr); while (*s != '\0' && *t != '\0') { if (*s++ != tolower(*t++)) { return false; @@ -359,7 +359,7 @@ namespace Ioexnl { // extracted from the entities name. Increment it until it is // unique... ex_entity_type type = map_exodus_type(entity->type()); - while (idset->find(std::make_pair(int(type), id)) != idset->end()) { + while (idset->find(std::make_pair(static_cast(type), id)) != idset->end()) { ++id; } @@ -384,14 +384,14 @@ namespace Ioexnl { // VECTOR_3D). If found, it returns the name. // - static char displace[] = "displacement"; + static const std::string displace = "displacement"; size_t max_span = 0; for (const auto &name : fields) { std::string lc_name(name); Ioss::Utils::fixup_name(lc_name); - size_t span = match(lc_name.c_str(), displace); + size_t span = match(lc_name, displace); if (span > max_span) { const Ioss::VariableType *var_type = block->get_field(name).transformed_storage(); int comp_count = var_type->component_count(); diff --git a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.h b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.h index 6e57c925bb..bb033ae3bd 100644 --- a/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.h +++ b/packages/seacas/libraries/ioss/src/exonull/Ioexnl_Utils.h @@ -123,9 +123,6 @@ namespace Ioexnl { } } - IOEXNL_EXPORT void filter_element_list(Ioss::Region *region, Ioss::Int64Vector &elements, - Ioss::Int64Vector &sides, bool remove_omitted_elements); - IOEXNL_EXPORT void separate_surface_element_sides(Ioss::Int64Vector &element, Ioss::Int64Vector &sides, Ioss::Region *region, Ioexnl::TopologyMap &topo_map, diff --git a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_FieldSerialization.h b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_FieldSerialization.h index cb61fdb10b..14e55cf8d4 100644 --- a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_FieldSerialization.h +++ b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_FieldSerialization.h @@ -54,14 +54,16 @@ namespace Iofaodel { // Applies FieldFunction 'op' to all fields encountered in the // Ioss::GroupingEntity - IOFAODEL_EXPORT void map_fields(const Ioss::Region ®ion, const Ioss::GroupingEntity &grouping_entity, - FieldFunction op); + IOFAODEL_EXPORT void map_fields(const Ioss::Region ®ion, + const Ioss::GroupingEntity &grouping_entity, FieldFunction op); - IOFAODEL_EXPORT lunasa::DataObject pack_field(const Ioss::Region ®ion, const Ioss::GroupingEntity &entity, - const Ioss::Field &field); + IOFAODEL_EXPORT lunasa::DataObject pack_field(const Ioss::Region ®ion, + const Ioss::GroupingEntity &entity, + const Ioss::Field &field); - IOFAODEL_EXPORT lunasa::DataObject pack_field(const Ioss::Region &r, const Ioss::GroupingEntity &e, - const Ioss::Field &f, void *data, size_t data_size); + IOFAODEL_EXPORT lunasa::DataObject pack_field(const Ioss::Region &r, + const Ioss::GroupingEntity &e, const Ioss::Field &f, + void *data, size_t data_size); // Put this in the meta data section of the LDO struct IOFAODEL_EXPORT field_entry_t diff --git a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_PropertySerialization.h b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_PropertySerialization.h index fc1875db43..13bac7acb7 100644 --- a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_PropertySerialization.h +++ b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_PropertySerialization.h @@ -37,11 +37,13 @@ namespace Iofaodel { // Applies PropertyFunction 'op' to all properties encountered in the // Ioss::GroupingEntity - IOFAODEL_EXPORT void map_properties(const Ioss::Region ®ion, const Ioss::GroupingEntity &grouping_entity, - PropertyFunction op); + IOFAODEL_EXPORT void map_properties(const Ioss::Region ®ion, + const Ioss::GroupingEntity &grouping_entity, + PropertyFunction op); - IOFAODEL_EXPORT lunasa::DataObject pack_property(const Ioss::Region ®ion, const Ioss::GroupingEntity &entity, - const Ioss::Property &property); + IOFAODEL_EXPORT lunasa::DataObject pack_property(const Ioss::Region ®ion, + const Ioss::GroupingEntity &entity, + const Ioss::Property &property); // Put this in the meta data section of the LDO struct IOFAODEL_EXPORT property_entry_t @@ -60,7 +62,7 @@ namespace Iofaodel { explicit property_entry_t(const Ioss::Property &property, const size_t start = 0); }; - IOFAODEL_EXPORT int64_t property_get_int(lunasa::DataObject ldo); - std::string property_get_string(lunasa::DataObject ldo); + IOFAODEL_EXPORT int64_t property_get_int(lunasa::DataObject ldo); + std::string property_get_string(lunasa::DataObject ldo); } // namespace Iofaodel diff --git a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C index 43b73f1432..95575c9f4c 100644 --- a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C +++ b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C @@ -38,9 +38,8 @@ namespace Iofaodel { state_entry_t::state_entry_t(const Ioss::Region &r) - : count(r.get_property("state_count").get_int()), value{0, - count * - sizeof(state_entry_t::basic_type)} + : count(r.get_property("state_count").get_int()), + value{0, count * sizeof(state_entry_t::basic_type)} { } diff --git a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h index 0732e27894..5f832aa07c 100644 --- a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h +++ b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h @@ -64,59 +64,67 @@ namespace Iofaodel { IOFAODEL_EXPORT int64_t unpack_sideblocks(lunasa::DataObject ldo); IOFAODEL_EXPORT lunasa::DataObject pack_structuredblock(const Ioss::StructuredBlock &sb); - IOFAODEL_EXPORT void unpack_structuredblock(lunasa::DataObject &ldo, Ioss::StructuredBlock &sb); + IOFAODEL_EXPORT void unpack_structuredblock(lunasa::DataObject &ldo, Ioss::StructuredBlock &sb); IOFAODEL_EXPORT kelpie::Key make_states_search_key(int parallel_rank, const Ioss::Region ®ion); IOFAODEL_EXPORT kelpie::Key make_states_key(int parallel_rank, const Ioss::Region ®ion); IOFAODEL_EXPORT kelpie::Key sideblocks_search_key(int rank, const Ioss::Region ®ion, - const Ioss::SideSet &sideset); + const Ioss::SideSet &sideset); - IOFAODEL_EXPORT kelpie::Key make_sideblock_key(int rank, const Ioss::Region ®ion, const Ioss::SideSet &sideset, - const Ioss::SideBlock &sideblock); + IOFAODEL_EXPORT kelpie::Key make_sideblock_key(int rank, const Ioss::Region ®ion, + const Ioss::SideSet &sideset, + const Ioss::SideBlock &sideblock); - IOFAODEL_EXPORT kelpie::Key structuredblock_search_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::StructuredBlock &structuredblock); + IOFAODEL_EXPORT kelpie::Key + structuredblock_search_key(int parallel_rank, const Ioss::Region ®ion, + const Ioss::StructuredBlock &structuredblock); - IOFAODEL_EXPORT kelpie::Key make_structuredblock_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::StructuredBlock &structuredblock); + IOFAODEL_EXPORT kelpie::Key + make_structuredblock_key(int parallel_rank, const Ioss::Region ®ion, + const Ioss::StructuredBlock &structuredblock); IOFAODEL_EXPORT kelpie::Key make_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::GroupingEntity &grouping_entity, const Ioss::Field &field); + const Ioss::GroupingEntity &grouping_entity, + const Ioss::Field &field); IOFAODEL_EXPORT kelpie::Key make_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::GroupingEntity &grouping_entity, const Ioss::Property &property); + const Ioss::GroupingEntity &grouping_entity, + const Ioss::Property &property); IOFAODEL_EXPORT kelpie::Key make_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::GroupingEntity &grouping_entity); + const Ioss::GroupingEntity &grouping_entity); IOFAODEL_EXPORT kelpie::Key entity_search_key(int rank, const Ioss::Region ®ion, - const std::string &entity_name); + const std::string &entity_name); IOFAODEL_EXPORT kelpie::Key entity_search_key(int rank, const Ioss::Region ®ion, - const Ioss::GroupingEntity &entity); + const Ioss::GroupingEntity &entity); IOFAODEL_EXPORT kelpie::Key property_search_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::GroupingEntity &grouping_entity); + const Ioss::GroupingEntity &grouping_entity); IOFAODEL_EXPORT kelpie::Key make_property_key(int rank, const Ioss::Region ®ion, - const std::string &entity_type, const std::string &entity_name, - const std::string &property_type, const std::string &property_name); + const std::string &entity_type, + const std::string &entity_name, + const std::string &property_type, + const std::string &property_name); IOFAODEL_EXPORT kelpie::Key field_search_key(int parallel_rank, const Ioss::Region ®ion, - const Ioss::GroupingEntity &grouping_entity); + const Ioss::GroupingEntity &grouping_entity); - IOFAODEL_EXPORT kelpie::Key field_search_key(int parallel_rank, int state, const Ioss::Region ®ion, - const Ioss::GroupingEntity &grouping_entity); + IOFAODEL_EXPORT kelpie::Key field_search_key(int parallel_rank, int state, + const Ioss::Region ®ion, + const Ioss::GroupingEntity &grouping_entity); IOFAODEL_EXPORT std::string to_string(const Ioss::Property::BasicType &t); IOFAODEL_EXPORT std::string to_string(const Ioss::Field::BasicType &t); IOFAODEL_EXPORT std::string to_string(const Ioss::Field::RoleType &t); IOFAODEL_EXPORT std::string to_string(const Ioss::EntityType &t); - IOFAODEL_EXPORT std::string get_entity_name(const kelpie::Key &k, const std::string &target); + IOFAODEL_EXPORT std::string get_entity_name(const kelpie::Key &k, const std::string &target); IOFAODEL_EXPORT std::set get_entity_names(const std::vector &keys, - const std::string &target); + const std::string &target); } // namespace Iofaodel diff --git a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h index 77be074e2c..98616c1cda 100644 --- a/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h +++ b/packages/seacas/libraries/ioss/src/gen_struc/Iogs_GeneratedMesh.h @@ -324,7 +324,7 @@ namespace Iogs { std::vector &z) const; /** - * Return the coordinates for componenet 'comp' (1=x, 2=y, 3=z) + * Return the coordinates for component 'comp' (1=x, 2=y, 3=z) * for all nodes on this processor. The * vector will be resized to the size required to contain the * nodal coordinates; all information in the vector will be @@ -335,7 +335,7 @@ namespace Iogs { virtual void coordinates(int component, std::vector &xyz) const; /** - * Return the coordinates for componenet 'comp' (1=x, 2=y, 3=z, 0=all) + * Return the coordinates for component 'comp' (1=x, 2=y, 3=z, 0=all) * for all nodes in zone `zone` on this processor. The * vector will be resized to the size required to contain the * nodal coordinates; all information in the vector will be diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C index e937f4c0ff..bd5382201a 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.C @@ -149,7 +149,6 @@ namespace Iogn { map[i] = mDashSurfaceData.sharedNodes[i].nodeId; proc[i] = mDashSurfaceData.sharedNodes[i].procId; } - return; } void DashSurfaceMesh::node_map(Ioss::IntVector &map) const diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h index d3984ba3dc..e3184db19d 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_DashSurfaceMesh.h @@ -35,9 +35,9 @@ namespace Iogn { inline std::string getTopologyName(Topology topology) { switch (topology) { - case Shell4: return std::string(Ioss::Shell4::name); - case Hex8: return std::string(Ioss::Hex8::name); - case Beam2: return std::string(Ioss::Beam2::name); + case Shell4: return {Ioss::Shell4::name}; + case Hex8: return {Ioss::Hex8::name}; + case Beam2: return {Ioss::Beam2::name}; } throw std::exception(); } @@ -65,7 +65,7 @@ namespace Iogn { std::vector> sidesetConnectivity; std::vector> sidesetTouchingBlocks; - ExodusData() = default; + ExodusData() = delete; ExodusData(std::vector coords, std::vector> elemBlockConnectivity, std::vector globalNumOfElemsInBlock, std::vector localNumOfElemsInBlock, std::vector blockTopoData, int globalNumNodes, diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C index 411df6ef5b..6ec3a48b19 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.C @@ -1557,7 +1557,6 @@ namespace Iogn { (cnt == int64_t(3 * element_count_proc(block_number)) && createTets)); } } - return; } void GeneratedMesh::nodeset_nodes(int64_t id, Ioss::Int64Vector &nodes) const diff --git a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h index 1db4850515..2addc90067 100644 --- a/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h +++ b/packages/seacas/libraries/ioss/src/generated/Iogn_GeneratedMesh.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -25,37 +25,37 @@ namespace Iogn { enum ShellLocation { MX = 0, PX = 1, MY = 2, PY = 3, MZ = 4, PZ = 5 }; /** - Generate a cube mesh of size 'num_x' by 'num_y' by 'num_z' elements. - By default, the mesh is generated on a single processor. If 'proc_count' is - greater than 1, then the mesh will be distributed over 'proc_count' processors - and this process will get the portion of the mesh for 'my_proc'. - The mesh will be decomposed along the 'Z' axis so 'num_z' must be greater than - or equal to 'proc_count' and for even distribution of the hexes 'num_z' mod 'proc_count' + Generate a cube mesh of size `num_x` by `num_y` by `num_z` elements. + By default, the mesh is generated on a single processor. If `proc_count` is + greater than 1, then the mesh will be distributed over `proc_count` processors + and this process will get the portion of the mesh for `my_proc`. + The mesh will be decomposed along the `Z` axis so `num_z` must be greater than + or equal to `proc_count` and for even distribution of the hexes `num_z` mod `proc_count` should be zero. The mesh can optionally include shell elements along each face of the cube mesh. - These are specified via the 'add_shell_block' function. + These are specified via the `add_shell_block` function. The mesh can optionally include nodesets/sidesets along each face of the cube mesh. These are specified via the - 'add_nodesets' and 'add_sidesets' functions. + `add_nodesets` and `add_sidesets` functions. - If the 'parameters' string constructor is used, the string + If the `parameters` string constructor is used, the string is parsed to determine the intervals in each direction and, optionally, additional information. The form of the string is "IxJxK" where I, J, and K are the number of intervals in the X, Y, and Z directions respectively and the "x" are - literal 'x' characters. For example, the constructor + literal `x` characters. For example, the constructor GeneratedMesh("10x12x14") will create the same mesh as GeneratedMesh(10,12,14) Additional valid options are: - - help -- no argument, shows valid options - - show -- no argument, prints out a summary of the + - `help` -- no argument, shows valid options + - `show` -- no argument, prints out a summary of the GeneratedMesh() parameters. The output will look similar to: - \code - "10x12x8|shell:xX|bbox:-10,-10,-10,10,10,10|nodeset:xyz|sideset:XYZ|show" + ``` + 10x12x8|shell:xX|bbox:-10,-10,-10,10,10,10|nodeset:xyz|sideset:XYZ|show Mesh Parameters: Intervals: 10 by 12 by 8 @@ -67,33 +67,33 @@ namespace Iogn { Block Count = 3 NodeSet Count = 3 SideSet Count = 3 - \endcode + ``` - - tets -- no argument - specifies that each hex should be + - `tets` -- no argument - specifies that each hex should be split into 6 tetrahedral elements. Cannot currently be used with shells or sidesets. - - pyramids -- no argument - specifies that each hex should be + - `pyramids` -- no argument - specifies that each hex should be split into 6 pyramidal elements. - - shell -- argument = xXyYzZ which specifies whether there is a shell - block at that location. 'x' is minimum x face, 'X' is maximum x face, + - `shell` -- argument = xXyYzZ which specifies whether there is a shell + block at that location. `x` is minimum x face, `X` is maximum x face, similarly for y and z. Note that the argument string is a single multicharacter string. You can add multiple shell blocks to a face, for example, shell:xxx would add three layered shell blocks on the minimum x face. An error is output if a non xXyYzZ character is found, but execution continues. - - nodeset -- argument = xXyYzZ which specifies whether there is - a nodeset at that location. 'x' is minimum x face, 'X' is + - `nodeset` -- argument = xXyYzZ which specifies whether there is + a nodeset at that location. `x` is minimum x face, `X` is maximum x face, similarly for y and z. Note that the argument string is a single multicharacter string. You can add multiple nodesets to a face, for example, nodeset:xxx would add three nodesets on the minimum x face. An error is output if a non xXyYzZ character is found, but execution continues. - - sideset -- argument = xXyYzZ which specifies whether there is - a sideset at that location. 'x' is minimum x face, 'X' is + - `sideset` -- argument = xXyYzZ which specifies whether there is + a sideset at that location. `x` is minimum x face, `X` is maximum x face, similarly for y and z. Note that the argument string is a single multicharacter string. You can add multiple sidesets to a face, for example, sideset:xxx would add three @@ -103,7 +103,7 @@ namespace Iogn { be on the shell elements; else the sideset will be on the hex elements. - - zdecomp -- argument = n0, n1, n2, ..., n#proc-1 which are the number + - `zdecomp` -- argument = n0, n1, n2, ..., n#proc-1 which are the number of intervals in the z direction for each processor in a pallel run. If this option is specified, then the total number of intervals in the z direction is the sum of the n0, n1, ... An interval count must be @@ -111,15 +111,15 @@ namespace Iogn { the number of intervals on each processor in the z direction is numZ/numProc with the extras added to the lower numbered processors. - - scale -- argument = xs, ys, zs which are the scale factors in the x, + - `scale` -- argument = xs, ys, zs which are the scale factors in the x, y, and z directions. All three must be specified if this option is present. - - offset -- argument = xoff, yoff, zoff which are the offsets in the + - `offset` -- argument = xoff, yoff, zoff which are the offsets in the x, y, and z directions. All three must be specified if this option is present. - - bbox -- argument = xmin, ymin, zmin, xmax, ymax, zmax + - `bbox` -- argument = xmin, ymin, zmin, xmax, ymax, zmax which specify the lower left and upper right corners of the bounding box for the generated mesh. This will calculate the scale and offset which will fit the mesh in @@ -128,8 +128,8 @@ namespace Iogn { specified later in the option list, you may not get the desired bounding box. - - rotate -- argument = axis,angle,axis,angle,... - where axis is 'x', 'y', or 'z' and angle is the rotation angle in + - `rotate` -- argument = axis,angle,axis,angle,... + where axis is `x`, `y`, or `z` and angle is the rotation angle in degrees. Multiple rotations are cumulative. The composite rotation matrix is applied at the time the coordinates are retrieved after scaling and offset are applied. @@ -152,9 +152,7 @@ namespace Iogn { output and execution will continue. An example of valid input is: - \code - "10x20x40|scale:1,0.5,0.25|offset:-5,-5,-5|shell:xX" - \endcode + `"10x20x40|scale:1,0.5,0.25|offset:-5,-5,-5|shell:xX"` This would create a mesh with 10 intervals in x, 20 in y, 40 in z The mesh would be centered on 0,0,0 with a range of 10 in each @@ -253,7 +251,7 @@ namespace Iogn { /** * Set rotation. Multiple calls are cumulative. - * Rotate 'angle_degrees' degrees about the axis 'axis' + * Rotate `angle_degrees` degrees about the axis `axis` * Center of rotation is about the origin and operates * on the scaled/offset coordinates of the mesh. */ @@ -280,12 +278,12 @@ namespace Iogn { virtual int nodeset_count() const; /** - * Return number of nodeset nodes on nodeset 'id' + * Return number of nodeset nodes on nodeset `id` */ int64_t nodeset_node_count(int64_t id) const; /** - * Return number of nodeset nodes on nodeset 'id' on the current processor + * Return number of nodeset nodes on nodeset `id` on the current processor */ virtual int64_t nodeset_node_count_proc(int64_t id) const; @@ -300,12 +298,12 @@ namespace Iogn { virtual int sideset_count() const; /** - * Return number of sideset 'sides' on sideset 'id' + * Return number of sideset `sides` on sideset `id` */ int64_t sideset_side_count(int64_t id) const; /** - * Return number of sideset 'sides' on sideset 'id' on the current + * Return number of sideset `sides` on sideset `id` on the current * processor. */ virtual int64_t sideset_side_count_proc(int64_t id) const; @@ -333,15 +331,15 @@ namespace Iogn { int timestep_count() const { return timestepCount; } /** * Return number of elements in the element block with id - * 'block_number'. The 'block_number' ranges from '1' to - * 'block_count()'. + * `block_number`. The `block_number` ranges from `1` to + * `block_count()`. */ virtual int64_t element_count(int64_t block_number) const; /** * Return number of elements on this processor in the element - * block with id 'block_number'. The 'block_number' ranges from - * '1' to 'block_count()'. + * block with id `block_number`. The `block_number` ranges from + * `1` to `block_count()`. */ virtual int64_t element_count_proc(int64_t block_number) const; @@ -359,7 +357,7 @@ namespace Iogn { virtual void owning_processor(int *owner, int64_t num_node); /** - * Fill the passed in 'map' argument with the node map + * Fill the passed in `map` argument with the node map * "map[local_position] = global_id" for the nodes on this * processor. */ @@ -367,7 +365,7 @@ namespace Iogn { virtual void node_map(Ioss::IntVector &map) const; /** - * Fill the passed in 'map' argument with the element map + * Fill the passed in `map` argument with the element map * "map[local_position] = global_id" for the elements on this * processor in block "block_number". */ @@ -375,7 +373,7 @@ namespace Iogn { virtual void element_map(int64_t block_number, Ioss::IntVector &map) const; /** - * Fill the passed in 'map' argument with the element map + * Fill the passed in `map` argument with the element map * "map[local_position] = global_id" for all elements on this * processor */ @@ -383,7 +381,7 @@ namespace Iogn { virtual void element_map(Ioss::IntVector &map) const; /** - * Fill the passed in 'map' argument with the element map pair + * Fill the passed in `map` argument with the element map pair * "map[local_position] = element global_id" and * "map[local_position+1] = element local face id (0-based)" for * all elements on the current processor having a face on the @@ -393,13 +391,13 @@ namespace Iogn { /** * Return the connectivity for the elements on this processor in - * the block with id 'block_number'. If the elements in this block - * have 'npe' nodes per element, then the first 'npe' entries in - * the 'conn' vector will be the nodal connectivity for the first - * element; the next 'npe' entries are the nodal connectivity for - * the second element. The 'connect' vector will be resized to the + * the block with id `block_number`. If the elements in this block + * have `npe` nodes per element, then the first `npe` entries in + * the `conn` vector will be the nodal connectivity for the first + * element; the next `npe` entries are the nodal connectivity for + * the second element. The `connect` vector will be resized to the * size required to contain the nodal connectivity for the - * specified block; all information in 'connect' will be overwritten. + * specified block; all information in `connect` will be overwritten. */ void connectivity(int64_t block_number, Ioss::Int64Vector &connect) const; void connectivity(int64_t block_number, Ioss::IntVector &connect) const; @@ -408,10 +406,10 @@ namespace Iogn { /** * Return the coordinates for all nodes on this processor. The - * first 3 entries in the 'coord' vector are the x, y, and z - * coordinates of the first node, etc. The 'coord' vector will be + * first 3 entries in the `coord` vector are the x, y, and z + * coordinates of the first node, etc. The `coord` vector will be * resized to the size required to contain the nodal coordinates; - * all information in 'coord' will be overwritten. + * all information in `coord` will be overwritten. */ virtual void coordinates(std::vector &coord) const; virtual void coordinates(double *coord) const; @@ -426,7 +424,7 @@ namespace Iogn { std::vector &z) const; /** - * Return the coordinates for componenet 'comp' (1=x, 2=y, 3=z) + * Return the coordinates for component `comp` (1=x, 2=y, 3=z) * for all nodes on this processor. The * vector will be resized to the size required to contain the * nodal coordinates; all information in the vector will be @@ -438,8 +436,8 @@ namespace Iogn { virtual void coordinates(int component, double *xyz) const; /** - * Return the list of nodes in nodeset 'id' on this processor. - * The 'nodes' vector will be resized to the size required to + * Return the list of nodes in nodeset `id` on this processor. + * The `nodes` vector will be resized to the size required to * contain the node list. The ids are global ids. */ virtual void nodeset_nodes(int64_t id, Ioss::Int64Vector &nodes) const; @@ -448,8 +446,8 @@ namespace Iogn { * Return the list of the face/ordinal pairs * "elem_sides[local_position] = element global_id" and * "elem_sides[local_position+1] = element local face id (0-based)" - * for the faces in sideset 'id' on this - * processor. The 'elem_sides' vector will be resized to the size + * for the faces in sideset `id` on this + * processor. The `elem_sides` vector will be resized to the size * required to contain the list. The element ids are global ids, * the side ordinal is 0-based. */ diff --git a/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C b/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C index be08422dbf..2d250e84fa 100644 --- a/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/heartbeat/Iohb_DatabaseIO.C @@ -47,7 +47,7 @@ namespace { std::string time_stamp(const std::string &format) { if (format.empty()) { - return std::string(""); + return {""}; } const int length = 256; static char time_string[length]; @@ -58,9 +58,9 @@ namespace { size_t error = strftime(time_string, length, format.c_str(), local_time); if (error != 0) { time_string[length - 1] = '\0'; - return std::string(time_string); + return {time_string}; } - return std::string("[ERROR]"); + return {"[ERROR]"}; } std::ostream *open_stream(const std::string &filename, bool *needs_delete, bool append_file) diff --git a/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h b/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h index 3409f4d3d2..89ecbaeba6 100644 --- a/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h +++ b/packages/seacas/libraries/ioss/src/hopscotch_growth_policy.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2018 Thibaut Goetghebuer-Planchon + * Copyright (c) 2018, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,167 +69,165 @@ #endif #endif -namespace tsl { - namespace hh { - +namespace tsl::hh { + + /** + * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a + * power of two. It allows the table to use a mask operation instead of a modulo + * operation to map a hash to a bucket. + * + * GrowthFactor must be a power of two >= 2. + */ + template class power_of_two_growth_policy + { + public: /** - * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a - * power of two. It allows the table to use a mask operation instead of a modulo - * operation to map a hash to a bucket. + * Called on the hash table creation and on rehash. The number of buckets for + * the table is passed in parameter. This number is a minimum, the policy may + * update this value with a higher value if needed (but not lower). * - * GrowthFactor must be a power of two >= 2. + * If 0 is given, min_bucket_count_in_out must still be 0 after the policy + * creation and bucket_for_hash must always return 0 in this case. */ - template class power_of_two_growth_policy + explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - /** - * Called on the hash table creation and on rehash. The number of buckets for - * the table is passed in parameter. This number is a minimum, the policy may - * update this value with a higher value if needed (but not lower). - * - * If 0 is given, min_bucket_count_in_out must still be 0 after the policy - * creation and bucket_for_hash must always return 0 in this case. - */ - explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); - m_mask = min_bucket_count_in_out - 1; - } - else { - m_mask = 0; - } + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - /** - * Return the bucket [0, bucket_count()) to which the hash belongs. - * If bucket_count() is 0, it must always return 0. - */ - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - - /** - * Return the bucket count to use when the bucket array grows on rehash. - */ - std::size_t next_bucket_count() const - { - if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - return (m_mask + 1) * GrowthFactor; + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); + m_mask = min_bucket_count_in_out - 1; } - - /** - * Return the maximum number of buckets supported by the policy. - */ - std::size_t max_bucket_count() const - { - // Largest power of two. - return (std::numeric_limits::max() / 2) + 1; + else { + m_mask = 0; } + } - /** - * Reset the growth policy as if it was created with a bucket count of 0. - * After a clear, the policy must always return 0 when bucket_for_hash is - * called. - */ - void clear() noexcept { m_mask = 0; } - - private: - static std::size_t round_up_to_power_of_two(std::size_t value) - { - if (is_power_of_two(value)) { - return value; - } - - if (value == 0) { - return 1; - } - - --value; - for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { - value |= value >> i; - } - - return value + 1; - } + /** + * Return the bucket [0, bucket_count()) to which the hash belongs. + * If bucket_count() is 0, it must always return 0. + */ + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - static constexpr bool is_power_of_two(std::size_t value) - { - return value != 0 && (value & (value - 1)) == 0; + /** + * Return the bucket count to use when the bucket array grows on rehash. + */ + std::size_t next_bucket_count() const + { + if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - private: - static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, - "GrowthFactor must be a power of two >= 2."); + return (m_mask + 1) * GrowthFactor; + } - std::size_t m_mask; - }; + /** + * Return the maximum number of buckets supported by the policy. + */ + std::size_t max_bucket_count() const + { + // Largest power of two. + return (std::numeric_limits::max() / 2) + 1; + } /** - * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo - * to map a hash to a bucket. Slower but it can be useful if you want a slower - * growth. + * Reset the growth policy as if it was created with a bucket count of 0. + * After a clear, the policy must always return 0 when bucket_for_hash is + * called. */ - template > class mod_growth_policy + void clear() noexcept { m_mask = 0; } + + private: + static std::size_t round_up_to_power_of_two(std::size_t value) + { + if (is_power_of_two(value)) { + return value; + } + + if (value == 0) { + return 1; + } + + --value; + for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { + value |= value >> i; + } + + return value + 1; + } + + static constexpr bool is_power_of_two(std::size_t value) + { + return value != 0 && (value & (value - 1)) == 0; + } + + private: + static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, + "GrowthFactor must be a power of two >= 2."); + + std::size_t m_mask; + }; + + /** + * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo + * to map a hash to a bucket. Slower but it can be useful if you want a slower + * growth. + */ + template > class mod_growth_policy + { + public: + explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) + { + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (min_bucket_count_in_out > 0) { + m_mod = min_bucket_count_in_out; + } + else { + m_mod = 1; + } + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } + + std::size_t next_bucket_count() const { - public: - explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - m_mod = min_bucket_count_in_out; - } - else { - m_mod = 1; - } + if (m_mod == max_bucket_count()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + const double next_bucket_count = std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); + if (!std::isnormal(next_bucket_count)) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } - - std::size_t next_bucket_count() const - { - if (m_mod == max_bucket_count()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - const double next_bucket_count = - std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); - if (!std::isnormal(next_bucket_count)) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (next_bucket_count > double(max_bucket_count())) { - return max_bucket_count(); - } - else { - return std::size_t(next_bucket_count); - } + if (next_bucket_count > double(max_bucket_count())) { + return max_bucket_count(); + } + else { + return std::size_t(next_bucket_count); } + } - std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } + std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } - void clear() noexcept { m_mod = 1; } + void clear() noexcept { m_mod = 1; } - private: - static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = - 1.0 * GrowthFactor::num / GrowthFactor::den; - static const std::size_t MAX_BUCKET_COUNT = std::size_t( - double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); + private: + static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = + 1.0 * GrowthFactor::num / GrowthFactor::den; + static const std::size_t MAX_BUCKET_COUNT = std::size_t( + double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); - static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); + static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); - std::size_t m_mod; - }; + std::size_t m_mod; + }; - namespace detail { + namespace detail { #if SIZE_MAX >= ULLONG_MAX #define TSL_HH_NB_PRIMES 51 @@ -239,163 +237,160 @@ namespace tsl { #define TSL_HH_NB_PRIMES 23 #endif - static constexpr const std::array PRIMES = {{ - 1u, - 5u, - 17u, - 29u, - 37u, - 53u, - 67u, - 79u, - 97u, - 131u, - 193u, - 257u, - 389u, - 521u, - 769u, - 1031u, - 1543u, - 2053u, - 3079u, - 6151u, - 12289u, - 24593u, - 49157u, + static constexpr const std::array PRIMES = {{ + 1u, + 5u, + 17u, + 29u, + 37u, + 53u, + 67u, + 79u, + 97u, + 131u, + 193u, + 257u, + 389u, + 521u, + 769u, + 1031u, + 1543u, + 2053u, + 3079u, + 6151u, + 12289u, + 24593u, + 49157u, #if SIZE_MAX >= ULONG_MAX - 98317ul, - 196613ul, - 393241ul, - 786433ul, - 1572869ul, - 3145739ul, - 6291469ul, - 12582917ul, - 25165843ul, - 50331653ul, - 100663319ul, - 201326611ul, - 402653189ul, - 805306457ul, - 1610612741ul, - 3221225473ul, - 4294967291ul, + 98317ul, + 196613ul, + 393241ul, + 786433ul, + 1572869ul, + 3145739ul, + 6291469ul, + 12582917ul, + 25165843ul, + 50331653ul, + 100663319ul, + 201326611ul, + 402653189ul, + 805306457ul, + 1610612741ul, + 3221225473ul, + 4294967291ul, #endif #if SIZE_MAX >= ULLONG_MAX - 6442450939ull, - 12884901893ull, - 25769803751ull, - 51539607551ull, - 103079215111ull, - 206158430209ull, - 412316860441ull, - 824633720831ull, - 1649267441651ull, - 3298534883309ull, - 6597069766657ull, + 6442450939ull, + 12884901893ull, + 25769803751ull, + 51539607551ull, + 103079215111ull, + 206158430209ull, + 412316860441ull, + 824633720831ull, + 1649267441651ull, + 3298534883309ull, + 6597069766657ull, #endif - }}; - - template static constexpr std::size_t mod(std::size_t hash) - { - return hash % PRIMES[IPrime]; - } + }}; - // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for - // faster modulo as the compiler can optimize the modulo code better with a - // constant known at the compilation. - static constexpr const std::array MOD_PRIME = - {{ - &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, - &mod<8>, &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, - &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, + template static constexpr std::size_t mod(std::size_t hash) + { + return hash % PRIMES[IPrime]; + } + + // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for + // faster modulo as the compiler can optimize the modulo code better with a + // constant known at the compilation. + static constexpr const std::array MOD_PRIME = {{ + &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, &mod<8>, + &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>, + &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, #if SIZE_MAX >= ULONG_MAX - &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, - &mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, - &mod<39>, + &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, &mod<31>, + &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, &mod<39>, #endif #if SIZE_MAX >= ULLONG_MAX - &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, - &mod<48>, &mod<49>, &mod<50>, + &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, &mod<48>, + &mod<49>, &mod<50>, #endif - }}; - - } // namespace detail - - /** - * Grow the hash table by using prime numbers as bucket count. Slower than - * tsl::hh::power_of_two_growth_policy in general but will probably distribute - * the values around better in the buckets with a poor hash function. - * - * To allow the compiler to optimize the modulo operation, a lookup table is - * used with constant primes numbers. - * - * With a switch the code would look like: - * \code - * switch(iprime) { // iprime is the current prime of the hash table - * case 0: hash % 5ul; - * break; - * case 1: hash % 17ul; - * break; - * case 2: hash % 29ul; - * break; - * ... - * } - * \endcode - * - * Due to the constant variable in the modulo the compiler is able to optimize - * the operation by a series of multiplications, substractions and shifts. - * - * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) - * * 5' in a 64 bits environment. - */ - class prime_growth_policy + }}; + + } // namespace detail + + /** + * Grow the hash table by using prime numbers as bucket count. Slower than + * tsl::hh::power_of_two_growth_policy in general but will probably distribute + * the values around better in the buckets with a poor hash function. + * + * To allow the compiler to optimize the modulo operation, a lookup table is + * used with constant primes numbers. + * + * With a switch the code would look like: + * \code + * switch(iprime) { // iprime is the current prime of the hash table + * case 0: hash % 5ul; + * break; + * case 1: hash % 17ul; + * break; + * case 2: hash % 29ul; + * break; + * ... + * } + * \endcode + * + * Due to the constant variable in the modulo the compiler is able to optimize + * the operation by a series of multiplications, substractions and shifts. + * + * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) + * * 5' in a 64 bits environment. + */ + class prime_growth_policy + { + public: + explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) - { - auto it_prime = - std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); - if (it_prime == detail::PRIMES.end()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = *it_prime; - } - else { - min_bucket_count_in_out = 0; - } + auto it_prime = + std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); + if (it_prime == detail::PRIMES.end()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept - { - return detail::MOD_PRIME[m_iprime](hash); + m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = *it_prime; + } + else { + min_bucket_count_in_out = 0; } + } - std::size_t next_bucket_count() const - { - if (m_iprime + 1 >= detail::PRIMES.size()) { - TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } + std::size_t bucket_for_hash(std::size_t hash) const noexcept + { + return detail::MOD_PRIME[m_iprime](hash); + } - return detail::PRIMES[m_iprime + 1]; + std::size_t next_bucket_count() const + { + if (m_iprime + 1 >= detail::PRIMES.size()) { + TSL_HH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t max_bucket_count() const { return detail::PRIMES.back(); } + return detail::PRIMES[m_iprime + 1]; + } + + std::size_t max_bucket_count() const { return detail::PRIMES.back(); } - void clear() noexcept { m_iprime = 0; } + void clear() noexcept { m_iprime = 0; } - private: - unsigned int m_iprime; + private: + unsigned int m_iprime; - static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), - "The type of m_iprime is not big enough."); - }; + static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), + "The type of m_iprime is not big enough."); + }; - } // namespace hh -} // namespace tsl +} // namespace tsl::hh #endif diff --git a/packages/seacas/libraries/ioss/src/hopscotch_hash.h b/packages/seacas/libraries/ioss/src/hopscotch_hash.h index 9117cff012..00f421125d 100644 --- a/packages/seacas/libraries/ioss/src/hopscotch_hash.h +++ b/packages/seacas/libraries/ioss/src/hopscotch_hash.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2017, 2022 Thibaut Goetghebuer-Planchon + * Copyright (c) 2017, 2022, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -47,6 +47,7 @@ #define TSL_HH_NO_RANGE_ERASE_WITH_CONST_ITERATOR #endif +// NOLINTBEGIN namespace tsl { namespace detail_hopscotch_hash { @@ -681,10 +682,11 @@ namespace tsl { } hopscotch_hash(hopscotch_hash &&other) noexcept( - std::is_nothrow_move_constructible::value &&std::is_nothrow_move_constructible< - KeyEqual>::value &&std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_constructible::value) + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value) : Hash(std::move(static_cast(other))), KeyEqual(std::move(static_cast(other))), GrowthPolicy(std::move(static_cast(other))), @@ -708,8 +710,8 @@ namespace tsl { hopscotch_hash &operator=(const hopscotch_hash &other) { if (&other != this) { - Hash:: operator=(other); - KeyEqual:: operator=(other); + Hash::operator=(other); + KeyEqual::operator=(other); GrowthPolicy::operator=(other); m_buckets_data = other.m_buckets_data; @@ -1467,7 +1469,7 @@ namespace tsl { /* * Return true if a rehash will change the position of a key-value in the * neighborhood of ibucket_neighborhood_check. In this case a rehash is needed - * instead of puting the value in overflow list. + * instead of putting the value in overflow list. */ bool will_neighborhood_change_on_rehash(size_t ibucket_neighborhood_check) const { @@ -1845,7 +1847,7 @@ namespace tsl { /** * Min size of the hash table before a rehash can occurs automatically (except * if m_max_load_threshold_rehash os reached). If the neighborhood of a bucket - * is full before the min is reacher, the elements are put into + * is full before the min is reached, the elements are put into * m_overflow_elements. */ size_type m_min_load_threshold_rehash; @@ -1862,5 +1864,6 @@ namespace tsl { } // end namespace detail_hopscotch_hash } // end namespace tsl +// NOLINTEND #endif diff --git a/packages/seacas/libraries/ioss/src/main/CMakeLists.txt b/packages/seacas/libraries/ioss/src/main/CMakeLists.txt index e4259a8ad7..ed0add3e98 100644 --- a/packages/seacas/libraries/ioss/src/main/CMakeLists.txt +++ b/packages/seacas/libraries/ioss/src/main/CMakeLists.txt @@ -278,12 +278,15 @@ TRIBITS_ADD_ADVANCED_TEST(exodus32_to_unstructured_cgns ) endif() +IF (TPL_Netcdf_Enables_PNetcdf OR NOT TPL_ENABLE_MPI) TRIBITS_ADD_TEST( io_shell ARGS "${DECOMP_ARG} --compare ${CMAKE_CURRENT_SOURCE_DIR}/test/8-block.g ${CMAKE_CURRENT_SOURCE_DIR}/test/8-block.g" NAME io_shell_compare_same_database NOEXEPREFIX NOEXESUFFIX + NUM_MPI_PROCS ${NPROCS} COMM mpi serial ) +ENDIF() TRIBITS_ADD_TEST( io_shell ARGS "${DECOMP_ARG} --compare ${CMAKE_CURRENT_SOURCE_DIR}/test/multiple_zones_fields.cgns ${CMAKE_CURRENT_SOURCE_DIR}/test/multiple_zones_fields.cgns" diff --git a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C index 741422a118..79aaa878b7 100644 --- a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C +++ b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C @@ -45,7 +45,9 @@ #include #include +#if !defined __NVCC__ #include +#endif #include namespace { @@ -68,11 +70,11 @@ namespace { if (options_.retrieve("output") != nullptr) { const std::string temp = options_.retrieve("output"); - histogram = temp.find("h") != std::string::npos; - work_per_processor = temp.find("w") != std::string::npos; - zone_proc_assignment = temp.find("z") != std::string::npos; - verbose = temp.find("v") != std::string::npos || verbose; - communication_map = temp.find("c") != std::string::npos; + histogram = temp.find('h') != std::string::npos; + work_per_processor = temp.find('w') != std::string::npos; + zone_proc_assignment = temp.find('z') != std::string::npos; + verbose = temp.find('v') != std::string::npos || verbose; + communication_map = temp.find('c') != std::string::npos; } if (options_.retrieve("version") != nullptr) { @@ -185,7 +187,7 @@ namespace { return true; } - explicit Interface(const std::string &app_version) : version(app_version) + explicit Interface(std::string app_version) : version(std::move(app_version)) { options_.usage("[options] input_file"); options_.enroll("help", Ioss::GetLongOption::NoValue, "Print this summary and exit", nullptr); @@ -242,8 +244,9 @@ namespace { double surface_ratio(const Iocgns::StructuredZoneData *zone) { size_t surf = - 2 * (zone->m_ordinal[0] * zone->m_ordinal[1] + zone->m_ordinal[0] * zone->m_ordinal[2] + - zone->m_ordinal[1] * zone->m_ordinal[2]); + (zone->m_ordinal[0] * zone->m_ordinal[1] + zone->m_ordinal[0] * zone->m_ordinal[2] + + zone->m_ordinal[1] * zone->m_ordinal[2]) * + static_cast(2); size_t vol = zone->cell_count(); // If a 'perfect' cube, then would be pl=cbrt(vol) on a side and surf would be 6*pl*pl @@ -390,7 +393,10 @@ namespace { auto search = comms.find(std::make_pair(value, key)); if (search == comms.end()) { valid = false; - fmt::print(stderr, fg(fmt::color::red), + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "ERROR: Could not find matching ZGC for {}, proc {} -> {}, proc {}\n", key.first, key.second, value.first, value.second); } @@ -441,7 +447,11 @@ namespace { for (const auto &proc : comms) { if (proc.second < 0) { // From decomposition - fmt::print(fg(fmt::color::yellow), "[{:{}}->{:{}}] ", proc.first, pw, -proc.second, + fmt::print( +#if !defined __NVCC__ + fg(fmt::color::yellow), +#endif + "[{:{}}->{:{}}] ", proc.first, pw, -proc.second, pw); } else { @@ -634,11 +644,19 @@ namespace { std::string stars(star_cnt, '*'); std::string format = "\tProcessor {:{}}, work = {:{}} ({:.2f})\t{}\n"; if (proc_work[i] == max_work) { - fmt::print(fg(fmt::color::red), format, i, proc_width, fmt::group_digits(proc_work[i]), + fmt::print( +#if !defined __NVCC__ + fg(fmt::color::red), +#endif + format, i, proc_width, fmt::group_digits(proc_work[i]), work_width, proc_work[i] / avg_work, stars); } else if (proc_work[i] == min_work) { - fmt::print(fg(fmt::color::green), format, i, proc_width, + fmt::print( +#if !defined __NVCC__ + fg(fmt::color::green), +#endif + format, i, proc_width, fmt::group_digits(proc_work[i]), work_width, proc_work[i] / avg_work, stars); } else { @@ -787,7 +805,10 @@ int main(int argc, char *argv[]) auto valid = validate_symmetric_communications(zones); if (!valid) { - fmt::print(stderr, fg(fmt::color::red), + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "\nERROR: Zone Grid Communication interfaces are not symmetric. There is an error " "in the decomposition.\n"); } diff --git a/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C b/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C index 45ae0dce57..29404dc8b3 100644 --- a/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C +++ b/packages/seacas/libraries/ioss/src/main/cth_pressure_map.C @@ -767,9 +767,7 @@ namespace { // Iterate through results fields and transfer to output // database... If a prefix is specified, only transfer fields // whose names begin with the prefix - Ioss::NameList::const_iterator IF; - for (IF = fields.begin(); IF != fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : fields) { if (field_name != "ids" && !oge->field_exists(field_name) && Ioss::Utils::substr_equal(prefix, field_name)) { // If the field does not already exist, add it to the output node block @@ -787,13 +785,10 @@ namespace { // database and transfer to output database. Ioss::NameList state_fields = ige->field_describe(role); - Ioss::NameList::const_iterator IF; - // Complication here is that if the 'role' is 'Ioss::Field::MESH', // then the 'ids' field must be transferred first... if (role == Ioss::Field::MESH) { - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : state_fields) { assert(oge->field_exists(field_name)); if (field_name == "ids") { transfer_field_data_internal(ige, oge, field_name); @@ -802,8 +797,7 @@ namespace { } } - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + for (const auto &field_name : state_fields) { // All of the 'Ioss::EntityBlock' derived classes have a // 'connectivity' field, but it is only interesting on the // Ioss::ElementBlock class. On the other classes, it just @@ -878,11 +872,11 @@ namespace { void add_sideset(Ioss::Region &ss_region, Ioss::Region & /* region */, Ioss::Region &output_region, Globals &globals) { - Ioss::SideSet *pressures = new Ioss::SideSet(output_region.get_database(), "cth_pressures"); + auto *pressures = new Ioss::SideSet(output_region.get_database(), "cth_pressures"); // Each element block in the sset file will be a surside in the mesh file... { - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { std::string name = (*i)->name(); name = "ss" + name; @@ -908,8 +902,8 @@ namespace { { // Each element block in the sset file will be a surface in the mesh file... { - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { std::string name = (*i)->name(); name = "ss" + name; @@ -975,8 +969,8 @@ namespace { if (globals.convert_gage) { ss_region.begin_state(1); - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { // The gage pressure conversion is currently only applied to the field "cth_pressure" @@ -1001,8 +995,8 @@ namespace { if (globals.offset_time > 0.0) { int ostep = output_region.add_state(0.0); output_region.begin_state(ostep); - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const std::string &eb_name = (*i)->name(); std::string name = "ss" + eb_name; @@ -1012,11 +1006,8 @@ namespace { std::exit(EXIT_FAILURE); } - Ioss::NameList state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); - Ioss::NameList::const_iterator IF; - - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + auto state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : state_fields) { // NOTE: Only dealing with the "cth_" fields here. // If there are other fields, we probably have an invalid // output database... @@ -1024,7 +1015,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); for (int ii = 0; ii < count; ii++) { rdata[ii] = globals.offset_pressure; } @@ -1052,22 +1043,19 @@ namespace { output_region.begin_state(ostep); ss_region.begin_state(istep); - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const std::string &eb_name = (*i)->name(); std::string name = "ss" + eb_name; - Ioss::SideBlock *fb = output_region.get_sideblock(name); + auto *fb = output_region.get_sideblock(name); if (fb == nullptr) { std::cerr << "INTERNAL ERROR: Could not find side block named '" << name << "'\n"; std::exit(EXIT_FAILURE); } - Ioss::NameList state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); - Ioss::NameList::const_iterator IF; - - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + auto state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : state_fields) { if (globals.convert_gage && field_name == cth_pressure) { // Subtract the time zero pressures (stored in // time_zero_field_data) from each time step @@ -1077,7 +1065,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); (*i)->get_field_data(field_name, &data[0], isize); for (int ii = 0; ii < count; ii++) { @@ -1095,7 +1083,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); (*i)->get_field_data(field_name, &data[0], isize); for (int ii = 0; ii < count; ii++) { @@ -1137,8 +1125,8 @@ namespace { // an // "equilibrium" state in case the CTH analysis was not run out to an equilibrium // state. If ZERO was specified, then it simply zeros out the pressure field at the last step. - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); + const auto &ebs = ss_region.get_element_blocks(); + auto i = ebs.begin(); while (i != ebs.end()) { const std::string &eb_name = (*i)->name(); std::string name = "ss" + eb_name; @@ -1149,11 +1137,8 @@ namespace { throw std::runtime_error(msg.str()); } - Ioss::NameList state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); - Ioss::NameList::const_iterator IF; - - for (IF = state_fields.begin(); IF != state_fields.end(); ++IF) { - std::string field_name = *IF; + auto state_fields = (*i)->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : state_fields) { if (Ioss::Utils::substr_equal("cth_", field_name)) { if (field_name == cth_pressure && (globals.final_pressure == Globals::ZERO || @@ -1171,7 +1156,7 @@ namespace { int isize = (*i)->get_field(field_name).get_size(); int count = (*i)->get_field(field_name).raw_count(); data.resize(isize); - double *rdata = reinterpret_cast(&data[0]); + auto *rdata = reinterpret_cast(&data[0]); for (int ii = 0; ii < count; ii++) { rdata[ii] = value; } @@ -1204,12 +1189,11 @@ namespace { { // Each element block in the sset file will be a surface in the mesh file... { - const Ioss::ElementBlockContainer &ebs = ss_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); - while (i != ebs.end()) { - std::string name = (*i)->name(); - name = "ss" + name; - Ioss::SideBlock *fb = output_region.get_sideblock(name); + const auto &ebs = ss_region.get_element_blocks(); + for (auto *eb : ebs) { + std::string name = eb->name(); + name = "ss" + name; + auto *fb = output_region.get_sideblock(name); assert(fb != nullptr); if (globals.debug) { @@ -1218,8 +1202,7 @@ namespace { // Each element variable in the sset file which begins with // "cth_" will be a sideset variable in the outptut file... } - transfer_fields((*i), fb, Ioss::Field::TRANSIENT, "cth_"); - ++i; + transfer_fields(eb, fb, Ioss::Field::TRANSIENT, "cth_"); } } } @@ -1228,20 +1211,17 @@ namespace { { // Define output fields... { - const Ioss::VariableType *v3d = Ioss::VariableType::factory("vector_3d"); + const auto *v3d = Ioss::VariableType::factory("vector_3d"); output_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT); - Ioss::NodeBlock *nb = (*output_region.get_node_blocks().begin()); - int num_nodes = nb->entity_count(); - Ioss::Field node_normal("node_normal", Ioss::Field::REAL, v3d, Ioss::Field::TRANSIENT, - num_nodes); + auto *nb = (*output_region.get_node_blocks().begin()); + int num_nodes = nb->entity_count(); + Ioss::Field node_normal("node_normal", Ioss::Field::REAL, v3d, Ioss::Field::TRANSIENT, + num_nodes); nb->field_add(node_normal); // Iterate over the element blocks and calculate both node normals and face normals... - const Ioss::ElementBlockContainer &ebs = output_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator ib = ebs.begin(); - while (ib != ebs.end()) { - Ioss::ElementBlock *eb = *ib; - ++ib; + const auto &ebs = output_region.get_element_blocks(); + for (auto *eb : ebs) { int num_elem = eb->entity_count(); Ioss::Field face_normal("face_normal", Ioss::Field::REAL, v3d, Ioss::Field::TRANSIENT, num_elem); @@ -1254,8 +1234,8 @@ namespace { int ostep = output_region.add_state(0.0); output_region.begin_state(ostep); - Ioss::NodeBlock *nb = (*region.get_node_blocks().begin()); - Ioss::NodeBlock *nbo = (*output_region.get_node_blocks().begin()); + auto *nb = (*region.get_node_blocks().begin()); + auto *nbo = (*output_region.get_node_blocks().begin()); // Get the nodal coordinates... int num_nodes = nb->entity_count(); @@ -1271,17 +1251,13 @@ namespace { std::fill(node_normal.begin(), node_normal.end(), 0.0); // Iterate over the element blocks and calculate both node normals and face normals... - std::vector conn; - std::vector face_normal; - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - - Ioss::ElementBlockContainer::const_iterator ib = ebs.begin(); - while (ib != ebs.end()) { - Ioss::ElementBlock *eb = *ib; - ++ib; + std::vector conn; + std::vector face_normal; + const auto &ebs = region.get_element_blocks(); + for (const auto *eb : ebs) { const std::string &name = (*eb).name(); - Ioss::ElementBlock *ebo = output_region.get_element_block(name); + auto *ebo = output_region.get_element_block(name); if (ebo == nullptr) { std::cerr << "INTERNAL ERROR: Could not find element block named '" << name << "'\n"; std::exit(EXIT_FAILURE); diff --git a/packages/seacas/libraries/ioss/src/main/io_info.C b/packages/seacas/libraries/ioss/src/main/io_info.C index 99792757ff..22377e5c68 100644 --- a/packages/seacas/libraries/ioss/src/main/io_info.C +++ b/packages/seacas/libraries/ioss/src/main/io_info.C @@ -7,6 +7,8 @@ #include "io_info.h" #include #include +#include +#include #include #define FMT_DEPRECATED_OSTREAM #include @@ -118,7 +120,12 @@ namespace { char group_name[33]; // Print name of this group... ex_inquire(exoid, EX_INQ_GROUP_NAME, &idum, &rdum, group_name); - fmt::print("{}{}\n", prefix, group_name); + if (group_name[0] == '/') { + fmt::print("{}/ (root)\n", prefix); + } + else { + fmt::print("{}{}\n", prefix, group_name); + } int num_children = ex_inquire_int(exoid, EX_INQ_NUM_CHILD_GROUPS); std::vector children(num_children); @@ -142,7 +149,7 @@ namespace { int exoid = ex_open(inpfile.c_str(), EX_READ, &CPU_word_size, &IO_word_size, &vers); - print_groups(exoid, ""); + print_groups(exoid, "\t"); #endif } @@ -258,7 +265,11 @@ namespace { if (!sb->m_zoneConnectivity.empty()) { fmt::print("\tConnectivity with other blocks:\n"); for (const auto &zgc : sb->m_zoneConnectivity) { - fmt::print("{}\n", zgc); +#if defined __NVCC__ + std::cout << zgc << "\n"; +#else + fmt::print("{}\n", zgc); +#endif } } if (!sb->m_boundaryConditions.empty()) { @@ -272,7 +283,11 @@ namespace { }); for (const auto &bc : sb_bc) { +#if defined __NVCC__ + std::cout << bc << "\n"; +#else fmt::print("{}\n", bc); +#endif } } if (interFace.compute_bbox()) { @@ -578,8 +593,6 @@ namespace Ioss { void io_info_set_db_properties(const Info::Interface &interFace, Ioss::DatabaseIO *dbi) { - std::string inpfile = interFace.filename(); - if (dbi == nullptr || !dbi->ok(true)) { std::exit(EXIT_FAILURE); } @@ -600,6 +613,7 @@ namespace Ioss { if (!interFace.groupname().empty()) { bool success = dbi->open_group(interFace.groupname()); if (!success) { + std::string inpfile = interFace.filename(); fmt::print("ERROR: Unable to open group '{}' in file '{}'\n", interFace.groupname(), inpfile); return; diff --git a/packages/seacas/libraries/ioss/src/main/io_modify.C b/packages/seacas/libraries/ioss/src/main/io_modify.C index 0206ed5383..cbe5b2a6e7 100644 --- a/packages/seacas/libraries/ioss/src/main/io_modify.C +++ b/packages/seacas/libraries/ioss/src/main/io_modify.C @@ -941,7 +941,7 @@ namespace { else { fmt::print(stderr, fg(fmt::color::red), "ERROR: Requested Assembly '{}' was not created during this execution. Not " - "deleteable.\n", + "deletable.\n", tokens[1]); return false; } @@ -967,7 +967,10 @@ namespace { if (Ioss::Utils::substr_equal(tokens[2], "add")) { // Must be at least 6 tokens... if (tokens.size() < 6) { - fmt::print(stderr, fg(fmt::color::red), + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "ERROR: ATTRIBUTE Command does not have enough tokens to be valid.\n" "\t\t{}\n", fmt::join(tokens, " ")); @@ -988,7 +991,7 @@ namespace { } // Now get name of attribute/property to create... - std::string att_name = tokens[3]; + const std::string &att_name = tokens[3]; // Now, the attribute type and whether vector or scalar... size_t value_count = tokens.size() - 5; @@ -1086,7 +1089,10 @@ namespace { // Must be at least 4 tokens... if (tokens.size() < 4) { - fmt::print(stderr, fg(fmt::color::red), + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "ERROR: RENAME Command does not have enough tokens to be valid.\n" "\t\t{}\n", fmt::join(tokens, " ")); @@ -1096,7 +1102,7 @@ namespace { // See if asking for actual entity by name or by type + id Ioss::GroupingEntity *ge = nullptr; - std::string new_name = tokens[tokens.size() - 1]; + const std::string &new_name = tokens[tokens.size() - 1]; if (tokens.size() == 5 && Ioss::Utils::str_equal(tokens[3], "to")) { // Type + ID @@ -1123,7 +1129,11 @@ namespace { } } else { - fmt::print(stderr, fg(fmt::color::yellow), "\tWARNING: Unrecognized rename syntax '{}'\n", + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::yellow), +#endif + "\tWARNING: Unrecognized rename syntax '{}'\n", fmt::join(tokens, " ")); handle_help("rename"); } @@ -1203,7 +1213,10 @@ namespace { // TIME SCALE {{scale}} // TIME OFFSET {{offset} if (tokens.size() < 3) { - fmt::print(stderr, fg(fmt::color::red), + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "ERROR: TIME Command does not have enough tokens to be valid.\n" "\t\t{}\n", fmt::join(tokens, " ")); @@ -1238,7 +1251,10 @@ namespace { // GEOMETRY OFFSET {{ELEMENTBLOCKS|BLOCKS|ASSEMBLY}} {{names}} {{X|Y|Z}} {{offset}} ... if (tokens.size() < 4) { - fmt::print(stderr, fg(fmt::color::red), + fmt::print(stderr, +#if !defined __NVCC__ + fg(fmt::color::red), +#endif "ERROR: GEOMETRY Command does not have enough tokens to be valid.\n" "\t\t{}\n", fmt::join(tokens, " ")); @@ -1257,8 +1273,8 @@ namespace { while (!(Ioss::Utils::str_equal(tokens[idx], "x") || Ioss::Utils::str_equal(tokens[idx], "y") || Ioss::Utils::str_equal(tokens[idx], "z"))) { - auto name = tokens[idx++]; - auto *ge = region.get_entity(name, Ioss::ELEMENTBLOCK); + const auto &name = tokens[idx++]; + auto *ge = region.get_entity(name, Ioss::ELEMENTBLOCK); if (ge == nullptr) { ge = region.get_entity(name, Ioss::ASSEMBLY); } @@ -1306,9 +1322,9 @@ namespace { // Get rotation axis... do { - std::string axis = tokens[idx++]; - double angle = std::stod(tokens[idx++]); - auto ok = update_rotation_matrix(rotation_matrix, axis, angle); + const std::string &axis = tokens[idx++]; + double angle = std::stod(tokens[idx++]); + auto ok = update_rotation_matrix(rotation_matrix, axis, angle); if (!ok) { return false; } @@ -1325,8 +1341,8 @@ namespace { // Get scale axis and scale factor... do { - std::string axis = tokens[idx++]; - double factor = std::stod(tokens[idx++]); + const std::string &axis = tokens[idx++]; + double factor = std::stod(tokens[idx++]); if (Ioss::Utils::substr_equal(axis, "x")) { scale[0] = factor; } @@ -1349,8 +1365,8 @@ namespace { // Get offset axis and offset factor... do { - std::string axis = tokens[idx++]; - double factor = std::stod(tokens[idx++]); + const std::string &axis = tokens[idx++]; + double factor = std::stod(tokens[idx++]); if (Ioss::Utils::substr_equal(axis, "x")) { offset[0] = factor; } diff --git a/packages/seacas/libraries/ioss/src/main/io_shell.C b/packages/seacas/libraries/ioss/src/main/io_shell.C index cc0f7ecb7e..15e754e68b 100644 --- a/packages/seacas/libraries/ioss/src/main/io_shell.C +++ b/packages/seacas/libraries/ioss/src/main/io_shell.C @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - codename = interFace.options_.basename(argv[0]); + codename = Ioss::GetLongOption::basename(argv[0]); Ioss::SerializeIO::setGroupFactor(interFace.serialize_io_size); mem_stats = interFace.memory_statistics; @@ -424,145 +424,145 @@ namespace { bool file_compare(IOShell::Interface &interFace, int rank) { Ioss::PropertyManager properties = set_properties(interFace); - const auto &inpfile = interFace.inputFile[0]; - - //======================================================================== - // INPUT Database #1... - //======================================================================== - Ioss::DatabaseIO *dbi1 = - Ioss::IOFactory::create(interFace.inFiletype, inpfile, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), properties); - if (dbi1 == nullptr || !dbi1->ok(true)) { - std::exit(EXIT_FAILURE); - } + const auto &inpfile = interFace.inputFile[0]; + + //======================================================================== + // INPUT Database #1... + //======================================================================== + Ioss::DatabaseIO *dbi1 = + Ioss::IOFactory::create(interFace.inFiletype, inpfile, Ioss::READ_MODEL, + Ioss::ParallelUtils::comm_world(), properties); + if (dbi1 == nullptr || !dbi1->ok(true)) { + std::exit(EXIT_FAILURE); + } - if (mem_stats) { - dbi1->progress("Database #1 Open"); - } - if (!interFace.lower_case_variable_names) { - dbi1->set_lower_case_variable_names(false); - } - if (interFace.outFiletype == "cgns") { - // CGNS stores BCs (SideSets) on the zones which - // correspond to element blocks. If split input sideblocks - // by element block, then output is much easier. - dbi1->set_surface_split_type(Ioss::SPLIT_BY_ELEMENT_BLOCK); - } - else { - dbi1->set_surface_split_type(Ioss::int_to_surface_split(interFace.surface_split_type)); - } - dbi1->set_field_separator(interFace.fieldSuffixSeparator); + if (mem_stats) { + dbi1->progress("Database #1 Open"); + } + if (!interFace.lower_case_variable_names) { + dbi1->set_lower_case_variable_names(false); + } + if (interFace.outFiletype == "cgns") { + // CGNS stores BCs (SideSets) on the zones which + // correspond to element blocks. If split input sideblocks + // by element block, then output is much easier. + dbi1->set_surface_split_type(Ioss::SPLIT_BY_ELEMENT_BLOCK); + } + else { + dbi1->set_surface_split_type(Ioss::int_to_surface_split(interFace.surface_split_type)); + } + dbi1->set_field_separator(interFace.fieldSuffixSeparator); - dbi1->set_field_recognition(!interFace.disable_field_recognition); + dbi1->set_field_recognition(!interFace.disable_field_recognition); - if (interFace.ints_64_bit) { - dbi1->set_int_byte_size_api(Ioss::USE_INT64_API); - } + if (interFace.ints_64_bit) { + dbi1->set_int_byte_size_api(Ioss::USE_INT64_API); + } - if (!interFace.groupName.empty()) { - bool success = dbi1->open_group(interFace.groupName); - if (!success) { - if (rank == 0) { - fmt::print(stderr, "ERROR: Unable to open group '{}' in file '{}'\n", - interFace.groupName, inpfile); - } - return false; + if (!interFace.groupName.empty()) { + bool success = dbi1->open_group(interFace.groupName); + if (!success) { + if (rank == 0) { + fmt::print(stderr, "ERROR: Unable to open group '{}' in file '{}'\n", interFace.groupName, + inpfile); } + return false; } + } - // NOTE: 'input_region1' owns 'dbi1' pointer at this time... - Ioss::Region input_region1(dbi1, "region_1"); + // NOTE: 'input_region1' owns 'dbi1' pointer at this time... + Ioss::Region input_region1(dbi1, "region_1"); - if (input_region1.mesh_type() == Ioss::MeshType::HYBRID) { - fmt::print(stderr, - "\nERROR: io_shell does not support '{}' meshes. Only 'Unstructured' or " - "'Structured' mesh is supported at this time.\n", - input_region1.mesh_type_string()); - return false; - } + if (input_region1.mesh_type() == Ioss::MeshType::HYBRID) { + fmt::print(stderr, + "\nERROR: io_shell does not support '{}' meshes. Only 'Unstructured' or " + "'Structured' mesh is supported at this time.\n", + input_region1.mesh_type_string()); + return false; + } - // Get integer size being used on input file #1 and set it in - // the interFace. - int int_byte_size_api = dbi1->int_byte_size_api(); - if (int_byte_size_api == 8) { - interFace.ints_64_bit = true; - } + // Get integer size being used on input file #1 and set it in + // the interFace. + int int_byte_size_api = dbi1->int_byte_size_api(); + if (int_byte_size_api == 8) { + interFace.ints_64_bit = true; + } - //======================================================================== - // INPUT Database #2... - //======================================================================== - Ioss::DatabaseIO *dbi2 = - Ioss::IOFactory::create(interFace.outFiletype, interFace.outputFile, Ioss::READ_MODEL, - Ioss::ParallelUtils::comm_world(), properties); - if (dbi2 == nullptr || !dbi2->ok(true)) { - std::exit(EXIT_FAILURE); - } + //======================================================================== + // INPUT Database #2... + //======================================================================== + Ioss::DatabaseIO *dbi2 = + Ioss::IOFactory::create(interFace.outFiletype, interFace.outputFile, Ioss::READ_MODEL, + Ioss::ParallelUtils::comm_world(), properties); + if (dbi2 == nullptr || !dbi2->ok(true)) { + std::exit(EXIT_FAILURE); + } - if (mem_stats) { - dbi2->progress("Database #2 Open"); - } - if (!interFace.lower_case_variable_names) { - dbi2->set_lower_case_variable_names(false); - } - if (interFace.outFiletype == "cgns") { - // CGNS stores BCs (SideSets) on the zones which - // correspond to element blocks. If split input sideblocks - // by element block, then output is much easier. - dbi2->set_surface_split_type(Ioss::SPLIT_BY_ELEMENT_BLOCK); - } - else { - dbi2->set_surface_split_type(Ioss::int_to_surface_split(interFace.surface_split_type)); - } - dbi2->set_field_separator(interFace.fieldSuffixSeparator); + if (mem_stats) { + dbi2->progress("Database #2 Open"); + } + if (!interFace.lower_case_variable_names) { + dbi2->set_lower_case_variable_names(false); + } + if (interFace.outFiletype == "cgns") { + // CGNS stores BCs (SideSets) on the zones which + // correspond to element blocks. If split input sideblocks + // by element block, then output is much easier. + dbi2->set_surface_split_type(Ioss::SPLIT_BY_ELEMENT_BLOCK); + } + else { + dbi2->set_surface_split_type(Ioss::int_to_surface_split(interFace.surface_split_type)); + } + dbi2->set_field_separator(interFace.fieldSuffixSeparator); - dbi2->set_field_recognition(!interFace.disable_field_recognition); + dbi2->set_field_recognition(!interFace.disable_field_recognition); - if (interFace.ints_64_bit) { - dbi2->set_int_byte_size_api(Ioss::USE_INT64_API); - } + if (interFace.ints_64_bit) { + dbi2->set_int_byte_size_api(Ioss::USE_INT64_API); + } - if (!interFace.groupName.empty()) { - bool success = dbi2->open_group(interFace.groupName); - if (!success) { - if (rank == 0) { - fmt::print(stderr, "ERROR: Unable to open group '{}' in file '{}'\n", - interFace.groupName, inpfile); - } - return false; + if (!interFace.groupName.empty()) { + bool success = dbi2->open_group(interFace.groupName); + if (!success) { + if (rank == 0) { + fmt::print(stderr, "ERROR: Unable to open group '{}' in file '{}'\n", interFace.groupName, + inpfile); } + return false; } + } - // NOTE: 'input_region2' owns 'dbi2' pointer at this time... - Ioss::Region input_region2(dbi2, "region_2"); + // NOTE: 'input_region2' owns 'dbi2' pointer at this time... + Ioss::Region input_region2(dbi2, "region_2"); - if (input_region2.mesh_type() == Ioss::MeshType::HYBRID) { - fmt::print(stderr, - "\nERROR: io_shell does not support '{}' meshes. Only 'Unstructured' or " - "'Structured' mesh is supported at this time.\n", - input_region2.mesh_type_string()); - return false; - } + if (input_region2.mesh_type() == Ioss::MeshType::HYBRID) { + fmt::print(stderr, + "\nERROR: io_shell does not support '{}' meshes. Only 'Unstructured' or " + "'Structured' mesh is supported at this time.\n", + input_region2.mesh_type_string()); + return false; + } - // Get integer size being used on input file #1 and set it in - // the interFace. - int_byte_size_api = dbi2->int_byte_size_api(); - if (int_byte_size_api == 8) { - interFace.ints_64_bit = true; - } + // Get integer size being used on input file #1 and set it in + // the interFace. + int_byte_size_api = dbi2->int_byte_size_api(); + if (int_byte_size_api == 8) { + interFace.ints_64_bit = true; + } - //======================================================================== - // COMPARE the databases... - //======================================================================== - auto options = set_mesh_copy_options(interFace); + //======================================================================== + // COMPARE the databases... + //======================================================================== + auto options = set_mesh_copy_options(interFace); - bool result = Ioss::Compare::compare_database(input_region1, input_region2, options); - if (result) { - fmt::print(stderr, "\n\nDATABASES are EQUAL"); - } - else { - fmt::print(stderr, "\n\nDATABASES are NOT equal"); - } - return result; + bool result = Ioss::Compare::compare_database(input_region1, input_region2, options); + if (result) { + fmt::print(stderr, "\n\nDATABASES are EQUAL"); + } + else { + fmt::print(stderr, "\n\nDATABASES are NOT equal"); + } + return result; } Ioss::PropertyManager set_properties(IOShell::Interface &interFace) diff --git a/packages/seacas/libraries/ioss/src/main/shell_interface.C b/packages/seacas/libraries/ioss/src/main/shell_interface.C index 079d9d5708..4c1ff94e6e 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_interface.C +++ b/packages/seacas/libraries/ioss/src/main/shell_interface.C @@ -21,7 +21,7 @@ #include // for string, char_traits #include // for vector -IOShell::Interface::Interface(const std::string &app_version) : version(app_version) +IOShell::Interface::Interface(std::string app_version) : version(std::move(app_version)) { enroll_options(); } @@ -345,7 +345,7 @@ bool IOShell::Interface::parse_options(int argc, char **argv, int my_processor) "\nThe following options were specified via the IO_SHELL_OPTIONS environment variable:\n" "\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, Ioss::GetLongOption::basename(*argv)); } int option_index = options_.parse(argc, argv); diff --git a/packages/seacas/libraries/ioss/src/main/shell_interface.h b/packages/seacas/libraries/ioss/src/main/shell_interface.h index 713d389a69..e7b6d88468 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_interface.h +++ b/packages/seacas/libraries/ioss/src/main/shell_interface.h @@ -20,7 +20,7 @@ namespace IOShell { class Interface { public: - explicit Interface(const std::string &app_version); + explicit Interface(std::string app_version); ~Interface(); bool parse_options(int argc, char **argv, int my_processor); @@ -40,7 +40,7 @@ namespace IOShell { std::string decomp_method; std::string decomp_extra{"processor_id"}; std::string compose_output{"default"}; - std::string customField{""}; + std::string customField{}; double maximum_time{std::numeric_limits::max()}; double minimum_time{-std::numeric_limits::max()}; double append_time{std::numeric_limits::max()}; diff --git a/packages/seacas/libraries/ioss/src/main/shell_to_hex.C b/packages/seacas/libraries/ioss/src/main/shell_to_hex.C index 97ba657b28..f42257caa6 100644 --- a/packages/seacas/libraries/ioss/src/main/shell_to_hex.C +++ b/packages/seacas/libraries/ioss/src/main/shell_to_hex.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -281,8 +281,8 @@ namespace { void transfer_nodeblock(Ioss::Region ®ion, Ioss::Region &output_region, bool debug) { - const Ioss::NodeBlockContainer &nbs = region.get_node_blocks(); - Ioss::NodeBlockContainer::const_iterator i = nbs.begin(); + const auto &nbs = region.get_node_blocks(); + auto i = nbs.begin(); while (i != nbs.end()) { const std::string &name = (*i)->name(); if (debug) { @@ -306,9 +306,9 @@ namespace { void transfer_elementblock(Ioss::Region ®ion, Ioss::Region &output_region, bool debug) { - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator i = ebs.begin(); - size_t total_elements = 0; + const auto &ebs = region.get_element_blocks(); + auto i = ebs.begin(); + size_t total_elements = 0; while (i != ebs.end()) { const std::string &name = (*i)->name(); if (debug) { @@ -342,14 +342,11 @@ namespace { void transfer_properties(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge) { - Ioss::NameList names; - ige->property_describe(&names); - + auto names = ige->property_describe(); // Iterate through properties and transfer to output database... - Ioss::NameList::const_iterator I; - for (I = names.begin(); I != names.end(); ++I) { - if (!oge->property_exists(*I)) { - oge->property_add(ige->get_property(*I)); + for (const auto &name : names) { + if (!oge->property_exists(name)) { + oge->property_add(ige->get_property(name)); } } } @@ -380,13 +377,13 @@ namespace { std::fill(node_normal.begin(), node_normal.end(), 0.0); // Iterate over the element blocks and calculate node normals - std::vector conn; - std::vector output_conn; - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - const Ioss::ElementBlockContainer &out_ebs = output_region.get_element_blocks(); + std::vector conn; + std::vector output_conn; + const auto &ebs = region.get_element_blocks(); + const auto &out_ebs = output_region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator ib = ebs.begin(); - Ioss::ElementBlockContainer::const_iterator out_ib = out_ebs.begin(); + auto ib = ebs.begin(); + auto out_ib = out_ebs.begin(); while (ib != ebs.end() && out_ib != out_ebs.end()) { Ioss::ElementBlock *eb = *ib; ++ib; diff --git a/packages/seacas/libraries/ioss/src/main/skinner.C b/packages/seacas/libraries/ioss/src/main/skinner.C index 0ee4a7d065..43bc4c0008 100644 --- a/packages/seacas/libraries/ioss/src/main/skinner.C +++ b/packages/seacas/libraries/ioss/src/main/skinner.C @@ -37,11 +37,17 @@ #include "skinner_interface.h" // ======================================================================== - namespace { template void skinner(Skinner::Interface &interFace, INT /*dummy*/); std::string codename; - std::string version = "0.99"; + std::string version = "1.02"; + + void transfer_field_data(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge, + Ioss::Field::RoleType role, const std::vector &ref_nodes); + + void transfer_field_data(Ioss::EntityBlock *ige, Ioss::EntityBlock *oge, + Ioss::Field::RoleType role, + const std::vector &boundary_faces); void output_table(const Ioss::ElementBlockContainer &ebs, std::map> &boundary_faces) @@ -70,6 +76,55 @@ namespace { } fmt::print("\t+{2:-^{0}}+{2:-^{1}}+\n", max_name, max_face, ""); } + + std::vector get_selected_steps(Ioss::Region ®ion, const Skinner::Interface &options) + { + // This routine checks all steps of the input database and selects those which + // meet the requirements specified in `options`. The returned (1-based) vector will have a + // value of `1` if the step is to be output and `0` if skipped. + int step_count = (int)region.get_property("state_count").get_int(); + std::vector selected_steps(step_count + 1); + + // If user specified a list of times to transfer to output database, + // process the list and find the times on the input database that are + // closest to the times in the list. + if (!options.selected_times.empty()) { + int selected_step = 0; + for (auto time : options.selected_times) { + double diff = std::numeric_limits::max(); + for (int step = 1; step <= step_count; step++) { + double db_time = region.get_state_time(step); + double cur_diff = std::abs(db_time - time); + if (cur_diff < diff) { + diff = std::abs(db_time - time); + selected_step = step; + } + } + if (selected_step > 0) { + selected_steps[selected_step] = 1; + } + } + } + else { + // User did not select specific times to be output... + // Just select them all + for (int i = 1; i <= step_count; i++) { + selected_steps[i] = 1; + } + } + + // Now, filter by min and max time... + for (int istep = 1; istep <= step_count; istep++) { + double time = region.get_state_time(istep); + if (time < options.minimum_time) { + selected_steps[istep] = 0; + } + if (time > options.maximum_time) { + selected_steps[istep] = 0; + } + } + return selected_steps; + } } // namespace int main(int argc, char *argv[]) @@ -319,6 +374,69 @@ namespace { block->put_field_data("connectivity", conn); } output_region.end_mode(Ioss::STATE_MODEL); + + size_t ts_count = region.get_optional_property("state_count", 0); + if (ts_count > 0 && interFace.output_transient()) { + + // Transfer all nodal variable names to the output database. + Ioss::NodeBlock *nbi = region.get_node_blocks()[0]; + + output_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT); + Ioss::NameList fields = nbi->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : fields) { + Ioss::Field field = nbi->get_field(field_name); + field.reset_count(ref_count); + nbo->field_add(field); + } + + // All element block variables... + for (auto &eb : ebs) { + const std::string &name = eb->name(); + auto *ebo = output_region.get_element_block(name); + if (ebo != nullptr) { + auto ebo_count = ebo->entity_count(); + Ioss::NameList efields = eb->field_describe(Ioss::Field::TRANSIENT); + for (const auto &field_name : efields) { + Ioss::Field field = eb->get_field(field_name); + field.reset_count(ebo_count); + ebo->field_add(field); + } + } + } + + output_region.end_mode(Ioss::STATE_DEFINE_TRANSIENT); + + auto selected_steps = get_selected_steps(region, interFace); + + output_region.begin_mode(Ioss::STATE_TRANSIENT); + for (size_t istep = 1; istep <= ts_count; istep++) { + if (selected_steps[istep] != 1) { + continue; + } + double time = region.get_state_time(istep); + int ostep = output_region.add_state(time); + fmt::print(stderr, "\r\tTime step {:5d} at time {:10.5e}", ostep, time); + + output_region.begin_state(ostep); + region.begin_state(istep); + + transfer_field_data(nbi, nbo, Ioss::Field::TRANSIENT, ref_nodes); + + // All element block variables... + for (auto &eb : ebs) { + const std::string &name = eb->name(); + auto *ebo = output_region.get_element_block(name); + if (ebo != nullptr) { + transfer_field_data(eb, ebo, Ioss::Field::TRANSIENT, boundary_faces[name]); + } + } + + output_region.end_state(ostep); + region.end_state(istep); + } + output_region.end_mode(Ioss::STATE_TRANSIENT); + } + if (my_rank == 0) { output_region.output_summary(std::cerr, false); } @@ -365,4 +483,88 @@ namespace { return properties; } + + void transfer_field_data_internal(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge, + const std::string &field_name, + const std::vector &ref_nodes) + { + if (oge->field_exists(field_name)) { + std::vector in; + ige->get_field_data(field_name, in); + + // Determine component count... + auto field = ige->get_field(field_name); + int comp_count = field.get_component_count(Ioss::Field::InOut::INPUT); + std::vector out; + out.reserve(oge->entity_count() * comp_count); + + for (size_t i = 0; i < ref_nodes.size(); i++) { + if (ref_nodes[i] == 1) { + for (int j = 0; j < comp_count; j++) { + auto value = in[comp_count * i + j]; + out.push_back(value); + } + } + } + assert(out.size() == (size_t)oge->entity_count() * (size_t)comp_count); + oge->put_field_data(field_name, out); + } + } + + void transfer_field_data(Ioss::GroupingEntity *ige, Ioss::GroupingEntity *oge, + Ioss::Field::RoleType role, const std::vector &ref_nodes) + { + // Iterate through the TRANSIENT-role fields of the input + // database and transfer to output database. + Ioss::NameList state_fields = ige->field_describe(role); + + for (const auto &field_name : state_fields) { + if (oge->field_exists(field_name)) { + transfer_field_data_internal(ige, oge, field_name, ref_nodes); + } + } + } + + void transfer_field_data_internal(Ioss::EntityBlock *ieb, Ioss::EntityBlock *oeb, + const std::string &field_name, + const std::vector &boundary_faces) + { + if (oeb->field_exists(field_name)) { + std::vector in; + ieb->get_field_data(field_name, in); + + // Determine component count... + auto field = ieb->get_field(field_name); + int comp_count = field.get_component_count(Ioss::Field::InOut::INPUT); + std::vector out; + out.reserve(oeb->entity_count() * comp_count); + + auto offset = ieb->get_offset(); + for (const auto &face : boundary_faces) { + auto element_id = face.element[0] / 10 - 1; + for (int j = 0; j < comp_count; j++) { + auto value = in[comp_count * (element_id - offset) + j]; + out.push_back(value); + } + } + assert(out.size() == (size_t)oeb->entity_count() * (size_t)comp_count); + oeb->put_field_data(field_name, out); + } + } + + void transfer_field_data(Ioss::EntityBlock *ieb, Ioss::EntityBlock *oeb, + Ioss::Field::RoleType role, + const std::vector &boundary_faces) + { + // Iterate through the TRANSIENT-role fields of the input + // database and transfer to output database. + Ioss::NameList state_fields = ieb->field_describe(role); + + for (const auto &field_name : state_fields) { + if (oeb->field_exists(field_name)) { + transfer_field_data_internal(ieb, oeb, field_name, boundary_faces); + } + } + } + } // namespace diff --git a/packages/seacas/libraries/ioss/src/main/skinner_interface.C b/packages/seacas/libraries/ioss/src/main/skinner_interface.C index 24a35c4b91..47a91d4cae 100644 --- a/packages/seacas/libraries/ioss/src/main/skinner_interface.C +++ b/packages/seacas/libraries/ioss/src/main/skinner_interface.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -8,6 +8,7 @@ #include "Ioss_GetLongOpt.h" // for GetLongOption, etc #include "Ioss_Utils.h" #include "skinner_interface.h" +#include "tokenize.h" #include // for nullptr #include // for exit, EXIT_SUCCESS, getenv #include @@ -56,13 +57,27 @@ void Skinner::Interface::enroll_options() "unknown"); options_.enroll("no_output", Ioss::GetLongOption::NoValue, - "Do not produce output file, just generate the faces", nullptr); + "Do not produce output file, just generate the faces", nullptr, nullptr, true); + + options_.enroll( + "output_transient", Ioss::GetLongOption::NoValue, + "Transfer nodal and element transient data from the input mesh to the output mesh.", nullptr); + + options_.enroll("Maximum_Time", Ioss::GetLongOption::MandatoryValue, + "Maximum time on input database to transfer to output database", nullptr); + + options_.enroll("Minimum_Time", Ioss::GetLongOption::MandatoryValue, + "Minimum time on input database to transfer to output database", nullptr); + + options_.enroll("select_times", Ioss::GetLongOption::MandatoryValue, + "comma-separated list of times that should be transferred to output database", + nullptr, nullptr, true); options_.enroll("ignore_face_hash_ids", Ioss::GetLongOption::NoValue, "Don't use face ids from hash of node ids; just use 1..num_face", nullptr); options_.enroll("blocks", Ioss::GetLongOption::NoValue, - "Skin block-by-block instead of entire model boundary", nullptr); + "Skin block-by-block instead of entire model boundary", nullptr, nullptr, true); options_.enroll("netcdf4", Ioss::GetLongOption::NoValue, "Output database will be a netcdf4 " @@ -76,13 +91,14 @@ void Skinner::Interface::enroll_options() options_.enroll("compress", Ioss::GetLongOption::MandatoryValue, "Specify the hdf5 compression level [0..9] to be used on the output file.", - nullptr); + nullptr, nullptr, true); +#if defined(SEACAS_HAVE_MPI) options_.enroll( "compose", Ioss::GetLongOption::OptionalValue, "If no argument, specify single-file output; if 'external', then file-per-processor.\n" "\t\tAll other options are ignored and just exist for backward-compatibility", - nullptr, "true"); + nullptr, "nullptr, true"); options_.enroll( "rcb", Ioss::GetLongOption::NoValue, @@ -132,7 +148,8 @@ void Skinner::Interface::enroll_options() options_.enroll("external", Ioss::GetLongOption::NoValue, "Files are decomposed externally into a file-per-processor in a parallel run.", - nullptr); + nullptr, nullptr, true); +#endif options_.enroll("debug", Ioss::GetLongOption::NoValue, "turn on debugging output", nullptr); @@ -153,7 +170,7 @@ bool Skinner::Interface::parse_options(int argc, char **argv) "variable:\n" "\t{}\n\n", options); - options_.parse(options, options_.basename(*argv)); + options_.parse(options, Ioss::GetLongOption::basename(*argv)); } int option_index = options_.parse(argc, argv); @@ -177,14 +194,30 @@ bool Skinner::Interface::parse_options(int argc, char **argv) exit(0); } - ints64Bit_ = options_.retrieve("64-bit") != nullptr; - netcdf4_ = options_.retrieve("netcdf4") != nullptr; - shuffle = options_.retrieve("shuffle") != nullptr; - noOutput_ = options_.retrieve("no_output") != nullptr; - useFaceHashIds_ = options_.retrieve("ignore_face_hash_ids") == nullptr; - debug = options_.retrieve("debug") != nullptr; - statistics = options_.retrieve("statistics") != nullptr; - blocks_ = options_.retrieve("blocks") != nullptr; + ints64Bit_ = options_.retrieve("64-bit") != nullptr; + netcdf4_ = options_.retrieve("netcdf4") != nullptr; + shuffle = options_.retrieve("shuffle") != nullptr; + noOutput_ = options_.retrieve("no_output") != nullptr; + outputTransient_ = options_.retrieve("output_transient") != nullptr; + useFaceHashIds_ = options_.retrieve("ignore_face_hash_ids") == nullptr; + debug = options_.retrieve("debug") != nullptr; + statistics = options_.retrieve("statistics") != nullptr; + blocks_ = options_.retrieve("blocks") != nullptr; + + maximum_time = options_.get_option_value("Maximum_Time", maximum_time); + minimum_time = options_.get_option_value("Minimum_Time", minimum_time); + + { + const char *temp = options_.retrieve("select_times"); + if (temp != nullptr) { + auto time_str = Ioss::tokenize(std::string(temp), ","); + for (const auto &str : time_str) { + auto time = std::stod(str); + selected_times.push_back(time); + } + Ioss::sort(selected_times.begin(), selected_times.end()); + } + } { const char *temp = options_.retrieve("compress"); @@ -193,6 +226,7 @@ bool Skinner::Interface::parse_options(int argc, char **argv) } } +#if defined(SEACAS_HAVE_MPI) if (options_.retrieve("rcb") != nullptr) { decomp_method = "RCB"; } @@ -234,28 +268,30 @@ bool Skinner::Interface::parse_options(int argc, char **argv) } { - const char *temp = options_.retrieve("in_type"); + const char *temp = options_.retrieve("compose"); if (temp != nullptr) { - inFiletype_ = temp; + compose_output = Ioss::Utils::lowercase(temp); } } +#endif + { - const char *temp = options_.retrieve("out_type"); + const char *temp = options_.retrieve("in_type"); if (temp != nullptr) { - outFiletype_ = temp; + inFiletype_ = temp; } } { - const char *temp = options_.retrieve("compose"); + const char *temp = options_.retrieve("out_type"); if (temp != nullptr) { - compose_output = Ioss::Utils::lowercase(temp); + outFiletype_ = temp; } } if (options_.retrieve("copyright") != nullptr) { - Ioss::Utils::copyright(std::cerr, "1999-2022"); + Ioss::Utils::copyright(std::cerr, "1999-2023"); exit(EXIT_SUCCESS); } diff --git a/packages/seacas/libraries/ioss/src/main/skinner_interface.h b/packages/seacas/libraries/ioss/src/main/skinner_interface.h index 9d2b4c1aaa..7051da4e94 100644 --- a/packages/seacas/libraries/ioss/src/main/skinner_interface.h +++ b/packages/seacas/libraries/ioss/src/main/skinner_interface.h @@ -25,6 +25,7 @@ namespace Skinner { bool ints_64_bit() const { return ints64Bit_; } bool no_output() const { return noOutput_; } + bool output_transient() const { return outputTransient_; } std::string input_filename() const { return inputFile_; } std::string output_filename() const { return outputFile_; } @@ -44,6 +45,8 @@ namespace Skinner { public: std::string decomp_method; std::string compose_output{"default"}; + double maximum_time{std::numeric_limits::max()}; + double minimum_time{-std::numeric_limits::max()}; int compression_level{0}; bool shuffle{false}; bool debug{false}; @@ -52,6 +55,10 @@ namespace Skinner { bool netcdf4_{false}; bool useFaceHashIds_{true}; bool noOutput_{false}; + bool outputTransient_{false}; bool blocks_{false}; + + //! If non-empty, then it is a list of times that should be transferred to the output file. + std::vector selected_times{}; }; } // namespace Skinner diff --git a/packages/seacas/libraries/ioss/src/main/sphgen.C b/packages/seacas/libraries/ioss/src/main/sphgen.C index d5356f3582..776236b3fc 100644 --- a/packages/seacas/libraries/ioss/src/main/sphgen.C +++ b/packages/seacas/libraries/ioss/src/main/sphgen.C @@ -225,9 +225,9 @@ namespace { // The first time, just count the number of hex elements since // that will be the number of output element and nodes in the // sphere mesh. - size_t sph_node_count = 0; - const Ioss::ElementBlockContainer &ebs = region.get_element_blocks(); - Ioss::ElementBlockContainer::const_iterator I = ebs.begin(); + size_t sph_node_count = 0; + const auto &ebs = region.get_element_blocks(); + auto I = ebs.begin(); while (I != ebs.end()) { Ioss::ElementBlock *eb = *I; ++I; @@ -236,11 +236,10 @@ namespace { sph_node_count += eb->entity_count(); // Add the element block... - int num_elem = eb->entity_count(); - std::string name = eb->name(); - Ioss::ElementBlock *ebn = - new Ioss::ElementBlock(output_region.get_database(), name, "sphere", num_elem); - int id = eb->get_property("id").get_int(); + int num_elem = eb->entity_count(); + std::string name = eb->name(); + auto *ebn = new Ioss::ElementBlock(output_region.get_database(), name, "sphere", num_elem); + int id = eb->get_property("id").get_int(); ebn->property_add(Ioss::Property("id", id)); ebn->field_add(Ioss::Field("radius", Ioss::Field::REAL, "scalar", Ioss::Field::ATTRIBUTE, num_elem, 1)); @@ -268,11 +267,11 @@ namespace { output_region.begin_mode(Ioss::STATE_MODEL); - Ioss::NodeBlock *nb = region.get_node_blocks()[0]; + auto *nb = region.get_node_blocks()[0]; std::vector coordinates; nb->get_field_data("mesh_model_coordinates", coordinates); - Ioss::NodeBlock *onb = output_region.get_node_blocks()[0]; + auto *onb = output_region.get_node_blocks()[0]; std::vector node_ids(sph_node_count); for (size_t i = 0; i < sph_node_count; i++) { node_ids[i] = i + 1; @@ -292,13 +291,13 @@ namespace { hex_volume(*I, coordinates, ¢roids[3 * offset], volume, radius, globals.scale_factor); // Find corresponding output element block... - Ioss::ElementBlock *output_eb = output_region.get_element_block((*I)->name()); + auto *output_eb = output_region.get_element_block((*I)->name()); if (output_eb == nullptr) { fmt::print(stderr, "ERROR: Could not find output element block '{}'\n", (*I)->name()); std::exit(EXIT_FAILURE); } - Ioss::NodeSet *output_ns = output_region.get_nodeset((*I)->name() + "_nodes"); + auto *output_ns = output_region.get_nodeset((*I)->name() + "_nodes"); if (output_ns == nullptr) { fmt::print(stderr, "ERROR: Could not find output node set '{}_nodes'\n", (*I)->name()); std::exit(EXIT_FAILURE); diff --git a/packages/seacas/libraries/ioss/src/main/vector3d.C b/packages/seacas/libraries/ioss/src/main/vector3d.C index ec9f0b0ef4..c054cc98ae 100644 --- a/packages/seacas/libraries/ioss/src/main/vector3d.C +++ b/packages/seacas/libraries/ioss/src/main/vector3d.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -90,7 +90,7 @@ vector3d operator/(const vector3d &lhs, double scalar) vector3d tmp(lhs); return tmp /= scalar; } - return vector3d(HUGE_VAL, HUGE_VAL, HUGE_VAL); + return {HUGE_VAL, HUGE_VAL, HUGE_VAL}; } vector3d &vector3d::operator/=(double scalar) diff --git a/packages/seacas/libraries/ioss/src/main/vector3d.h b/packages/seacas/libraries/ioss/src/main/vector3d.h index 98eaa56948..68beaba3e1 100644 --- a/packages/seacas/libraries/ioss/src/main/vector3d.h +++ b/packages/seacas/libraries/ioss/src/main/vector3d.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -48,7 +48,7 @@ vector3d operator-(const vector3d &lhs, const vector3d &rhs); //---------------------------------------------------------------------------- inline vector3d vector3d::cross(const vector3d &from) const { - return vector3d(y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x); + return {y * from.z - z * from.y, z * from.x - x * from.z, x * from.y - y * from.x}; } //---------------------------------------------------------------------------- inline vector3d &vector3d::operator+=(const vector3d &from) diff --git a/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.C b/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.C index fc4a7b1fa7..00d2818d23 100644 --- a/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.C +++ b/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.C @@ -9,9 +9,9 @@ #include -#include // for nullptr +#include // for nullptr #include -#include // for string +#include // for string #include "Ioss_CodeTypes.h" // for Ioss_MPI_Comm #include "Ioss_DBUsage.h" // for DatabaseUsage diff --git a/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.h b/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.h index fa2b22f106..80cb6b6253 100644 --- a/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.h +++ b/packages/seacas/libraries/ioss/src/null/Ionull_IOFactory.h @@ -10,9 +10,9 @@ #include "Ioss_DatabaseIO.h" // for DatabaseIO #include -#include // for DatabaseUsage -#include // for IOFactory -#include // for string +#include // for DatabaseUsage +#include // for IOFactory +#include // for string namespace Ioss { class PropertyManager; } // namespace Ioss diff --git a/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C b/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C index 3fe8cd5184..2592f4d6c4 100644 --- a/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/pamgen/Iopg_DatabaseIO.C @@ -372,10 +372,10 @@ namespace Iopg { // A nemesis file typically separates nodes into multiple // communication sets by processor. (each set specifies - // nodes/elements that communicate with only a single processor). - // For Sierra, we want a single node commun. map and a single - // element commun. map specifying all communications so we combine - // all sets into a single set. + // nodes/elements that communicate with only a single + // processor). For Sierra, we want a single node communication + // map and a single element communication map specifying all + // communications so we combine all sets into a single set. error = im_ne_get_init_global(get_file_pointer(), &global_nodes, &global_elements, &global_eblocks, &global_nsets, &global_ssets); if (error < 0) diff --git a/packages/seacas/libraries/ioss/src/pdqsort.h b/packages/seacas/libraries/ioss/src/pdqsort.h index 1f718a55ed..c7e7396466 100644 --- a/packages/seacas/libraries/ioss/src/pdqsort.h +++ b/packages/seacas/libraries/ioss/src/pdqsort.h @@ -36,6 +36,7 @@ #define PDQSORT_PREFER_MOVE(x) (x) #endif +// NOLINTBEGIN namespace pdqsort_detail { enum { // Partitions below this size are sorted using insertion sort. @@ -612,3 +613,4 @@ template inline void pdqsort_branchless(Iter begin, Iter end) #undef PDQSORT_PREFER_MOVE #endif +// NOLINTEND diff --git a/packages/seacas/libraries/ioss/src/robin_growth_policy.h b/packages/seacas/libraries/ioss/src/robin_growth_policy.h index 36752ef422..69abb23fd0 100644 --- a/packages/seacas/libraries/ioss/src/robin_growth_policy.h +++ b/packages/seacas/libraries/ioss/src/robin_growth_policy.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * Copyright (c) 2017, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -71,167 +71,165 @@ #define TSL_RH_UNUSED(x) static_cast(x) -namespace tsl { - namespace rh { - +namespace tsl::rh { + + /** + * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a + * power of two. It allows the table to use a mask operation instead of a modulo + * operation to map a hash to a bucket. + * + * GrowthFactor must be a power of two >= 2. + */ + template class power_of_two_growth_policy + { + public: /** - * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a - * power of two. It allows the table to use a mask operation instead of a modulo - * operation to map a hash to a bucket. + * Called on the hash table creation and on rehash. The number of buckets for + * the table is passed in parameter. This number is a minimum, the policy may + * update this value with a higher value if needed (but not lower). * - * GrowthFactor must be a power of two >= 2. + * If 0 is given, min_bucket_count_in_out must still be 0 after the policy + * creation and bucket_for_hash must always return 0 in this case. */ - template class power_of_two_growth_policy + explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - /** - * Called on the hash table creation and on rehash. The number of buckets for - * the table is passed in parameter. This number is a minimum, the policy may - * update this value with a higher value if needed (but not lower). - * - * If 0 is given, min_bucket_count_in_out must still be 0 after the policy - * creation and bucket_for_hash must always return 0 in this case. - */ - explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); - m_mask = min_bucket_count_in_out - 1; - } - else { - m_mask = 0; - } + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - /** - * Return the bucket [0, bucket_count()) to which the hash belongs. - * If bucket_count() is 0, it must always return 0. - */ - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - - /** - * Return the number of buckets that should be used on next growth. - */ - std::size_t next_bucket_count() const - { - if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - return (m_mask + 1) * GrowthFactor; + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); + m_mask = min_bucket_count_in_out - 1; } - - /** - * Return the maximum number of buckets supported by the policy. - */ - std::size_t max_bucket_count() const - { - // Largest power of two. - return (std::numeric_limits::max() / 2) + 1; + else { + m_mask = 0; } + } - /** - * Reset the growth policy as if it was created with a bucket count of 0. - * After a clear, the policy must always return 0 when bucket_for_hash is - * called. - */ - void clear() noexcept { m_mask = 0; } - - private: - static std::size_t round_up_to_power_of_two(std::size_t value) - { - if (is_power_of_two(value)) { - return value; - } - - if (value == 0) { - return 1; - } - - --value; - for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { - value |= value >> i; - } - - return value + 1; - } + /** + * Return the bucket [0, bucket_count()) to which the hash belongs. + * If bucket_count() is 0, it must always return 0. + */ + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } - static constexpr bool is_power_of_two(std::size_t value) - { - return value != 0 && (value & (value - 1)) == 0; + /** + * Return the number of buckets that should be used on next growth. + */ + std::size_t next_bucket_count() const + { + if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - protected: - static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, - "GrowthFactor must be a power of two >= 2."); + return (m_mask + 1) * GrowthFactor; + } - std::size_t m_mask; - }; + /** + * Return the maximum number of buckets supported by the policy. + */ + std::size_t max_bucket_count() const + { + // Largest power of two. + return (std::numeric_limits::max() / 2) + 1; + } /** - * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo - * to map a hash to a bucket. Slower but it can be useful if you want a slower - * growth. + * Reset the growth policy as if it was created with a bucket count of 0. + * After a clear, the policy must always return 0 when bucket_for_hash is + * called. */ - template > class mod_growth_policy + void clear() noexcept { m_mask = 0; } + + private: + static std::size_t round_up_to_power_of_two(std::size_t value) + { + if (is_power_of_two(value)) { + return value; + } + + if (value == 0) { + return 1; + } + + --value; + for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { + value |= value >> i; + } + + return value + 1; + } + + static constexpr bool is_power_of_two(std::size_t value) + { + return value != 0 && (value & (value - 1)) == 0; + } + + protected: + static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, + "GrowthFactor must be a power of two >= 2."); + + std::size_t m_mask; + }; + + /** + * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo + * to map a hash to a bucket. Slower but it can be useful if you want a slower + * growth. + */ + template > class mod_growth_policy + { + public: + explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) + { + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (min_bucket_count_in_out > 0) { + m_mod = min_bucket_count_in_out; + } + else { + m_mod = 1; + } + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } + + std::size_t next_bucket_count() const { - public: - explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) - { - if (min_bucket_count_in_out > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (min_bucket_count_in_out > 0) { - m_mod = min_bucket_count_in_out; - } - else { - m_mod = 1; - } + if (m_mod == max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + const double next_bucket_count = std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); + if (!std::isnormal(next_bucket_count)) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } - - std::size_t next_bucket_count() const - { - if (m_mod == max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - const double next_bucket_count = - std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); - if (!std::isnormal(next_bucket_count)) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - if (next_bucket_count > double(max_bucket_count())) { - return max_bucket_count(); - } - else { - return std::size_t(next_bucket_count); - } + if (next_bucket_count > double(max_bucket_count())) { + return max_bucket_count(); + } + else { + return std::size_t(next_bucket_count); } + } - std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } + std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } - void clear() noexcept { m_mod = 1; } + void clear() noexcept { m_mod = 1; } - private: - static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = - 1.0 * GrowthFactor::num / GrowthFactor::den; - static const std::size_t MAX_BUCKET_COUNT = std::size_t( - double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); + private: + static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = + 1.0 * GrowthFactor::num / GrowthFactor::den; + static const std::size_t MAX_BUCKET_COUNT = std::size_t( + double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); - static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); + static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); - std::size_t m_mod; - }; + std::size_t m_mod; + }; - namespace detail { + namespace detail { #if SIZE_MAX >= ULLONG_MAX #define TSL_RH_NB_PRIMES 51 @@ -241,163 +239,160 @@ namespace tsl { #define TSL_RH_NB_PRIMES 23 #endif - static constexpr const std::array PRIMES = {{ - 1u, - 5u, - 17u, - 29u, - 37u, - 53u, - 67u, - 79u, - 97u, - 131u, - 193u, - 257u, - 389u, - 521u, - 769u, - 1031u, - 1543u, - 2053u, - 3079u, - 6151u, - 12289u, - 24593u, - 49157u, + static constexpr const std::array PRIMES = {{ + 1u, + 5u, + 17u, + 29u, + 37u, + 53u, + 67u, + 79u, + 97u, + 131u, + 193u, + 257u, + 389u, + 521u, + 769u, + 1031u, + 1543u, + 2053u, + 3079u, + 6151u, + 12289u, + 24593u, + 49157u, #if SIZE_MAX >= ULONG_MAX - 98317ul, - 196613ul, - 393241ul, - 786433ul, - 1572869ul, - 3145739ul, - 6291469ul, - 12582917ul, - 25165843ul, - 50331653ul, - 100663319ul, - 201326611ul, - 402653189ul, - 805306457ul, - 1610612741ul, - 3221225473ul, - 4294967291ul, + 98317ul, + 196613ul, + 393241ul, + 786433ul, + 1572869ul, + 3145739ul, + 6291469ul, + 12582917ul, + 25165843ul, + 50331653ul, + 100663319ul, + 201326611ul, + 402653189ul, + 805306457ul, + 1610612741ul, + 3221225473ul, + 4294967291ul, #endif #if SIZE_MAX >= ULLONG_MAX - 6442450939ull, - 12884901893ull, - 25769803751ull, - 51539607551ull, - 103079215111ull, - 206158430209ull, - 412316860441ull, - 824633720831ull, - 1649267441651ull, - 3298534883309ull, - 6597069766657ull, + 6442450939ull, + 12884901893ull, + 25769803751ull, + 51539607551ull, + 103079215111ull, + 206158430209ull, + 412316860441ull, + 824633720831ull, + 1649267441651ull, + 3298534883309ull, + 6597069766657ull, #endif - }}; - - template static constexpr std::size_t mod(std::size_t hash) - { - return hash % PRIMES[IPrime]; - } + }}; - // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for - // faster modulo as the compiler can optimize the modulo code better with a - // constant known at the compilation. - static constexpr const std::array MOD_PRIME = - {{ - &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, - &mod<8>, &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, - &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, + template static constexpr std::size_t mod(std::size_t hash) + { + return hash % PRIMES[IPrime]; + } + + // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for + // faster modulo as the compiler can optimize the modulo code better with a + // constant known at the compilation. + static constexpr const std::array MOD_PRIME = {{ + &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, &mod<8>, + &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, &mod<16>, &mod<17>, + &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, #if SIZE_MAX >= ULONG_MAX - &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, - &mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, - &mod<39>, + &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, &mod<31>, + &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, &mod<39>, #endif #if SIZE_MAX >= ULLONG_MAX - &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, - &mod<48>, &mod<49>, &mod<50>, + &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, &mod<48>, + &mod<49>, &mod<50>, #endif - }}; - - } // namespace detail - - /** - * Grow the hash table by using prime numbers as bucket count. Slower than - * tsl::rh::power_of_two_growth_policy in general but will probably distribute - * the values around better in the buckets with a poor hash function. - * - * To allow the compiler to optimize the modulo operation, a lookup table is - * used with constant primes numbers. - * - * With a switch the code would look like: - * \code - * switch(iprime) { // iprime is the current prime of the hash table - * case 0: hash % 5ul; - * break; - * case 1: hash % 17ul; - * break; - * case 2: hash % 29ul; - * break; - * ... - * } - * \endcode - * - * Due to the constant variable in the modulo the compiler is able to optimize - * the operation by a series of multiplications, substractions and shifts. - * - * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) - * * 5' in a 64 bits environment. - */ - class prime_growth_policy + }}; + + } // namespace detail + + /** + * Grow the hash table by using prime numbers as bucket count. Slower than + * tsl::rh::power_of_two_growth_policy in general but will probably distribute + * the values around better in the buckets with a poor hash function. + * + * To allow the compiler to optimize the modulo operation, a lookup table is + * used with constant primes numbers. + * + * With a switch the code would look like: + * \code + * switch(iprime) { // iprime is the current prime of the hash table + * case 0: hash % 5ul; + * break; + * case 1: hash % 17ul; + * break; + * case 2: hash % 29ul; + * break; + * ... + * } + * \endcode + * + * Due to the constant variable in the modulo the compiler is able to optimize + * the operation by a series of multiplications, substractions and shifts. + * + * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) + * * 5' in a 64 bits environment. + */ + class prime_growth_policy + { + public: + explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) { - public: - explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) - { - auto it_prime = - std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); - if (it_prime == detail::PRIMES.end()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } - - m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); - if (min_bucket_count_in_out > 0) { - min_bucket_count_in_out = *it_prime; - } - else { - min_bucket_count_in_out = 0; - } + auto it_prime = + std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); + if (it_prime == detail::PRIMES.end()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t bucket_for_hash(std::size_t hash) const noexcept - { - return detail::MOD_PRIME[m_iprime](hash); + m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = *it_prime; + } + else { + min_bucket_count_in_out = 0; } + } - std::size_t next_bucket_count() const - { - if (m_iprime + 1 >= detail::PRIMES.size()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); - } + std::size_t bucket_for_hash(std::size_t hash) const noexcept + { + return detail::MOD_PRIME[m_iprime](hash); + } - return detail::PRIMES[m_iprime + 1]; + std::size_t next_bucket_count() const + { + if (m_iprime + 1 >= detail::PRIMES.size()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); } - std::size_t max_bucket_count() const { return detail::PRIMES.back(); } + return detail::PRIMES[m_iprime + 1]; + } + + std::size_t max_bucket_count() const { return detail::PRIMES.back(); } - void clear() noexcept { m_iprime = 0; } + void clear() noexcept { m_iprime = 0; } - private: - unsigned int m_iprime; + private: + unsigned int m_iprime; - static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), - "The type of m_iprime is not big enough."); - }; + static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), + "The type of m_iprime is not big enough."); + }; - } // namespace rh -} // namespace tsl +} // namespace tsl::rh #endif diff --git a/packages/seacas/libraries/ioss/src/robin_hash.h b/packages/seacas/libraries/ioss/src/robin_hash.h index e652d02fb3..bac810087f 100644 --- a/packages/seacas/libraries/ioss/src/robin_hash.h +++ b/packages/seacas/libraries/ioss/src/robin_hash.h @@ -1,7 +1,7 @@ /** * MIT License * - * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * Copyright (c) 2017, 2023 Thibaut Goetghebuer-Planchon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,1559 +40,1545 @@ #include #include +// NOLINTBEGIN #include "robin_growth_policy.h" -namespace tsl { +namespace tsl::detail_robin_hash { + + template struct make_void + { + using type = void; + }; + + template struct has_is_transparent : std::false_type + { + }; + + template + struct has_is_transparent::type> + : std::true_type + { + }; + + template struct is_power_of_two_policy : std::false_type + { + }; + + template + struct is_power_of_two_policy> : std::true_type + { + }; + + // Only available in C++17, we need to be compatible with C++11 + template const T &clamp(const T &v, const T &lo, const T &hi) + { + return std::min(hi, std::max(lo, v)); + } + + template + static T numeric_cast(U value, const char *error_message = "numeric_cast() failed.") + { + T ret = static_cast(value); + if (static_cast(ret) != value) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } - namespace detail_robin_hash { + const bool is_same_signedness = (std::is_unsigned::value && std::is_unsigned::value) || + (std::is_signed::value && std::is_signed::value); + if (!is_same_signedness && (ret < T{}) != (value < U{})) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } - template struct make_void - { - using type = void; - }; + return ret; + } - template struct has_is_transparent : std::false_type + template static T deserialize_value(Deserializer &deserializer) + { + // MSVC < 2017 is not conformant, circumvent the problem by removing the + // template keyword +#if defined(_MSC_VER) && _MSC_VER < 1910 + return deserializer.Deserializer::operator()(); +#else + return deserializer.Deserializer::template operator()(); +#endif + } + + /** + * Fixed size type used to represent size_type values on serialization. Need to + * be big enough to represent a std::size_t on 32 and 64 bits platforms, and + * must be the same size on both platforms. + */ + using slz_size_type = std::uint64_t; + static_assert(std::numeric_limits::max() >= + std::numeric_limits::max(), + "slz_size_type must be >= std::size_t"); + + using truncated_hash_type = std::uint32_t; + + /** + * Helper class that stores a truncated hash if StoreHash is true and nothing + * otherwise. + */ + template class bucket_entry_hash + { + public: + bool bucket_hash_equal(std::size_t /*hash*/) const noexcept { return true; } + + truncated_hash_type truncated_hash() const noexcept { return 0; } + + protected: + void set_hash(truncated_hash_type /*hash*/) noexcept {} + }; + + template <> class bucket_entry_hash + { + public: + bool bucket_hash_equal(std::size_t my_hash) const noexcept { - }; + return m_hash == truncated_hash_type(my_hash); + } - template - struct has_is_transparent::type> - : std::true_type + truncated_hash_type truncated_hash() const noexcept { return m_hash; } + + protected: + void set_hash(truncated_hash_type my_hash) noexcept { m_hash = my_hash; } + + private: + truncated_hash_type m_hash; + }; + + /** + * Each bucket entry has: + * - A value of type `ValueType`. + * - An integer to store how far the value of the bucket, if any, is from its + * ideal bucket (ex: if the current bucket 5 has the value 'foo' and + * `hash('foo') % nb_buckets` == 3, `dist_from_ideal_bucket()` will return 2 as + * the current value of the bucket is two buckets away from its ideal bucket) If + * there is no value in the bucket (i.e. `empty()` is true) + * `dist_from_ideal_bucket()` will be < 0. + * - A marker which tells us if the bucket is the last bucket of the bucket + * array (useful for the iterator of the hash table). + * - If `StoreHash` is true, 32 bits of the hash of the value, if any, are also + * stored in the bucket. If the size of the hash is more than 32 bits, it is + * truncated. We don't store the full hash as storing the hash is a potential + * opportunity to use the unused space due to the alignment of the bucket_entry + * structure. We can thus potentially store the hash without any extra space + * (which would not be possible with 64 bits of the hash). + */ + template + class bucket_entry : public bucket_entry_hash + { + using bucket_hash = bucket_entry_hash; + + public: + using value_type = ValueType; + using distance_type = std::int16_t; + + bucket_entry() noexcept + : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(false) { - }; + tsl_rh_assert(empty()); + } - template struct is_power_of_two_policy : std::false_type + bucket_entry(bool last_bucket) noexcept + : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(last_bucket) { - }; + tsl_rh_assert(empty()); + } - template - struct is_power_of_two_policy> - : std::true_type + bucket_entry(const bucket_entry &other) noexcept( + std::is_nothrow_copy_constructible::value) + : bucket_hash(other), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(other.m_last_bucket) { - }; + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(other.value()); + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + } + tsl_rh_assert(empty() == other.empty()); + } - // Only available in C++17, we need to be compatible with C++11 - template const T &clamp(const T &v, const T &lo, const T &hi) + /** + * Never really used, but still necessary as we must call resize on an empty + * `std::vector`. and we need to support move-only types. See + * robin_hash constructor for details. + */ + bucket_entry(bucket_entry &&other) noexcept( + std::is_nothrow_move_constructible::value) + : bucket_hash(std::move(other)), + m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(other.m_last_bucket) { - return std::min(hi, std::max(lo, v)); + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(std::move(other.value())); + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + } + tsl_rh_assert(empty() == other.empty()); } - template - static T numeric_cast(U value, const char *error_message = "numeric_cast() failed.") + bucket_entry &operator=(const bucket_entry &other) noexcept( + std::is_nothrow_copy_constructible::value) { - T ret = static_cast(value); - if (static_cast(ret) != value) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + if (this != &other) { + clear(); + + bucket_hash::operator=(other); + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(other.value()); + } + + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + m_last_bucket = other.m_last_bucket; } - const bool is_same_signedness = (std::is_unsigned::value && std::is_unsigned::value) || - (std::is_signed::value && std::is_signed::value); - if (!is_same_signedness && (ret < T{}) != (value < U{})) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + return *this; + } + + bucket_entry &operator=(bucket_entry &&) = delete; + + ~bucket_entry() noexcept { clear(); } + + void clear() noexcept + { + if (!empty()) { + destroy_value(); + m_dist_from_ideal_bucket = EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; } + } - return ret; + bool empty() const noexcept + { + return m_dist_from_ideal_bucket == EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; } - template static T deserialize_value(Deserializer &deserializer) + value_type &value() noexcept { - // MSVC < 2017 is not conformant, circumvent the problem by removing the - // template keyword -#if defined(_MSC_VER) && _MSC_VER < 1910 - return deserializer.Deserializer::operator()(); + tsl_rh_assert(!empty()); +#if defined(__cplusplus) && __cplusplus >= 201703L + return *std::launder(reinterpret_cast(std::addressof(m_value))); #else - return deserializer.Deserializer::template operator()(); + return *reinterpret_cast(std::addressof(m_value)); #endif } - /** - * Fixed size type used to represent size_type values on serialization. Need to - * be big enough to represent a std::size_t on 32 and 64 bits platforms, and - * must be the same size on both platforms. - */ - using slz_size_type = std::uint64_t; - static_assert(std::numeric_limits::max() >= - std::numeric_limits::max(), - "slz_size_type must be >= std::size_t"); + const value_type &value() const noexcept + { + tsl_rh_assert(!empty()); +#if defined(__cplusplus) && __cplusplus >= 201703L + return *std::launder(reinterpret_cast(std::addressof(m_value))); +#else + return *reinterpret_cast(std::addressof(m_value)); +#endif + } - using truncated_hash_type = std::uint32_t; + distance_type dist_from_ideal_bucket() const noexcept { return m_dist_from_ideal_bucket; } - /** - * Helper class that stores a truncated hash if StoreHash is true and nothing - * otherwise. - */ - template class bucket_entry_hash + bool last_bucket() const noexcept { return m_last_bucket; } + + void set_as_last_bucket() noexcept { m_last_bucket = true; } + + template + void set_value_of_empty_bucket(distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, Args &&...value_type_args) { - public: - bool bucket_hash_equal(std::size_t /*hash*/) const noexcept { return true; } + tsl_rh_assert(dist_from_ideal_bucket >= 0); + tsl_rh_assert(empty()); - truncated_hash_type truncated_hash() const noexcept { return 0; } + ::new (static_cast(std::addressof(m_value))) + value_type(std::forward(value_type_args)...); + this->set_hash(my_hash); + m_dist_from_ideal_bucket = dist_from_ideal_bucket; - protected: - void set_hash(truncated_hash_type /*hash*/) noexcept {} - }; + tsl_rh_assert(!empty()); + } - template <> class bucket_entry_hash + void swap_with_value_in_bucket(distance_type &dist_from_ideal_bucket, + truncated_hash_type &my_hash, value_type &value) { - public: - bool bucket_hash_equal(std::size_t my_hash) const noexcept - { - return m_hash == truncated_hash_type(my_hash); - } + tsl_rh_assert(!empty()); + tsl_rh_assert(dist_from_ideal_bucket > m_dist_from_ideal_bucket); - truncated_hash_type truncated_hash() const noexcept { return m_hash; } + using std::swap; + swap(value, this->value()); + swap(dist_from_ideal_bucket, m_dist_from_ideal_bucket); - protected: - void set_hash(truncated_hash_type my_hash) noexcept { m_hash = truncated_hash_type(my_hash); } + if (StoreHash) { + const truncated_hash_type tmp_hash = this->truncated_hash(); + this->set_hash(my_hash); + my_hash = tmp_hash; + } + else { + // Avoid warning of unused variable if StoreHash is false + TSL_RH_UNUSED(my_hash); + } + } - private: - truncated_hash_type m_hash; - }; + static truncated_hash_type truncate_hash(std::size_t my_hash) noexcept + { + return truncated_hash_type(my_hash); + } + + private: + void destroy_value() noexcept + { + tsl_rh_assert(!empty()); + value().~value_type(); + } + public: + static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1; + static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 8192; + static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <= std::numeric_limits::max() - 1, + "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= " + "std::numeric_limits::max() - 1."); + + private: + distance_type m_dist_from_ideal_bucket; + bool m_last_bucket; + alignas(value_type) unsigned char m_value[sizeof(value_type)]; + }; + + /** + * Internal common class used by `robin_map` and `robin_set`. + * + * ValueType is what will be stored by `robin_hash` (usually `std::pair` + * for map and `Key` for set). + * + * `KeySelect` should be a `FunctionObject` which takes a `ValueType` in + * parameter and returns a reference to the key. + * + * `ValueSelect` should be a `FunctionObject` which takes a `ValueType` in + * parameter and returns a reference to the value. `ValueSelect` should be void + * if there is no value (in a set for example). + * + * The strong exception guarantee only holds if the expression + * `std::is_nothrow_swappable\:\:value && + * std::is_nothrow_move_constructible\:\:value` is true. + * + * Behaviour is undefined if the destructor of `ValueType` throws. + */ + template + class robin_hash : private Hash, private KeyEqual, private GrowthPolicy + { + private: + template + using has_mapped_type = typename std::integral_constant::value>; + + static_assert(noexcept(std::declval().bucket_for_hash(std::size_t(0))), + "GrowthPolicy::bucket_for_hash must be noexcept."); + static_assert(noexcept(std::declval().clear()), + "GrowthPolicy::clear must be noexcept."); + + public: + template class robin_iterator; + + using key_type = typename KeySelect::key_type; + using value_type = ValueType; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using hasher = Hash; + using key_equal = KeyEqual; + using allocator_type = Allocator; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; + using iterator = robin_iterator; + using const_iterator = robin_iterator; + + private: /** - * Each bucket entry has: - * - A value of type `ValueType`. - * - An integer to store how far the value of the bucket, if any, is from its - * ideal bucket (ex: if the current bucket 5 has the value 'foo' and - * `hash('foo') % nb_buckets` == 3, `dist_from_ideal_bucket()` will return 2 as - * the current value of the bucket is two buckets away from its ideal bucket) If - * there is no value in the bucket (i.e. `empty()` is true) - * `dist_from_ideal_bucket()` will be < 0. - * - A marker which tells us if the bucket is the last bucket of the bucket - * array (useful for the iterator of the hash table). - * - If `StoreHash` is true, 32 bits of the hash of the value, if any, are also - * stored in the bucket. If the size of the hash is more than 32 bits, it is - * truncated. We don't store the full hash as storing the hash is a potential - * opportunity to use the unused space due to the alignment of the bucket_entry - * structure. We can thus potentially store the hash without any extra space - * (which would not be possible with 64 bits of the hash). + * Either store the hash because we are asked by the `StoreHash` template + * parameter or store the hash because it doesn't cost us anything in size and + * can be used to speed up rehash. */ - template - class bucket_entry : public bucket_entry_hash - { - using bucket_hash = bucket_entry_hash; + static constexpr bool STORE_HASH = + StoreHash || + ((sizeof(tsl::detail_robin_hash::bucket_entry) == + sizeof(tsl::detail_robin_hash::bucket_entry)) && + (sizeof(std::size_t) == sizeof(truncated_hash_type) || + is_power_of_two_policy::value) && + // Don't store the hash for primitive types with default hash. + (!std::is_arithmetic::value || !std::is_same>::value)); - public: - using value_type = ValueType; - using distance_type = std::int16_t; + /** + * Only use the stored hash on lookup if we are explicitly asked. We are not + * sure how slow the KeyEqual operation is. An extra comparison may slow + * things down with a fast KeyEqual. + */ + static constexpr bool USE_STORED_HASH_ON_LOOKUP = StoreHash; - bucket_entry() noexcept - : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(false) - { - tsl_rh_assert(empty()); + /** + * We can only use the hash on rehash if the size of the hash type is the same + * as the stored one or if we use a power of two modulo. In the case of the + * power of two modulo, we just mask the least significant bytes, we just have + * to check that the truncated_hash_type didn't truncated more bytes. + */ + static bool USE_STORED_HASH_ON_REHASH(size_type bucket_count) + { + if (STORE_HASH && sizeof(std::size_t) == sizeof(truncated_hash_type)) { + TSL_RH_UNUSED(bucket_count); + return true; } - - bucket_entry(bool last_bucket) noexcept - : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(last_bucket) - { - tsl_rh_assert(empty()); + else if (STORE_HASH && is_power_of_two_policy::value) { + return bucket_count == 0 || + (bucket_count - 1) <= std::numeric_limits::max(); } - - bucket_entry(const bucket_entry &other) noexcept( - std::is_nothrow_copy_constructible::value) - : bucket_hash(other), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(other.m_last_bucket) - { - if (!other.empty()) { - ::new (static_cast(std::addressof(m_value))) value_type(other.value()); - m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; - } - tsl_rh_assert(empty() == other.empty()); + else { + TSL_RH_UNUSED(bucket_count); + return false; } + } - /** - * Never really used, but still necessary as we must call resize on an empty - * `std::vector`. and we need to support move-only types. See - * robin_hash constructor for details. - */ - bucket_entry(bucket_entry &&other) noexcept( - std::is_nothrow_move_constructible::value) - : bucket_hash(std::move(other)), - m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), - m_last_bucket(other.m_last_bucket) - { - if (!other.empty()) { - ::new (static_cast(std::addressof(m_value))) value_type(std::move(other.value())); - m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; - } - tsl_rh_assert(empty() == other.empty()); - } + using bucket_entry = tsl::detail_robin_hash::bucket_entry; + using distance_type = typename bucket_entry::distance_type; - bucket_entry &operator=(const bucket_entry &other) noexcept( - std::is_nothrow_copy_constructible::value) - { - if (this != &other) { - clear(); + using buckets_allocator = + typename std::allocator_traits::template rebind_alloc; + using buckets_container_type = std::vector; - bucket_hash::operator=(other); - if (!other.empty()) { - ::new (static_cast(std::addressof(m_value))) value_type(other.value()); - } + public: + /** + * The 'operator*()' and 'operator->()' methods return a const reference and + * const pointer respectively to the stored value type. + * + * In case of a map, to get a mutable reference to the value associated to a + * key (the '.second' in the stored pair), you have to call 'value()'. + * + * The main reason for this is that if we returned a `std::pair&` + * instead of a `const std::pair&`, the user may modify the key which + * will put the map in a undefined state. + */ + template class robin_iterator + { + friend class robin_hash; - m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; - m_last_bucket = other.m_last_bucket; - } + private: + using bucket_entry_ptr = + typename std::conditional::type; - return *this; - } + robin_iterator(bucket_entry_ptr bucket) noexcept : m_bucket(bucket) {} - bucket_entry &operator=(bucket_entry &&) = delete; + public: + using iterator_category = std::forward_iterator_tag; + using value_type = const typename robin_hash::value_type; + using difference_type = std::ptrdiff_t; + using reference = value_type &; + using pointer = value_type *; - ~bucket_entry() noexcept { clear(); } + robin_iterator() noexcept = default; - void clear() noexcept + // Copy constructor from iterator to const_iterator. + template ::type * = nullptr> + robin_iterator(const robin_iterator &other) noexcept : m_bucket(other.m_bucket) { - if (!empty()) { - destroy_value(); - m_dist_from_ideal_bucket = EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; - } } - bool empty() const noexcept - { - return m_dist_from_ideal_bucket == EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; - } + robin_iterator(const robin_iterator &other) = default; + robin_iterator(robin_iterator &&other) = default; + robin_iterator &operator=(const robin_iterator &other) = default; + robin_iterator &operator=(robin_iterator &&other) = default; - value_type &value() noexcept + const typename robin_hash::key_type &key() const { return KeySelect()(m_bucket->value()); } + + template ::value && IsConst>::type * = nullptr> + const typename U::value_type &value() const { - tsl_rh_assert(!empty()); -#if defined(__cplusplus) && __cplusplus >= 201703L - return *std::launder(reinterpret_cast(std::addressof(m_value))); -#else - return *reinterpret_cast(std::addressof(m_value)); -#endif + return U()(m_bucket->value()); } - const value_type &value() const noexcept + template ::value && !IsConst>::type * = nullptr> + typename U::value_type &value() const { - tsl_rh_assert(!empty()); -#if defined(__cplusplus) && __cplusplus >= 201703L - return *std::launder(reinterpret_cast(std::addressof(m_value))); -#else - return *reinterpret_cast(std::addressof(m_value)); -#endif + return U()(m_bucket->value()); } - distance_type dist_from_ideal_bucket() const noexcept { return m_dist_from_ideal_bucket; } - - bool last_bucket() const noexcept { return m_last_bucket; } + reference operator*() const { return m_bucket->value(); } - void set_as_last_bucket() noexcept { m_last_bucket = true; } + pointer operator->() const { return std::addressof(m_bucket->value()); } - template - void set_value_of_empty_bucket(distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, Args &&...value_type_args) + robin_iterator &operator++() { - tsl_rh_assert(dist_from_ideal_bucket >= 0); - tsl_rh_assert(empty()); - - ::new (static_cast(std::addressof(m_value))) - value_type(std::forward(value_type_args)...); - this->set_hash(my_hash); - m_dist_from_ideal_bucket = dist_from_ideal_bucket; + while (true) { + if (m_bucket->last_bucket()) { + ++m_bucket; + return *this; + } - tsl_rh_assert(!empty()); + ++m_bucket; + if (!m_bucket->empty()) { + return *this; + } + } } - void swap_with_value_in_bucket(distance_type &dist_from_ideal_bucket, - truncated_hash_type &my_hash, value_type &value) + robin_iterator operator++(int) { - tsl_rh_assert(!empty()); - tsl_rh_assert(dist_from_ideal_bucket > m_dist_from_ideal_bucket); - - using std::swap; - swap(value, this->value()); - swap(dist_from_ideal_bucket, m_dist_from_ideal_bucket); + robin_iterator tmp(*this); + ++*this; - if (StoreHash) { - const truncated_hash_type tmp_hash = this->truncated_hash(); - this->set_hash(my_hash); - my_hash = tmp_hash; - } - else { - // Avoid warning of unused variable if StoreHash is false - TSL_RH_UNUSED(my_hash); - } + return tmp; } - static truncated_hash_type truncate_hash(std::size_t my_hash) noexcept + friend bool operator==(const robin_iterator &lhs, const robin_iterator &rhs) { - return truncated_hash_type(my_hash); + return lhs.m_bucket == rhs.m_bucket; } - private: - void destroy_value() noexcept + friend bool operator!=(const robin_iterator &lhs, const robin_iterator &rhs) { - tsl_rh_assert(!empty()); - value().~value_type(); + return !(lhs == rhs); } - public: - static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1; - static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 8192; - static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <= std::numeric_limits::max() - 1, - "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= " - "std::numeric_limits::max() - 1."); - private: - distance_type m_dist_from_ideal_bucket; - bool m_last_bucket; - alignas(value_type) unsigned char m_value[sizeof(value_type)]; + bucket_entry_ptr m_bucket; }; + public: +#if defined(__cplusplus) && __cplusplus >= 201402L + robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, + const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, + float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) + : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), + m_buckets_data(bucket_count, alloc), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(bucket_count) + { + if (bucket_count > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); + } + + if (m_bucket_count > 0) { + tsl_rh_assert(!m_buckets_data.empty()); + m_buckets_data.back().set_as_last_bucket(); + } + + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + } +#else /** - * Internal common class used by `robin_map` and `robin_set`. + * C++11 doesn't support the creation of a std::vector with a custom allocator + * and 'count' default-inserted elements. The needed constructor `explicit + * vector(size_type count, const Allocator& alloc = Allocator());` is only + * available in C++14 and later. We thus must resize after using the + * `vector(const Allocator& alloc)` constructor. * - * ValueType is what will be stored by `robin_hash` (usually `std::pair` - * for map and `Key` for set). - * - * `KeySelect` should be a `FunctionObject` which takes a `ValueType` in - * parameter and returns a reference to the key. - * - * `ValueSelect` should be a `FunctionObject` which takes a `ValueType` in - * parameter and returns a reference to the value. `ValueSelect` should be void - * if there is no value (in a set for example). - * - * The strong exception guarantee only holds if the expression - * `std::is_nothrow_swappable\:\:value && - * std::is_nothrow_move_constructible\:\:value` is true. - * - * Behaviour is undefined if the destructor of `ValueType` throws. + * We can't use `vector(size_type count, const T& value, const Allocator& + * alloc)` as it requires the value T to be copyable. */ - template - class robin_hash : private Hash, private KeyEqual, private GrowthPolicy + robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, + const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, + float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) + : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), m_buckets_data(alloc), + m_buckets(static_empty_bucket_ptr()), m_bucket_count(bucket_count) { - private: - template - using has_mapped_type = typename std::integral_constant::value>; + if (bucket_count > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); + } - static_assert(noexcept(std::declval().bucket_for_hash(std::size_t(0))), - "GrowthPolicy::bucket_for_hash must be noexcept."); - static_assert(noexcept(std::declval().clear()), - "GrowthPolicy::clear must be noexcept."); + if (m_bucket_count > 0) { + m_buckets_data.resize(m_bucket_count); + m_buckets = m_buckets_data.data(); - public: - template class robin_iterator; - - using key_type = typename KeySelect::key_type; - using value_type = ValueType; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using hasher = Hash; - using key_equal = KeyEqual; - using allocator_type = Allocator; - using reference = value_type &; - using const_reference = const value_type &; - using pointer = value_type *; - using const_pointer = const value_type *; - using iterator = robin_iterator; - using const_iterator = robin_iterator; + tsl_rh_assert(!m_buckets_data.empty()); + m_buckets_data.back().set_as_last_bucket(); + } - private: - /** - * Either store the hash because we are asked by the `StoreHash` template - * parameter or store the hash because it doesn't cost us anything in size and - * can be used to speed up rehash. - */ - static constexpr bool STORE_HASH = - StoreHash || ((sizeof(tsl::detail_robin_hash::bucket_entry) == - sizeof(tsl::detail_robin_hash::bucket_entry)) && - (sizeof(std::size_t) == sizeof(truncated_hash_type) || - is_power_of_two_policy::value) && - // Don't store the hash for primitive types with default hash. - (!std::is_arithmetic::value || - !std::is_same>::value)); + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + } +#endif - /** - * Only use the stored hash on lookup if we are explicitly asked. We are not - * sure how slow the KeyEqual operation is. An extra comparison may slow - * things down with a fast KeyEqual. - */ - static constexpr bool USE_STORED_HASH_ON_LOOKUP = StoreHash; + robin_hash(const robin_hash &other) + : Hash(other), KeyEqual(other), GrowthPolicy(other), m_buckets_data(other.m_buckets_data), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), + m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert), + m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) + { + } - /** - * We can only use the hash on rehash if the size of the hash type is the same - * as the stored one or if we use a power of two modulo. In the case of the - * power of two modulo, we just mask the least significant bytes, we just have - * to check that the truncated_hash_type didn't truncated more bytes. - */ - static bool USE_STORED_HASH_ON_REHASH(size_type bucket_count) - { - if (STORE_HASH && sizeof(std::size_t) == sizeof(truncated_hash_type)) { - TSL_RH_UNUSED(bucket_count); - return true; - } - else if (STORE_HASH && is_power_of_two_policy::value) { - return bucket_count == 0 || - (bucket_count - 1) <= std::numeric_limits::max(); - } - else { - TSL_RH_UNUSED(bucket_count); - return false; - } - } + robin_hash(robin_hash &&other) noexcept( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_constructible::value) + : Hash(std::move(static_cast(other))), + KeyEqual(std::move(static_cast(other))), + GrowthPolicy(std::move(static_cast(other))), + m_buckets_data(std::move(other.m_buckets_data)), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), + m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert), + m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) + { + other.clear_and_shrink(); + } - using bucket_entry = tsl::detail_robin_hash::bucket_entry; - using distance_type = typename bucket_entry::distance_type; + robin_hash &operator=(const robin_hash &other) + { + if (&other != this) { + Hash::operator=(other); + KeyEqual::operator=(other); + GrowthPolicy::operator=(other); - using buckets_allocator = - typename std::allocator_traits::template rebind_alloc; - using buckets_container_type = std::vector; + m_buckets_data = other.m_buckets_data; + m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data(); + m_bucket_count = other.m_bucket_count; + m_nb_elements = other.m_nb_elements; - public: - /** - * The 'operator*()' and 'operator->()' methods return a const reference and - * const pointer respectively to the stored value type. - * - * In case of a map, to get a mutable reference to the value associated to a - * key (the '.second' in the stored pair), you have to call 'value()'. - * - * The main reason for this is that if we returned a `std::pair&` - * instead of a `const std::pair&`, the user may modify the key which - * will put the map in a undefined state. - */ - template class robin_iterator - { - friend class robin_hash; + m_load_threshold = other.m_load_threshold; + m_min_load_factor = other.m_min_load_factor; + m_max_load_factor = other.m_max_load_factor; - private: - using bucket_entry_ptr = - typename std::conditional::type; + m_grow_on_next_insert = other.m_grow_on_next_insert; + m_try_shrink_on_next_insert = other.m_try_shrink_on_next_insert; + } - robin_iterator(bucket_entry_ptr bucket) noexcept : m_bucket(bucket) {} + return *this; + } - public: - using iterator_category = std::forward_iterator_tag; - using value_type = const typename robin_hash::value_type; - using difference_type = std::ptrdiff_t; - using reference = value_type &; - using pointer = value_type *; + robin_hash &operator=(robin_hash &&other) + { + other.swap(*this); + other.clear_and_shrink(); - robin_iterator() noexcept {} + return *this; + } - // Copy constructor from iterator to const_iterator. - template ::type * = nullptr> - robin_iterator(const robin_iterator &other) noexcept : m_bucket(other.m_bucket) - { - } + allocator_type get_allocator() const { return m_buckets_data.get_allocator(); } - robin_iterator(const robin_iterator &other) = default; - robin_iterator(robin_iterator &&other) = default; - robin_iterator &operator=(const robin_iterator &other) = default; - robin_iterator &operator=(robin_iterator &&other) = default; + /* + * Iterators + */ + iterator begin() noexcept + { + std::size_t i = 0; + while (i < m_bucket_count && m_buckets[i].empty()) { + i++; + } - const typename robin_hash::key_type &key() const { return KeySelect()(m_bucket->value()); } + return iterator(m_buckets + i); + } - template ::value && IsConst>::type * = nullptr> - const typename U::value_type &value() const - { - return U()(m_bucket->value()); - } + const_iterator begin() const noexcept { return cbegin(); } - template ::value && !IsConst>::type * = nullptr> - typename U::value_type &value() const - { - return U()(m_bucket->value()); - } + const_iterator cbegin() const noexcept + { + std::size_t i = 0; + while (i < m_bucket_count && m_buckets[i].empty()) { + i++; + } - reference operator*() const { return m_bucket->value(); } + return const_iterator(m_buckets + i); + } - pointer operator->() const { return std::addressof(m_bucket->value()); } + iterator end() noexcept { return iterator(m_buckets + m_bucket_count); } - robin_iterator &operator++() - { - while (true) { - if (m_bucket->last_bucket()) { - ++m_bucket; - return *this; - } + const_iterator end() const noexcept { return cend(); } - ++m_bucket; - if (!m_bucket->empty()) { - return *this; - } - } - } + const_iterator cend() const noexcept { return const_iterator(m_buckets + m_bucket_count); } - robin_iterator operator++(int) - { - robin_iterator tmp(*this); - ++*this; + /* + * Capacity + */ + bool empty() const noexcept { return m_nb_elements == 0; } - return tmp; - } + size_type size() const noexcept { return m_nb_elements; } - friend bool operator==(const robin_iterator &lhs, const robin_iterator &rhs) - { - return lhs.m_bucket == rhs.m_bucket; - } + size_type max_size() const noexcept { return m_buckets_data.max_size(); } - friend bool operator!=(const robin_iterator &lhs, const robin_iterator &rhs) - { - return !(lhs == rhs); + /* + * Modifiers + */ + void clear() noexcept + { + if (m_min_load_factor > 0.0f) { + clear_and_shrink(); + } + else { + for (auto &bucket : m_buckets_data) { + bucket.clear(); } - private: - bucket_entry_ptr m_bucket; - }; - - public: -#if defined(__cplusplus) && __cplusplus >= 201402L - robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, - const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, - float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) - : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), - m_buckets_data(bucket_count, alloc), - m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), - m_bucket_count(bucket_count), m_nb_elements(0), m_grow_on_next_insert(false), - m_try_shrink_on_next_insert(false) - { - if (bucket_count > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); - } + m_nb_elements = 0; + m_grow_on_next_insert = false; + } + } - if (m_bucket_count > 0) { - tsl_rh_assert(!m_buckets_data.empty()); - m_buckets_data.back().set_as_last_bucket(); - } + template std::pair insert(P &&value) + { + return insert_impl(KeySelect()(value), std::forward

(value)); + } - this->min_load_factor(min_load_factor); - this->max_load_factor(max_load_factor); + template iterator insert_hint(const_iterator hint, P &&value) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) { + return mutable_iterator(hint); } -#else - /** - * C++11 doesn't support the creation of a std::vector with a custom allocator - * and 'count' default-inserted elements. The needed contructor `explicit - * vector(size_type count, const Allocator& alloc = Allocator());` is only - * available in C++14 and later. We thus must resize after using the - * `vector(const Allocator& alloc)` constructor. - * - * We can't use `vector(size_type count, const T& value, const Allocator& - * alloc)` as it requires the value T to be copyable. - */ - robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, - const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, - float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) - : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), m_buckets_data(alloc), - m_buckets(static_empty_bucket_ptr()), m_bucket_count(bucket_count), m_nb_elements(0), - m_grow_on_next_insert(false), m_try_shrink_on_next_insert(false) - { - if (bucket_count > max_bucket_count()) { - TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); - } - if (m_bucket_count > 0) { - m_buckets_data.resize(m_bucket_count); - m_buckets = m_buckets_data.data(); + return insert(std::forward

(value)).first; + } - tsl_rh_assert(!m_buckets_data.empty()); - m_buckets_data.back().set_as_last_bucket(); + template void insert(InputIt first, InputIt last) + { + if (std::is_base_of::iterator_category>::value) { + const auto nb_elements_insert = std::distance(first, last); + const size_type nb_free_buckets = m_load_threshold - size(); + tsl_rh_assert(m_load_threshold >= size()); + + if (nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) { + reserve(size() + size_type(nb_elements_insert)); } - - this->min_load_factor(min_load_factor); - this->max_load_factor(max_load_factor); } -#endif - robin_hash(const robin_hash &other) - : Hash(other), KeyEqual(other), GrowthPolicy(other), m_buckets_data(other.m_buckets_data), - m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), - m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), - m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), - m_max_load_factor(other.m_max_load_factor), - m_grow_on_next_insert(other.m_grow_on_next_insert), - m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) - { + for (; first != last; ++first) { + insert(*first); } + } - robin_hash(robin_hash &&other) noexcept( - std::is_nothrow_move_constructible::value &&std::is_nothrow_move_constructible< - KeyEqual>::value &&std::is_nothrow_move_constructible::value - &&std::is_nothrow_move_constructible::value) - : Hash(std::move(static_cast(other))), - KeyEqual(std::move(static_cast(other))), - GrowthPolicy(std::move(static_cast(other))), - m_buckets_data(std::move(other.m_buckets_data)), - m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), - m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), - m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), - m_max_load_factor(other.m_max_load_factor), - m_grow_on_next_insert(other.m_grow_on_next_insert), - m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) - { - other.clear_and_shrink(); + template std::pair insert_or_assign(K &&key, M &&obj) + { + auto it = try_emplace(std::forward(key), std::forward(obj)); + if (!it.second) { + it.first.value() = std::forward(obj); } - robin_hash &operator=(const robin_hash &other) - { - if (&other != this) { - Hash:: operator=(other); - KeyEqual:: operator=(other); - GrowthPolicy::operator=(other); - - m_buckets_data = other.m_buckets_data; - m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data(); - m_bucket_count = other.m_bucket_count; - m_nb_elements = other.m_nb_elements; - - m_load_threshold = other.m_load_threshold; - m_min_load_factor = other.m_min_load_factor; - m_max_load_factor = other.m_max_load_factor; - - m_grow_on_next_insert = other.m_grow_on_next_insert; - m_try_shrink_on_next_insert = other.m_try_shrink_on_next_insert; - } + return it; + } + + template iterator insert_or_assign(const_iterator hint, K &&key, M &&obj) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + auto it = mutable_iterator(hint); + it.value() = std::forward(obj); - return *this; + return it; } - robin_hash &operator=(robin_hash &&other) - { - other.swap(*this); - other.clear_and_shrink(); + return insert_or_assign(std::forward(key), std::forward(obj)).first; + } - return *this; - } + template std::pair emplace(Args &&...args) + { + return insert(value_type(std::forward(args)...)); + } - allocator_type get_allocator() const { return m_buckets_data.get_allocator(); } + template iterator emplace_hint(const_iterator hint, Args &&...args) + { + return insert_hint(hint, value_type(std::forward(args)...)); + } - /* - * Iterators - */ - iterator begin() noexcept - { - std::size_t i = 0; - while (i < m_bucket_count && m_buckets[i].empty()) { - i++; - } + template std::pair try_emplace(K &&key, Args &&...args) + { + return insert_impl(key, std::piecewise_construct, std::forward_as_tuple(std::forward(key)), + std::forward_as_tuple(std::forward(args)...)); + } - return iterator(m_buckets + i); + template + iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + return mutable_iterator(hint); } - const_iterator begin() const noexcept { return cbegin(); } + return try_emplace(std::forward(key), std::forward(args)...).first; + } - const_iterator cbegin() const noexcept - { - std::size_t i = 0; - while (i < m_bucket_count && m_buckets[i].empty()) { - i++; - } + /** + * Here to avoid `template size_type erase(const K& key)` being used + * when we use an `iterator` instead of a `const_iterator`. + */ + iterator erase(iterator pos) + { + erase_from_bucket(pos); - return const_iterator(m_buckets + i); + /** + * Erase bucket used a backward shift after clearing the bucket. + * Check if there is a new value in the bucket, if not get the next + * non-empty. + */ + if (pos.m_bucket->empty()) { + ++pos; } - iterator end() noexcept { return iterator(m_buckets + m_bucket_count); } + m_try_shrink_on_next_insert = true; - const_iterator end() const noexcept { return cend(); } + return pos; + } - const_iterator cend() const noexcept { return const_iterator(m_buckets + m_bucket_count); } + iterator erase(const_iterator pos) { return erase(mutable_iterator(pos)); } - /* - * Capacity - */ - bool empty() const noexcept { return m_nb_elements == 0; } + iterator erase(const_iterator first, const_iterator last) + { + if (first == last) { + return mutable_iterator(first); + } - size_type size() const noexcept { return m_nb_elements; } + auto first_mutable = mutable_iterator(first); + auto last_mutable = mutable_iterator(last); + for (auto it = first_mutable.m_bucket; it != last_mutable.m_bucket; ++it) { + if (!it->empty()) { + it->clear(); + m_nb_elements--; + } + } - size_type max_size() const noexcept { return m_buckets_data.max_size(); } + if (last_mutable == end()) { + m_try_shrink_on_next_insert = true; + return end(); + } /* - * Modifiers + * Backward shift on the values which come after the deleted values. + * We try to move the values closer to their ideal bucket. */ - void clear() noexcept - { - if (m_min_load_factor > 0.0f) { - clear_and_shrink(); - } - else { - for (auto &bucket : m_buckets_data) { - bucket.clear(); - } + auto icloser_bucket = static_cast(first_mutable.m_bucket - m_buckets); + auto ito_move_closer_value = static_cast(last_mutable.m_bucket - m_buckets); + tsl_rh_assert(ito_move_closer_value > icloser_bucket); + + const std::size_t ireturn_bucket = + ito_move_closer_value - + std::min(ito_move_closer_value - icloser_bucket, + std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); + + while (ito_move_closer_value < m_bucket_count && + m_buckets[ito_move_closer_value].dist_from_ideal_bucket() > 0) { + icloser_bucket = + ito_move_closer_value - + std::min(ito_move_closer_value - icloser_bucket, + std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); - m_nb_elements = 0; - m_grow_on_next_insert = false; - } - } + tsl_rh_assert(m_buckets[icloser_bucket].empty()); + const distance_type new_distance = + distance_type(m_buckets[ito_move_closer_value].dist_from_ideal_bucket() - + (ito_move_closer_value - icloser_bucket)); + m_buckets[icloser_bucket].set_value_of_empty_bucket( + new_distance, m_buckets[ito_move_closer_value].truncated_hash(), + std::move(m_buckets[ito_move_closer_value].value())); + m_buckets[ito_move_closer_value].clear(); - template std::pair insert(P &&value) - { - return insert_impl(KeySelect()(value), std::forward

(value)); + ++icloser_bucket; + ++ito_move_closer_value; } - template iterator insert_hint(const_iterator hint, P &&value) - { - if (hint != cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) { - return mutable_iterator(hint); - } - - return insert(std::forward

(value)).first; - } + m_try_shrink_on_next_insert = true; - template void insert(InputIt first, InputIt last) - { - if (std::is_base_of::iterator_category>::value) { - const auto nb_elements_insert = std::distance(first, last); - const size_type nb_free_buckets = m_load_threshold - size(); - tsl_rh_assert(m_load_threshold >= size()); - - if (nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) { - reserve(size() + size_type(nb_elements_insert)); - } - } + return iterator(m_buckets + ireturn_bucket); + } - for (; first != last; ++first) { - insert(*first); - } - } + template size_type erase(const K &key) { return erase(key, hash_key(key)); } - template std::pair insert_or_assign(K &&key, M &&obj) - { - auto it = try_emplace(std::forward(key), std::forward(obj)); - if (!it.second) { - it.first.value() = std::forward(obj); - } + template size_type erase(const K &key, std::size_t my_hash) + { + auto it = find(key, my_hash); + if (it != end()) { + erase_from_bucket(it); + m_try_shrink_on_next_insert = true; - return it; + return 1; } - - template iterator insert_or_assign(const_iterator hint, K &&key, M &&obj) - { - if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { - auto it = mutable_iterator(hint); - it.value() = std::forward(obj); - - return it; - } - - return insert_or_assign(std::forward(key), std::forward(obj)).first; + else { + return 0; } + } - template std::pair emplace(Args &&...args) - { - return insert(value_type(std::forward(args)...)); - } + void swap(robin_hash &other) + { + using std::swap; + + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(m_buckets_data, other.m_buckets_data); + swap(m_buckets, other.m_buckets); + swap(m_bucket_count, other.m_bucket_count); + swap(m_nb_elements, other.m_nb_elements); + swap(m_load_threshold, other.m_load_threshold); + swap(m_min_load_factor, other.m_min_load_factor); + swap(m_max_load_factor, other.m_max_load_factor); + swap(m_grow_on_next_insert, other.m_grow_on_next_insert); + swap(m_try_shrink_on_next_insert, other.m_try_shrink_on_next_insert); + } - template iterator emplace_hint(const_iterator hint, Args &&...args) - { - return insert_hint(hint, value_type(std::forward(args)...)); - } + /* + * Lookup + */ + template ::value>::type * = nullptr> + typename U::value_type &at(const K &key) + { + return at(key, hash_key(key)); + } - template - std::pair try_emplace(K &&key, Args &&...args) - { - return insert_impl(key, std::piecewise_construct, - std::forward_as_tuple(std::forward(key)), - std::forward_as_tuple(std::forward(args)...)); - } + template ::value>::type * = nullptr> + typename U::value_type &at(const K &key, std::size_t my_hash) + { + return const_cast( + static_cast(this)->at(key, my_hash)); + } - template - iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args) - { - if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { - return mutable_iterator(hint); - } + template ::value>::type * = nullptr> + const typename U::value_type &at(const K &key) const + { + return at(key, hash_key(key)); + } - return try_emplace(std::forward(key), std::forward(args)...).first; + template ::value>::type * = nullptr> + const typename U::value_type &at(const K &key, std::size_t my_hash) const + { + auto it = find(key, my_hash); + if (it != cend()) { + return it.value(); } - - /** - * Here to avoid `template size_type erase(const K& key)` being used - * when we use an `iterator` instead of a `const_iterator`. - */ - iterator erase(iterator pos) - { - erase_from_bucket(pos); - - /** - * Erase bucket used a backward shift after clearing the bucket. - * Check if there is a new value in the bucket, if not get the next - * non-empty. - */ - if (pos.m_bucket->empty()) { - ++pos; - } - - m_try_shrink_on_next_insert = true; - - return pos; + else { + TSL_RH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find key."); } + } - iterator erase(const_iterator pos) { return erase(mutable_iterator(pos)); } - - iterator erase(const_iterator first, const_iterator last) - { - if (first == last) { - return mutable_iterator(first); - } + template ::value>::type * = nullptr> + typename U::value_type &operator[](K &&key) + { + return try_emplace(std::forward(key)).first.value(); + } - auto first_mutable = mutable_iterator(first); - auto last_mutable = mutable_iterator(last); - for (auto it = first_mutable.m_bucket; it != last_mutable.m_bucket; ++it) { - if (!it->empty()) { - it->clear(); - m_nb_elements--; - } - } + template size_type count(const K &key) const { return count(key, hash_key(key)); } - if (last_mutable == end()) { - m_try_shrink_on_next_insert = true; - return end(); - } + template size_type count(const K &key, std::size_t my_hash) const + { + if (find(key, my_hash) != cend()) { + return 1; + } + else { + return 0; + } + } - /* - * Backward shift on the values which come after the deleted values. - * We try to move the values closer to their ideal bucket. - */ - std::size_t icloser_bucket = static_cast(first_mutable.m_bucket - m_buckets); - std::size_t ito_move_closer_value = - static_cast(last_mutable.m_bucket - m_buckets); - tsl_rh_assert(ito_move_closer_value > icloser_bucket); + template iterator find(const K &key) { return find_impl(key, hash_key(key)); } - const std::size_t ireturn_bucket = - ito_move_closer_value - - std::min(ito_move_closer_value - icloser_bucket, - std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); + template iterator find(const K &key, std::size_t my_hash) + { + return find_impl(key, my_hash); + } - while (ito_move_closer_value < m_bucket_count && - m_buckets[ito_move_closer_value].dist_from_ideal_bucket() > 0) { - icloser_bucket = - ito_move_closer_value - - std::min(ito_move_closer_value - icloser_bucket, - std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); - - tsl_rh_assert(m_buckets[icloser_bucket].empty()); - const distance_type new_distance = - distance_type(m_buckets[ito_move_closer_value].dist_from_ideal_bucket() - - (ito_move_closer_value - icloser_bucket)); - m_buckets[icloser_bucket].set_value_of_empty_bucket( - new_distance, m_buckets[ito_move_closer_value].truncated_hash(), - std::move(m_buckets[ito_move_closer_value].value())); - m_buckets[ito_move_closer_value].clear(); - - ++icloser_bucket; - ++ito_move_closer_value; - } + template const_iterator find(const K &key) const + { + return find_impl(key, hash_key(key)); + } - m_try_shrink_on_next_insert = true; + template const_iterator find(const K &key, std::size_t my_hash) const + { + return find_impl(key, my_hash); + } - return iterator(m_buckets + ireturn_bucket); - } + template bool contains(const K &key) const { return contains(key, hash_key(key)); } - template size_type erase(const K &key) { return erase(key, hash_key(key)); } + template bool contains(const K &key, std::size_t my_hash) const + { + return count(key, my_hash) != 0; + } - template size_type erase(const K &key, std::size_t my_hash) - { - auto it = find(key, my_hash); - if (it != end()) { - erase_from_bucket(it); - m_try_shrink_on_next_insert = true; + template std::pair equal_range(const K &key) + { + return equal_range(key, hash_key(key)); + } - return 1; - } - else { - return 0; - } - } + template std::pair equal_range(const K &key, std::size_t my_hash) + { + iterator it = find(key, my_hash); + return std::make_pair(it, (it == end()) ? it : std::next(it)); + } - void swap(robin_hash &other) - { - using std::swap; - - swap(static_cast(*this), static_cast(other)); - swap(static_cast(*this), static_cast(other)); - swap(static_cast(*this), static_cast(other)); - swap(m_buckets_data, other.m_buckets_data); - swap(m_buckets, other.m_buckets); - swap(m_bucket_count, other.m_bucket_count); - swap(m_nb_elements, other.m_nb_elements); - swap(m_load_threshold, other.m_load_threshold); - swap(m_min_load_factor, other.m_min_load_factor); - swap(m_max_load_factor, other.m_max_load_factor); - swap(m_grow_on_next_insert, other.m_grow_on_next_insert); - swap(m_try_shrink_on_next_insert, other.m_try_shrink_on_next_insert); - } + template std::pair equal_range(const K &key) const + { + return equal_range(key, hash_key(key)); + } - /* - * Lookup - */ - template ::value>::type * = nullptr> - typename U::value_type &at(const K &key) - { - return at(key, hash_key(key)); - } + template + std::pair equal_range(const K &key, std::size_t my_hash) const + { + const_iterator it = find(key, my_hash); + return std::make_pair(it, (it == cend()) ? it : std::next(it)); + } - template ::value>::type * = nullptr> - typename U::value_type &at(const K &key, std::size_t my_hash) - { - return const_cast( - static_cast(this)->at(key, my_hash)); - } + /* + * Bucket interface + */ + size_type bucket_count() const { return m_bucket_count; } - template ::value>::type * = nullptr> - const typename U::value_type &at(const K &key) const - { - return at(key, hash_key(key)); - } + size_type max_bucket_count() const + { + return std::min(GrowthPolicy::max_bucket_count(), m_buckets_data.max_size()); + } - template ::value>::type * = nullptr> - const typename U::value_type &at(const K &key, std::size_t my_hash) const - { - auto it = find(key, my_hash); - if (it != cend()) { - return it.value(); - } - else { - TSL_RH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find key."); - } + /* + * Hash policy + */ + float load_factor() const + { + if (bucket_count() == 0) { + return 0; } - template ::value>::type * = nullptr> - typename U::value_type &operator[](K &&key) - { - return try_emplace(std::forward(key)).first.value(); - } + return float(m_nb_elements) / float(bucket_count()); + } - template size_type count(const K &key) const { return count(key, hash_key(key)); } + float min_load_factor() const { return m_min_load_factor; } - template size_type count(const K &key, std::size_t my_hash) const - { - if (find(key, my_hash) != cend()) { - return 1; - } - else { - return 0; - } - } + float max_load_factor() const { return m_max_load_factor; } - template iterator find(const K &key) { return find_impl(key, hash_key(key)); } + void min_load_factor(float ml) + { + m_min_load_factor = clamp(ml, float(MINIMUM_MIN_LOAD_FACTOR), float(MAXIMUM_MIN_LOAD_FACTOR)); + } - template iterator find(const K &key, std::size_t my_hash) - { - return find_impl(key, my_hash); - } + void max_load_factor(float ml) + { + m_max_load_factor = clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR), float(MAXIMUM_MAX_LOAD_FACTOR)); + m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor); + tsl_rh_assert(bucket_count() == 0 || m_load_threshold < bucket_count()); + } - template const_iterator find(const K &key) const - { - return find_impl(key, hash_key(key)); - } + void rehash(size_type my_count) + { + my_count = std::max(my_count, size_type(std::ceil(float(size()) / max_load_factor()))); + rehash_impl(my_count); + } - template const_iterator find(const K &key, std::size_t my_hash) const - { - return find_impl(key, my_hash); - } + void reserve(size_type my_count) + { + rehash(size_type(std::ceil(float(my_count) / max_load_factor()))); + } - template bool contains(const K &key) const { return contains(key, hash_key(key)); } + /* + * Observers + */ + hasher hash_function() const { return static_cast(*this); } - template bool contains(const K &key, std::size_t my_hash) const - { - return count(key, my_hash) != 0; - } + key_equal key_eq() const { return static_cast(*this); } - template std::pair equal_range(const K &key) - { - return equal_range(key, hash_key(key)); - } + /* + * Other + */ + iterator mutable_iterator(const_iterator pos) + { + return iterator(const_cast(pos.m_bucket)); + } - template - std::pair equal_range(const K &key, std::size_t my_hash) - { - iterator it = find(key, my_hash); - return std::make_pair(it, (it == end()) ? it : std::next(it)); - } + template void serialize(Serializer &serializer) const + { + serialize_impl(serializer); + } - template std::pair equal_range(const K &key) const - { - return equal_range(key, hash_key(key)); - } + template void deserialize(Deserializer &deserializer, bool hash_compatible) + { + deserialize_impl(deserializer, hash_compatible); + } - template - std::pair equal_range(const K &key, std::size_t my_hash) const - { - const_iterator it = find(key, my_hash); - return std::make_pair(it, (it == cend()) ? it : std::next(it)); - } + private: + template std::size_t hash_key(const K &key) const { return Hash::operator()(key); } - /* - * Bucket interface - */ - size_type bucket_count() const { return m_bucket_count; } + template bool compare_keys(const K1 &key1, const K2 &key2) const + { + return KeyEqual::operator()(key1, key2); + } - size_type max_bucket_count() const - { - return std::min(GrowthPolicy::max_bucket_count(), m_buckets_data.max_size()); - } + std::size_t bucket_for_hash(std::size_t my_hash) const + { + const std::size_t bucket = GrowthPolicy::bucket_for_hash(my_hash); + tsl_rh_assert(bucket < m_bucket_count || (bucket == 0 && m_bucket_count == 0)); - /* - * Hash policy - */ - float load_factor() const - { - if (bucket_count() == 0) { - return 0; - } + return bucket; + } - return float(m_nb_elements) / float(bucket_count()); - } + template ::value>::type * = nullptr> + std::size_t next_bucket(std::size_t index) const noexcept + { + tsl_rh_assert(index < bucket_count()); - float min_load_factor() const { return m_min_load_factor; } + return (index + 1) & this->m_mask; + } - float max_load_factor() const { return m_max_load_factor; } + template ::value>::type * = nullptr> + std::size_t next_bucket(std::size_t index) const noexcept + { + tsl_rh_assert(index < bucket_count()); - void min_load_factor(float ml) - { - m_min_load_factor = - clamp(ml, float(MINIMUM_MIN_LOAD_FACTOR), float(MAXIMUM_MIN_LOAD_FACTOR)); - } + index++; + return (index != bucket_count()) ? index : 0; + } - void max_load_factor(float ml) - { - m_max_load_factor = - clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR), float(MAXIMUM_MAX_LOAD_FACTOR)); - m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor); - tsl_rh_assert(bucket_count() == 0 || m_load_threshold < bucket_count()); - } + template iterator find_impl(const K &key, std::size_t my_hash) + { + return mutable_iterator(static_cast(this)->find(key, my_hash)); + } - void rehash(size_type my_count) - { - my_count = std::max(my_count, size_type(std::ceil(float(size()) / max_load_factor()))); - rehash_impl(my_count); - } + template const_iterator find_impl(const K &key, std::size_t my_hash) const + { + std::size_t ibucket = bucket_for_hash(my_hash); + distance_type dist_from_ideal_bucket = 0; + + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + if (TSL_RH_LIKELY( + (!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && + compare_keys(KeySelect()(m_buckets[ibucket].value()), key))) { + return const_iterator(m_buckets + ibucket); + } - void reserve(size_type my_count) - { - rehash(size_type(std::ceil(float(my_count) / max_load_factor()))); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; } - /* - * Observers - */ - hasher hash_function() const { return static_cast(*this); } + return cend(); + } - key_equal key_eq() const { return static_cast(*this); } + void erase_from_bucket(iterator pos) + { + pos.m_bucket->clear(); + m_nb_elements--; - /* - * Other + /** + * Backward shift, swap the empty bucket, previous_ibucket, with the values + * on its right, ibucket, until we cross another empty bucket or if the + * other bucket has a distance_from_ideal_bucket == 0. + * + * We try to move the values closer to their ideal bucket. */ - iterator mutable_iterator(const_iterator pos) - { - return iterator(const_cast(pos.m_bucket)); - } + auto previous_ibucket = static_cast(pos.m_bucket - m_buckets); + auto ibucket = next_bucket(previous_ibucket); - template void serialize(Serializer &serializer) const - { - serialize_impl(serializer); - } + while (m_buckets[ibucket].dist_from_ideal_bucket() > 0) { + tsl_rh_assert(m_buckets[previous_ibucket].empty()); - template - void deserialize(Deserializer &deserializer, bool hash_compatible) - { - deserialize_impl(deserializer, hash_compatible); - } + const auto new_distance = distance_type(m_buckets[ibucket].dist_from_ideal_bucket() - 1); + m_buckets[previous_ibucket].set_value_of_empty_bucket( + new_distance, m_buckets[ibucket].truncated_hash(), + std::move(m_buckets[ibucket].value())); + m_buckets[ibucket].clear(); - private: - template std::size_t hash_key(const K &key) const { return Hash::operator()(key); } - - template bool compare_keys(const K1 &key1, const K2 &key2) const - { - return KeyEqual::operator()(key1, key2); + previous_ibucket = ibucket; + ibucket = next_bucket(ibucket); } + } - std::size_t bucket_for_hash(std::size_t my_hash) const - { - const std::size_t bucket = GrowthPolicy::bucket_for_hash(my_hash); - tsl_rh_assert(bucket < m_bucket_count || (bucket == 0 && m_bucket_count == 0)); - - return bucket; - } - - template ::value>::type * = nullptr> - std::size_t next_bucket(std::size_t index) const noexcept - { - tsl_rh_assert(index < bucket_count()); - - return (index + 1) & this->m_mask; - } + template + std::pair insert_impl(const K &key, Args &&...value_type_args) + { + const std::size_t my_hash = hash_key(key); - template ::value>::type * = nullptr> - std::size_t next_bucket(std::size_t index) const noexcept - { - tsl_rh_assert(index < bucket_count()); + std::size_t ibucket = bucket_for_hash(my_hash); + distance_type dist_from_ideal_bucket = 0; - index++; - return (index != bucket_count()) ? index : 0; - } + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + if ((!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && + compare_keys(KeySelect()(m_buckets[ibucket].value()), key)) { + return std::make_pair(iterator(m_buckets + ibucket), false); + } - template iterator find_impl(const K &key, std::size_t my_hash) - { - return mutable_iterator(static_cast(this)->find(key, my_hash)); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; } - template const_iterator find_impl(const K &key, std::size_t my_hash) const - { - std::size_t ibucket = bucket_for_hash(my_hash); - distance_type dist_from_ideal_bucket = 0; + while (rehash_on_extreme_load(dist_from_ideal_bucket)) { + ibucket = bucket_for_hash(my_hash); + dist_from_ideal_bucket = 0; while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { - if (TSL_RH_LIKELY( - (!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && - compare_keys(KeySelect()(m_buckets[ibucket].value()), key))) { - return const_iterator(m_buckets + ibucket); - } - ibucket = next_bucket(ibucket); dist_from_ideal_bucket++; } - - return cend(); } - void erase_from_bucket(iterator pos) - { - pos.m_bucket->clear(); - m_nb_elements--; - - /** - * Backward shift, swap the empty bucket, previous_ibucket, with the values - * on its right, ibucket, until we cross another empty bucket or if the - * other bucket has a distance_from_ideal_bucket == 0. - * - * We try to move the values closer to their ideal bucket. - */ - std::size_t previous_ibucket = static_cast(pos.m_bucket - m_buckets); - std::size_t ibucket = next_bucket(previous_ibucket); - - while (m_buckets[ibucket].dist_from_ideal_bucket() > 0) { - tsl_rh_assert(m_buckets[previous_ibucket].empty()); - - const distance_type new_distance = - distance_type(m_buckets[ibucket].dist_from_ideal_bucket() - 1); - m_buckets[previous_ibucket].set_value_of_empty_bucket( - new_distance, m_buckets[ibucket].truncated_hash(), - std::move(m_buckets[ibucket].value())); - m_buckets[ibucket].clear(); - - previous_ibucket = ibucket; - ibucket = next_bucket(ibucket); - } + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, + bucket_entry::truncate_hash(my_hash), + std::forward(value_type_args)...); + } + else { + insert_value(ibucket, dist_from_ideal_bucket, bucket_entry::truncate_hash(my_hash), + std::forward(value_type_args)...); } - template - std::pair insert_impl(const K &key, Args &&...value_type_args) - { - const std::size_t my_hash = hash_key(key); + m_nb_elements++; + /* + * The value will be inserted in ibucket in any case, either because it was + * empty or by stealing the bucket (robin hood). + */ + return std::make_pair(iterator(m_buckets + ibucket), true); + } - std::size_t ibucket = bucket_for_hash(my_hash); - distance_type dist_from_ideal_bucket = 0; + template + void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, Args &&...value_type_args) + { + value_type value(std::forward(value_type_args)...); + insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + } - while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { - if ((!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && - compare_keys(KeySelect()(m_buckets[ibucket].value()), key)) { - return std::make_pair(iterator(m_buckets + ibucket), false); + void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &&value) + { + insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + } + + /* + * We don't use `value_type&& value` as last argument due to a bug in MSVC + * when `value_type` is a pointer, The compiler is not able to see the + * difference between `std::string*` and `std::string*&&` resulting in a + * compilation error. + * + * The `value` will be in a moved state at the end of the function. + */ + void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &value) + { + tsl_rh_assert(dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()); + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + + while (!m_buckets[ibucket].empty()) { + if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { + if (dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) { + /** + * The number of probes is really high, rehash the map on the next + * insert. Difficult to do now as rehash may throw an exception. + */ + m_grow_on_next_insert = true; } - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); } - while (rehash_on_extreme_load(dist_from_ideal_bucket)) { - ibucket = bucket_for_hash(my_hash); - dist_from_ideal_bucket = 0; + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } - while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; - } - } + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, + std::move(value)); + } - if (m_buckets[ibucket].empty()) { - m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, - bucket_entry::truncate_hash(my_hash), - std::forward(value_type_args)...); - } - else { - insert_value(ibucket, dist_from_ideal_bucket, bucket_entry::truncate_hash(my_hash), - std::forward(value_type_args)...); + void rehash_impl(size_type my_count) + { + robin_hash new_table(my_count, static_cast(*this), static_cast(*this), + get_allocator(), m_min_load_factor, m_max_load_factor); + + const bool use_stored_hash = USE_STORED_HASH_ON_REHASH(new_table.bucket_count()); + for (auto &bucket : m_buckets_data) { + if (bucket.empty()) { + continue; } - m_nb_elements++; - /* - * The value will be inserted in ibucket in any case, either because it was - * empty or by stealing the bucket (robin hood). - */ - return std::make_pair(iterator(m_buckets + ibucket), true); - } + const std::size_t my_hash = use_stored_hash + ? bucket.truncated_hash() + : new_table.hash_key(KeySelect()(bucket.value())); - template - void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, Args &&...value_type_args) - { - value_type value(std::forward(value_type_args)...); - insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + new_table.insert_value_on_rehash(new_table.bucket_for_hash(my_hash), 0, + bucket_entry::truncate_hash(my_hash), + std::move(bucket.value())); } - void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, value_type &&value) - { - insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); - } - - /* - * We don't use `value_type&& value` as last argument due to a bug in MSVC - * when `value_type` is a pointer, The compiler is not able to see the - * difference between `std::string*` and `std::string*&&` resulting in a - * compilation error. - * - * The `value` will be in a moved state at the end of the function. - */ - void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, value_type &value) - { - tsl_rh_assert(dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()); - m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; + new_table.m_nb_elements = m_nb_elements; + new_table.swap(*this); + } - while (!m_buckets[ibucket].empty()) { - if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { - if (dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) { - /** - * The number of probes is really high, rehash the map on the next - * insert. Difficult to do now as rehash may throw an exception. - */ - m_grow_on_next_insert = true; - } + void clear_and_shrink() noexcept + { + GrowthPolicy::clear(); + m_buckets_data.clear(); + m_buckets = static_empty_bucket_ptr(); + m_bucket_count = 0; + m_nb_elements = 0; + m_load_threshold = 0; + m_grow_on_next_insert = false; + m_try_shrink_on_next_insert = false; + } + void insert_value_on_rehash(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &&value) + { + while (true) { + if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, + std::move(value)); + return; + } + else { m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); } - - ibucket = next_bucket(ibucket); - dist_from_ideal_bucket++; } - m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, - std::move(value)); + dist_from_ideal_bucket++; + ibucket = next_bucket(ibucket); } + } - void rehash_impl(size_type my_count) - { - robin_hash new_table(my_count, static_cast(*this), static_cast(*this), - get_allocator(), m_min_load_factor, m_max_load_factor); + /** + * Grow the table if m_grow_on_next_insert is true or we reached the + * max_load_factor. Shrink the table if m_try_shrink_on_next_insert is true + * (an erase occurred) and we're below the min_load_factor. + * + * Return true if the table has been rehashed. + */ + bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) + { + if (m_grow_on_next_insert || + curr_dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT || + size() >= m_load_threshold) { + rehash_impl(GrowthPolicy::next_bucket_count()); + m_grow_on_next_insert = false; - const bool use_stored_hash = USE_STORED_HASH_ON_REHASH(new_table.bucket_count()); - for (auto &bucket : m_buckets_data) { - if (bucket.empty()) { - continue; - } + return true; + } - const std::size_t my_hash = use_stored_hash - ? bucket.truncated_hash() - : new_table.hash_key(KeySelect()(bucket.value())); + if (m_try_shrink_on_next_insert) { + m_try_shrink_on_next_insert = false; + if (m_min_load_factor != 0.0f && load_factor() < m_min_load_factor) { + reserve(size() + 1); - new_table.insert_value_on_rehash(new_table.bucket_for_hash(my_hash), 0, - bucket_entry::truncate_hash(my_hash), - std::move(bucket.value())); + return true; } - - new_table.m_nb_elements = m_nb_elements; - new_table.swap(*this); } - void clear_and_shrink() noexcept - { - GrowthPolicy::clear(); - m_buckets_data.clear(); - m_buckets = static_empty_bucket_ptr(); - m_bucket_count = 0; - m_nb_elements = 0; - m_load_threshold = 0; - m_grow_on_next_insert = false; - m_try_shrink_on_next_insert = false; - } + return false; + } - void insert_value_on_rehash(std::size_t ibucket, distance_type dist_from_ideal_bucket, - truncated_hash_type my_hash, value_type &&value) - { - while (true) { - if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { - if (m_buckets[ibucket].empty()) { - m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, - std::move(value)); - return; - } - else { - m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); - } - } + template void serialize_impl(Serializer &serializer) const + { + const slz_size_type version = SERIALIZATION_PROTOCOL_VERSION; + serializer(version); - dist_from_ideal_bucket++; - ibucket = next_bucket(ibucket); - } - } + // Indicate if the truncated hash of each bucket is stored. Use a + // std::int16_t instead of a bool to avoid the need for the serializer to + // support an extra 'bool' type. + const auto hash_stored_for_bucket = static_cast(STORE_HASH); + serializer(hash_stored_for_bucket); - /** - * Grow the table if m_grow_on_next_insert is true or we reached the - * max_load_factor. Shrink the table if m_try_shrink_on_next_insert is true - * (an erase occurred) and we're below the min_load_factor. - * - * Return true if the table has been rehashed. - */ - bool rehash_on_extreme_load(distance_type curr_dist_from_ideal_bucket) - { - if (m_grow_on_next_insert || - curr_dist_from_ideal_bucket > bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT || - size() >= m_load_threshold) { - rehash_impl(GrowthPolicy::next_bucket_count()); - m_grow_on_next_insert = false; + const slz_size_type nb_elements = m_nb_elements; + serializer(nb_elements); - return true; - } + const slz_size_type bucket_count = m_buckets_data.size(); + serializer(bucket_count); + + const float min_load_factor = m_min_load_factor; + serializer(min_load_factor); - if (m_try_shrink_on_next_insert) { - m_try_shrink_on_next_insert = false; - if (m_min_load_factor != 0.0f && load_factor() < m_min_load_factor) { - reserve(size() + 1); + const float max_load_factor = m_max_load_factor; + serializer(max_load_factor); - return true; + for (const bucket_entry &bucket : m_buckets_data) { + if (bucket.empty()) { + const std::int16_t empty_bucket = bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; + serializer(empty_bucket); + } + else { + const std::int16_t dist_from_ideal_bucket = bucket.dist_from_ideal_bucket(); + serializer(dist_from_ideal_bucket); + if (STORE_HASH) { + const std::uint32_t truncated_hash = bucket.truncated_hash(); + serializer(truncated_hash); } + serializer(bucket.value()); } - - return false; } + } - template void serialize_impl(Serializer &serializer) const - { - const slz_size_type version = SERIALIZATION_PROTOCOL_VERSION; - serializer(version); - - // Indicate if the truncated hash of each bucket is stored. Use a - // std::int16_t instead of a bool to avoid the need for the serializer to - // support an extra 'bool' type. - const std::int16_t hash_stored_for_bucket = static_cast(STORE_HASH); - serializer(hash_stored_for_bucket); + template + void deserialize_impl(Deserializer &deserializer, bool hash_compatible) + { + tsl_rh_assert(m_buckets_data.empty()); // Current hash table must be empty - const slz_size_type nb_elements = m_nb_elements; - serializer(nb_elements); + const slz_size_type version = deserialize_value(deserializer); + // For now we only have one version of the serialization protocol. + // If it doesn't match there is a problem with the file. + if (version != SERIALIZATION_PROTOCOL_VERSION) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "Can't deserialize the ordered_map/set. " + "The protocol version header is invalid."); + } - const slz_size_type bucket_count = m_buckets_data.size(); - serializer(bucket_count); + const bool hash_stored_for_bucket = + deserialize_value(deserializer) ? true : false; + if (hash_compatible && STORE_HASH != hash_stored_for_bucket) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Can't deserialize a map with a different StoreHash " + "than the one used during the serialization when " + "hash compatibility is used"); + } - const float min_load_factor = m_min_load_factor; - serializer(min_load_factor); + const slz_size_type nb_elements = deserialize_value(deserializer); + const slz_size_type bucket_count_ds = deserialize_value(deserializer); + const float min_load_factor = deserialize_value(deserializer); + const float max_load_factor = deserialize_value(deserializer); - const float max_load_factor = m_max_load_factor; - serializer(max_load_factor); + if (min_load_factor < MINIMUM_MIN_LOAD_FACTOR || min_load_factor > MAXIMUM_MIN_LOAD_FACTOR) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Invalid min_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); + } - for (const bucket_entry &bucket : m_buckets_data) { - if (bucket.empty()) { - const std::int16_t empty_bucket = bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; - serializer(empty_bucket); - } - else { - const std::int16_t dist_from_ideal_bucket = bucket.dist_from_ideal_bucket(); - serializer(dist_from_ideal_bucket); - if (STORE_HASH) { - const std::uint32_t truncated_hash = bucket.truncated_hash(); - serializer(truncated_hash); - } - serializer(bucket.value()); - } - } + if (max_load_factor < MINIMUM_MAX_LOAD_FACTOR || max_load_factor > MAXIMUM_MAX_LOAD_FACTOR) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Invalid max_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); } - template - void deserialize_impl(Deserializer &deserializer, bool hash_compatible) - { - tsl_rh_assert(m_buckets_data.empty()); // Current hash table must be empty - - const slz_size_type version = deserialize_value(deserializer); - // For now we only have one version of the serialization protocol. - // If it doesn't match there is a problem with the file. - if (version != SERIALIZATION_PROTOCOL_VERSION) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "Can't deserialize the ordered_map/set. " - "The protocol version header is invalid."); - } + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); - const bool hash_stored_for_bucket = - deserialize_value(deserializer) ? true : false; - if (hash_compatible && STORE_HASH != hash_stored_for_bucket) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, - "Can't deserialize a map with a different StoreHash " - "than the one used during the serialization when " - "hash compatibility is used"); - } + if (bucket_count_ds == 0) { + tsl_rh_assert(nb_elements == 0); + return; + } - const slz_size_type nb_elements = deserialize_value(deserializer); - const slz_size_type bucket_count_ds = deserialize_value(deserializer); - const float min_load_factor = deserialize_value(deserializer); - const float max_load_factor = deserialize_value(deserializer); - - if (min_load_factor < MINIMUM_MIN_LOAD_FACTOR || - min_load_factor > MAXIMUM_MIN_LOAD_FACTOR) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, - "Invalid min_load_factor. Check that the serializer " - "and deserializer support floats correctly as they " - "can be converted implicitly to ints."); - } + if (!hash_compatible) { + reserve(numeric_cast(nb_elements, "Deserialized nb_elements is too big.")); + for (slz_size_type ibucket = 0; ibucket < bucket_count_ds; ibucket++) { + const distance_type dist_from_ideal_bucket = + deserialize_value(deserializer); + if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { + if (hash_stored_for_bucket) { + TSL_RH_UNUSED(deserialize_value(deserializer)); + } - if (max_load_factor < MINIMUM_MAX_LOAD_FACTOR || - max_load_factor > MAXIMUM_MAX_LOAD_FACTOR) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, - "Invalid max_load_factor. Check that the serializer " - "and deserializer support floats correctly as they " - "can be converted implicitly to ints."); + insert(deserialize_value(deserializer)); + } } - this->min_load_factor(min_load_factor); - this->max_load_factor(max_load_factor); + tsl_rh_assert(nb_elements == size()); + } + else { + m_bucket_count = + numeric_cast(bucket_count_ds, "Deserialized bucket_count is too big."); - if (bucket_count_ds == 0) { - tsl_rh_assert(nb_elements == 0); - return; + GrowthPolicy::operator=(GrowthPolicy(m_bucket_count)); + // GrowthPolicy should not modify the bucket count we got from + // deserialization + if (m_bucket_count != bucket_count_ds) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "The GrowthPolicy is not the same even " + "though hash_compatible is true."); } - if (!hash_compatible) { - reserve(numeric_cast(nb_elements, "Deserialized nb_elements is too big.")); - for (slz_size_type ibucket = 0; ibucket < bucket_count_ds; ibucket++) { - const distance_type dist_from_ideal_bucket = - deserialize_value(deserializer); - if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { - if (hash_stored_for_bucket) { - TSL_RH_UNUSED(deserialize_value(deserializer)); - } - - insert(deserialize_value(deserializer)); + m_nb_elements = + numeric_cast(nb_elements, "Deserialized nb_elements is too big."); + m_buckets_data.resize(m_bucket_count); + m_buckets = m_buckets_data.data(); + + for (bucket_entry &bucket : m_buckets_data) { + const distance_type dist_from_ideal_bucket = + deserialize_value(deserializer); + if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { + truncated_hash_type truncated_hash = 0; + if (hash_stored_for_bucket) { + tsl_rh_assert(hash_stored_for_bucket); + truncated_hash = deserialize_value(deserializer); } - } - - tsl_rh_assert(nb_elements == size()); - } - else { - m_bucket_count = - numeric_cast(bucket_count_ds, "Deserialized bucket_count is too big."); - - GrowthPolicy::operator=(GrowthPolicy(m_bucket_count)); - // GrowthPolicy should not modify the bucket count we got from - // deserialization - if (m_bucket_count != bucket_count_ds) { - TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "The GrowthPolicy is not the same even " - "though hash_compatible is true."); - } - m_nb_elements = - numeric_cast(nb_elements, "Deserialized nb_elements is too big."); - m_buckets_data.resize(m_bucket_count); - m_buckets = m_buckets_data.data(); - - for (bucket_entry &bucket : m_buckets_data) { - const distance_type dist_from_ideal_bucket = - deserialize_value(deserializer); - if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { - truncated_hash_type truncated_hash = 0; - if (hash_stored_for_bucket) { - tsl_rh_assert(hash_stored_for_bucket); - truncated_hash = deserialize_value(deserializer); - } - - bucket.set_value_of_empty_bucket(dist_from_ideal_bucket, truncated_hash, - deserialize_value(deserializer)); - } + bucket.set_value_of_empty_bucket(dist_from_ideal_bucket, truncated_hash, + deserialize_value(deserializer)); } + } - if (!m_buckets_data.empty()) { - m_buckets_data.back().set_as_last_bucket(); - } + if (!m_buckets_data.empty()) { + m_buckets_data.back().set_as_last_bucket(); } } + } - public: - static const size_type DEFAULT_INIT_BUCKETS_SIZE = 0; + public: + static const size_type DEFAULT_INIT_BUCKETS_SIZE = 0; - static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.5f; - static constexpr float MINIMUM_MAX_LOAD_FACTOR = 0.2f; - static constexpr float MAXIMUM_MAX_LOAD_FACTOR = 0.95f; + static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.5f; + static constexpr float MINIMUM_MAX_LOAD_FACTOR = 0.2f; + static constexpr float MAXIMUM_MAX_LOAD_FACTOR = 0.95f; - static constexpr float DEFAULT_MIN_LOAD_FACTOR = 0.0f; - static constexpr float MINIMUM_MIN_LOAD_FACTOR = 0.0f; - static constexpr float MAXIMUM_MIN_LOAD_FACTOR = 0.15f; + static constexpr float DEFAULT_MIN_LOAD_FACTOR = 0.0f; + static constexpr float MINIMUM_MIN_LOAD_FACTOR = 0.0f; + static constexpr float MAXIMUM_MIN_LOAD_FACTOR = 0.15f; - static_assert(MINIMUM_MAX_LOAD_FACTOR < MAXIMUM_MAX_LOAD_FACTOR, - "MINIMUM_MAX_LOAD_FACTOR should be < MAXIMUM_MAX_LOAD_FACTOR"); - static_assert(MINIMUM_MIN_LOAD_FACTOR < MAXIMUM_MIN_LOAD_FACTOR, - "MINIMUM_MIN_LOAD_FACTOR should be < MAXIMUM_MIN_LOAD_FACTOR"); - static_assert(MAXIMUM_MIN_LOAD_FACTOR < MINIMUM_MAX_LOAD_FACTOR, - "MAXIMUM_MIN_LOAD_FACTOR should be < MINIMUM_MAX_LOAD_FACTOR"); + static_assert(MINIMUM_MAX_LOAD_FACTOR < MAXIMUM_MAX_LOAD_FACTOR, + "MINIMUM_MAX_LOAD_FACTOR should be < MAXIMUM_MAX_LOAD_FACTOR"); + static_assert(MINIMUM_MIN_LOAD_FACTOR < MAXIMUM_MIN_LOAD_FACTOR, + "MINIMUM_MIN_LOAD_FACTOR should be < MAXIMUM_MIN_LOAD_FACTOR"); + static_assert(MAXIMUM_MIN_LOAD_FACTOR < MINIMUM_MAX_LOAD_FACTOR, + "MAXIMUM_MIN_LOAD_FACTOR should be < MINIMUM_MAX_LOAD_FACTOR"); - private: - /** - * Protocol version currenlty used for serialization. - */ - static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; - - /** - * Return an always valid pointer to an static empty bucket_entry with - * last_bucket() == true. - */ - bucket_entry *static_empty_bucket_ptr() noexcept - { - static bucket_entry empty_bucket(true); - tsl_rh_assert(empty_bucket.empty()); - return &empty_bucket; - } + private: + /** + * Protocol version currently used for serialization. + */ + static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; - private: - buckets_container_type m_buckets_data; + /** + * Return an always valid pointer to an static empty bucket_entry with + * last_bucket() == true. + */ + bucket_entry *static_empty_bucket_ptr() noexcept + { + static bucket_entry empty_bucket(true); + tsl_rh_assert(empty_bucket.empty()); + return &empty_bucket; + } - /** - * Points to m_buckets_data.data() if !m_buckets_data.empty() otherwise points - * to static_empty_bucket_ptr. This variable is useful to avoid the cost of - * checking if m_buckets_data is empty when trying to find an element. - * - * TODO Remove m_buckets_data and only use a pointer instead of a - * pointer+vector to save some space in the robin_hash object. Manage the - * Allocator manually. - */ - bucket_entry *m_buckets; + private: + buckets_container_type m_buckets_data; - /** - * Used a lot in find, avoid the call to m_buckets_data.size() which is a bit - * slower. - */ - size_type m_bucket_count; + /** + * Points to m_buckets_data.data() if !m_buckets_data.empty() otherwise points + * to static_empty_bucket_ptr. This variable is useful to avoid the cost of + * checking if m_buckets_data is empty when trying to find an element. + * + * TODO Remove m_buckets_data and only use a pointer instead of a + * pointer+vector to save some space in the robin_hash object. Manage the + * Allocator manually. + */ + bucket_entry *m_buckets; - size_type m_nb_elements; + /** + * Used a lot in find, avoid the call to m_buckets_data.size() which is a bit + * slower. + */ + size_type m_bucket_count; - size_type m_load_threshold; + size_type m_nb_elements{0}; - float m_min_load_factor; - float m_max_load_factor; + size_type m_load_threshold{0}; - bool m_grow_on_next_insert; + float m_min_load_factor; + float m_max_load_factor; - /** - * We can't shrink down the map on erase operations as the erase methods need - * to return the next iterator. Shrinking the map would invalidate all the - * iterators and we could not return the next iterator in a meaningful way, On - * erase, we thus just indicate on erase that we should try to shrink the hash - * table on the next insert if we go below the min_load_factor. - */ - bool m_try_shrink_on_next_insert; - }; + bool m_grow_on_next_insert{false}; - } // namespace detail_robin_hash + /** + * We can't shrink down the map on erase operations as the erase methods need + * to return the next iterator. Shrinking the map would invalidate all the + * iterators and we could not return the next iterator in a meaningful way, On + * erase, we thus just indicate on erase that we should try to shrink the hash + * table on the next insert if we go below the min_load_factor. + */ + bool m_try_shrink_on_next_insert{false}; + }; -} // namespace tsl +} // namespace tsl::detail_robin_hash +// NOLINTEND #endif diff --git a/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C b/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C index 32a7cf3a38..e950fd9374 100644 --- a/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C +++ b/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.C @@ -148,8 +148,8 @@ namespace Iotm { { int64_t count = 0; - for (auto iter = m_blockPartition.begin(); iter != m_blockPartition.end(); iter++) { - count += iter->second.elemIds.size(); + for (const auto &part : m_blockPartition) { + count += part.second.elemIds.size(); } return count; @@ -246,6 +246,9 @@ namespace Iotm { class NodeCommunicationMap { public: + NodeCommunicationMap() = delete; + NodeCommunicationMap(const NodeCommunicationMap &) = delete; + NodeCommunicationMap(int myProc, Ioss::Int64Vector &map, std::vector &processors) : m_myProcessor(myProc), m_nodeMap(map), m_processorMap(processors) { @@ -269,9 +272,6 @@ namespace Iotm { } private: - NodeCommunicationMap(); - NodeCommunicationMap(const NodeCommunicationMap &); - void add_comm_map_pair(int64_t id, int proc) { m_nodeMap[m_fillIndex] = id; diff --git a/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.h b/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.h index 34f6a45751..cd896eb3be 100644 --- a/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.h +++ b/packages/seacas/libraries/ioss/src/text_mesh/Iotm_TextMesh.h @@ -219,7 +219,7 @@ namespace Iotm { std::vector &z) const; /** - * Return the coordinates for componenet 'comp' (1=x, 2=y, 3=z) + * Return the coordinates for component 'comp' (1=x, 2=y, 3=z) * for all nodes on this processor. The * vector will be resized to the size required to contain the * nodal coordinates; all information in the vector will be diff --git a/packages/seacas/libraries/ioss/src/transform/Iotr_Scale3D.h b/packages/seacas/libraries/ioss/src/transform/Iotr_Scale3D.h index 411cf0efc0..fe97ab697c 100644 --- a/packages/seacas/libraries/ioss/src/transform/Iotr_Scale3D.h +++ b/packages/seacas/libraries/ioss/src/transform/Iotr_Scale3D.h @@ -8,8 +8,8 @@ #include "iotr_export.h" -#include // for VariableType #include // for Transform, Factory +#include // for VariableType #include #include diff --git a/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt b/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt index fc80c0dfe3..2fbcd70ffb 100644 --- a/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt +++ b/packages/seacas/libraries/ioss/src/unit_tests/CMakeLists.txt @@ -1,18 +1,30 @@ TRIBITS_ADD_EXECUTABLE( Utst_textmesh - SOURCES unitMain.C UnitTestTextMesh.C UnitTestReadAllBlockData.C + SOURCES unitMain.C UnitTestTextMesh.C ) TRIBITS_ADD_EXECUTABLE( - Utst_allblockread - SOURCES unitMain.C UnitTestReadAllBlockData.C + Utst_blockbatchread + SOURCES unitMain.C UnitTestElementBlockBatchRead.C ) TRIBITS_ADD_TEST( - Utst_allblockread - NAME Utst_allblockread - NUM_MPI_PROCS 1 + Utst_blockbatchread + NAME Utst_blockbatchread + NUM_MPI_PROCS 2 +) + +TRIBITS_ADD_TEST( + Utst_blockbatchread + NAME Utst_blockbatchread + NUM_MPI_PROCS 4 +) + +TRIBITS_ADD_TEST( + Utst_blockbatchread + NAME Utst_blockbatchread + NUM_MPI_PROCS 8 ) TRIBITS_ADD_TEST( diff --git a/packages/seacas/libraries/ioss/src/unit_tests/UnitTestElementBlockBatchRead.C b/packages/seacas/libraries/ioss/src/unit_tests/UnitTestElementBlockBatchRead.C new file mode 100644 index 0000000000..d4ab6b91e5 --- /dev/null +++ b/packages/seacas/libraries/ioss/src/unit_tests/UnitTestElementBlockBatchRead.C @@ -0,0 +1,453 @@ +// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with +// NTESS, the U.S. Government retains certain rights in this software. +// +// See packages/seacas/LICENSE for details + +#include +#include + +#ifdef SEACAS_HAVE_MPI +#include "mpi.h" +#endif +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include + +#include // for unlink + +#include +#include +#include // for DatabaseIO +#include // for Field, etc +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace { + + std::string get_randomized_many_block_mesh_desc(unsigned numBlocks) + { + std::ostringstream oss; + std::vector elementIds(numBlocks); + std::iota(elementIds.begin(), elementIds.end(), 1); + + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(elementIds.begin(), elementIds.end(), g); + + unsigned proc = 0; + for (unsigned i = 0; i < numBlocks; ++i) { + unsigned elemId = elementIds[i]; + unsigned firstNodeId = i * 4 + 1; + oss << proc << "," << elemId << ",HEX_8,"; + for (unsigned node = firstNodeId; node < firstNodeId + 8; ++node) { + oss << node << ","; + } + unsigned blockId = i + 1; + oss << "block_" << blockId; + + if (i < numBlocks - 1) { + oss << "\n"; + } + } + + oss << "|coordinates:"; + + std::vector planeCoords = {0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0}; + + for (double coord : planeCoords) { + oss << coord << ","; + } + + for (unsigned i = 1; i <= numBlocks; ++i) { + for (unsigned point = 0; point < 4; ++point) { + planeCoords[3 * point + 2] += 1; + } + + for (double coord : planeCoords) { + oss << coord << ","; + } + } + + return oss.str(); + } + + void define_model(const Ioss::Region &i_region, Ioss::Region &o_region) + { + Ioss::DatabaseIO *o_database = o_region.get_database(); + + o_region.begin_mode(Ioss::STATE_DEFINE_MODEL); + + Ioss::NodeBlock *i_nb = i_region.get_node_blocks()[0]; + int64_t spatial_dim = 3; + int64_t num_nodes = i_nb->entity_count(); + Ioss::NodeBlock *o_nb = new Ioss::NodeBlock(o_database, "nodeblock_1", num_nodes, spatial_dim); + o_region.add(o_nb); + + for (Ioss::ElementBlock *i_eb : i_region.get_element_blocks()) { + Ioss::ElementBlock *o_eb = new Ioss::ElementBlock( + o_database, i_eb->name(), i_eb->topology()->name(), i_eb->entity_count()); + o_eb->property_add(i_eb->get_property("id")); + o_region.add(o_eb); + } + + o_region.end_mode(Ioss::STATE_DEFINE_MODEL); + } + + void write_model(const Ioss::Region &i_region, Ioss::Region &o_region) + { + Ioss::NodeBlock *i_nb = i_region.get_node_blocks()[0]; + Ioss::NodeBlock *o_nb = o_region.get_node_blocks()[0]; + + o_region.begin_mode(Ioss::STATE_MODEL); + std::vector coordinates; + std::vector node_ids; + i_nb->get_field_data("ids", node_ids); + i_nb->get_field_data("mesh_model_coordinates", coordinates); + + o_nb->put_field_data("ids", node_ids); + o_nb->put_field_data("mesh_model_coordinates", coordinates); + + for (Ioss::ElementBlock *i_eb : i_region.get_element_blocks()) { + Ioss::ElementBlock *o_eb = o_region.get_element_block(i_eb->name()); + std::vector elem_ids; + std::vector connectivity; + + i_eb->get_field_data("ids", elem_ids); + i_eb->get_field_data("connectivity", connectivity); + + o_eb->put_field_data("ids", elem_ids); + o_eb->put_field_data("connectivity", connectivity); + } + + o_region.end_mode(Ioss::STATE_MODEL); + } + + void define_transient(const Ioss::Region &i_region, Ioss::Region &o_region, + const std::string &elemFieldName) + { + o_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT); + + for (Ioss::ElementBlock *o_eb : o_region.get_element_blocks()) { + size_t num_elem = o_eb->get_property("entity_count").get_int(); + std::string storage = "scalar"; + + Ioss::Field field(elemFieldName, Ioss::Field::REAL, storage, 1, Ioss::Field::Field::TRANSIENT, + num_elem); + o_eb->field_add(field); + } + o_region.end_mode(Ioss::STATE_DEFINE_TRANSIENT); + } + + void write_transient(Ioss::Region &o_region, const std::string &elemFieldName) + { + o_region.begin_mode(Ioss::STATE_TRANSIENT); + int step = o_region.add_state(0.0); + o_region.begin_state(step); + + for (Ioss::ElementBlock *o_eb : o_region.get_element_blocks()) { + size_t num_elem = o_eb->get_property("entity_count").get_int(); + + std::vector field_data(num_elem); + std::vector elem_ids; + + o_eb->get_field_data("ids", elem_ids); + for (size_t i = 0; i < elem_ids.size(); i++) { + field_data[i] = (double)elem_ids[i]; + } + + o_eb->put_field_data(elemFieldName, field_data); + } + + o_region.end_state(step); + o_region.end_mode(Ioss::STATE_TRANSIENT); + } + + void generate_randomized_many_block_mesh_from_textmesh(int numBlocks, + const std::string &elemFieldName, + const std::string &outFile) + { + Ioss::Init::Initializer io; + + Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); + + if (util.parallel_rank() == 0) { + std::string meshDesc = get_randomized_many_block_mesh_desc(numBlocks); + + Ioss::PropertyManager propertyManager; + + Ioss::DatabaseIO *i_database = + Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, + Ioss::ParallelUtils::comm_self(), propertyManager); + Ioss::Region i_region(i_database, "input_model"); + EXPECT_TRUE(i_database != nullptr); + EXPECT_TRUE(i_database->ok(true)); + + Ioss::DatabaseIO *o_database = + Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, + Ioss::ParallelUtils::comm_self(), propertyManager); + Ioss::Region o_region(o_database, "output_model"); + EXPECT_TRUE(o_database != nullptr); + EXPECT_TRUE(o_database->ok(true)); + + define_model(i_region, o_region); + write_model(i_region, o_region); + + define_transient(i_region, o_region, elemFieldName); + write_transient(o_region, elemFieldName); + + o_database->finalize_database(); + o_database->flush_database(); + o_database->closeDatabase(); + } + } + + template + std::pair + do_connectivity_timing_impl(const Ioss::Region ®ion, + const Ioss::ElementBlockContainer &elemBlocks) + { + std::vector blockBatchConnectivity; + + double startTime = Ioss::Utils::timer(); + std::vector dataOffset = + region.get_entity_field_data("connectivity", elemBlocks, blockBatchConnectivity); + double elapsedBlockBatchConnectivityTime = Ioss::Utils::timer() - startTime; + + double elapsedConnectivityTime = 0.0; + for (unsigned i = 0; i < elemBlocks.size(); i++) { + const Ioss::ElementBlock *entity = elemBlocks[i]; + int64_t iblk = int64_t(i); + + std::vector connectivity; + startTime = Ioss::Utils::timer(); + int64_t numToGet = entity->get_field_data("connectivity", connectivity); + elapsedConnectivityTime += Ioss::Utils::timer() - startTime; + + unsigned numComponents = entity->topology()->number_nodes(); + int64_t numEntities = entity->entity_count(); + EXPECT_EQ(numToGet, numEntities); + + int64_t blockBatchNumToGet = dataOffset[iblk + 1] - dataOffset[iblk]; + EXPECT_EQ(blockBatchNumToGet, numEntities * numComponents); + + for (unsigned eIndex = 0; eIndex < numEntities; eIndex++) { + for (unsigned comp = 0; comp < numComponents; comp++) { + size_t connIndex = eIndex * numComponents + comp; + size_t blockBatchConnIndex = dataOffset[iblk] + connIndex; + + INT connValue = connectivity[connIndex]; + INT blockBatchConnValue = blockBatchConnectivity[blockBatchConnIndex]; + + EXPECT_EQ(connValue, blockBatchConnValue); + } + } + } + + return std::make_pair(elapsedConnectivityTime, elapsedBlockBatchConnectivityTime); + } + + std::pair do_connectivity_timing(const Ioss::Region ®ion, + const Ioss::ElementBlockContainer &elemBlocks) + { + auto result = std::pair(0.0, 0.0); + + bool is64Bit = (region.get_database()->int_byte_size_api() == 8); + if (is64Bit) { + result = do_connectivity_timing_impl(region, elemBlocks); + } + else { + result = do_connectivity_timing_impl(region, elemBlocks); + } + + return result; + } + + std::pair + do_field_timing_and_verification(const Ioss::Region ®ion, + const Ioss::ElementBlockContainer &elemBlocks, + const std::string &fieldName) + { + std::vector blockFieldData; + + double startBlockFieldTime = Ioss::Utils::timer(); + std::vector dataOffset = + region.get_entity_field_data(fieldName, elemBlocks, blockFieldData); + double elapsedBlockFieldTime = Ioss::Utils::timer() - startBlockFieldTime; + + double elapsedFieldTime = 0.0; + + std::vector fieldData; + + for (unsigned i = 0; i < elemBlocks.size(); i++) { + const Ioss::ElementBlock *entity = elemBlocks[i]; + + int64_t iblk = int64_t(i); + + if (entity->field_exists(fieldName)) { + double startFieldTime = Ioss::Utils::timer(); + int64_t numToGet = entity->get_field_data(fieldName, fieldData); + elapsedFieldTime += Ioss::Utils::timer() - startFieldTime; + + Ioss::Field iossField = entity->get_field(fieldName); + unsigned numComponents = iossField.raw_storage()->component_count(); + int64_t numEntities = entity->entity_count(); + int64_t expectedNumToGet = numEntities * numComponents; + EXPECT_EQ(numToGet, expectedNumToGet); + + int64_t blockNumToGet = dataOffset[iblk + 1] - dataOffset[iblk]; + EXPECT_EQ(blockNumToGet, expectedNumToGet); + + for (unsigned eIndex = 0; eIndex < numEntities; eIndex++) { + for (unsigned comp = 0; comp < numComponents; comp++) { + size_t fieldIndex = eIndex * numComponents + comp; + size_t blockFieldIndex = dataOffset[iblk] + fieldIndex; + + double fieldValue = fieldData[fieldIndex]; + double blockFieldValue = blockFieldData[blockFieldIndex]; + + EXPECT_NEAR(fieldValue, blockFieldValue, 1.0e-5); + } + } + } + } + + return std::make_pair(elapsedFieldTime, elapsedBlockFieldTime); + } + + Ioss::ElementBlockContainer get_all_blocks(const Ioss::Region ®ion) + { + return region.get_element_blocks(); + } + + Ioss::ElementBlockContainer get_alternate_blocks(const Ioss::Region ®ion) + { + const Ioss::ElementBlockContainer &elemBlocks = region.get_element_blocks(); + + Ioss::ElementBlockContainer alternateElemBlocks; + alternateElemBlocks.reserve(elemBlocks.size() / 2); + + for (unsigned i = 0; i < elemBlocks.size(); i++) { + if (i % 2 == 0) { + alternateElemBlocks.push_back(elemBlocks[i]); + } + } + + return alternateElemBlocks; + } + + using ElemBlockFunc = std::function; + + void run_block_batch_test(int numBlocks, ElemBlockFunc func) + { + std::ostringstream oss; + oss << "randomizedManyBlocks_"; + oss << numBlocks << ".g"; + + std::string outFile(oss.str()); + std::string elemFieldName = "elem_field"; + generate_randomized_many_block_mesh_from_textmesh(numBlocks, elemFieldName, outFile); + + { + Ioss_MPI_Comm comm = Ioss::ParallelUtils::comm_world(); + Ioss::ParallelUtils util(comm); + util.barrier(); + + std::string decompMethod = "RCB"; + Ioss::Property decompProp("DECOMPOSITION_METHOD", decompMethod); + Ioss::PropertyManager propertyManager; + propertyManager.add(decompProp); + + Ioss::DatabaseIO *database = + Ioss::IOFactory::create("exodus", outFile, Ioss::READ_MODEL, comm, propertyManager); + Ioss::Region region(database, "input_model"); + EXPECT_TRUE(database != nullptr); + EXPECT_TRUE(database->ok(true)); + + region.property_add(decompProp); + region.begin_state(1); + + Ioss::ElementBlockContainer elemBlocks = func(region); + + double elapsedConnectivityTime; + double elapsedBlockBatchConnectivityTime; + std::tie(elapsedConnectivityTime, elapsedBlockBatchConnectivityTime) = + do_connectivity_timing(region, elemBlocks); + + double maxBlockBatchConnectivityDuration = + util.global_minmax(elapsedBlockBatchConnectivityTime, Ioss::ParallelUtils::DO_MAX); + double minBlockBatchConnectivityDuration = + util.global_minmax(elapsedBlockBatchConnectivityTime, Ioss::ParallelUtils::DO_MIN); + + double maxConnectivityDuration = + util.global_minmax(elapsedConnectivityTime, Ioss::ParallelUtils::DO_MAX); + double minConnectivityDuration = + util.global_minmax(elapsedConnectivityTime, Ioss::ParallelUtils::DO_MIN); + + if (util.parallel_rank() == 0) { + std::cout << std::endl; + std::cout << "MAX connectivity read time = " << std::setw(8) << std::fixed + << maxConnectivityDuration + << " : MIN connectivity read time = " << std::setw(8) << std::fixed + << minConnectivityDuration << std::endl; + std::cout << "MAX BATCH connectivity read time = " << std::setw(8) << std::fixed + << maxBlockBatchConnectivityDuration + << " : MIN BATCH connectivity read time = " << std::setw(8) << std::fixed + << minBlockBatchConnectivityDuration << std::endl; + std::cout << std::endl; + } + + double elapsedFieldTime; + double elapsedBlockBatchFieldTime; + + std::tie(elapsedFieldTime, elapsedBlockBatchFieldTime) = + do_field_timing_and_verification(region, elemBlocks, elemFieldName); + + double maxBlockBatchFieldDuration = + util.global_minmax(elapsedBlockBatchFieldTime, Ioss::ParallelUtils::DO_MAX); + double minBlockBatchFieldDuration = + util.global_minmax(elapsedBlockBatchFieldTime, Ioss::ParallelUtils::DO_MIN); + + double maxFieldDuration = util.global_minmax(elapsedFieldTime, Ioss::ParallelUtils::DO_MAX); + double minFieldDuration = util.global_minmax(elapsedFieldTime, Ioss::ParallelUtils::DO_MIN); + + if (util.parallel_rank() == 0) { + std::cout << std::endl; + std::cout << "MAX field read time = " << std::setw(8) << std::fixed + << maxFieldDuration << " : MIN field read time = " << std::setw(8) + << std::fixed << minFieldDuration << std::endl; + std::cout << "MAX BATCH field read time = " << std::setw(8) << std::fixed + << maxBlockBatchFieldDuration << " : MIN BATCH field read time = " << std::setw(8) + << std::fixed << minBlockBatchFieldDuration << std::endl; + std::cout << std::endl; + } + } + + unlink(outFile.c_str()); + } + + TEST(TestReadBlockBatch, readAllBlocks) + { + int numBlocks = 1000; + run_block_batch_test(numBlocks, get_all_blocks); + } + + TEST(TestReadBlockBatch, readAlternateBlocks) + { + int numBlocks = 1000; + run_block_batch_test(numBlocks, get_alternate_blocks); + } + +} // namespace diff --git a/packages/seacas/libraries/ioss/src/unit_tests/UnitTestReadAllBlockData.C b/packages/seacas/libraries/ioss/src/unit_tests/UnitTestReadAllBlockData.C deleted file mode 100644 index aa53974add..0000000000 --- a/packages/seacas/libraries/ioss/src/unit_tests/UnitTestReadAllBlockData.C +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions -// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with -// NTESS, the U.S. Government retains certain rights in this software. -// -// See packages/seacas/LICENSE for details - -#include -#include - -#ifdef SEACAS_HAVE_MPI -#include "mpi.h" -#endif -#include "gtest/gtest.h" - -#include -#include -#include -#include -#include // for unlink - -#include -#include -#include -#include -#include // for DatabaseIO -#include // for Field, etc -#include - -#include -#include -#include -#include - -#include - -namespace { - -std::string get_randomized_many_block_mesh_desc(unsigned numBlocks) -{ - std::ostringstream oss; - std::vector elementIds(numBlocks); - std::iota(elementIds.begin(), elementIds.end(), 1); - - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(elementIds.begin(), elementIds.end(), g); - - unsigned proc = 0; - for(unsigned i = 0; i < numBlocks; ++i) { - unsigned elemId = elementIds[i]; - unsigned firstNodeId = i * 4 + 1; - oss << proc << "," << elemId << ",HEX_8,"; - for(unsigned node = firstNodeId; node < firstNodeId + 8; ++node) { - oss << node << ","; - } - unsigned blockId = i + 1; - oss << "block_" << blockId; - - if(i < numBlocks - 1) { - oss << "\n"; - } - } - - oss << "|coordinates:"; - - std::vector planeCoords = { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0 }; - - for (double coord : planeCoords) { - oss << coord << ","; - } - - for(unsigned i = 1; i <= numBlocks; ++i) { - for(unsigned point = 0; point < 4; ++point) { - planeCoords[3 * point + 2] += 1; - } - - for (double coord : planeCoords) { - oss << coord << ","; - } - } - - return oss.str(); -} - -void define_model(const Ioss::Region& i_region, Ioss::Region& o_region) -{ - Ioss::DatabaseIO *o_database = o_region.get_database(); - - o_region.begin_mode(Ioss::STATE_DEFINE_MODEL); - - Ioss::NodeBlock *i_nb = i_region.get_node_blocks()[0]; - int64_t spatial_dim = 3; - int64_t num_nodes = i_nb->entity_count(); - Ioss::NodeBlock *o_nb = new Ioss::NodeBlock(o_database, "nodeblock_1", num_nodes, spatial_dim); - o_region.add(o_nb); - - for(Ioss::ElementBlock* i_eb : i_region.get_element_blocks()) - { - Ioss::ElementBlock *o_eb = new Ioss::ElementBlock(o_database, i_eb->name(), i_eb->topology()->name(), i_eb->entity_count()); - o_eb->property_add(i_eb->get_property("id")); - o_region.add(o_eb); - } - - o_region.end_mode(Ioss::STATE_DEFINE_MODEL); -} - -void write_model(const Ioss::Region& i_region, Ioss::Region& o_region) -{ - Ioss::NodeBlock *i_nb = i_region.get_node_blocks()[0]; - Ioss::NodeBlock *o_nb = o_region.get_node_blocks()[0]; - - o_region.begin_mode(Ioss::STATE_MODEL); - std::vector coordinates; - std::vector node_ids; - i_nb->get_field_data("ids", node_ids); - i_nb->get_field_data("mesh_model_coordinates", coordinates); - - o_nb->put_field_data("ids", node_ids); - o_nb->put_field_data("mesh_model_coordinates", coordinates); - - for(Ioss::ElementBlock* i_eb : i_region.get_element_blocks()) - { - Ioss::ElementBlock *o_eb = o_region.get_element_block(i_eb->name()); - std::vector elem_ids; - std::vector connectivity; - - i_eb->get_field_data("ids", elem_ids); - i_eb->get_field_data("connectivity", connectivity); - - o_eb->put_field_data("ids", elem_ids); - o_eb->put_field_data("connectivity", connectivity); - } - - o_region.end_mode(Ioss::STATE_MODEL); -} - -void define_transient(const Ioss::Region& i_region, Ioss::Region& o_region, const std::string& elemFieldName) -{ - o_region.begin_mode(Ioss::STATE_DEFINE_TRANSIENT); - - for(Ioss::ElementBlock* o_eb : o_region.get_element_blocks()) - { - size_t num_elem = o_eb->get_property("entity_count").get_int(); - std::string storage = "scalar"; - - Ioss::Field field(elemFieldName, Ioss::Field::REAL, storage, 1, Ioss::Field::Field::TRANSIENT, num_elem); - o_eb->field_add(field); - } - o_region.end_mode(Ioss::STATE_DEFINE_TRANSIENT); -} - -void write_transient(Ioss::Region& o_region, const std::string& elemFieldName) -{ - o_region.begin_mode(Ioss::STATE_TRANSIENT); - int step = o_region.add_state(0.0); - o_region.begin_state(step); - - for(Ioss::ElementBlock* o_eb : o_region.get_element_blocks()) - { - size_t num_elem = o_eb->get_property("entity_count").get_int(); - - std::vector field_data(num_elem); - std::vector elem_ids; - - o_eb->get_field_data("ids", elem_ids); - for(size_t i=0; iput_field_data(elemFieldName, field_data); - } - - o_region.end_state(step); - o_region.end_mode(Ioss::STATE_TRANSIENT); -} - -void generate_randomized_many_block_mesh_from_textmesh(int numBlocks, const std::string& elemFieldName, const std::string& outFile) -{ - Ioss::Init::Initializer io; - - Ioss::ParallelUtils util(Ioss::ParallelUtils::comm_world()); - - if(util.parallel_rank() == 0) { - std::string meshDesc = get_randomized_many_block_mesh_desc(numBlocks); - - Ioss::PropertyManager propertyManager; - - Ioss::DatabaseIO* i_database = Ioss::IOFactory::create("textmesh", meshDesc, Ioss::READ_MODEL, Ioss::ParallelUtils::comm_self(), propertyManager); - Ioss::Region i_region(i_database, "input_model"); - EXPECT_TRUE(i_database != nullptr); - EXPECT_TRUE(i_database->ok(true)); - - Ioss::DatabaseIO *o_database = Ioss::IOFactory::create("exodus", outFile, Ioss::WRITE_RESULTS, Ioss::ParallelUtils::comm_self(), propertyManager); - Ioss::Region o_region(o_database, "output_model"); - EXPECT_TRUE(o_database != nullptr); - EXPECT_TRUE(o_database->ok(true)); - - define_model(i_region, o_region); - write_model(i_region, o_region); - - define_transient(i_region, o_region, elemFieldName); - write_transient(o_region, elemFieldName); - - o_database->finalize_database(); - o_database->flush_database(); - o_database->closeDatabase(); - } -} - -template -std::pair do_connectivity_timing_impl(const Ioss::Region& region) -{ - const Ioss::ElementBlockContainer& elemBlocks = region.get_element_blocks(); - - std::vector allConnectivity; - - double startTime = Ioss::Utils::timer(); - std::vector dataOffset = region.get_all_block_field_data("connectivity", allConnectivity); - double elapsedAllBlockConnectivityTime = Ioss::Utils::timer() - startTime; - - double elapsedConnectivityTime = 0.0; - for(unsigned i=0; iget_optional_property("iblk", int64_t(i)); - - std::vector connectivity; - startTime = Ioss::Utils::timer(); - int64_t numToGet = entity->get_field_data("connectivity", connectivity); - elapsedConnectivityTime += Ioss::Utils::timer() - startTime; - - unsigned numComponents = entity->topology()->number_nodes(); - int64_t numEntities = entity->entity_count(); - EXPECT_EQ(numToGet, numEntities); - - int64_t allBlockNumToGet = dataOffset[iblk+1] - dataOffset[iblk]; - EXPECT_EQ(allBlockNumToGet, numEntities*numComponents); - - for(unsigned eIndex=0; eIndex do_connectivity_timing(const Ioss::Region& region) -{ - auto result = std::pair(0.0, 0.0); - - bool is64Bit = (region.get_database()->int_byte_size_api() == 8); - if(is64Bit) { - result = do_connectivity_timing_impl(region); - } else { - result = do_connectivity_timing_impl(region); - } - - return result; -} - -std::pair do_field_timing_and_verification(const Ioss::Region& region, const std::string& fieldName) -{ - const Ioss::ElementBlockContainer& elemBlocks = region.get_element_blocks(); - - std::vector allFieldData; - - double startAllBlockFieldTime = Ioss::Utils::timer(); - std::vector dataOffset = region.get_all_block_field_data(fieldName, allFieldData); - double elapsedAllBlockFieldTime = Ioss::Utils::timer() - startAllBlockFieldTime; - - double elapsedFieldTime = 0.0; - - std::vector blockFieldData; - - for(unsigned i=0; iget_optional_property("iblk", int64_t(i)); - - if(entity->field_exists(fieldName)) { - double startFieldTime = Ioss::Utils::timer(); - int64_t numToGet = entity->get_field_data(fieldName, blockFieldData); - elapsedFieldTime += Ioss::Utils::timer() - startFieldTime; - - Ioss::Field iossField = entity->get_field(fieldName); - unsigned numComponents = iossField.raw_storage()->component_count(); - int64_t numEntities = entity->entity_count(); - int64_t expectedNumToGet = numEntities*numComponents; - EXPECT_EQ(numToGet, expectedNumToGet); - - int64_t allBlockNumToGet = dataOffset[iblk+1] - dataOffset[iblk]; - EXPECT_EQ(allBlockNumToGet, expectedNumToGet); - - for(unsigned eIndex=0; eIndexok(true)); - - region.property_add(decompProp); - region.begin_state(1); - - double elapsedConnectivityTime; - double elapsedAllBlockConnectivityTime; - std::tie(elapsedConnectivityTime, elapsedAllBlockConnectivityTime) = do_connectivity_timing(region); - - double maxAllBlockConnectivityDuration = util.global_minmax(elapsedAllBlockConnectivityTime, Ioss::ParallelUtils::DO_MAX); - double minAllBlockConnectivityDuration = util.global_minmax(elapsedAllBlockConnectivityTime, Ioss::ParallelUtils::DO_MIN); - - double maxConnectivityDuration = util.global_minmax(elapsedConnectivityTime, Ioss::ParallelUtils::DO_MAX); - double minConnectivityDuration = util.global_minmax(elapsedConnectivityTime, Ioss::ParallelUtils::DO_MIN); - - if (util.parallel_rank() == 0) { - std::cout << std::endl; - std::cout << "MAX connectivity read time = " << maxConnectivityDuration << ": MIN connectivity read time = " << minConnectivityDuration << std::endl; - std::cout << "MAX all-block connectivity read time = " << maxAllBlockConnectivityDuration << ": MIN all-block connectivity read time = " << minAllBlockConnectivityDuration << std::endl; - std::cout << std::endl; - } - - double elapsedFieldTime; - double elapsedAllBlockFieldTime; - - std::tie(elapsedFieldTime, elapsedAllBlockFieldTime) = do_field_timing_and_verification(region, elemFieldName); - - double maxAllBlockFieldDuration = util.global_minmax(elapsedAllBlockFieldTime, Ioss::ParallelUtils::DO_MAX); - double minAllBlockFieldDuration = util.global_minmax(elapsedAllBlockFieldTime, Ioss::ParallelUtils::DO_MIN); - - double maxFieldDuration = util.global_minmax(elapsedFieldTime, Ioss::ParallelUtils::DO_MAX); - double minFieldDuration = util.global_minmax(elapsedFieldTime, Ioss::ParallelUtils::DO_MIN); - - if (util.parallel_rank() == 0) { - std::cout << std::endl; - std::cout << "MAX field read time = " << maxFieldDuration << ": MIN field read time = " << minFieldDuration << std::endl; - std::cout << "MAX all-block field read time = " << maxAllBlockFieldDuration << ": MIN all-block field read time = " << minAllBlockFieldDuration << std::endl; - std::cout << std::endl; - } - } - - unlink(outFile.c_str()); -} - - -} // namespace diff --git a/packages/seacas/libraries/ioss/src/unit_tests/unitMain.C b/packages/seacas/libraries/ioss/src/unit_tests/unitMain.C index 2aec54a258..946339640e 100644 --- a/packages/seacas/libraries/ioss/src/unit_tests/unitMain.C +++ b/packages/seacas/libraries/ioss/src/unit_tests/unitMain.C @@ -6,6 +6,7 @@ #include #include + #ifdef SEACAS_HAVE_MPI #include #endif diff --git a/packages/seacas/libraries/ioss/src/utest/CMakeLists.txt b/packages/seacas/libraries/ioss/src/utest/CMakeLists.txt index f19564f89a..4da2253e33 100644 --- a/packages/seacas/libraries/ioss/src/utest/CMakeLists.txt +++ b/packages/seacas/libraries/ioss/src/utest/CMakeLists.txt @@ -122,6 +122,18 @@ TRIBITS_ADD_EXECUTABLE_AND_TEST( ) ENDIF() +IF (TPL_ENABLE_ADIOS2) +TRIBITS_ADD_EXECUTABLE_AND_TEST( + Ut_ioad + NAME Ut_ioad + SOURCES Ut_ioad.C + NOEXEPREFIX + NOEXESUFFIX + INSTALLABLE + NUM_MPI_PROCS 1 +) +ENDIF() + TRIBITS_INCLUDE_DIRECTORIES( "${CMAKE_CURRENT_SOURCE_DIR}/../" "${CMAKE_CURRENT_BINARY_DIR}/../" diff --git a/packages/seacas/libraries/ioss/src/adios/utest/Ut_ioad.C b/packages/seacas/libraries/ioss/src/utest/Ut_ioad.C similarity index 99% rename from packages/seacas/libraries/ioss/src/adios/utest/Ut_ioad.C rename to packages/seacas/libraries/ioss/src/utest/Ut_ioad.C index 8a4dd47528..e96b6f23ba 100644 --- a/packages/seacas/libraries/ioss/src/adios/utest/Ut_ioad.C +++ b/packages/seacas/libraries/ioss/src/utest/Ut_ioad.C @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) #ifdef SEACAS_HAVE_MPI MPI_Init(&argc, &argv); #endif - const int result = doctest::Context().run(argc, argv); + const int result = doctest::Context().run(); #ifdef SEACAS_HAVE_MPI MPI_Finalize(); #endif @@ -423,9 +423,9 @@ void create_database(std::string type, std::string file_name) DOCTEST_TEST_CASE("Ioad") { - Ioss::Init::Initializer::initialize_ioss(); - std::string exodus_db_name = "phantom.e"; - std::string adios_db_name = "phantom.bp"; + Ioss::Init::Initializer init_db; + std::string exodus_db_name = "phantom.e"; + std::string adios_db_name = "phantom.bp"; create_database("exodus", exodus_db_name); create_database("adios", adios_db_name); // Database pointers are deleted by their respective region destructors. diff --git a/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C b/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C index 00c6a4bc2b..e5a6a3b7ec 100644 --- a/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/utest/Utst_IofxDatabaseIO.C @@ -276,20 +276,20 @@ namespace { output_region.add(output_node_block); const auto &input_element_blocks = input_region.get_element_blocks(); - for (size_t blk = 0; blk < input_element_blocks.size(); ++blk) { - const Ioss::ElementTopology *topology = input_element_blocks[blk]->topology(); - int block_id = input_element_blocks[blk]->get_property("id").get_int(); + for (const auto &block : input_element_blocks) { + const auto *topology = block->topology(); + int block_id = block->get_property("id").get_int(); - std::string name = input_element_blocks[blk]->name(); - std::string exotype = topology->name(); - int64_t num_elements = input_element_blocks[blk]->entity_count(); + const std::string &name = block->name(); + std::string exotype = topology->name(); + int64_t num_elements = block->entity_count(); auto *output_element_block = new Ioss::ElementBlock(db_out, name, exotype, num_elements); output_element_block->property_add(Ioss::Property("original_topology_type", exotype)); output_element_block->property_add(Ioss::Property("id", block_id)); output_region.add(output_element_block); - int num_attributes = input_element_blocks[blk]->get_property("attribute_count").get_int(); + int num_attributes = block->get_property("attribute_count").get_int(); for (int j = 0; j < num_attributes; ++j) { output_element_block->field_add(Ioss::Field("attribute", Ioss::Field::REAL, "scalar", Ioss::Field::ATTRIBUTE, num_elements, j + 1)); @@ -297,9 +297,9 @@ namespace { } const auto &nodesets_input = input_region.get_nodesets(); - for (size_t i = 0; i < nodesets_input.size(); ++i) { - std::string nodeset_name = nodesets_input[i]->name(); - int64_t number_nodes_in_nodeset = nodesets_input[i]->entity_count(); + for (const auto &nset : nodesets_input) { + const std::string &nodeset_name = nset->name(); + int64_t number_nodes_in_nodeset = nset->entity_count(); auto *const nodeset = new Ioss::NodeSet(db_out, nodeset_name, number_nodes_in_nodeset); output_region.add(nodeset); @@ -308,24 +308,24 @@ namespace { } const auto &sidesets_input = input_region.get_sidesets(); - for (size_t i = 0; i < sidesets_input.size(); ++i) { - std::string sideset_name = sidesets_input[i]->name(); + for (const auto &sset : sidesets_input) { + const std::string &sideset_name = sset->name(); auto *const sideset_output = new Ioss::SideSet(db_out, sideset_name); output_region.add(sideset_output); - const auto &side_blocks = sidesets_input[i]->get_side_blocks(); - for (size_t k = 0; k < side_blocks.size(); ++k) { - const std::string &topo_name = side_blocks[k]->topology()->name(); - int64_t side_count = side_blocks[k]->entity_count(); - const std::string &parent_topo_name = side_blocks[k]->parent_element_topology()->name(); - const std::string &side_block_name = side_blocks[k]->name(); + const auto &side_blocks = sset->get_side_blocks(); + for (const auto &sblock : side_blocks) { + const std::string &topo_name = sblock->topology()->name(); + int64_t side_count = sblock->entity_count(); + const std::string &parent_topo_name = sblock->parent_element_topology()->name(); + const std::string &side_block_name = sblock->name(); auto *side_block = new Ioss::SideBlock(db_out, side_block_name, topo_name, parent_topo_name, side_count); sideset_output->add(side_block); - int nodes_per_side = side_blocks[k]->topology()->number_nodes(); + int nodes_per_side = sblock->topology()->number_nodes(); std::string storage_type = "Real["; storage_type += std::to_string(nodes_per_side); storage_type += "]"; diff --git a/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C b/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C index 076bad7855..761c406724 100644 --- a/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C +++ b/packages/seacas/libraries/ioss/src/utest/Utst_structured_decomp.C @@ -283,6 +283,18 @@ DOCTEST_TEST_CASE("cube_2blocks") cleanup(zones); } +DOCTEST_TEST_CASE("2blocks_example") +{ + int zone = 1; + std::vector zones; + zones.push_back(new Iocgns::StructuredZoneData(zone++, "8x4x1")); + zones.push_back(new Iocgns::StructuredZoneData(zone++, "8x8x1")); + double load_balance_tolerance = 1.1; + + check_split_assign(zones, load_balance_tolerance, 4, 0.9, 1.1); + cleanup(zones); +} + DOCTEST_TEST_CASE("bump") { int zone = 1; diff --git a/packages/seacas/libraries/mapvarlib/avg.f b/packages/seacas/libraries/mapvarlib/avg.f index 768821c9e0..2baef0254f 100644 --- a/packages/seacas/libraries/mapvarlib/avg.f +++ b/packages/seacas/libraries/mapvarlib/avg.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -20,7 +20,7 @@ SUBROUTINE AVG(IGLND,INVCN,MAXLN,INVLEN,SOLEA,SOLENA,ITT,iblk) C IGLND INT The global node number C INVCN INT The inverse connectivity (1:maxln,1:numnda) -C MAXLN INT The maximum nomber of elements connected to any node +C MAXLN INT The maximum number of elements connected to any node C INVLEN INT The number of elements connected to this node C SOLEA REAL Element variables (1:numeba,1:nvarel) C SOLENA REAL Element variables at nodes" (1:nodesa,1:nvarel) diff --git a/packages/seacas/libraries/mapvarlib/bs.f b/packages/seacas/libraries/mapvarlib/bs.f index 783e03905f..990477a02d 100644 --- a/packages/seacas/libraries/mapvarlib/bs.f +++ b/packages/seacas/libraries/mapvarlib/bs.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -9,7 +9,7 @@ SUBROUTINE BS(N,S,F,L,X) C********************************************************************** -C Subroutine BS does the back substitution for the soultion of the +C Subroutine BS does the back substitution for the solution of the C local least squares extrapolation technique for element variables C from their element centroid location to a nodal location. C The least squares solution is started by a Gauss elimination in diff --git a/packages/seacas/libraries/mapvarlib/frge.f b/packages/seacas/libraries/mapvarlib/frge.f index 70537178bc..2e66f12336 100644 --- a/packages/seacas/libraries/mapvarlib/frge.f +++ b/packages/seacas/libraries/mapvarlib/frge.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -9,7 +9,7 @@ SUBROUTINE FRGE(N,S,L,G) C********************************************************************** -C Subroutine BS does the back substitution for the soultion of the +C Subroutine BS does the back substitution for the solution of the C local least squares extrapolation technique for element variables C from their element centroid location to a nodal location. C The least squares solution is started by a Gauss elimination in diff --git a/packages/seacas/libraries/supes/ext_lib/exparm.c b/packages/seacas/libraries/supes/ext_lib/exparm.c index 2402554fc5..04fd8fdb24 100644 --- a/packages/seacas/libraries/supes/ext_lib/exparm.c +++ b/packages/seacas/libraries/supes/ext_lib/exparm.c @@ -251,8 +251,10 @@ void exparm(char *hard, char *soft, FTNINT *mode, FTNINT *kcsu, FTNINT *knsu, FT #endif /* Linux, Interix */ /********************************************************************/ - if (isatty(0) != 0) /* Test stdin as to whether or not it's a terminal. */ - *mode = 1; /* Indicates an interactive process. */ - else + if (isatty(0) != 0) { /* Test stdin as to whether or not it's a terminal. */ + *mode = 1; /* Indicates an interactive process. */ + } + else { *mode = 0; /* Else running from a procedure. */ + } } diff --git a/packages/seacas/libraries/supes/ext_lib/exupcs.c b/packages/seacas/libraries/supes/ext_lib/exupcs.c index b0f2ab76a9..fbba7cf27c 100644 --- a/packages/seacas/libraries/supes/ext_lib/exupcs.c +++ b/packages/seacas/libraries/supes/ext_lib/exupcs.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -19,10 +19,12 @@ void exupcs(char *string, long int StrLength) int i; for (i = 0; i < StrLength; i++, string++) { - if (!isprint(*string)) + if (!isprint(*string)) { *string = ' '; - else if (isalpha(*string) && islower(*string)) + } + else if (isalpha(*string) && islower(*string)) { *string = toupper(*string); + } } return; } diff --git a/packages/seacas/libraries/supes/mem_mgr/srchc.f b/packages/seacas/libraries/supes/mem_mgr/srchc.f index 17296933b1..dcaa05b395 100644 --- a/packages/seacas/libraries/supes/mem_mgr/srchc.f +++ b/packages/seacas/libraries/supes/mem_mgr/srchc.f @@ -1,11 +1,11 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C C See packages/seacas/LICENSE for details SUBROUTINE SRCHC(IVEC,ILBIN,IUBIN,NUM,ICOD,LOC) -C THIS SUBROUTINE SEARCHES ROW ILB THOURGH ROW IUB OF A +C THIS SUBROUTINE SEARCHES ROW ILB THROUGH ROW IUB OF A C NUMERICALLY ORDERED CHARACTER COLUMN VECTOR FOR THE OCCURRENCE C THE VALUE NUM. C IF NUM IS FOUND ICOD IS SET TO UNITY AND LOC IS THE ROW NUMBER diff --git a/packages/seacas/libraries/supes/mem_mgr/srchi.f b/packages/seacas/libraries/supes/mem_mgr/srchi.f index 984352f6bf..26f4e113bb 100644 --- a/packages/seacas/libraries/supes/mem_mgr/srchi.f +++ b/packages/seacas/libraries/supes/mem_mgr/srchi.f @@ -1,11 +1,11 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C C See packages/seacas/LICENSE for details SUBROUTINE SRCHI(IVEC,ILBIN,IUBIN,NUM,ICOD,LOC) -C THIS SUBROUTINE SEARCHES ROW ILB THOURGH ROW IUB OF A +C THIS SUBROUTINE SEARCHES ROW ILB THROUGH ROW IUB OF A C NUMERICALLY ORDERED INTEGER COLUMN VECTOR FOR THE OCCURRENCE C THE VALUE NUM. C IF NUM IS FOUND ICOD IS SET TO UNITY AND LOC IS THE ROW NUMBER diff --git a/packages/seacas/libraries/suplib/locrea.f b/packages/seacas/libraries/suplib/locrea.f index c35e906b3e..3d30392fe0 100644 --- a/packages/seacas/libraries/suplib/locrea.f +++ b/packages/seacas/libraries/suplib/locrea.f @@ -1,11 +1,11 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C C See packages/seacas/LICENSE for details C======================================================================= - INTEGER FUNCTION LOCREA (VALU, NVALUS, VALUS) + INTEGER FUNCTION LOCREA (VALUE, NVALUES, VALUES) C======================================================================= C --*** LOCREA *** (ETCLIB) Find closest real value @@ -15,16 +15,16 @@ INTEGER FUNCTION LOCREA (VALU, NVALUS, VALUS) C --real values (which may not be ordered). C -- C --Parameters: -C -- VALU - the value to be searched for -C -- NVALUS - the number of values in the list -C -- VALUS - the list of values +C -- VALUE - the value to be searched for +C -- NVALUES - the number of values in the list +C -- VALUES - the list of values - REAL VALUS(*) + REAL VALUES(*) - DIF = ABS (VALUS(1) - VALU) + DIF = ABS (VALUES(1) - VALUE) IX = 1 - DO 10 I = 2, NVALUS - DIFI = ABS (VALUS(I) - VALU) + DO 10 I = 2, NVALUES + DIFI = ABS (VALUES(I) - VALUE) IF (DIF .GT. DIFI) THEN DIF = DIFI IX = I diff --git a/packages/seacas/libraries/suplib_cpp/FileInfo.C b/packages/seacas/libraries/suplib_cpp/FileInfo.C index 47c9929ad8..9afa9bc5a8 100644 --- a/packages/seacas/libraries/suplib_cpp/FileInfo.C +++ b/packages/seacas/libraries/suplib_cpp/FileInfo.C @@ -209,7 +209,7 @@ std::string FileInfo::extension() const return filename_.substr(ind + 1, filename_.size()); } - return std::string(); + return {}; } std::string FileInfo::pathname() const @@ -219,7 +219,7 @@ std::string FileInfo::pathname() const return filename_.substr(0, ind); } - return std::string(); + return {}; } std::string FileInfo::tailname() const diff --git a/packages/seacas/libraries/suplib_cpp/GetLongOpt.h b/packages/seacas/libraries/suplib_cpp/GetLongOpt.h index 6f1ca175fe..026d0ce0d9 100644 --- a/packages/seacas/libraries/suplib_cpp/GetLongOpt.h +++ b/packages/seacas/libraries/suplib_cpp/GetLongOpt.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-, 20232023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -36,7 +36,6 @@ class GetLongOption Cell() = default; }; -private: Cell *table{nullptr}; // option table const char *ustring{nullptr}; // usage message char *pname{nullptr}; // program basename @@ -44,7 +43,6 @@ class GetLongOption char optmarker; // option marker bool options_parsed{false}; // parsed options, cannot enroll anymore options -private: int setcell(Cell *c, char *valtoken, char *nexttoken, const char *name); public: diff --git a/packages/seacas/libraries/suplib_cpp/glob.h b/packages/seacas/libraries/suplib_cpp/glob.h index 69e3025f6d..99467d12da 100644 --- a/packages/seacas/libraries/suplib_cpp/glob.h +++ b/packages/seacas/libraries/suplib_cpp/glob.h @@ -19,9 +19,9 @@ namespace glob { class Error : public std::exception { public: - Error(const std::string &msg) : msg_{msg} {} + explicit Error(std::string msg) : msg_{std::move(msg)} {} - const char *what() const throw() override { return msg_.c_str(); } + const char *what() const noexcept override { return msg_.c_str(); } private: std::string msg_; @@ -84,26 +84,26 @@ namespace glob { template class StateFail : public State { public: - StateFail(Automata &states) : State(StateType::FAIL, states) {} + explicit StateFail(Automata &states) : State(StateType::FAIL, states) {} bool Check(const String &, size_t) override { return false; } std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; template class StateMatch : public State { public: - StateMatch(Automata &states) : State(StateType::MATCH, states) {} + explicit StateMatch(Automata &states) : State(StateType::MATCH, states) {} bool Check(const String &, size_t) override { return true; } std::tuple Next(const String &, size_t pos) override { - return std::tuple(0, ++pos); + return {0, ++pos}; } }; @@ -118,8 +118,8 @@ namespace glob { Automata(Automata &&automata) : states_{std::move(automata.states_)}, match_state_{automata.match_state_}, - fail_state_{exchange(automata.fail_state_, 0)}, start_state_{ - exchange(automata.start_state_, 0)} + fail_state_{exchange(automata.fail_state_, 0)}, + start_state_{exchange(automata.start_state_, 0)} { } @@ -201,15 +201,15 @@ namespace glob { // the string if (comp_end) { if ((state_pos == match_state_) && (str_pos == str.length())) { - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } - return std::tuple(false, str_pos); + return {false, str_pos}; } else { // if comp_end is false, compare only if the states reached the // match state - return std::tuple(state_pos == match_state_, str_pos); + return {state_pos == match_state_, str_pos}; } } @@ -256,11 +256,11 @@ namespace glob { using State::GetAutomata; public: - StateAny(Automata &states) : State(StateType::QUESTION, states) {} + explicit StateAny(Automata &states) : State(StateType::QUESTION, states) {} bool Check(const String &, size_t) override { - // as it match any char, it is always trye + // as it match any char, it is always tried return true; } @@ -278,11 +278,11 @@ namespace glob { using State::GetAutomata; public: - StateStar(Automata &states) : State(StateType::MULT, states) {} + explicit StateStar(Automata &states) : State(StateType::MULT, states) {} bool Check(const String &, size_t) override { - // as it match any char, it is always trye + // as it match any char, it is always tried return true; } @@ -322,7 +322,7 @@ namespace glob { template class SetItemChar : public SetItem { public: - SetItemChar(charT c) : c_{c} {} + explicit SetItemChar(charT c) : c_{c} {} bool Check(charT c) const override { return c == c_; } @@ -403,8 +403,7 @@ namespace glob { StateGroup(Automata &states, Type type, std::vector>> &&automatas) - : State(StateType::GROUP, states), type_{type}, automatas_{std::move(automatas)}, - match_one_{false} + : State(StateType::GROUP, states), type_{type}, automatas_{std::move(automatas)} { } @@ -421,11 +420,11 @@ namespace glob { for (auto &automata : automatas_) { std::tie(r, str_pos) = automata->Exec(str_part, false); if (r) { - return std::tuple(r, pos + str_pos); + return {r, pos + str_pos}; } } - return std::tuple(false, pos + str_pos); + return {false, pos + str_pos}; } bool Check(const String &str, size_t pos) override @@ -471,7 +470,7 @@ namespace glob { return NextNeg(str, pos); } } - return std::tuple(0, 0); + return {0, 0}; } std::tuple NextNeg(const String &str, size_t pos) @@ -484,7 +483,7 @@ namespace glob { return std::tuple(GetAutomata().FailState(), new_pos); } - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } std::tuple NextBasic(const String &str, size_t pos) @@ -494,10 +493,10 @@ namespace glob { std::tie(r, new_pos) = BasicCheck(str, pos); if (r) { this->SetMatchedStr(this->MatchedStr() + str.substr(pos, new_pos - pos)); - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } - return std::tuple(GetAutomata().FailState(), new_pos); + return {GetAutomata().FailState(), new_pos}; } std::tuple NextAny(const String &str, size_t pos) @@ -507,10 +506,10 @@ namespace glob { std::tie(r, new_pos) = BasicCheck(str, pos); if (r) { this->SetMatchedStr(this->MatchedStr() + str.substr(pos, new_pos - pos)); - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } std::tuple NextStar(const String &str, size_t pos) @@ -522,14 +521,14 @@ namespace glob { this->SetMatchedStr(this->MatchedStr() + str.substr(pos, new_pos - pos)); if (GetAutomata().GetState(GetNextStates()[1]).Type() == StateType::MATCH && new_pos == str.length()) { - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } else { - return std::tuple(GetNextStates()[0], new_pos); + return {GetNextStates()[0], new_pos}; } } - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } std::tuple NextPlus(const String &str, size_t pos) @@ -545,10 +544,10 @@ namespace glob { // state is the match state, goes to next state to avoid state mistake if (GetAutomata().GetState(GetNextStates()[1]).Type() == StateType::MATCH && new_pos == str.length()) { - return std::tuple(GetNextStates()[1], new_pos); + return {GetNextStates()[1], new_pos}; } else { - return std::tuple(GetNextStates()[0], new_pos); + return {GetNextStates()[0], new_pos}; } } @@ -556,21 +555,21 @@ namespace glob { // one time -> goes to next state bool res = GetAutomata().GetState(GetNextStates()[1]).Check(str, pos); if (res && match_one_) { - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } if (match_one_) { - return std::tuple(GetNextStates()[1], pos); + return {GetNextStates()[1], pos}; } else { - return std::tuple(GetAutomata().FailState(), new_pos); + return {GetAutomata().FailState(), new_pos}; } } private: Type type_{}; std::vector>> automatas_; - bool match_one_; + bool match_one_{false}; }; #define TOKEN(X, Y) X, @@ -598,7 +597,7 @@ namespace glob { template class Token { public: - Token(TokenKind kind) : kind_{kind} {} + explicit Token(TokenKind kind) : kind_{kind} {} Token(TokenKind kind, charT value) : kind_{kind}, value_{value} {} TokenKind Kind() const { return kind_; } @@ -632,7 +631,7 @@ namespace glob { public: static const char kEndOfInput = -1; - Lexer(const String &str) : str_(str), pos_{0}, c_{str[0]} {} + explicit Lexer(const String &str) : str_(str), c_{str[0]} {} std::vector> Scanner() { @@ -790,7 +789,7 @@ namespace glob { } String str_; - size_t pos_; + size_t pos_{0}; charT c_; }; @@ -840,7 +839,7 @@ namespace glob { virtual void Accept(AstVisitor *visitor) = 0; protected: - AstNode(Type type) : type_{type} {} + explicit AstNode(Type type) : type_{type} {} private: Type type_; @@ -861,9 +860,9 @@ namespace glob { template class CharNode : public AstNode { public: - CharNode(charT c) : AstNode(AstNode::Type::CHAR), c_{c} {} + explicit CharNode(charT c) : AstNode(AstNode::Type::CHAR), c_{c} {} - virtual void Accept(AstVisitor *visitor) { visitor->VisitCharNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitCharNode(this); } char GetValue() const { return c_; } @@ -875,12 +874,12 @@ namespace glob { { public: RangeNode(AstNodePtr &&start, AstNodePtr &&end) - : AstNode(AstNode::Type::RANGE), start_{std::move(start)}, end_{ - std::move(end)} + : AstNode(AstNode::Type::RANGE), start_{std::move(start)}, + end_{std::move(end)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitRangeNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitRangeNode(this); } AstNode *GetStart() const { return start_.get(); } @@ -894,12 +893,12 @@ namespace glob { template class SetItemsNode : public AstNode { public: - SetItemsNode(std::vector> &&items) + explicit SetItemsNode(std::vector> &&items) : AstNode(AstNode::Type::SET_ITEMS), items_{std::move(items)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitSetItemsNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitSetItemsNode(this); } std::vector> &GetItems() { return items_; } @@ -910,12 +909,12 @@ namespace glob { template class PositiveSetNode : public AstNode { public: - PositiveSetNode(AstNodePtr &&set) + explicit PositiveSetNode(AstNodePtr &&set) : AstNode(AstNode::Type::POS_SET), set_{std::move(set)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitPositiveSetNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitPositiveSetNode(this); } AstNode *GetSet() { return set_.get(); } @@ -926,12 +925,12 @@ namespace glob { template class NegativeSetNode : public AstNode { public: - NegativeSetNode(AstNodePtr &&set) + explicit NegativeSetNode(AstNodePtr &&set) : AstNode(AstNode::Type::NEG_SET), set_{std::move(set)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitNegativeSetNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitNegativeSetNode(this); } AstNode *GetSet() { return set_.get(); } @@ -944,7 +943,7 @@ namespace glob { public: StarNode() : AstNode(AstNode::Type::STAR) {} - virtual void Accept(AstVisitor *visitor) { visitor->VisitStarNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitStarNode(this); } }; template class AnyNode : public AstNode @@ -952,7 +951,7 @@ namespace glob { public: AnyNode() : AstNode(AstNode::Type::ANY) {} - virtual void Accept(AstVisitor *visitor) { visitor->VisitAnyNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitAnyNode(this); } }; template class GroupNode : public AstNode @@ -961,12 +960,12 @@ namespace glob { enum class GroupType { BASIC, ANY, STAR, PLUS, NEG, AT }; GroupNode(GroupType group_type, AstNodePtr &&glob) - : AstNode(AstNode::Type::GROUP), glob_{std::move(glob)}, group_type_{ - group_type} + : AstNode(AstNode::Type::GROUP), glob_{std::move(glob)}, + group_type_{group_type} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitGroupNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitGroupNode(this); } AstNode *GetGlob() { return glob_.get(); } @@ -980,12 +979,12 @@ namespace glob { template class ConcatNode : public AstNode { public: - ConcatNode(std::vector> &&basic_glob) + explicit ConcatNode(std::vector> &&basic_glob) : AstNode(AstNode::Type::CONCAT_GLOB), basic_glob_{std::move(basic_glob)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitConcatNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitConcatNode(this); } std::vector> &GetBasicGlobs() { return basic_glob_; } @@ -996,12 +995,12 @@ namespace glob { template class UnionNode : public AstNode { public: - UnionNode(std::vector> &&items) + explicit UnionNode(std::vector> &&items) : AstNode(AstNode::Type::UNION), items_{std::move(items)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitUnionNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitUnionNode(this); } std::vector> &GetItems() { return items_; } @@ -1012,12 +1011,12 @@ namespace glob { template class GlobNode : public AstNode { public: - GlobNode(AstNodePtr &&glob) + explicit GlobNode(AstNodePtr &&glob) : AstNode(AstNode::Type::GLOB), glob_{std::move(glob)} { } - virtual void Accept(AstVisitor *visitor) { visitor->VisitGlobNode(this); } + void Accept(AstVisitor *visitor) override { visitor->VisitGlobNode(this); } AstNode *GetConcat() { return glob_.get(); } @@ -1030,7 +1029,7 @@ namespace glob { public: Parser() = delete; - Parser(std::vector> &&tok_vec) : tok_vec_{std::move(tok_vec)}, pos_{0} {} + explicit Parser(std::vector> &&tok_vec) : tok_vec_{std::move(tok_vec)}, pos_{0} {} AstNodePtr GenAst() { return ParserGlob(); } @@ -1206,17 +1205,18 @@ namespace glob { inline const Token &PeekAhead() const { - if (pos_ >= (tok_vec_.size() - 1)) + if (pos_ >= (tok_vec_.size() - 1)) { return tok_vec_.back(); + } return tok_vec_.at(pos_ + 1); } inline Token &NextToken() { - if (pos_ >= (tok_vec_.size() - 1)) + if (pos_ >= (tok_vec_.size() - 1)) { return tok_vec_.back(); - + } Token &tk = tok_vec_.at(pos_); pos_++; return tk; @@ -1224,8 +1224,9 @@ namespace glob { inline bool Advance() { - if (pos_ == tok_vec_.size() - 1) + if (pos_ == tok_vec_.size() - 1) { return false; + } ++pos_; return true; @@ -1258,8 +1259,8 @@ namespace glob { private: void ExecConcat(AstNode *node, Automata &automata) { - ConcatNode *concat_node = static_cast *>(node); - std::vector> &basic_globs = concat_node->GetBasicGlobs(); + auto *concat_node = static_cast *>(node); + auto &basic_globs = concat_node->GetBasicGlobs(); for (auto &basic_glob : basic_globs) { ExecBasicGlob(basic_glob.get(), automata); @@ -1287,8 +1288,8 @@ namespace glob { void ExecChar(AstNode *node, Automata &automata) { - CharNode *char_node = static_cast *>(node); - char c = char_node->GetValue(); + auto *char_node = static_cast *>(node); + char c = char_node->GetValue(); NewState>(automata, c); } @@ -1305,7 +1306,7 @@ namespace glob { void ExecPositiveSet(AstNode *node, Automata &automata) { - PositiveSetNode *pos_set_node = static_cast *>(node); + auto *pos_set_node = static_cast *>(node); auto items = ProcessSetItems(pos_set_node->GetSet()); NewState>(automata, std::move(items)); @@ -1313,7 +1314,7 @@ namespace glob { void ExecNegativeSet(AstNode *node, Automata &automata) { - NegativeSetNode *pos_set_node = static_cast *>(node); + auto *pos_set_node = static_cast *>(node); auto items = ProcessSetItems(pos_set_node->GetSet()); NewState>(automata, std::move(items), /*neg*/ true); @@ -1321,7 +1322,7 @@ namespace glob { std::vector>> ProcessSetItems(AstNode *node) { - SetItemsNode *set_node = static_cast *>(node); + auto *set_node = static_cast *>(node); std::vector>> vec; auto &items = set_node->GetItems(); for (auto &item : items) { @@ -1334,15 +1335,14 @@ namespace glob { std::unique_ptr> ProcessSetItem(AstNode *node) { if (node->GetType() == AstNode::Type::CHAR) { - CharNode *char_node = static_cast *>(node); - char c = char_node->GetValue(); + auto *char_node = static_cast *>(node); + char c = char_node->GetValue(); return std::unique_ptr>(new SetItemChar(c)); } else if (node->GetType() == AstNode::Type::RANGE) { - RangeNode *range_node = static_cast *>(node); - CharNode *start_node = static_cast *>(range_node->GetStart()); - - CharNode *end_node = static_cast *>(range_node->GetEnd()); + auto *range_node = static_cast *>(node); + auto *start_node = static_cast *>(range_node->GetStart()); + auto *end_node = static_cast *>(range_node->GetEnd()); char start_char = start_node->GetValue(); char end_char = end_node->GetValue(); @@ -1355,9 +1355,9 @@ namespace glob { void ExecGroup(AstNode *node, Automata &automata) { - GroupNode *group_node = static_cast *>(node); - AstNode *union_node = group_node->GetGlob(); - std::vector>> automatas = ExecUnion(union_node); + auto *group_node = static_cast *>(node); + auto *union_node = group_node->GetGlob(); + auto automatas = ExecUnion(union_node); typename StateGroup::Type state_group_type{}; switch (group_node->GetGroupType()) { @@ -1386,8 +1386,8 @@ namespace glob { std::vector>> ExecUnion(AstNode *node) { - UnionNode *union_node = static_cast *>(node); - auto &items = union_node->GetItems(); + auto *union_node = static_cast *>(node); + auto &items = union_node->GetItems(); std::vector>> vec_automatas; for (auto &item : items) { std::unique_ptr> automata_ptr(new Automata); @@ -1424,7 +1424,7 @@ namespace glob { template class ExtendedGlob { public: - ExtendedGlob(const String &pattern) + explicit ExtendedGlob(const String &pattern) { Lexer l(pattern); std::vector> tokens = l.Scanner(); @@ -1462,7 +1462,7 @@ namespace glob { template class SimpleGlob { public: - SimpleGlob(const String &pattern) { Parser(pattern); } + explicit SimpleGlob(const String &pattern) { Parser(pattern); } SimpleGlob(const SimpleGlob &) = delete; SimpleGlob &operator=(SimpleGlob &) = delete; @@ -1540,7 +1540,7 @@ namespace glob { template > class BasicGlob { public: - BasicGlob(const String &pattern) : glob_{pattern} {} + explicit BasicGlob(const String &pattern) : glob_{pattern} {} BasicGlob(const BasicGlob &) = delete; BasicGlob &operator=(BasicGlob &) = delete; diff --git a/packages/seacas/libraries/suplib_cpp/iqsort.C b/packages/seacas/libraries/suplib_cpp/iqsort.C index db7fecb61b..a4350b37cd 100644 --- a/packages/seacas/libraries/suplib_cpp/iqsort.C +++ b/packages/seacas/libraries/suplib_cpp/iqsort.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -32,7 +32,7 @@ template void index_qsort(const T v[], INT iv[], size namespace { /* The following 'indexed qsort' routine is modified from Sedgewicks * algorithm It selects the pivot based on the median of the left, - * right, and center values to try to avoid degenerate cases ocurring + * right, and center values to try to avoid degenerate cases occurring * when a single value is chosen. It performs a quicksort on * intervals down to the QSORT_CUTOFF size and then performs a final * insertion sort on the almost sorted final array. Based on data in diff --git a/packages/seacas/libraries/suplib_cpp/pdqsort.h b/packages/seacas/libraries/suplib_cpp/pdqsort.h index cb48087de1..22b4ce1226 100644 --- a/packages/seacas/libraries/suplib_cpp/pdqsort.h +++ b/packages/seacas/libraries/suplib_cpp/pdqsort.h @@ -1,7 +1,7 @@ /* pdqsort.h - Pattern-defeating quicksort. - Copyright (c) 2021, 2022 Orson Peters + Copyright (c) 2021, 2022, 2023 Orson Peters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -177,9 +177,9 @@ namespace pdqsort_detail { template inline T *align_cacheline(T *p) { #if defined(UINTPTR_MAX) && __cplusplus >= 201103L - std::uintptr_t ip = reinterpret_cast(p); + auto ip = reinterpret_cast(p); #else - std::size_t ip = reinterpret_cast(p); + auto ip = reinterpret_cast(p); #endif int icacheline_size = int(cacheline_size); ip = (ip + icacheline_size - 1) & -icacheline_size; diff --git a/packages/seacas/libraries/suplib_cpp/scopeguard.h b/packages/seacas/libraries/suplib_cpp/scopeguard.h index 21604f05c8..b05152ba10 100644 --- a/packages/seacas/libraries/suplib_cpp/scopeguard.h +++ b/packages/seacas/libraries/suplib_cpp/scopeguard.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -18,7 +18,7 @@ template class RefHolder public: explicit RefHolder(T &ref) : ref_(ref) {} - operator T &() const { return ref_; } + operator T &() const { return ref_; } RefHolder &operator=(const RefHolder &) = delete; }; @@ -26,6 +26,7 @@ template inline RefHolder ByRef(T &t) { return RefHolder(t); } class ScopeGuardImplBase { +public: ScopeGuardImplBase &operator=(const ScopeGuardImplBase &) = delete; protected: diff --git a/packages/seacas/libraries/suplib_cpp/smart_assert.C b/packages/seacas/libraries/suplib_cpp/smart_assert.C index be4be93513..eff0fba972 100644 --- a/packages/seacas/libraries/suplib_cpp/smart_assert.C +++ b/packages/seacas/libraries/suplib_cpp/smart_assert.C @@ -87,8 +87,9 @@ namespace smart_assert { typedef assert_context::vals_array ac_vals_array; const ac_vals_array &aVals = context.get_vals_array(); if (!aVals.empty()) { - bool bFirstTime = true; - ac_vals_array::const_iterator first = aVals.begin(), last = aVals.end(); + bool bFirstTime = true; + auto first = aVals.begin(); + auto last = aVals.end(); while (first != last) { if (bFirstTime) { out << "Values: "; diff --git a/packages/seacas/libraries/suplib_cpp/smart_assert.h b/packages/seacas/libraries/suplib_cpp/smart_assert.h index f0558454c1..5a0429cbb3 100644 --- a/packages/seacas/libraries/suplib_cpp/smart_assert.h +++ b/packages/seacas/libraries/suplib_cpp/smart_assert.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -56,7 +56,7 @@ class assert_context using string = std::string; public: - assert_context() {} + assert_context() = default; // where the assertion failed: file & line void set_file_line(const char *file, int line) @@ -71,13 +71,13 @@ class assert_context void set_expr(const string &str) { expr_ = str; } const string &get_expr() const { return expr_; } - typedef std::pair val_and_str; - using vals_array = std::vector; + using val_and_str = std::pair; + using vals_array = std::vector; // return values array as a vector of pairs: // [Value, corresponding string] const vals_array &get_vals_array() const { return vals_; } // adds one value and its corresponding string - void add_val(const string &val, const string &str) { vals_.push_back(val_and_str(val, str)); } + void add_val(const string &val, const string &str) { vals_.emplace_back(val, str); } // get/set level of assertion void set_level(int nLevel) { level_ = nLevel; } @@ -160,8 +160,7 @@ struct Assert Assert &SMART_ASSERT_A; Assert &SMART_ASSERT_B; - explicit Assert(const char *expr) - : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this), needs_handling_(true) + explicit Assert(const char *expr) : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this) { context_.set_expr(expr); @@ -172,8 +171,7 @@ struct Assert } Assert(const Assert &other) - : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this), context_(other.context_), - needs_handling_(true) + : SMART_ASSERT_A(*this), SMART_ASSERT_B(*this), context_(other.context_) { other.needs_handling_ = false; } @@ -275,8 +273,8 @@ struct Assert } // the handler - typedef std::map handlers_collection; - static handlers_collection &handlers() + using handlers_collection = std::map; + static handlers_collection &handlers() { static handlers_collection inst; return inst; @@ -284,7 +282,7 @@ struct Assert static assert_func get_handler(int nLevel) { - handlers_collection::const_iterator found = handlers().find(nLevel); + auto found = handlers().find(nLevel); if (found != handlers().end()) { return (*found).second; } @@ -293,7 +291,6 @@ struct Assert return (*handlers().find(lvl_debug)).second; } -private: assert_context context_{}; mutable bool needs_handling_{true}; }; diff --git a/packages/seacas/libraries/suplib_cpp/time_stamp.C b/packages/seacas/libraries/suplib_cpp/time_stamp.C index 0e285cbeb1..f2ee4dc8b2 100644 --- a/packages/seacas/libraries/suplib_cpp/time_stamp.C +++ b/packages/seacas/libraries/suplib_cpp/time_stamp.C @@ -10,7 +10,7 @@ std::string time_stamp(const std::string &format) { if (format.empty()) { - return std::string(""); + return {""}; } std::time_t t = std::time(nullptr); diff --git a/packages/seacas/libraries/suplib_cpp/timer.C b/packages/seacas/libraries/suplib_cpp/timer.C index f1faaab0a8..aa5c32f070 100644 --- a/packages/seacas/libraries/suplib_cpp/timer.C +++ b/packages/seacas/libraries/suplib_cpp/timer.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -7,8 +7,8 @@ #include // for ratio double seacas_timer() { - static auto start = std::chrono::steady_clock::now(); - auto now = std::chrono::steady_clock::now(); - std::chrono::duration diff = now - start; + static auto start = std::chrono::steady_clock::now(); + auto now = std::chrono::steady_clock::now(); + const std::chrono::duration diff = now - start; return diff.count(); } diff --git a/packages/seacas/libraries/svdi/cdr/cdrsrc.c b/packages/seacas/libraries/svdi/cdr/cdrsrc.c index 49c8a45c85..51d023a5a5 100644 --- a/packages/seacas/libraries/svdi/cdr/cdrsrc.c +++ b/packages/seacas/libraries/svdi/cdr/cdrsrc.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2022 National Technology & Engineering Solutions + * Copyright(C) 1999-2023 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -550,7 +550,7 @@ void cdrc2a_(char *charac, int *asci) { *asci = (int)charac[0]; } Notes and Revisions: This routine just copies the input to the output and appends a - zero word, the C/FORTRAN parameter passsing handles the rest. + zero word, the C/FORTRAN parameter passing handles the rest. Parameters: title - IN - character string of any length diff --git a/packages/seacas/libraries/svdi/cgi/met_metxlate.c b/packages/seacas/libraries/svdi/cgi/met_metxlate.c index af9029fa27..3f69a3d952 100644 --- a/packages/seacas/libraries/svdi/cgi/met_metxlate.c +++ b/packages/seacas/libraries/svdi/cgi/met_metxlate.c @@ -4075,7 +4075,7 @@ static void xcqlna(anything **params, anything **surf_list) /* line type */ *(int *)params[3] = cur_state->line_type; - /* line width spcification mode - only support scaled */ + /* line width specification mode - only support scaled */ *(int *)params[4] = CSCA; /* line width */ @@ -4115,7 +4115,7 @@ static void xcqmka(anything **params, anything **surf_list) /* marker type */ *(int *)params[3] = cur_state->mark_type; - /* marker size spcification mode - only support scaled */ + /* marker size specification mode - only support scaled */ *(int *)params[4] = CSCA; /* marker size */ diff --git a/packages/seacas/libraries/svdi/cgi/pst_pstxlate.c b/packages/seacas/libraries/svdi/cgi/pst_pstxlate.c index fa126c3b89..b4356383c8 100644 --- a/packages/seacas/libraries/svdi/cgi/pst_pstxlate.c +++ b/packages/seacas/libraries/svdi/cgi/pst_pstxlate.c @@ -4084,7 +4084,7 @@ static void xcqlna(anything **params, anything **surf_list) /* line type */ *(int *)params[3] = cur_state->line_type; - /* line width spcification mode - only support scaled */ + /* line width specification mode - only support scaled */ *(int *)params[4] = CSCA; /* line width */ @@ -4124,7 +4124,7 @@ static void xcqmka(anything **params, anything **surf_list) /* marker type */ *(int *)params[3] = cur_state->mark_type; - /* marker size spcification mode - only support scaled */ + /* marker size specification mode - only support scaled */ *(int *)params[4] = CSCA; /* marker size */ diff --git a/packages/seacas/libraries/svdi/cgi/x11_x11xlate.c b/packages/seacas/libraries/svdi/cgi/x11_x11xlate.c index 34eb8a5d95..6e7233fd07 100644 --- a/packages/seacas/libraries/svdi/cgi/x11_x11xlate.c +++ b/packages/seacas/libraries/svdi/cgi/x11_x11xlate.c @@ -4077,7 +4077,7 @@ static void xcqlna(anything **params, anything **surf_list) /* line type */ *(int *)params[3] = cur_state->line_type; - /* line width spcification mode - only support scaled */ + /* line width specification mode - only support scaled */ *(int *)params[4] = CSCA; /* line width */ @@ -4117,7 +4117,7 @@ static void xcqmka(anything **params, anything **surf_list) /* marker type */ *(int *)params[3] = cur_state->mark_type; - /* marker size spcification mode - only support scaled */ + /* marker size specification mode - only support scaled */ *(int *)params[4] = CSCA; /* marker size */ diff --git a/packages/seacas/libraries/svdi/post/postm.f b/packages/seacas/libraries/svdi/post/postm.f index 842b7028bc..3aca7867e9 100644 --- a/packages/seacas/libraries/svdi/post/postm.f +++ b/packages/seacas/libraries/svdi/post/postm.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -121,7 +121,7 @@ SUBROUTINE PPLOOP C VECTOR(7) - Used to find out the default foregound and background C colors from VDIQOS and to reinitialize the system at a C new file id. -C DRAWN - True if something has been drawn since inititalization or +C DRAWN - True if something has been drawn since initialization or C the background color has changed from default. C FIRST - True until after the first newpage since initialization @@ -303,7 +303,7 @@ SUBROUTINE PPLOOP 330 CONTINUE GOTO 350 -C IS IT A KNOWN ALHPA ESCAPE? +C IS IT A KNOWN ALPHA ESCAPE? 340 CONTINUE GOTO 1 diff --git a/packages/seacas/libraries/svdi/post/posts.f b/packages/seacas/libraries/svdi/post/posts.f index c9160ea5c8..7732f5c9db 100644 --- a/packages/seacas/libraries/svdi/post/posts.f +++ b/packages/seacas/libraries/svdi/post/posts.f @@ -1,4 +1,4 @@ -C Copyright(C) 1999-2020 National Technology & Engineering Solutions +C Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions C of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with C NTESS, the U.S. Government retains certain rights in this software. C @@ -121,7 +121,7 @@ SUBROUTINE PPLOOP C VECTOR(7) - Used to find out the default foregound and background C colors from VDIQOS and to reinitialize the system at a C new file id. -C DRAWN - True if something has been drawn since inititalization or +C DRAWN - True if something has been drawn since initialization or C the background color has changed from default. C FIRST - True until after the first newpage since initialization @@ -302,7 +302,7 @@ SUBROUTINE PPLOOP 330 CONTINUE GOTO 350 -C IS IT A KNOWN ALHPA ESCAPE? +C IS IT A KNOWN ALPHA ESCAPE? 340 CONTINUE GOTO 1 diff --git a/packages/seacas/scripts/CMakeLists.txt b/packages/seacas/scripts/CMakeLists.txt index ff35f62914..d63de072ba 100644 --- a/packages/seacas/scripts/CMakeLists.txt +++ b/packages/seacas/scripts/CMakeLists.txt @@ -8,6 +8,12 @@ SET( SEPARATOR "_") ASSERT_DEFINED(${PROJECT_NAME}_ENABLE_SEACASNemspread) ASSERT_DEFINED(${PROJECT_NAME}_ENABLE_SEACASNemslice) IF (${PROJECT_NAME}_ENABLE_SEACASNemspread AND ${PROJECT_NAME}_ENABLE_SEACASNemslice) +IF (${PROJECT_NAME}_ENABLE_Zoltan) + SET( DECOMP_DEFAULT rib ) +ELSE() + SET( DECOMP_DEFAULT inertial ) +ENDIF() + CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/decomp.in ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/decomp @@ -99,7 +105,7 @@ IF (${PROJECT_NAME}_ENABLE_SEACASExodus) MESSAGE(STATUS "A Python-3 version of exodus.py and exomerge.py will be installed.") ENDIF() - IF (BUILD_SHARED_LIBS) + IF (BUILD_SHARED_LIBS OR SEACASExodus_ENABLE_SHARED) IF (NOT "${CMAKE_INSTALL_PREFIX}" STREQUAL "") IF( ${${PROJECT_NAME}_INSTALL_INCLUDE_DIR} MATCHES "^${CMAKE_INSTALL_PREFIX}.*" ) STRING( REGEX REPLACE "^${CMAKE_INSTALL_PREFIX}" "" diff --git a/packages/seacas/scripts/decomp b/packages/seacas/scripts/decomp index 8f45b9a69c..4ef4a9944a 100755 --- a/packages/seacas/scripts/decomp +++ b/packages/seacas/scripts/decomp @@ -21,18 +21,18 @@ Usage: decomp [-h] --processors [-n ] [--rcb] [--rcb_ignore_z] [--rib] [--hsfc] [--random] [--scattered] [--weight ] [...others...] meshfile.ext -Decomposition methods: [0..3] = speed ranking 0=fastest +Decomposition methods: Default is -l rib. [0..3] = speed ranking 0=fastest. (See chaco and/or zoltan documentation for more details) --multikl: [3] Multilevel KL. Gives high quality partitions. Slow, high memory use. --spectral: [2] use eigenvectors of a matrix constructed from the graph to partition the graph. --hsfc [?] Hilbert Space-Filling Curve (uses Zoltan) - --rib: [?] (default) Recursive Inertial Bisection (uses Zoltan) + --rib: [?] Recursive Inertial Bisection (uses Zoltan) (default if zoltan enabled) --rcb: [?] Recursive Coordinate Bisection (uses Zoltan) --rcb_ignore_z: [?] Recursive Coordinate Bisection (uses Zoltan), ignoring the z dimension coordinates --inertial: [1] vertices divided into sets of equal mass by planes - orthogonal to the principle axis. Good, fast, medium memory + orthogonal to the principle axis. Good, fast, medium memory (default if zoltan not enabled) --linear: [0] vertices in order first n/p to proc 0, next to proc 1. (fast and sometimes good). --random: [0] vertices are assigned randomly to sets in a way that @@ -80,18 +80,18 @@ Usage: decomp [-h] -p [-n ] [-l rcb] [-l rcb_ignore_z] [-l rib] [-l hsfc] [-l random] [-l scattered] [...others...] meshfile.ext -Decomposition methods: [0..3] = speed ranking 0=fastest +Decomposition methods: Default is -l rib. [0..3] = speed ranking 0=fastest. (See chaco and/or zoltan documentation for more details) -l multikl: [3] Multilevel KL. Gives high quality partitions. Slow, high memory use. -l spectral: [2] use eigenvectors of a matrix constructed from the graph to partition the graph. -l hsfc [?] Hilbert Space-Filling Curve (uses Zoltan) - -l rib: [?] (default) Recursive Inertial Bisection (uses Zoltan) + -l rib: [?] Recursive Inertial Bisection (uses Zoltan) (default if zoltan enabled) -l rcb: [?] Recursive Coordinate Bisection (uses Zoltan) -l rcb_ignore_z: [?] Recursive Coordinate Bisection (uses Zoltan) ignoring the z dimension coordinates -l inertial: [1] vertices divided into sets of equal mass by planes - orthogonal to the principle axis. Good, fast, medium memory + orthogonal to the principle axis. Good, fast, medium memory (default if zoltan not enabled) -l linear: [0] vertices in order first n/p to proc 0, next to proc 1. (fast and sometimes good). -l random: [0] vertices are assigned randomly to sets in a way that diff --git a/packages/seacas/scripts/decomp.in b/packages/seacas/scripts/decomp.in index cf23d427c1..e8969ee525 100644 --- a/packages/seacas/scripts/decomp.in +++ b/packages/seacas/scripts/decomp.in @@ -21,18 +21,18 @@ Usage: decomp [-h] --processors [-n ] [--rcb] [--rcb_ignore_z] [--rib] [--hsfc] [--random] [--scattered] [--weight ] [...others...] meshfile.ext -Decomposition methods: [0..3] = speed ranking 0=fastest +Decomposition methods: Default is @DECOMP_DEFAULT@. [0..3] = speed ranking 0=fastest. (See chaco and/or zoltan documentation for more details) --multikl: [3] Multilevel KL. Gives high quality partitions. Slow, high memory use. --spectral: [2] use eigenvectors of a matrix constructed from the graph to partition the graph. --hsfc [?] Hilbert Space-Filling Curve (uses Zoltan) - --rib: [?] (default) Recursive Inertial Bisection (uses Zoltan) + --rib: [?] Recursive Inertial Bisection (uses Zoltan) (default if zoltan enabled) --rcb: [?] Recursive Coordinate Bisection (uses Zoltan) --rcb_ignore_z: [?] Recursive Coordinate Bisection (uses Zoltan), ignoring the z dimension coordinates --inertial: [1] vertices divided into sets of equal mass by planes - orthogonal to the principle axis. Good, fast, medium memory + orthogonal to the principle axis. Good, fast, medium memory (default if zoltan not enabled) --linear: [0] vertices in order first n/p to proc 0, next to proc 1. (fast and sometimes good). --random: [0] vertices are assigned randomly to sets in a way that @@ -76,18 +76,18 @@ Usage: decomp [-h] -p [-n ] [-l rcb] [-l rcb_ignore_z] [-l rib] [-l hsfc] [-l random] [-l scattered] [...others...] meshfile.ext -Decomposition methods: [0..3] = speed ranking 0=fastest +Decomposition methods: Default is @DECOMP_DEFAULT@. [0..3] = speed ranking 0=fastest. (See chaco and/or zoltan documentation for more details) -l multikl: [3] Multilevel KL. Gives high quality partitions. Slow, high memory use. -l spectral: [2] use eigenvectors of a matrix constructed from the graph to partition the graph. -l hsfc [?] Hilbert Space-Filling Curve (uses Zoltan) - -l rib: [?] (default) Recursive Inertial Bisection (uses Zoltan) + -l rib: [?] Recursive Inertial Bisection (uses Zoltan) (default if zoltan enabled) -l rcb: [?] Recursive Coordinate Bisection (uses Zoltan) -l rcb_ignore_z: [?] Recursive Coordinate Bisection (uses Zoltan) ignoring the z dimension coordinates -l inertial: [1] vertices divided into sets of equal mass by planes - orthogonal to the principle axis. Good, fast, medium memory + orthogonal to the principle axis. Good, fast, medium memory (default if zoltan not enabled) -l linear: [0] vertices in order first n/p to proc 0, next to proc 1. (fast and sometimes good). -l random: [0] vertices are assigned randomly to sets in a way that @@ -280,7 +280,7 @@ basename='' processors='' debug_level='0' decomp_type="-e" -decomp_method="-l rib" +decomp_method="-l @DECOMP_DEFAULT@" nem_slice_flag="-c" weighting='' rootdir="$(pwd)/" diff --git a/packages/seacas/scripts/exodus3.in.py b/packages/seacas/scripts/exodus3.in.py index dafd5ea930..542121007e 100644 --- a/packages/seacas/scripts/exodus3.in.py +++ b/packages/seacas/scripts/exodus3.in.py @@ -125,7 +125,7 @@ def getExodusVersion(): def _parse_exodus_version(version_string): if version_string: - assert version_string.startswith("#define EXODUS_VERSION "), "Received a incorrectly formated verstion string. Please check the CMakeLists.txt" + assert version_string.startswith("#define EXODUS_VERSION "), "Received a incorrectly formatted verstion string. Please check the CMakeLists.txt" return int(version_string.strip().split()[-1].strip('"').replace('.', '')) else: return 0 @@ -1592,7 +1592,7 @@ def num_elems(self): def get_num_map(self, mapType, idx): """ get user-defined map of exodus element/node/edge/face index to user- or - application- defined element/node/edge/face values. Map values are arbitary integers + application- defined element/node/edge/face values. Map values are arbitrary integers >>> elem_num_map = exo.get_num_map('EX_ELEM_MAP', 1) @@ -1624,7 +1624,7 @@ def get_num_map(self, mapType, idx): def put_num_map(self, mapType, idx, num_map): """ put user-defined map of exodus element/node/edge/face index to user- or - application- defined element/node/edge/face values. Map values are arbitary integers + application- defined element/node/edge/face values. Map values are arbitrary integers Parameters @@ -5783,7 +5783,7 @@ def __ex_put_block( numAttrsPerElem): obj_type = ctypes.c_int(get_entity_type(object_type)) block_id = ctypes.c_longlong(object_id) - if type(eType) == str: + if isinstance(eType, str): eType = eType.encode('ascii') elem_type = ctypes.create_string_buffer(eType.upper(), MAX_NAME_LENGTH + 1) num_elem_this_blk = ctypes.c_longlong(numElems) diff --git a/packages/seacas/scripts/exomerge3.py b/packages/seacas/scripts/exomerge3.py index 6eccbd5f20..06ec11e687 100644 --- a/packages/seacas/scripts/exomerge3.py +++ b/packages/seacas/scripts/exomerge3.py @@ -48,7 +48,9 @@ import operator if sys.version_info[0] < 3: - raise Exception("Python-3 version. If using python-2, try `import exomerge2 as exomerge`") + raise Exception( + "Python-3 version. If using python-2, try `import exomerge2 as exomerge`" + ) # import exodus module # (exodus.py should be in the same directory as this file) @@ -62,7 +64,7 @@ VERSION = __version__ # contact person for issues -CONTACT = 'Tim Kostka ' +CONTACT = "Tim Kostka " # show the banner on first use SHOW_BANNER = True @@ -82,11 +84,12 @@ # is the renamed function, or None. # e.g. DEPRECATED_FUNCTIONS['build_hex8_cube'] = 'create_hex8_cube' DEPRECATED_FUNCTIONS = dict() -DEPRECATED_FUNCTIONS['write'] = 'export' +DEPRECATED_FUNCTIONS["write"] = "export" class DummyFile(object): """Dummy class used to suppress output to stdout.""" + def write(self, x): """Ignore the write command.""" @@ -115,79 +118,117 @@ class ExodusModel(object): # define translation from two faces to a 3D cohesive element COHESIVE_FORMULA = dict() - COHESIVE_FORMULA['quad4'] = ['hex8', (0, 1, 2, 3, 4, 5, 6, 7)] - COHESIVE_FORMULA['tri3'] = ['wedge6', (0, 1, 2, 3, 4, 5)] - COHESIVE_FORMULA['tri6'] = [ - 'wedge12', (0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11) - ] + COHESIVE_FORMULA["quad4"] = ["hex8", (0, 1, 2, 3, 4, 5, 6, 7)] + COHESIVE_FORMULA["tri3"] = ["wedge6", (0, 1, 2, 3, 4, 5)] + COHESIVE_FORMULA["tri6"] = ["wedge12", (0, 1, 2, 6, 7, 8, 3, 4, 5, 9, 10, 11)] # define calculation for element length/area/volume VOLUME_FORMULA = dict() - VOLUME_FORMULA['line2'] = [1.0, (0, 1)] - VOLUME_FORMULA['line3'] = VOLUME_FORMULA['line2'] - VOLUME_FORMULA['tri3'] = [0.5, (0, 1), (0, 2)] - VOLUME_FORMULA['tri6'] = VOLUME_FORMULA['tri3'] - VOLUME_FORMULA['quad4'] = [0.5, (0, 2), (1, 3)] - VOLUME_FORMULA['quad6'] = VOLUME_FORMULA['quad4'] - VOLUME_FORMULA['quad8'] = VOLUME_FORMULA['quad4'] - VOLUME_FORMULA['tet4'] = [1.0 / 6.0, (0, 1), (0, 2), (0, 3)] - VOLUME_FORMULA['tet10'] = VOLUME_FORMULA['tet4'] - VOLUME_FORMULA['wedge6'] = [ - 0.5, ((0, 3), (1, 4)), ((0, 3), (2, 5)), ((0, 1, 2), (3, 4, 5)) + VOLUME_FORMULA["line2"] = [1.0, (0, 1)] + VOLUME_FORMULA["line3"] = VOLUME_FORMULA["line2"] + VOLUME_FORMULA["tri3"] = [0.5, (0, 1), (0, 2)] + VOLUME_FORMULA["tri6"] = VOLUME_FORMULA["tri3"] + VOLUME_FORMULA["quad4"] = [0.5, (0, 2), (1, 3)] + VOLUME_FORMULA["quad6"] = VOLUME_FORMULA["quad4"] + VOLUME_FORMULA["quad8"] = VOLUME_FORMULA["quad4"] + VOLUME_FORMULA["tet4"] = [1.0 / 6.0, (0, 1), (0, 2), (0, 3)] + VOLUME_FORMULA["tet10"] = VOLUME_FORMULA["tet4"] + VOLUME_FORMULA["wedge6"] = [ + 0.5, + ((0, 3), (1, 4)), + ((0, 3), (2, 5)), + ((0, 1, 2), (3, 4, 5)), ] - VOLUME_FORMULA['wedge12'] = VOLUME_FORMULA['wedge6'] - VOLUME_FORMULA['wedge15'] = VOLUME_FORMULA['wedge6'] - VOLUME_FORMULA['wedge16'] = VOLUME_FORMULA['wedge6'] - VOLUME_FORMULA['hex8'] = [ - 1.0, ((0, 3, 4, 7), (1, 2, 5, 6)), ((0, 1, 4, 5), (2, 3, 6, 7)), - ((0, 1, 2, 3), (4, 5, 6, 7)) + VOLUME_FORMULA["wedge12"] = VOLUME_FORMULA["wedge6"] + VOLUME_FORMULA["wedge15"] = VOLUME_FORMULA["wedge6"] + VOLUME_FORMULA["wedge16"] = VOLUME_FORMULA["wedge6"] + VOLUME_FORMULA["hex8"] = [ + 1.0, + ((0, 3, 4, 7), (1, 2, 5, 6)), + ((0, 1, 4, 5), (2, 3, 6, 7)), + ((0, 1, 2, 3), (4, 5, 6, 7)), ] - VOLUME_FORMULA['hex20'] = VOLUME_FORMULA['hex8'] + VOLUME_FORMULA["hex20"] = VOLUME_FORMULA["hex8"] # define mapping of the external faces of an element FACE_MAPPING = dict() - FACE_MAPPING['hex8'] = [('quad4', (0, 1, 5, 4)), ('quad4', (1, 2, 6, 5)), - ('quad4', (2, 3, 7, 6)), ('quad4', (3, 0, 4, 7)), - ('quad4', (0, 3, 2, 1)), ('quad4', (4, 5, 6, 7))] - FACE_MAPPING['hex20'] = [('quad8', (0, 1, 5, 4, 8, 13, 16, 12)), - ('quad8', (1, 2, 6, 5, 9, 14, 17, 13)), - ('quad8', (2, 3, 7, 6, 10, 15, 18, 14)), - ('quad8', (3, 0, 4, 7, 11, 12, 19, 15)), - ('quad8', (0, 3, 2, 1, 11, 10, 9, 8)), - ('quad8', (4, 5, 6, 7, 16, 17, 18, 19))] - FACE_MAPPING['tet4'] = [('tri3', (0, 1, 3)), ('tri3', (1, 2, 3)), - ('tri3', (2, 0, 3)), ('tri3', (0, 2, 1))] - FACE_MAPPING['tet10'] = [('tri6', (0, 1, 3, 4, 8, 7)), - ('tri6', (1, 2, 3, 5, 9, 8)), - ('tri6', (2, 0, 3, 6, 7, 9)), - ('tri6', (0, 2, 1, 6, 5, 4))] - FACE_MAPPING['wedge6'] = [('quad4', (0, 1, 4, 3)), ('quad4', (1, 2, 5, 4)), - ('quad4', (2, 0, 3, 5)), ('tri3', (0, 2, 1)), - ('tri3', (3, 4, 5))] - FACE_MAPPING['wedge12'] = [('quad6', (0, 1, 4, 3, 6, 9)), - ('quad6', (1, 2, 5, 4, 7, 10)), - ('quad6', (2, 0, 3, 5, 8, 11)), - ('tri6', (0, 2, 1, 8, 7, 6)), - ('tri6', (3, 4, 5, 11, 10, 9))] - FACE_MAPPING['wedge15'] = [('quad8', (0, 1, 4, 3, 6, 10, 12, 9)), - ('quad8', (1, 2, 5, 4, 7, 11, 13, 10)), - ('quad8', (2, 0, 3, 5, 8, 9, 14, 11)), - ('tri6', (0, 2, 1, 8, 7, 6)), - ('tri6', (3, 4, 5, 12, 13, 14))] - FACE_MAPPING['wedge16'] = FACE_MAPPING['wedge15'] - FACE_MAPPING['tri3'] = [('line2', (0, 1)), ('line2', (1, 2)), - ('line2', (2, 0))] - FACE_MAPPING['tri6'] = [('line3', (0, 1, 3)), ('line3', (1, 2, 4)), - ('line3', (2, 0, 5))] - FACE_MAPPING['quad4'] = [('line2', (0, 1)), ('line2', (1, 2)), - ('line2', (2, 3)), ('line2', (3, 0))] - FACE_MAPPING['quad6'] = [('line3', (0, 1, 4)), ('line2', (1, 2)), - ('line3', (2, 5, 3)), ('line2', (3, 0))] - FACE_MAPPING['quad8'] = [('line3', (0, 1, 4)), ('line3', (1, 2, 5)), - ('line3', (2, 3, 6)), ('line3', (3, 0, 7))] - FACE_MAPPING['line2'] = [('point', tuple([0])), ('point', tuple([1]))] - FACE_MAPPING['line3'] = FACE_MAPPING['line2'] - FACE_MAPPING['point'] = [] + FACE_MAPPING["hex8"] = [ + ("quad4", (0, 1, 5, 4)), + ("quad4", (1, 2, 6, 5)), + ("quad4", (2, 3, 7, 6)), + ("quad4", (3, 0, 4, 7)), + ("quad4", (0, 3, 2, 1)), + ("quad4", (4, 5, 6, 7)), + ] + FACE_MAPPING["hex20"] = [ + ("quad8", (0, 1, 5, 4, 8, 13, 16, 12)), + ("quad8", (1, 2, 6, 5, 9, 14, 17, 13)), + ("quad8", (2, 3, 7, 6, 10, 15, 18, 14)), + ("quad8", (3, 0, 4, 7, 11, 12, 19, 15)), + ("quad8", (0, 3, 2, 1, 11, 10, 9, 8)), + ("quad8", (4, 5, 6, 7, 16, 17, 18, 19)), + ] + FACE_MAPPING["tet4"] = [ + ("tri3", (0, 1, 3)), + ("tri3", (1, 2, 3)), + ("tri3", (2, 0, 3)), + ("tri3", (0, 2, 1)), + ] + FACE_MAPPING["tet10"] = [ + ("tri6", (0, 1, 3, 4, 8, 7)), + ("tri6", (1, 2, 3, 5, 9, 8)), + ("tri6", (2, 0, 3, 6, 7, 9)), + ("tri6", (0, 2, 1, 6, 5, 4)), + ] + FACE_MAPPING["wedge6"] = [ + ("quad4", (0, 1, 4, 3)), + ("quad4", (1, 2, 5, 4)), + ("quad4", (2, 0, 3, 5)), + ("tri3", (0, 2, 1)), + ("tri3", (3, 4, 5)), + ] + FACE_MAPPING["wedge12"] = [ + ("quad6", (0, 1, 4, 3, 6, 9)), + ("quad6", (1, 2, 5, 4, 7, 10)), + ("quad6", (2, 0, 3, 5, 8, 11)), + ("tri6", (0, 2, 1, 8, 7, 6)), + ("tri6", (3, 4, 5, 11, 10, 9)), + ] + FACE_MAPPING["wedge15"] = [ + ("quad8", (0, 1, 4, 3, 6, 10, 12, 9)), + ("quad8", (1, 2, 5, 4, 7, 11, 13, 10)), + ("quad8", (2, 0, 3, 5, 8, 9, 14, 11)), + ("tri6", (0, 2, 1, 8, 7, 6)), + ("tri6", (3, 4, 5, 12, 13, 14)), + ] + FACE_MAPPING["wedge16"] = FACE_MAPPING["wedge15"] + FACE_MAPPING["tri3"] = [("line2", (0, 1)), ("line2", (1, 2)), ("line2", (2, 0))] + FACE_MAPPING["tri6"] = [ + ("line3", (0, 1, 3)), + ("line3", (1, 2, 4)), + ("line3", (2, 0, 5)), + ] + FACE_MAPPING["quad4"] = [ + ("line2", (0, 1)), + ("line2", (1, 2)), + ("line2", (2, 3)), + ("line2", (3, 0)), + ] + FACE_MAPPING["quad6"] = [ + ("line3", (0, 1, 4)), + ("line2", (1, 2)), + ("line3", (2, 5, 3)), + ("line2", (3, 0)), + ] + FACE_MAPPING["quad8"] = [ + ("line3", (0, 1, 4)), + ("line3", (1, 2, 5)), + ("line3", (2, 3, 6)), + ("line3", (3, 0, 7)), + ] + FACE_MAPPING["line2"] = [("point", tuple([0])), ("point", tuple([1]))] + FACE_MAPPING["line3"] = FACE_MAPPING["line2"] + FACE_MAPPING["point"] = [] # define all standard element types STANDARD_ELEMENT_TYPES = set(FACE_MAPPING.keys()) @@ -196,154 +237,291 @@ class ExodusModel(object): # for 2d elements, this flips the element normal # for 1d elements, this changes the direction INVERTED_CONNECTIVITY = dict() - INVERTED_CONNECTIVITY['hex8'] = (4, 5, 6, 7, 0, 1, 2, 3) - INVERTED_CONNECTIVITY['hex20'] = (4, 5, 6, 7, 0, 1, 2, 3, 16, 17, 18, 19, - 8, 9, 10, 11, 12, 13, 14, 15) - INVERTED_CONNECTIVITY['tet4'] = (0, 2, 1, 3) - INVERTED_CONNECTIVITY['tet10'] = (0, 2, 1, 3, 6, 5, 4, 7, 9, 8) - INVERTED_CONNECTIVITY['wedge6'] = (3, 4, 5, 0, 1, 2) - INVERTED_CONNECTIVITY['wedge12'] = (3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8) - INVERTED_CONNECTIVITY['wedge15'] = (3, 4, 5, 0, 1, 2, 12, 13, 14, 6, 7, 8, - 9, 10, 11) - INVERTED_CONNECTIVITY['wedge16'] = (3, 4, 5, 0, 1, 2, 12, 13, 14, 6, 7, 8, - 9, 10, 11, 15) - INVERTED_CONNECTIVITY['tri3'] = (0, 2, 1) - INVERTED_CONNECTIVITY['tri6'] = (0, 2, 1, 5, 4, 3) - INVERTED_CONNECTIVITY['quad4'] = (0, 3, 2, 1) - INVERTED_CONNECTIVITY['quad6'] = (3, 2, 1, 0, 5, 4) - INVERTED_CONNECTIVITY['quad8'] = (0, 3, 2, 1, 7, 6, 5, 4) - INVERTED_CONNECTIVITY['line2'] = (1, 0) - INVERTED_CONNECTIVITY['line3'] = (1, 0, 2) - INVERTED_CONNECTIVITY['point'] = tuple([0]) + INVERTED_CONNECTIVITY["hex8"] = (4, 5, 6, 7, 0, 1, 2, 3) + INVERTED_CONNECTIVITY["hex20"] = ( + 4, + 5, + 6, + 7, + 0, + 1, + 2, + 3, + 16, + 17, + 18, + 19, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + ) + INVERTED_CONNECTIVITY["tet4"] = (0, 2, 1, 3) + INVERTED_CONNECTIVITY["tet10"] = (0, 2, 1, 3, 6, 5, 4, 7, 9, 8) + INVERTED_CONNECTIVITY["wedge6"] = (3, 4, 5, 0, 1, 2) + INVERTED_CONNECTIVITY["wedge12"] = (3, 4, 5, 0, 1, 2, 9, 10, 11, 6, 7, 8) + INVERTED_CONNECTIVITY["wedge15"] = ( + 3, + 4, + 5, + 0, + 1, + 2, + 12, + 13, + 14, + 6, + 7, + 8, + 9, + 10, + 11, + ) + INVERTED_CONNECTIVITY["wedge16"] = ( + 3, + 4, + 5, + 0, + 1, + 2, + 12, + 13, + 14, + 6, + 7, + 8, + 9, + 10, + 11, + 15, + ) + INVERTED_CONNECTIVITY["tri3"] = (0, 2, 1) + INVERTED_CONNECTIVITY["tri6"] = (0, 2, 1, 5, 4, 3) + INVERTED_CONNECTIVITY["quad4"] = (0, 3, 2, 1) + INVERTED_CONNECTIVITY["quad6"] = (3, 2, 1, 0, 5, 4) + INVERTED_CONNECTIVITY["quad8"] = (0, 3, 2, 1, 7, 6, 5, 4) + INVERTED_CONNECTIVITY["line2"] = (1, 0) + INVERTED_CONNECTIVITY["line3"] = (1, 0, 2) + INVERTED_CONNECTIVITY["point"] = tuple([0]) # define a connectivity permutation which rotates the given 2d face ROTATED_CONNECTIVITY = dict() - ROTATED_CONNECTIVITY['quad4'] = (3, 0, 1, 2) - ROTATED_CONNECTIVITY['quad8'] = (3, 0, 1, 2, 7, 4, 5, 6) - ROTATED_CONNECTIVITY['tri3'] = (2, 0, 1) - ROTATED_CONNECTIVITY['tri6'] = (2, 0, 1, 5, 3, 4) + ROTATED_CONNECTIVITY["quad4"] = (3, 0, 1, 2) + ROTATED_CONNECTIVITY["quad8"] = (3, 0, 1, 2, 7, 4, 5, 6) + ROTATED_CONNECTIVITY["tri3"] = (2, 0, 1) + ROTATED_CONNECTIVITY["tri6"] = (2, 0, 1, 5, 3, 4) # define the topological dimension of each element DIMENSION = dict() - DIMENSION['point'] = 0 - DIMENSION['line2'] = 1 - DIMENSION['line3'] = 1 - DIMENSION['tri3'] = 2 - DIMENSION['tri6'] = 2 - DIMENSION['quad4'] = 2 - DIMENSION['quad6'] = 2 - DIMENSION['quad8'] = 2 - DIMENSION['hex8'] = 3 - DIMENSION['hex20'] = 3 - DIMENSION['tet4'] = 3 - DIMENSION['tet10'] = 3 - DIMENSION['wedge6'] = 3 - DIMENSION['wedge12'] = 3 - DIMENSION['wedge15'] = 3 - DIMENSION['wedge16'] = 3 + DIMENSION["point"] = 0 + DIMENSION["line2"] = 1 + DIMENSION["line3"] = 1 + DIMENSION["tri3"] = 2 + DIMENSION["tri6"] = 2 + DIMENSION["quad4"] = 2 + DIMENSION["quad6"] = 2 + DIMENSION["quad8"] = 2 + DIMENSION["hex8"] = 3 + DIMENSION["hex20"] = 3 + DIMENSION["tet4"] = 3 + DIMENSION["tet10"] = 3 + DIMENSION["wedge6"] = 3 + DIMENSION["wedge12"] = 3 + DIMENSION["wedge15"] = 3 + DIMENSION["wedge16"] = 3 # define the number of nodes per element NODES_PER_ELEMENT = dict( - (key, len(value)) - for key, value in list(INVERTED_CONNECTIVITY.items())) + (key, len(value)) for key, value in list(INVERTED_CONNECTIVITY.items()) + ) # define how to triangulate faces of 3D elements TRIANGULATED_FACES = dict() - TRIANGULATED_FACES['tri3'] = [(0, 1, 2)] - TRIANGULATED_FACES['tri6'] = [(0, 3, 5), (1, 4, 3), (2, 5, 4), (3, 4, 5)] - TRIANGULATED_FACES['quad4'] = [(0, 1, (0, 1, 2, 3)), (1, 2, (0, 1, 2, 3)), - (2, 3, (0, 1, 2, 3)), (3, 0, (0, 1, 2, 3))] - TRIANGULATED_FACES['quad6'] = [(0, 4, (4, 5)), (4, 1, (4, 5)), - (1, 2, (4, 5)), (2, 5, (4, 5)), - (5, 3, (4, 5)), (3, 0, (4, 5))] - TRIANGULATED_FACES['quad8'] = [(4, 7, 0), (5, 4, 1), (6, 5, 2), (7, 6, 3), - (7, 4, (4, 5, 6, 7)), (4, 5, (4, 5, 6, 7)), - (5, 6, (4, 5, 6, 7)), (6, 7, (4, 5, 6, 7))] + TRIANGULATED_FACES["tri3"] = [(0, 1, 2)] + TRIANGULATED_FACES["tri6"] = [(0, 3, 5), (1, 4, 3), (2, 5, 4), (3, 4, 5)] + TRIANGULATED_FACES["quad4"] = [ + (0, 1, (0, 1, 2, 3)), + (1, 2, (0, 1, 2, 3)), + (2, 3, (0, 1, 2, 3)), + (3, 0, (0, 1, 2, 3)), + ] + TRIANGULATED_FACES["quad6"] = [ + (0, 4, (4, 5)), + (4, 1, (4, 5)), + (1, 2, (4, 5)), + (2, 5, (4, 5)), + (5, 3, (4, 5)), + (3, 0, (4, 5)), + ] + TRIANGULATED_FACES["quad8"] = [ + (4, 7, 0), + (5, 4, 1), + (6, 5, 2), + (7, 6, 3), + (7, 4, (4, 5, 6, 7)), + (4, 5, (4, 5, 6, 7)), + (5, 6, (4, 5, 6, 7)), + (6, 7, (4, 5, 6, 7)), + ] # define formulas for converting between element types ELEMENT_CONVERSIONS = dict() - ELEMENT_CONVERSIONS['hex8'] = dict() - ELEMENT_CONVERSIONS['hex8']['hex20'] = [[ - 0, 1, 2, 3, 4, 5, 6, 7, (0, 1), (1, 2), (2, 3), (0, 3), (0, 4), (1, 5), - (2, 6), (3, 7), (4, 5), (5, 6), (6, 7), (4, 7) - ]] - ELEMENT_CONVERSIONS['hex20'] = dict() - ELEMENT_CONVERSIONS['hex20']['hex8'] = [list(range(8))] - ELEMENT_CONVERSIONS['tet4'] = dict() - ELEMENT_CONVERSIONS['tet4']['tet10'] = [[ - 0, 1, 2, 3, (0, 1), (1, 2), (0, 2), (0, 3), (1, 3), (2, 3) - ]] - ELEMENT_CONVERSIONS['tet10'] = dict() - ELEMENT_CONVERSIONS['tet10']['tet4'] = [list(range(4))] - ELEMENT_CONVERSIONS['wedge6'] = dict() - ELEMENT_CONVERSIONS['wedge6']['wedge15'] = [[ - 0, 1, 2, 3, 4, 5, (0, 1), (1, 2), (0, 2), (0, 3), (1, 4), (2, 5), - (3, 4), (4, 5), (3, 5) - ]] - ELEMENT_CONVERSIONS['wedge6']['wedge16'] = [[ - 0, 1, 2, 3, 4, 5, (0, 1), (1, 2), (0, 2), (0, 3), (1, 4), (2, 5), - (3, 4), (4, 5), (3, 5), (0, 1, 2, 3, 4, 5) - ]] - ELEMENT_CONVERSIONS['wedge12'] = dict() - ELEMENT_CONVERSIONS['wedge12']['wedge6'] = [list(range(6))] - ELEMENT_CONVERSIONS['wedge12']['wedge15'] = [[ - 0, 1, 2, 3, 4, 5, 6, 7, 8, (0, 3), (1, 4), (2, 5), 9, 10, 11 - ]] - ELEMENT_CONVERSIONS['wedge15'] = dict() - ELEMENT_CONVERSIONS['wedge15']['wedge6'] = [list(range(6))] - ELEMENT_CONVERSIONS['wedge15']['wedge16'] = [[ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, (0, 1, 2, 3, 4, 5) - ]] - ELEMENT_CONVERSIONS['wedge16'] = dict() - ELEMENT_CONVERSIONS['wedge16']['wedge6'] = [list(range(6))] - ELEMENT_CONVERSIONS['wedge16']['wedge15'] = [list(range(15))] + ELEMENT_CONVERSIONS["hex8"] = dict() + ELEMENT_CONVERSIONS["hex8"]["hex20"] = [ + [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + (0, 1), + (1, 2), + (2, 3), + (0, 3), + (0, 4), + (1, 5), + (2, 6), + (3, 7), + (4, 5), + (5, 6), + (6, 7), + (4, 7), + ] + ] + ELEMENT_CONVERSIONS["hex20"] = dict() + ELEMENT_CONVERSIONS["hex20"]["hex8"] = [list(range(8))] + ELEMENT_CONVERSIONS["tet4"] = dict() + ELEMENT_CONVERSIONS["tet4"]["tet10"] = [ + [0, 1, 2, 3, (0, 1), (1, 2), (0, 2), (0, 3), (1, 3), (2, 3)] + ] + ELEMENT_CONVERSIONS["tet10"] = dict() + ELEMENT_CONVERSIONS["tet10"]["tet4"] = [list(range(4))] + ELEMENT_CONVERSIONS["wedge6"] = dict() + ELEMENT_CONVERSIONS["wedge6"]["wedge15"] = [ + [ + 0, + 1, + 2, + 3, + 4, + 5, + (0, 1), + (1, 2), + (0, 2), + (0, 3), + (1, 4), + (2, 5), + (3, 4), + (4, 5), + (3, 5), + ] + ] + ELEMENT_CONVERSIONS["wedge6"]["wedge16"] = [ + [ + 0, + 1, + 2, + 3, + 4, + 5, + (0, 1), + (1, 2), + (0, 2), + (0, 3), + (1, 4), + (2, 5), + (3, 4), + (4, 5), + (3, 5), + (0, 1, 2, 3, 4, 5), + ] + ] + ELEMENT_CONVERSIONS["wedge12"] = dict() + ELEMENT_CONVERSIONS["wedge12"]["wedge6"] = [list(range(6))] + ELEMENT_CONVERSIONS["wedge12"]["wedge15"] = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, (0, 3), (1, 4), (2, 5), 9, 10, 11] + ] + ELEMENT_CONVERSIONS["wedge15"] = dict() + ELEMENT_CONVERSIONS["wedge15"]["wedge6"] = [list(range(6))] + ELEMENT_CONVERSIONS["wedge15"]["wedge16"] = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, (0, 1, 2, 3, 4, 5)] + ] + ELEMENT_CONVERSIONS["wedge16"] = dict() + ELEMENT_CONVERSIONS["wedge16"]["wedge6"] = [list(range(6))] + ELEMENT_CONVERSIONS["wedge16"]["wedge15"] = [list(range(15))] # define the order of each element ELEMENT_ORDER = dict() - ELEMENT_ORDER['hex8'] = 1 - ELEMENT_ORDER['hex20'] = 2 - ELEMENT_ORDER['tet4'] = 1 - ELEMENT_ORDER['tet10'] = 2 - ELEMENT_ORDER['wedge6'] = 1 - ELEMENT_ORDER['wedge12'] = 1 - ELEMENT_ORDER['wedge15'] = 2 - ELEMENT_ORDER['wedge16'] = 2 - ELEMENT_ORDER['tri3'] = 1 - ELEMENT_ORDER['tri6'] = 2 - ELEMENT_ORDER['quad4'] = 1 - ELEMENT_ORDER['quad6'] = 1 - ELEMENT_ORDER['quad8'] = 2 - ELEMENT_ORDER['line2'] = 1 - ELEMENT_ORDER['line3'] = 2 - ELEMENT_ORDER['point'] = 1 + ELEMENT_ORDER["hex8"] = 1 + ELEMENT_ORDER["hex20"] = 2 + ELEMENT_ORDER["tet4"] = 1 + ELEMENT_ORDER["tet10"] = 2 + ELEMENT_ORDER["wedge6"] = 1 + ELEMENT_ORDER["wedge12"] = 1 + ELEMENT_ORDER["wedge15"] = 2 + ELEMENT_ORDER["wedge16"] = 2 + ELEMENT_ORDER["tri3"] = 1 + ELEMENT_ORDER["tri6"] = 2 + ELEMENT_ORDER["quad4"] = 1 + ELEMENT_ORDER["quad6"] = 1 + ELEMENT_ORDER["quad8"] = 2 + ELEMENT_ORDER["line2"] = 1 + ELEMENT_ORDER["line3"] = 2 + ELEMENT_ORDER["point"] = 1 # define components of multi-component fields MULTI_COMPONENT_FIELD_SUBSCRIPTS = dict() - MULTI_COMPONENT_FIELD_SUBSCRIPTS['vector'] = ('x', 'y', 'z') - MULTI_COMPONENT_FIELD_SUBSCRIPTS['symmetric_3x3_tensor'] = ('xx', 'yy', - 'zz', 'xy', - 'yz', 'zx') - MULTI_COMPONENT_FIELD_SUBSCRIPTS['full_3x3_tensor'] = ('xx', 'yy', 'zz', - 'xy', 'yz', 'zx', - 'yx', 'zy', 'xz') + MULTI_COMPONENT_FIELD_SUBSCRIPTS["vector"] = ("x", "y", "z") + MULTI_COMPONENT_FIELD_SUBSCRIPTS["symmetric_3x3_tensor"] = ( + "xx", + "yy", + "zz", + "xy", + "yz", + "zx", + ) + MULTI_COMPONENT_FIELD_SUBSCRIPTS["full_3x3_tensor"] = ( + "xx", + "yy", + "zz", + "xy", + "yz", + "zx", + "yx", + "zy", + "xz", + ) ALL_MULTI_COMPONENT_FIELD_SUBSCRIPTS = set( - itertools.chain(*list(MULTI_COMPONENT_FIELD_SUBSCRIPTS.values()))) + itertools.chain(*list(MULTI_COMPONENT_FIELD_SUBSCRIPTS.values())) + ) def __init__(self): """Initialize the model.""" # (only) the first time this module is used, show an info banner global SHOW_BANNER if SHOW_BANNER: - print(('\n\nYou are using Exomerge v%s -- A lightweight Python ' - 'interface for manipulating\nExodusII files. (Python-3 version)' % (VERSION))) + print( + ( + "\n\nYou are using Exomerge v%s -- A lightweight Python " + "interface for manipulating\nExodusII files. (Python-3 version)" + % (VERSION) + ) + ) # print out the exodus banner after formatting it to fit within # 79 characters exodus_text = exodus.EXODUS_PY_COPYRIGHT - exodus_text = exodus_text.strip().replace('\n', ' ') - exodus_text = exodus_text.replace('. ', '. ') - exodus_text = exodus_text.replace('. ', '. ') + exodus_text = exodus_text.strip().replace("\n", " ") + exodus_text = exodus_text.replace(". ", ". ") + exodus_text = exodus_text.replace(". ", ". ") exodus_text = textwrap.fill(exodus_text, width=79) - print(('\n%s\n' % exodus_text)) + print(("\n%s\n" % exodus_text)) SHOW_BANNER = False # list of [x, y, z] coordinates for each node self.nodes = [] @@ -393,28 +571,27 @@ def __getattr__(self, name): """ # for special methods, use default behavior - if name[:2] == '__': + if name[:2] == "__": raise AttributeError # get non-special function names - names = [x for x in dir(self.__class__) if x[:2] != '__'] + names = [x for x in dir(self.__class__) if x[:2] != "__"] # if the name appears to be singular, search for the plural version - if not name.endswith('s'): - trial = name + 's' + if not name.endswith("s"): + trial = name + "s" if trial in names: return getattr(self, trial) # if the name appears to be plural, search for the singular version - if name.endswith('s'): + if name.endswith("s"): trial = name[:-1] - if not trial.endswith('s') and trial in names: + if not trial.endswith("s") and trial in names: return getattr(self, trial) # we can't find the name, so find names close to it to offer as # suggestions # filter names by closeness - names = dict( - (x, difflib.SequenceMatcher(None, x, name).ratio()) for x in names) - sorted_names = sorted(iter(names.items()), - key=operator.itemgetter(1), - reverse=True) + names = dict((x, difflib.SequenceMatcher(None, x, name).ratio()) for x in names) + sorted_names = sorted( + iter(names.items()), key=operator.itemgetter(1), reverse=True + ) # get the closest 5 matching function names closest_names = [x[0] for x in sorted_names[0:5]] # in an interactive shell, just issue a warning, else @@ -424,16 +601,18 @@ def __getattr__(self, name): else: call = self._error call( - 'Function not found.', + "Function not found.", 'The function "%s" does not exist. Perhaps you meant to ' - 'call one of the following functions:\n\n%s' % - (name, '\n'.join(closest_names))) + "call one of the following functions:\n\n%s" + % (name, "\n".join(closest_names)), + ) @staticmethod def _is_interactive(): """Return True if we're in an interactive shell.""" import __main__ as main - return not hasattr(main, '__file__') + + return not hasattr(main, "__file__") @staticmethod def _assert(condition): @@ -464,22 +643,38 @@ def _cubic_interpolation(x, x0, x1, x2, x3): assert x1 <= x <= x2 values = [] # proportion of y0 - values.append(((x - x1) * (x - x2)**2) / ((x0 - x2) * (x1 - x2)**2)) + values.append(((x - x1) * (x - x2) ** 2) / ((x0 - x2) * (x1 - x2) ** 2)) # proportion of y1 - values.append(-(((x - x2) * - (-(x * x1 * (x1 + 3 * x2)) - x1 * - (x1**2 - 4 * x1 * x2 + x2**2) + x**2 * - (x1 + x2 - 2 * x3) + x2 * (-3 * x1 + x2) * x3 + x * - (3 * x1 + x2) * x3)) / ((x1 - x2)**3 * (x1 - x3)))) + values.append( + -( + ( + (x - x2) + * ( + -(x * x1 * (x1 + 3 * x2)) + - x1 * (x1**2 - 4 * x1 * x2 + x2**2) + + x**2 * (x1 + x2 - 2 * x3) + + x2 * (-3 * x1 + x2) * x3 + + x * (3 * x1 + x2) * x3 + ) + ) + / ((x1 - x2) ** 3 * (x1 - x3)) + ) + ) # proportion of y2 values.append( - ((x - x1) * - (x0 * x1 * (x1 - 3 * x2) + x**2 * (-2 * x0 + x1 + x2) - x2 * - (x1**2 - 4 * x1 * x2 + x2**2) + x * - (-(x2 * (3 * x1 + x2)) + x0 * (x1 + 3 * x2)))) / ((x0 - x2) * - (-x1 + x2)**3)) + ( + (x - x1) + * ( + x0 * x1 * (x1 - 3 * x2) + + x**2 * (-2 * x0 + x1 + x2) + - x2 * (x1**2 - 4 * x1 * x2 + x2**2) + + x * (-(x2 * (3 * x1 + x2)) + x0 * (x1 + 3 * x2)) + ) + ) + / ((x0 - x2) * (-x1 + x2) ** 3) + ) # proportion of y3 - values.append(((x - x1)**2 * (x - x2)) / ((x1 - x2)**2 * (x3 - x1))) + values.append(((x - x1) ** 2 * (x - x2)) / ((x1 - x2) ** 2 * (x3 - x1))) return values def _new_element_block_id(self): @@ -513,10 +708,10 @@ def _new_element_field_name(self, quantity=1): id_ = 1 names = [] for _ in range(quantity): - name = 'temp%d' % id_ + name = "temp%d" % id_ while name in self.get_element_field_names(): id_ += 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ names.append(name) id_ += 1 if quantity == 1: @@ -526,28 +721,28 @@ def _new_element_field_name(self, quantity=1): def _new_node_field_name(self): """Return a node field name which is not used in the model.""" id_ = 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ while name in self.get_node_field_names(): id_ += 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ return name def _new_side_set_field_name(self): """Return a side set field name which is not used in the model.""" id_ = 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ while name in self.get_side_set_field_names(): id_ += 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ return name def _new_node_set_field_name(self): """Return a node set field name which is not used in the model.""" id_ = 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ while name in self.get_node_set_field_names(): id_ += 1 - name = 'temp%d' % id_ + name = "temp%d" % id_ return name def _delete_elements(self, element_block_id, element_indices): @@ -563,7 +758,8 @@ def _delete_elements(self, element_block_id, element_indices): """ # validate input [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) self._input_check(element_indices, [list, 0, int]) # get element block information element_count = self.get_element_count(element_block_id) @@ -574,11 +770,11 @@ def _delete_elements(self, element_block_id, element_indices): max_element_index = max(element_indices) if max_element_index >= element_count: self._error( - 'Invalid element indices', - 'The element index list contains invalid entries. ' - 'There are only %d elements in this element block and ' - 'the list contains a reference to index %d.' % - (max_element_index)) + "Invalid element indices", + "The element index list contains invalid entries. " + "There are only %d elements in this element block and " + "the list contains a reference to index %d." % (max_element_index), + ) # select valid elements indices_to_delete = set() invalid_indices = [] @@ -594,19 +790,20 @@ def _delete_elements(self, element_block_id, element_indices): # warn about duplicate indices if duplicate_indices: self._warning( - 'Duplicate element indices', - 'The element index list contains duplicate ' - 'indices. Elements can only be deleted once so ' - 'duplicates will be ignored. There were %d ' - 'duplicates.' % (len(duplicate_indices))) + "Duplicate element indices", + "The element index list contains duplicate " + "indices. Elements can only be deleted once so " + "duplicates will be ignored. There were %d " + "duplicates." % (len(duplicate_indices)), + ) del duplicate_indices # error if invalid indices encountered if invalid_indices: self._error( - 'Invalid element indices', - 'The element index list contains invalid entries. ' - 'There were a total of %d invalid indices.' % - len(invalid_indices)) + "Invalid element indices", + "The element index list contains invalid entries. " + "There were a total of %d invalid indices." % len(invalid_indices), + ) del invalid_indices # create list of nodes used by elements to delete nodes_per_element = self.get_nodes_per_element(element_block_id) @@ -614,16 +811,20 @@ def _delete_elements(self, element_block_id, element_indices): used_nodes = [] for element_index in indices_to_delete: used_nodes.extend( - connectivity[element_index * - nodes_per_element:(element_index + 1) * - nodes_per_element]) + connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] + ) used_nodes = set(used_nodes) # remove references to these elements within each side set for id_ in self.get_side_set_ids(): # look for members to delete members = self.get_side_set_members(id_) members_to_delete = [ - x for x in members + x + for x in members if (x[0] == element_block_id and x[1] in indices_to_delete) ] # delete those members (if any exist) @@ -631,8 +832,7 @@ def _delete_elements(self, element_block_id, element_indices): self._delete_side_set_members(id_, members_to_delete) # create translation list element_count = self.get_element_count(element_block_id) - remaining_indices = sorted( - set(range(element_count)) - set(indices_to_delete)) + remaining_indices = sorted(set(range(element_count)) - set(indices_to_delete)) # create element map # old element i is new element new_index[i] new_index = [False] * element_count @@ -642,15 +842,19 @@ def _delete_elements(self, element_block_id, element_indices): del indices_to_delete fields = self._get_element_block_fields(element_block_id) for this_field in list(fields.values()): - this_field[:] = [[values[x] for x in remaining_indices] - for values in this_field] + this_field[:] = [ + [values[x] for x in remaining_indices] for values in this_field + ] # delete elements from the block new_connectivity = [] for element_index in remaining_indices: new_connectivity.extend( - connectivity[element_index * - nodes_per_element:(element_index + 1) * - nodes_per_element]) + connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] + ) # set the new connectivity self.get_connectivity(element_block_id)[:] = new_connectivity # set the number of elements @@ -661,8 +865,7 @@ def _delete_elements(self, element_block_id, element_indices): new_members = [] for member in members: if member[0] == element_block_id: - new_members.append( - (member[0], new_index[member[1]], member[2])) + new_members.append((member[0], new_index[member[1]], member[2])) else: new_members.append(member) members[:] = new_members @@ -674,11 +877,13 @@ def _delete_elements(self, element_block_id, element_indices): # delete those nodes self._delete_nodes(nodes_to_delete) - def threshold_element_blocks(self, - expression, - element_block_ids='all', - timestep='last', - new_element_block_id=None): + def threshold_element_blocks( + self, + expression, + element_block_ids="all", + timestep="last", + new_element_block_id=None, + ): """ Delete elements which do not satisfy a condition. @@ -692,51 +897,50 @@ def threshold_element_blocks(self, >>> model.threshold_element_block('all', 'eqps >= 0.01') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + element_block_ids = self._format_element_block_id_list(element_block_ids) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) if new_element_block_id is not None: if self.element_block_exists(new_element_block_id): - self._exists_error(new_element_block_id, 'element block') + self._exists_error(new_element_block_id, "element block") # create a temporary field name on these elements name = self._new_element_field_name() # evaluate the expression - self.calculate_element_field('%s = %s' % (name, expression), - element_block_ids=element_block_ids) + self.calculate_element_field( + "%s = %s" % (name, expression), element_block_ids=element_block_ids + ) # go through each element block and delete elements for id_ in element_block_ids: - values = self.get_element_field_values(name, - element_block_id=id_, - timestep=timestep) + values = self.get_element_field_values( + name, element_block_id=id_, timestep=timestep + ) # if we're saving elements, duplicate the block, and delete the # ones we're keeping if new_element_block_id is not None: indices_to_keep = [i for i, x in enumerate(values) if x] temporary_element_block_id = self._new_element_block_id() - self.duplicate_element_block(id_, - temporary_element_block_id, - duplicate_nodes=False) - self._delete_elements(temporary_element_block_id, - indices_to_keep) + self.duplicate_element_block( + id_, temporary_element_block_id, duplicate_nodes=False + ) + self._delete_elements(temporary_element_block_id, indices_to_keep) if temporary_element_block_id != new_element_block_id: if self.element_block_exists(new_element_block_id): self.combine_element_blocks( [temporary_element_block_id, new_element_block_id], - new_element_block_id) + new_element_block_id, + ) else: - self.rename_element_block(temporary_element_block_id, - new_element_block_id) + self.rename_element_block( + temporary_element_block_id, new_element_block_id + ) # delete elements which don't meet the threshold indices_to_delete = [i for i, x in enumerate(values) if not x] self._delete_elements(id_, indices_to_delete) # delete the temporary element field self.delete_element_field(name, element_block_ids=element_block_ids) if new_element_block_id is not None: - self.delete_element_field(name, - element_block_ids=new_element_block_id) + self.delete_element_field(name, element_block_ids=new_element_block_id) def _get_list_ids(self, thing): """ @@ -778,8 +982,7 @@ def _verify(self, allow_aliased_lists=True): for values in all_values: self._assert(len(values) == node_count) # verify self.element_blocks - for _, info, connectivity, fields in list( - self.element_blocks.values()): + for _, info, connectivity, fields in list(self.element_blocks.values()): self._assert(len(info) == 4) self._assert(len(connectivity) == info[1] * info[2]) if connectivity: @@ -802,7 +1005,8 @@ def _verify(self, allow_aliased_lists=True): # verify self.side_sets element_count = dict( (id_, info[1]) - for id_, (_, info, _, _) in list(self.element_blocks.items())) + for id_, (_, info, _, _) in list(self.element_blocks.items()) + ) for _, members, fields in list(self.side_sets.values()): member_count = len(members) if members: @@ -832,26 +1036,26 @@ def _verify(self, allow_aliased_lists=True): # get the code line the assertion failed on _, _, trace = sys.exc_info() error_line = traceback.extract_tb(trace)[0][3] - if error_line.startswith('self._assert('): + if error_line.startswith("self._assert("): error_line = error_line[13:-1] error_line_number = traceback.extract_tb(trace)[0][1] # write out the error/warning message self._error( - 'Corrupted database information.', - 'The finite element model information failed a validity ' - 'check. The following assertion failed:\n' - '\n' - '[%d] %s\n' - '\n' - 'This resulted from one of the two scenarios:\n' - '* You changed information in the database ' - 'inconsistently.\n' - '* There is a bug within the code.\n' - '\n' - 'If you believe it is the latter, please contact support ' - 'with as much information as necessary.\n' - '* Support contact: %s' % - (error_line_number, error_line, CONTACT)) + "Corrupted database information.", + "The finite element model information failed a validity " + "check. The following assertion failed:\n" + "\n" + "[%d] %s\n" + "\n" + "This resulted from one of the two scenarios:\n" + "* You changed information in the database " + "inconsistently.\n" + "* There is a bug within the code.\n" + "\n" + "If you believe it is the latter, please contact support " + "with as much information as necessary.\n" + "* Support contact: %s" % (error_line_number, error_line, CONTACT), + ) exit(1) @staticmethod @@ -880,58 +1084,58 @@ def _print_message(messages, width=79): messages = [messages] for i, message in enumerate(messages): if not isinstance(message, tuple): - messages[i] = ('', message) + messages[i] = ("", message) # store the message width max_header_width = max(len(x[0]) for x in messages) width = max(width, max_header_width + 20 + 6) # print the top frame after a blank line - print('') - print(('*' * width)) - print(('*' + (' ' * (width - 2)) + '*')) + print("") + print(("*" * width)) + print(("*" + (" " * (width - 2)) + "*")) # process each message # * Header: Text * for message in messages: header = message[0] # format text into broken lines - text = '' - for line in message[1].split('\n'): + text = "" + for line in message[1].split("\n"): text += textwrap.fill(line, width=width - 6 - len(header)) - text += '\n' + text += "\n" # remove trailing newlines - while text and text[-1] == '\n': + while text and text[-1] == "\n": text = text[:-1] # break into a list - text = text.split('\n') + text = text.split("\n") # process each line for i, txt in enumerate(text): if i == 0: - line = '%s%s' % (header, txt) + line = "%s%s" % (header, txt) else: - line = '%s%s' % (' ' * len(header), txt) + line = "%s%s" % (" " * len(header), txt) if len(line) < width - 6: - line += ' ' * (width - 6 - len(line)) - print(('* %s *' % (line))) - print(('*' + (' ' * (width - 2)) + '*')) + line += " " * (width - 6 - len(line)) + print(("* %s *" % (line))) + print(("*" + (" " * (width - 2)) + "*")) # print the bottom frame - print(('*' * width)) + print(("*" * width)) @staticmethod def _get_trace(omitted_frames=1): """Return a compressed stack trace.""" - last_file = '' - message = '' + last_file = "" + message = "" for frame in inspect.stack()[omitted_frames:]: - this_file = frame[1].split('/')[-1] + this_file = frame[1].split("/")[-1] if this_file != last_file: - message += this_file + ':' + message += this_file + ":" last_file = this_file else: - message += ' ' * len(last_file) + ' ' - message += frame[3] + ':' + str(frame[2]) - message += '\n' + message += " " * len(last_file) + " " + message += frame[3] + ":" + str(frame[2]) + message += "\n" return message - def _bug(self, short='Possible bug', detailed='', exit_code=1): + def _bug(self, short="Possible bug", detailed="", exit_code=1): """ Print out an error message possibly caused by a bug and exit. @@ -939,34 +1143,38 @@ def _bug(self, short='Possible bug', detailed='', exit_code=1): information. """ - messages = [(' ERROR: ', short)] + messages = [(" ERROR: ", short)] if detailed: - messages.append(('Message: ', detailed)) + messages.append(("Message: ", detailed)) messages.append( - ('Support: ', 'This error may have been caused by a bug in the ' - 'code. If you believe this is the case, please ' - 'contact support and provide enough information ' - 'to duplicate the issue.\n\nSupport contact: %s' % CONTACT)) - messages.append((' Trace: ', self._get_trace())) + ( + "Support: ", + "This error may have been caused by a bug in the " + "code. If you believe this is the case, please " + "contact support and provide enough information " + "to duplicate the issue.\n\nSupport contact: %s" % CONTACT, + ) + ) + messages.append((" Trace: ", self._get_trace())) self._print_message(messages) exit(exit_code) - def _error(self, short='Unspecified error', detailed='', exit_code=1): + def _error(self, short="Unspecified error", detailed="", exit_code=1): """Print out an error message and exit.""" - messages = [(' ERROR: ', short)] + messages = [(" ERROR: ", short)] if detailed: - messages.append(('Message: ', detailed)) - messages.append((' Trace: ', self._get_trace())) + messages.append(("Message: ", detailed)) + messages.append((" Trace: ", self._get_trace())) self._print_message(messages) exit(exit_code) - def _warning(self, short='Unspecified warning', detailed=''): + def _warning(self, short="Unspecified warning", detailed=""): """Print out a warning message, but don't exit.""" - messages = [('WARNING: ', short)] + messages = [("WARNING: ", short)] if detailed: - messages.append(('Message: ', detailed)) + messages.append(("Message: ", detailed)) if EXIT_ON_WARNING: - messages.append((' Trace: ', self._get_trace())) + messages.append((" Trace: ", self._get_trace())) self._print_message(messages) if EXIT_ON_WARNING: exit(1) @@ -980,23 +1188,21 @@ def _get_qa_record(): """ now = datetime.datetime.today() - return ('exomerge', VERSION, now.strftime('%Y/%m/%d'), - now.strftime('%H:%M:%S')) + return ("exomerge", VERSION, now.strftime("%Y/%m/%d"), now.strftime("%H:%M:%S")) - def _ensure_acceptable_id(self, this_id, acceptable_ids, entity=''): + def _ensure_acceptable_id(self, this_id, acceptable_ids, entity=""): """Ensure ID is acceptable, or error out.""" if this_id not in acceptable_ids: if entity == "": self._error("Reference to undefined entity.") else: - id_list = string.join([str(x) + ',' - for x in acceptable_ids])[:-1] + id_list = string.join([str(x) + "," for x in acceptable_ids])[:-1] self._error( "Reference to undefined %s." % (entity), - "A reference to %s \"%s\" was encountered but is " - "not defined. There are %d defined %ss: %s" % - (entity, str(this_id), len(acceptable_ids), entity, - id_list)) + 'A reference to %s "%s" was encountered but is ' + "not defined. There are %d defined %ss: %s" + % (entity, str(this_id), len(acceptable_ids), entity, id_list), + ) @staticmethod def _get_matching_strings(string_pattern, list_of_strings): @@ -1014,8 +1220,8 @@ def _get_matching_strings(string_pattern, list_of_strings): """ # convert pattern to a regex expression - regex_pattern = '^' + string_pattern + '$' - regex_pattern = regex_pattern.replace('.', r'\.').replace('*', '.*') + regex_pattern = "^" + string_pattern + "$" + regex_pattern = regex_pattern.replace(".", r"\.").replace("*", ".*") matches = [x for x in list_of_strings if re.match(regex_pattern, x)] return matches @@ -1031,77 +1237,85 @@ def _plural(name): bunnies """ - if name[-1] == 'y': - return name[:-1] + 'ies' - return name + 's' + if name[-1] == "y": + return name[:-1] + "ies" + return name + "s" def _format_element_block_id_list(self, id_list, *args, **kwargs): """Return a validated list of element block IDs.""" blocks = self.element_blocks - entity = 'element block' + entity = "element block" # get element block translations - tuples = [(value[0], key) for key, value in list(blocks.items()) - if value[0]] + tuples = [(value[0], key) for key, value in list(blocks.items()) if value[0]] # ensure element block names are unique if len(set(x[0] for x in tuples)) != len(tuples): self._warning( - 'Duplicate %s names' % entity, - 'At least two %s have the same name. ' - 'This may cause problems.' % self._plural(entity)) - return self._format_id_list(id_list, - sorted(blocks.keys()), - entity=entity, - *args, - translator=dict(tuples), - **kwargs) + "Duplicate %s names" % entity, + "At least two %s have the same name. " + "This may cause problems." % self._plural(entity), + ) + return self._format_id_list( + id_list, + sorted(blocks.keys()), + entity=entity, + *args, + translator=dict(tuples), + **kwargs + ) def _format_side_set_id_list(self, id_list, *args, **kwargs): """Return a validated list of side set IDs.""" ssets = self.side_sets - entity = 'side set' + entity = "side set" # get element block translations - tuples = [(value[0], key) for key, value in list(ssets.items()) - if value[0]] + tuples = [(value[0], key) for key, value in list(ssets.items()) if value[0]] # ensure element block names are unique if len(set(x[0] for x in tuples)) != len(tuples): self._warning( - 'Duplicate %s names' % entity, - 'At least two %s have the same name. ' - 'This may cause problems.' % self._plural(entity)) - return self._format_id_list(id_list, - sorted(ssets.keys()), - entity=entity, - *args, - translator=dict(tuples), - **kwargs) + "Duplicate %s names" % entity, + "At least two %s have the same name. " + "This may cause problems." % self._plural(entity), + ) + return self._format_id_list( + id_list, + sorted(ssets.keys()), + entity=entity, + *args, + translator=dict(tuples), + **kwargs + ) def _format_node_set_id_list(self, id_list, *args, **kwargs): """Return a validated list of node set IDs.""" nsets = self.node_sets - entity = 'node set' + entity = "node set" # get element block translations - tuples = [(value[0], key) for key, value in list(nsets.items()) - if value[0]] + tuples = [(value[0], key) for key, value in list(nsets.items()) if value[0]] # ensure element block names are unique if len(set(x[0] for x in tuples)) != len(tuples): self._warning( - 'Duplicate %s names' % entity, - 'At least two %s have the same name. ' - 'This may cause problems.' % self._plural(entity)) - return self._format_id_list(id_list, - sorted(nsets.keys()), - entity=entity, - *args, - translator=dict(tuples), - **kwargs) - - def _format_id_list(self, - id_list, - acceptable_ids, - entity='', - single=False, - empty_list_okay=True, - translator={}): + "Duplicate %s names" % entity, + "At least two %s have the same name. " + "This may cause problems." % self._plural(entity), + ) + return self._format_id_list( + id_list, + sorted(nsets.keys()), + entity=entity, + *args, + translator=dict(tuples), + **kwargs + ) + + def _format_id_list( + self, + id_list, + acceptable_ids, + entity="", + single=False, + empty_list_okay=True, + translator={}, + ): """ Return a validated list of IDs. @@ -1119,37 +1333,39 @@ def _format_id_list(self, if not isinstance(id_list, list): id_list = [id_list] for id_ in id_list: - if id_ == 'none': + if id_ == "none": pass - elif id_ == 'all': + elif id_ == "all": new_id_list.extend(acceptable_ids) - elif id_ == 'first': + elif id_ == "first": if not acceptable_ids: self._error( - 'Empty entity list.', + "Empty entity list.", 'The "first" identifier was used to refer to a %s ' - 'but no %ss exist.' % (entity, entity)) + "but no %ss exist." % (entity, entity), + ) new_id_list.append(acceptable_ids[0]) - elif id_ == 'last': + elif id_ == "last": if not acceptable_ids: self._error( - 'Empty entity list.', + "Empty entity list.", 'The "last" identifier was used to refer to a %s ' - 'but no %ss exist.' % (entity, entity)) + "but no %ss exist." % (entity, entity), + ) new_id_list.append(acceptable_ids[-1]) - elif id_ == 'auto': + elif id_ == "auto": if len(acceptable_ids) != 1: self._error( - 'Ambiguous reference.', + "Ambiguous reference.", 'The "auto" identifier was used to refer to a %s ' - 'but exactly one %s does not exist. There are %d ' - 'defined %ss.' % - (entity, entity, len(acceptable_ids), entity)) + "but exactly one %s does not exist. There are %d " + "defined %ss." % (entity, entity, len(acceptable_ids), entity), + ) new_id_list.append(acceptable_ids[0]) - elif id_ == 'last_if_any': + elif id_ == "last_if_any": if acceptable_ids: new_id_list.append(acceptable_ids[-1]) - elif id_ == 'first_if_any': + elif id_ == "first_if_any": if acceptable_ids: new_id_list.append(acceptable_ids[-1]) else: @@ -1157,18 +1373,16 @@ def _format_id_list(self, id_list = new_id_list # now apply the translation list if translator: - id_list = [ - translator[x] if x in translator else x for x in id_list - ] + id_list = [translator[x] if x in translator else x for x in id_list] # for ids with a wildcard, find all that match if id_list and isinstance(id_list[0], str): for i in reversed(range(len(id_list))): this_id = id_list[i] - if '*' in this_id: + if "*" in this_id: del id_list[i] for new_id in reversed( - self._get_matching_strings(this_id, - acceptable_ids)): + self._get_matching_strings(this_id, acceptable_ids) + ): id_list.insert(i, new_id) # do not allow duplicates # and ensure all given ids are valid @@ -1180,37 +1394,49 @@ def _format_id_list(self, if id_ in acceptable_ids: unique_ids.append(id_) else: - id_list = ', '.join([str(x) for x in acceptable_ids]) + id_list = ", ".join([str(x) for x in acceptable_ids]) self._warning( - 'Reference to undefined %s.' % (entity), - 'A reference to %s \"%s\" was encountered but is ' - 'not defined. This %s will not be included in the ' - 'operation.\n\nThere are %d defined %s: %s' % - (entity, id_, entity, len(acceptable_ids), - self._plural(entity), id_list)) + "Reference to undefined %s." % (entity), + 'A reference to %s "%s" was encountered but is ' + "not defined. This %s will not be included in the " + "operation.\n\nThere are %d defined %s: %s" + % ( + entity, + id_, + entity, + len(acceptable_ids), + self._plural(entity), + id_list, + ), + ) # return the unique list id_list = unique_ids # if only a single item was requested, ensure it exists if single and len(id_list) != 1: if not id_list: self._error( - 'No %s specified.' % entity, - 'A single %s is required but none ' - 'were specified.' % entity) + "No %s specified." % entity, + "A single %s is required but none " "were specified." % entity, + ) self._error( - 'Multiple %ss specified.' % entity, - 'A single %s is required but %d %ss were specified: %s' % - (entity, len(id_list), entity, ', '.join( - [str(x) for x in id_list]))) + "Multiple %ss specified." % entity, + "A single %s is required but %d %ss were specified: %s" + % (entity, len(id_list), entity, ", ".join([str(x) for x in id_list])), + ) # if list is empty and that's a problem, error out if not empty_list_okay and not id_list: self._error( - 'No %ss specified.' % entity, - 'We require at least one %s to be specified for this ' - 'opration but none were specified.\n\nThere are %d ' - 'defined %s: %s' % - (entity, len(acceptable_ids), self._plural(entity), ', '.join( - [str(x) for x in acceptable_ids]))) + "No %ss specified." % entity, + "We require at least one %s to be specified for this " + "opration but none were specified.\n\nThere are %d " + "defined %s: %s" + % ( + entity, + len(acceptable_ids), + self._plural(entity), + ", ".join([str(x) for x in acceptable_ids]), + ), + ) return id_list def _get_standard_element_type(self, element_type, warning=True): @@ -1232,43 +1458,44 @@ def _get_standard_element_type(self, element_type, warning=True): """ if isinstance(element_type, bytes): - element_type = element_type.decode('utf8').lower() + element_type = element_type.decode("utf8").lower() else: element_type = element_type.lower() translation_list = { - 'hex': 'hex8', - 'tet': 'tet4', - 'tetra': 'tet4', - 'tetra10': 'tet10', - 'tri': 'tri3', - 'triangle': 'tri3', - 'quad': 'quad4', - 'shell4': 'quad4', - 'wedge': 'wedge6' + "hex": "hex8", + "tet": "tet4", + "tetra": "tet4", + "tetra10": "tet10", + "tri": "tri3", + "triangle": "tri3", + "quad": "quad4", + "shell4": "quad4", + "wedge": "wedge6", } if element_type in translation_list: element_type = translation_list[element_type] if warning and element_type not in self.STANDARD_ELEMENT_TYPES: self._warning( - 'Nonstandard element type', + "Nonstandard element type", 'The element type "%s" is not a standard ' - 'element type. This may cause issues with ' - 'handling element blocks with elements of ' - 'this type.' % (element_type)) + "element type. This may cause issues with " + "handling element blocks with elements of " + "this type." % (element_type), + ) return element_type def _get_default_field_value(self, name): """Return the default value for a field with the given name.""" if self._is_displacement_field_prefix(name[:-2]): return 0.0 - return float('nan') + return float("nan") @staticmethod def _is_displacement_field_prefix(name): """Return 'True' if name is a displacement field prefix.""" - default_name = 'displacement' - if len(name) >= 3 and name.lower() == default_name[:len(name)]: + default_name = "displacement" + if len(name) >= 3 and name.lower() == default_name[: len(name)]: return True return False @@ -1279,10 +1506,10 @@ def _get_displacement_field_prefix(self): If no displacement field exists, this will return the default prefix. """ - prefix = 'disp' + prefix = "disp" for node_field_name in self.get_node_field_names(): # if it doesn't end in "_x", it's not a prefix - if len(node_field_name) < 3 or node_field_name[-2] != '_': + if len(node_field_name) < 3 or node_field_name[-2] != "_": continue # check against acceptable names this_prefix = node_field_name[:-2] @@ -1301,7 +1528,8 @@ def _get_element_faces(self, element_block_ids): """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) + element_block_ids, empty_list_okay=False + ) members = [] for id_ in element_block_ids: mapping = self._get_face_mapping_from_id(id_) @@ -1313,10 +1541,11 @@ def _get_element_faces(self, element_block_ids): def _get_block_info(self, element_block_id): """Return the info of an element block.""" [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) return self.element_blocks[element_block_id][1] - def _get_external_element_faces(self, element_block_ids='all'): + def _get_external_element_faces(self, element_block_ids="all"): """ Return a list of external element faces. @@ -1326,8 +1555,7 @@ def _get_external_element_faces(self, element_block_ids='all'): * '(element_block_id, element_index, face_index)' """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) external_faces = dict() for id_ in element_block_ids: info = self._get_block_info(id_) @@ -1336,19 +1564,16 @@ def _get_external_element_faces(self, element_block_ids='all'): for element_index in range(info[1]): for face_index, (_, face) in enumerate(face_mapping): sorted_nodes = tuple( - sorted([ - connectivity[element_index * info[2] + x] - for x in face - ])) + sorted( + [connectivity[element_index * info[2] + x] for x in face] + ) + ) if sorted_nodes in external_faces: external_faces[sorted_nodes] = None else: this_face = (id_, element_index, face_index) external_faces[sorted_nodes] = this_face - return [ - value for value in list(external_faces.values()) - if value is not None - ] + return [value for value in list(external_faces.values()) if value is not None] @staticmethod def _mean(values): @@ -1371,8 +1596,7 @@ def _order_element_faces_by_block(members): for element_block_id, element_index, face_index in members: if element_block_id not in members_by_block: members_by_block[element_block_id] = [] - members_by_block[element_block_id].append( - (element_index, face_index)) + members_by_block[element_block_id].append((element_index, face_index)) return members_by_block def _get_dimension(self, element_type): @@ -1385,14 +1609,15 @@ def _get_triangulated_faces(self, element_type): element_type = self._get_standard_element_type(element_type) if element_type not in self.TRIANGULATED_FACES: self._bug( - 'Invalid element type.', - 'We do not know how to subdivide an element of type ' - '"%s" into triangles.' % element_type) + "Invalid element type.", + "We do not know how to subdivide an element of type " + '"%s" into triangles.' % element_type, + ) return self.TRIANGULATED_FACES[element_type] - def _convert_side_set_to_triangle_block(self, - side_set_ids, - new_element_block_id='auto'): + def _convert_side_set_to_triangle_block( + self, side_set_ids, new_element_block_id="auto" + ): """ Create a new 'tri3' element block composed of the given side set. @@ -1400,25 +1625,26 @@ def _convert_side_set_to_triangle_block(self, """ side_set_ids = self._format_side_set_id_list(side_set_ids) - if new_element_block_id == 'auto': + if new_element_block_id == "auto": new_element_block_id = self._new_element_block_id() new_nodes = [] # find members of all the given side sets by block members_by_block = self._order_element_faces_by_block( - itertools.chain( - *[self.get_side_set_members(x) for x in side_set_ids])) + itertools.chain(*[self.get_side_set_members(x) for x in side_set_ids]) + ) # ensure all blocks are 3D for id_ in list(members_by_block.keys()): element_type = self._get_element_type(id_) dimension = self._get_dimension(element_type) if dimension != 3: self._error( - 'Incompatible element dimension.', - 'We expect the side set to contain faces of 3D ' - 'elements. However, the side set contains at ' - 'least one face from element block %d which ' - 'contains %dD elements of type "%s".' % - (id_, dimension, element_type)) + "Incompatible element dimension.", + "We expect the side set to contain faces of 3D " + "elements. However, the side set contains at " + "least one face from element block %d which " + 'contains %dD elements of type "%s".' + % (id_, dimension, element_type), + ) # Now we need to create the triangles from each member of the side set. faces = dict() for element_block_id, members in list(members_by_block.items()): @@ -1427,12 +1653,13 @@ def _convert_side_set_to_triangle_block(self, face_mapping = self._get_face_mapping_from_id(element_block_id) for element_index, face_index in members: face_element_map = face_mapping[face_index] - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] local_node = tuple(local_node[x] for x in face_element_map[1]) - if not face_element_map[0] in faces: + if face_element_map[0] not in faces: faces[face_element_map[0]] = [local_node] else: faces[face_element_map[0]].append(local_node) @@ -1448,8 +1675,7 @@ def _convert_side_set_to_triangle_block(self, if isinstance(index, int): connectivity.append(local_face_indices[index]) continue - averaged_nodes = tuple(local_face_indices[x] - for x in index) + averaged_nodes = tuple(local_face_indices[x] for x in index) if not new_nodes or new_nodes[-1] != averaged_nodes: new_nodes.append(averaged_nodes) next_node_index += 1 @@ -1457,9 +1683,9 @@ def _convert_side_set_to_triangle_block(self, # create the new nodes self._create_averaged_nodes(new_nodes, []) # create the new element block - self.create_element_block(new_element_block_id, - ['tri3', len(connectivity) // 3, 3, 0], - connectivity) + self.create_element_block( + new_element_block_id, ["tri3", len(connectivity) // 3, 3, 0], connectivity + ) @staticmethod def _sign(x): @@ -1475,10 +1701,14 @@ def _sign(x): return -1 return 0 - def _partition_triangle_block_from_node_field(self, element_block_id, - new_element_block_id, - node_field_name, timestep, - interval_list): + def _partition_triangle_block_from_node_field( + self, + element_block_id, + new_element_block_id, + node_field_name, + timestep, + interval_list, + ): """ Subdivide a 'tri3' element block based on the given field intervals. @@ -1489,29 +1719,28 @@ def _partition_triangle_block_from_node_field(self, element_block_id, """ [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) - [node_field_name] = self._format_id_list([node_field_name], - self.get_node_field_names(), - 'node field', - single=True) - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + [element_block_id], single=True + ) + [node_field_name] = self._format_id_list( + [node_field_name], self.get_node_field_names(), "node field", single=True + ) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) # verify block is actually a tri3 block - if self._get_element_type(element_block_id) != 'tri3': + if self._get_element_type(element_block_id) != "tri3": self._error( - 'Invalid element type', - 'This function can only be used to divide element ' - 'blocks composed of "tri3" elements.') + "Invalid element type", + "This function can only be used to divide element " + 'blocks composed of "tri3" elements.', + ) timestep_index = self.timesteps.index(timestep) connectivity = self.get_connectivity(element_block_id) element_count = self.get_element_count(element_block_id) new_connectivity = [] element_interval_values = [] triangles = [ - tuple(connectivity[x * 3:(x + 1) * 3]) - for x in range(element_count) + tuple(connectivity[x * 3: (x + 1) * 3]) for x in range(element_count) ] for index, upper_bound in enumerate(interval_list): # hold new vertices we have to create @@ -1526,15 +1755,19 @@ def _partition_triangle_block_from_node_field(self, element_block_id, for d in range(3): d2 = (d + 1) % 3 edge = (tri[d], tri[d2]) - if (self._sign(values[tri[d]] - upper_bound) * - self._sign(values[tri[d2]] - upper_bound) == -1): + if ( + self._sign(values[tri[d]] - upper_bound) + * self._sign(values[tri[d2]] - upper_bound) + == -1 + ): if edge not in new_vertex: opposite_edge = tuple(reversed(edge)) new_vertex[edge] = next_node_index new_vertex[opposite_edge] = next_node_index next_node_index += 1 phi = (upper_bound - values[tri[d]]) / ( - values[tri[d2]] - values[tri[d]]) + values[tri[d2]] - values[tri[d]] + ) new_node = ((tri[d], 1.0 - phi), (tri[d2], phi)) new_nodes.append(new_node) self._create_averaged_nodes(new_nodes, []) @@ -1543,24 +1776,30 @@ def _partition_triangle_block_from_node_field(self, element_block_id, this_partition = [] values = self.node_fields[node_field_name][timestep_index] for tri in triangles: - if (values[tri[0]] <= upper_bound - and values[tri[1]] <= upper_bound - and values[tri[2]] <= upper_bound): + if ( + values[tri[0]] <= upper_bound + and values[tri[1]] <= upper_bound + and values[tri[2]] <= upper_bound + ): this_partition.append(tri) - elif (values[tri[0]] >= upper_bound - and values[tri[1]] >= upper_bound - and values[tri[2]] >= upper_bound): + elif ( + values[tri[0]] >= upper_bound + and values[tri[1]] >= upper_bound + and values[tri[2]] >= upper_bound + ): new_triangles.append(tri) else: # find vertex below the bound d = 0 - while (values[tri[d]] >= upper_bound - or values[tri[(d + 1) % 3]] < upper_bound): + while ( + values[tri[d]] >= upper_bound + or values[tri[(d + 1) % 3]] < upper_bound + ): d += 1 tri = tuple(tri[(d + x) % 3] for x in range(3)) case = tuple( - self._sign(values[tri[x]] - upper_bound) - for x in range(3)) + self._sign(values[tri[x]] - upper_bound) for x in range(3) + ) if case == (-1, 1, -1): m1 = new_vertex[(tri[0], tri[1])] m2 = new_vertex[(tri[1], tri[2])] @@ -1590,21 +1829,21 @@ def _partition_triangle_block_from_node_field(self, element_block_id, # above triangles new_triangles.append((m1, tri[1], tri[2])) else: - self._bug('Unknown case') + self._bug("Unknown case") triangles = new_triangles new_connectivity.extend(itertools.chain(*this_partition)) - element_interval_values.extend([float(index)] * - len(this_partition)) + element_interval_values.extend([float(index)] * len(this_partition)) # add rest of triangle to last partition new_connectivity.extend(itertools.chain(*triangles)) - element_interval_values.extend([float(len(interval_list))] * - len(triangles)) + element_interval_values.extend([float(len(interval_list))] * len(triangles)) self.create_element_block( new_element_block_id, - ['tri3', len(new_connectivity) // 3, 3, 0], new_connectivity) - self.create_element_field('interval', new_element_block_id, 0.0) + ["tri3", len(new_connectivity) // 3, 3, 0], + new_connectivity, + ) + self.create_element_field("interval", new_element_block_id, 0.0) fields = self._get_element_block_fields(new_element_block_id) - field = fields['interval'] + field = fields["interval"] for index in range(len(self.timesteps)): field[index] = list(element_interval_values) @@ -1615,33 +1854,36 @@ def _get_coordinates_at_time(self, timestep): This includes the displacement if it exists. """ - timestep = self._format_id_list(timestep, self.get_timesteps(), - 'timestep') + timestep = self._format_id_list(timestep, self.get_timesteps(), "timestep") if len(timestep) > 1: self._error( - 'Ambiguous timestep.', - 'More than one timestep was specified. We expected ' - 'one or zero timesteps.') + "Ambiguous timestep.", + "More than one timestep was specified. We expected " + "one or zero timesteps.", + ) if not timestep: return [tuple(x) for x in self.nodes] timestep_index = self.timesteps.index(timestep[0]) displacement_values = [ x[timestep_index] for x in self._get_displacement_field_values() ] - return [(x + dx, y + dy, z + dz) - for (x, y, - z), dx, dy, dz in zip(self.nodes, *displacement_values)] - - def export_wrl_model(self, - filename, - node_field_name, - element_block_ids='all', - timestep='last', - field_range='auto', - intervals=9, - colorspace='rgb', - displacement_timestep='auto', - export_exodus_copy=True): + return [ + (x + dx, y + dy, z + dz) + for (x, y, z), dx, dy, dz in zip(self.nodes, *displacement_values) + ] + + def export_wrl_model( + self, + filename, + node_field_name, + element_block_ids="all", + timestep="last", + field_range="auto", + intervals=9, + colorspace="rgb", + displacement_timestep="auto", + export_exodus_copy=True, + ): """ Export the exterior of the model to a colored WRL file. @@ -1651,31 +1893,25 @@ def export_wrl_model(self, >>> model.export_wrl_model('colored_eqps_model.wrl', 'eqps') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - [node_field_name] = self._format_id_list([node_field_name], - self.get_node_field_names(), - 'node field', - single=True) - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + element_block_ids = self._format_element_block_id_list(element_block_ids) + [node_field_name] = self._format_id_list( + [node_field_name], self.get_node_field_names(), "node field", single=True + ) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) timestep_index = self.timesteps.index(timestep) - if displacement_timestep == 'auto': + if displacement_timestep == "auto": if self.displacement_field_exists(): displacement_timestep = timestep else: - displacement_timestep = 'none' + displacement_timestep = "none" else: [displacement_timestep] = self._format_id_list( - [displacement_timestep], - self.get_timesteps(), - 'timestep', - single=True) + [displacement_timestep], self.get_timesteps(), "timestep", single=True + ) # all element blocks should either be 3D elements, or 'tri3' elements - element_types = set( - self._get_element_type(x) for x in element_block_ids) + element_types = set(self._get_element_type(x) for x in element_block_ids) element_dimensions = set(self._get_dimension(x) for x in element_types) # if we have all 3D elements, create a skin if element_dimensions == set([3]): @@ -1683,49 +1919,50 @@ def export_wrl_model(self, external_side_set_id = self._new_side_set_id() self.create_side_set( external_side_set_id, - self._get_external_element_faces(element_block_ids)) + self._get_external_element_faces(element_block_ids), + ) self._convert_side_set_to_triangle_block( - external_side_set_id, triangle_element_block_id) + external_side_set_id, triangle_element_block_id + ) self.delete_side_set(external_side_set_id) - elif element_dimensions == set([2]) and element_types == set(['tri3']): + elif element_dimensions == set([2]) and element_types == set(["tri3"]): # merge all blocks into another block ids_to_merge = [] for id_ in element_block_ids: ids_to_merge.append(self._new_element_block_id()) self.duplicate_element_block(id_, ids_to_merge[-1]) triangle_element_block_id = self._new_element_block_id() - self.combine_element_blocks(ids_to_merge, - triangle_element_block_id) + self.combine_element_blocks(ids_to_merge, triangle_element_block_id) # these blocks better form a watertight enclosure - external_sides = self._get_external_element_faces( - triangle_element_block_id) + external_sides = self._get_external_element_faces(triangle_element_block_id) if external_sides: self._warning( - 'Enclosure is not watertight.', + "Enclosure is not watertight.", 'The "tri3" element blocks passed to this function do not ' - 'form a watertight enclosure. An output file will still ' - 'be created, but it is unlikely to be useful as a WRL ' - 'model. We found %d unmatched sides.' % - len(external_sides)) + "form a watertight enclosure. An output file will still " + "be created, but it is unlikely to be useful as a WRL " + "model. We found %d unmatched sides." % len(external_sides), + ) else: self._error( - 'Invalid input.', - 'We expect a list of 3D element blocks or a list of ' - '2D element blocks composed of triangles.') + "Invalid input.", + "We expect a list of 3D element blocks or a list of " + "2D element blocks composed of triangles.", + ) # now that we have a triangle block, subdivide it subdivided_element_block_id = self._new_element_block_id() # set up intervals - if field_range == 'auto': - indices = self.get_nodes_in_element_block( - triangle_element_block_id) + if field_range == "auto": + indices = self.get_nodes_in_element_block(triangle_element_block_id) values = self.node_fields[node_field_name][timestep_index] this_values = [values[x] for x in indices] field_range = [min(this_values), max(this_values)] if field_range[0] >= field_range[1]: self._error( - 'Invalid field range.', - 'The given field range [%g - %g] was not valid.' % - (field_range[0], field_range[1])) + "Invalid field range.", + "The given field range [%g - %g] was not valid." + % (field_range[0], field_range[1]), + ) if isinstance(intervals, int): intervals = [ (1 - phi) * field_range[0] + phi * field_range[1] @@ -1733,87 +1970,95 @@ def export_wrl_model(self, ] # partition that block based on the node field self._partition_triangle_block_from_node_field( - triangle_element_block_id, subdivided_element_block_id, - node_field_name, timestep, intervals) + triangle_element_block_id, + subdivided_element_block_id, + node_field_name, + timestep, + intervals, + ) # save model as an ExodusII file so we can view it if export_exodus_copy: temp_nodes = self.nodes self.nodes = self._get_coordinates_at_time(displacement_timestep) - exodus_filename = filename.rsplit('.', 1)[0] + '_wrl.e' - self.export_model(exodus_filename, - element_block_ids=subdivided_element_block_id, - element_field_names='interval', - node_field_names='none', - node_set_ids='none', - side_set_ids='none', - global_variable_names='none', - timesteps=[timestep]) + exodus_filename = filename.rsplit(".", 1)[0] + "_wrl.e" + self.export_model( + exodus_filename, + element_block_ids=subdivided_element_block_id, + element_field_names="interval", + node_field_names="none", + node_set_ids="none", + side_set_ids="none", + global_variable_names="none", + timesteps=[timestep], + ) self.nodes = temp_nodes # save triangles to the WRL file - with open(filename, 'w') as output: - output.write('#VRML V2.0 utf8\n') - output.write('Transform {\n') - output.write(' translation 0.0 0.0 0.0\n') - output.write(' children Shape {\n') - output.write(' appearance Appearance {material Material {} }\n') - output.write(' geometry IndexedFaceSet {\n') - output.write(' coord Coordinate {\n') - output.write(' point [\n') - for position in self._get_coordinates_at_time( - displacement_timestep): - output.write(','.join(str(x) for x in position)) - output.write(',') - output.write('\n ]\n') - output.write(' }\n') - output.write(' coordIndex [\n') + with open(filename, "w") as output: + output.write("#VRML V2.0 utf8\n") + output.write("Transform {\n") + output.write(" translation 0.0 0.0 0.0\n") + output.write(" children Shape {\n") + output.write(" appearance Appearance {material Material {} }\n") + output.write(" geometry IndexedFaceSet {\n") + output.write(" coord Coordinate {\n") + output.write(" point [\n") + for position in self._get_coordinates_at_time(displacement_timestep): + output.write(",".join(str(x) for x in position)) + output.write(",") + output.write("\n ]\n") + output.write(" }\n") + output.write(" coordIndex [\n") connectivity = self.get_connectivity(subdivided_element_block_id) element_count = self.get_element_count(subdivided_element_block_id) for element_index in range(element_count): - output.write('%d,%d,%d,-1,' % - (connectivity[element_index * 3 + 0], - connectivity[element_index * 3 + 1], - connectivity[element_index * 3 + 2])) - output.write('\n ]\n') - output.write(' color Color {\n') - output.write(' color [\n') - if colorspace == 'rgb': + output.write( + "%d,%d,%d,-1," + % ( + connectivity[element_index * 3 + 0], + connectivity[element_index * 3 + 1], + connectivity[element_index * 3 + 2], + ) + ) + output.write("\n ]\n") + output.write(" color Color {\n") + output.write(" color [\n") + if colorspace == "rgb": colorspace = [ - colorsys.hls_to_rgb(2.0 / 3 - 2.0 / 3 * x / len(intervals), - 0.5, 1) + colorsys.hls_to_rgb(2.0 / 3 - 2.0 / 3 * x / len(intervals), 0.5, 1) for x in range(len(intervals) + 1) ] if len(colorspace) != len(intervals) + 1: self._error( - 'Unrecognized colorspace.', - 'The given colorspace was not recognized. We ' + "Unrecognized colorspace.", + "The given colorspace was not recognized. We " 'expected a string such as "rgb" or a list of ' - 'length %d with RGB triplets. Instead, we found ' - '"%s".' % (len(intervals) + 1, str(colorspace))) + "length %d with RGB triplets. Instead, we found " + '"%s".' % (len(intervals) + 1, str(colorspace)), + ) for color in colorspace: - output.write(' %s,\n' % - ' '.join(str(x) for x in color)) - output.write(' ]\n') - output.write(' }\n') - output.write(' colorIndex [\n') - output.write(' ') + output.write(" %s,\n" % " ".join(str(x) for x in color)) + output.write(" ]\n") + output.write(" }\n") + output.write(" colorIndex [\n") + output.write(" ") values = self.get_element_field_values( - 'interval', subdivided_element_block_id, - self.timesteps[timestep_index]) - output.write(','.join(str(int(x)) for x in values)) - output.write('\n') - output.write(' ]\n') - output.write(' colorPerVertex FALSE\n') - output.write(' }\n') - output.write(' }\n') - output.write('}\n') + "interval", subdivided_element_block_id, self.timesteps[timestep_index] + ) + output.write(",".join(str(int(x)) for x in values)) + output.write("\n") + output.write(" ]\n") + output.write(" colorPerVertex FALSE\n") + output.write(" }\n") + output.write(" }\n") + output.write("}\n") # delete the temporary element blocks self.delete_element_block( - [triangle_element_block_id, subdivided_element_block_id]) + [triangle_element_block_id, subdivided_element_block_id] + ) - def export_stl_file(self, - filename, - element_block_ids='all', - displacement_timestep='auto'): + def export_stl_file( + self, filename, element_block_ids="all", displacement_timestep="auto" + ): """ Export the exterior of the model to an STL file. @@ -1824,47 +2069,46 @@ def export_stl_file(self, >>> model.export_stl_file('mesh_surface.stl') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - if displacement_timestep == 'auto': + element_block_ids = self._format_element_block_id_list(element_block_ids) + if displacement_timestep == "auto": if self.timesteps and self.displacement_field_exists(): - displacement_timestep = 'last' + displacement_timestep = "last" else: - displacement_timestep = 'none' + displacement_timestep = "none" # create a new element block composed of triangles triangle_element_block_id = self._new_element_block_id() external_side_set_id = self._new_side_set_id() self.create_side_set( - external_side_set_id, - self._get_external_element_faces(element_block_ids)) - self._convert_side_set_to_triangle_block(external_side_set_id, - triangle_element_block_id) + external_side_set_id, self._get_external_element_faces(element_block_ids) + ) + self._convert_side_set_to_triangle_block( + external_side_set_id, triangle_element_block_id + ) # export that set - displacement_timestep = self._format_id_list(displacement_timestep, - self.get_timesteps(), - 'timestep') + displacement_timestep = self._format_id_list( + displacement_timestep, self.get_timesteps(), "timestep" + ) # get coordinates at the time we care about c = self._get_coordinates_at_time(displacement_timestep) # create the STL file connectivity = self.get_connectivity(triangle_element_block_id) - with open(filename, 'wb') as output: - output.write(b' ' * 80) - output.write(struct.pack(' 0.0: normal = tuple(x / scale for x in normal) - output.write(struct.pack('<3f', *normal)) + output.write(struct.pack("<3f", *normal)) for vertex in tri: - output.write(struct.pack('<3f', *c[vertex])) - output.write(struct.pack('>> model.calculate_global_variable('total = potential + kinetic') """ - if '=' not in expression: + if "=" not in expression: self._error( - 'Invalid expression', + "Invalid expression", 'A "=" sign must be present in the expression but ' - 'was not found.\n\nExpression: %s' % expression) - (name, expression) = expression.split('=', 1) + "was not found.\n\nExpression: %s" % expression, + ) + (name, expression) = expression.split("=", 1) new_name = name.strip() self.create_global_variable(new_name) # create list of variable names and modify them in the expression - variable_names = set(['time']) + variable_names = set(["time"]) variable_names.update(self.get_global_variable_names()) - eval_expression = self._transform_eval_expression( - expression, variable_names) - function = eval('lambda var: ' + eval_expression) + eval_expression = self._transform_eval_expression(expression, variable_names) + function = eval("lambda var: " + eval_expression) var = dict() try: for index, time in enumerate(self.timesteps): - var['time'] = time + var["time"] = time for name, values in list(self.global_variables.items()): var[name] = values[index] value = float(function(var)) self.global_variables[new_name][index] = value except (SyntaxError, NameError): self._error_evaluating_expression( - "%s = %s" % (new_name, eval_expression), var) + "%s = %s" % (new_name, eval_expression), var + ) def calculate_node_field(self, expression): """ @@ -2274,37 +2545,37 @@ def calculate_node_field(self, expression): >>> model.calculate_node_field('temp_C = temp_K - 273.15') """ - if '=' not in expression: + if "=" not in expression: self._error( - 'Invalid expression', + "Invalid expression", 'A "=" sign must be present in the expression but ' - 'was not found.\n\nExpression: %s' % expression) - (name, expression) = expression.split('=', 1) + "was not found.\n\nExpression: %s" % expression, + ) + (name, expression) = expression.split("=", 1) new_name = name.strip() self.create_node_field(new_name) new_values = self.node_fields[new_name] # create list of variable names and modify them in the expression - variable_names = set(['time']) - variable_names.update(['X', 'Y', 'Z']) + variable_names = set(["time"]) + variable_names.update(["X", "Y", "Z"]) variable_names.update(self.get_global_variable_names()) variable_names.update(self.get_node_field_names()) - eval_expression = self._transform_eval_expression( - expression, variable_names) + eval_expression = self._transform_eval_expression(expression, variable_names) var = dict() - function = eval('lambda var: ' + eval_expression) + function = eval("lambda var: " + eval_expression) try: for time_index, time in enumerate(self.timesteps): # set time - var['time'] = time + var["time"] = time # set global variables for name, values in list(self.global_variables.items()): var[name] = values[time_index] # go through each node for node_index in range(len(self.nodes)): # set coordinate values - var['X'] = self.nodes[node_index][0] - var['Y'] = self.nodes[node_index][1] - var['Z'] = self.nodes[node_index][2] + var["X"] = self.nodes[node_index][0] + var["Y"] = self.nodes[node_index][1] + var["Z"] = self.nodes[node_index][2] # set node field values for name, values in list(self.node_fields.items()): var[name] = values[time_index][node_index] @@ -2312,9 +2583,10 @@ def calculate_node_field(self, expression): new_values[time_index][node_index] = value except (SyntaxError, NameError): self._error_evaluating_expression( - "%s = %s" % (new_name, eval_expression), var) + "%s = %s" % (new_name, eval_expression), var + ) - def calculate_node_set_field(self, expression, node_set_ids='all'): + def calculate_node_set_field(self, expression, node_set_ids="all"): """ Store a node set field calculated from the given expression. @@ -2330,12 +2602,13 @@ def calculate_node_set_field(self, expression, node_set_ids='all'): """ node_set_ids = self._format_node_set_id_list(node_set_ids) - if '=' not in expression: + if "=" not in expression: self._error( - 'Invalid expression', + "Invalid expression", 'A "=" sign must be present in the expression but ' - 'was not found.\n\nExpression: %s' % expression) - (name, expression) = expression.split('=', 1) + "was not found.\n\nExpression: %s" % expression, + ) + (name, expression) = expression.split("=", 1) new_name = name.strip() # for each node set for node_set_id in node_set_ids: @@ -2344,28 +2617,29 @@ def calculate_node_set_field(self, expression, node_set_ids='all'): fields = self._get_node_set_fields(node_set_id) new_values = fields[new_name] # create list of variable names and modify them in the expression - variable_names = set(['time']) - variable_names.update(['X', 'Y', 'Z']) + variable_names = set(["time"]) + variable_names.update(["X", "Y", "Z"]) variable_names.update(self.get_global_variable_names()) variable_names.update(self.get_node_field_names()) variable_names.update(list(fields.keys())) eval_expression = self._transform_eval_expression( - expression, variable_names) - function = eval('lambda var: ' + eval_expression) + expression, variable_names + ) + function = eval("lambda var: " + eval_expression) var = dict() try: for time_index, time in enumerate(self.timesteps): # set time - var['time'] = time + var["time"] = time # set global variables for name, values in list(self.global_variables.items()): var[name] = values[time_index] # go through each node for member_index, node_index in enumerate(members): # set coordinate values - var['X'] = self.nodes[node_index][0] - var['Y'] = self.nodes[node_index][1] - var['Z'] = self.nodes[node_index][2] + var["X"] = self.nodes[node_index][0] + var["Y"] = self.nodes[node_index][1] + var["Z"] = self.nodes[node_index][2] # set node fields for name, values in list(self.node_fields.items()): var[name] = values[time_index][node_index] @@ -2376,9 +2650,10 @@ def calculate_node_set_field(self, expression, node_set_ids='all'): new_values[time_index][member_index] = value except (SyntaxError, NameError): self._error_evaluating_expression( - "%s = %s" % (new_name, eval_expression), var) + "%s = %s" % (new_name, eval_expression), var + ) - def calculate_side_set_field(self, expression, side_set_ids='all'): + def calculate_side_set_field(self, expression, side_set_ids="all"): """ Store a side set field calculated from the given expression. @@ -2391,12 +2666,13 @@ def calculate_side_set_field(self, expression, side_set_ids='all'): """ side_set_ids = self._format_side_set_id_list(side_set_ids) - if '=' not in expression: + if "=" not in expression: self._error( - 'Invalid expression', + "Invalid expression", 'A "=" sign must be present in the expression but ' - 'was not found.\n\nExpression: %s' % expression) - (name, expression) = expression.split('=', 1) + "was not found.\n\nExpression: %s" % expression, + ) + (name, expression) = expression.split("=", 1) new_name = name.strip() # for each side set for side_set_id in side_set_ids: @@ -2405,17 +2681,18 @@ def calculate_side_set_field(self, expression, side_set_ids='all'): fields = self._get_side_set_fields(side_set_id) new_values = fields[new_name] # create list of variable names and modify them in the expression - variable_names = set(['time']) + variable_names = set(["time"]) variable_names.update(self.get_global_variable_names()) variable_names.update(list(fields.keys())) eval_expression = self._transform_eval_expression( - expression, variable_names) - function = eval('lambda var: ' + eval_expression) + expression, variable_names + ) + function = eval("lambda var: " + eval_expression) var = dict() try: for time_index, time in enumerate(self.timesteps): # set time - var['time'] = time + var["time"] = time # set global variables for name, values in list(self.global_variables.items()): var[name] = values[time_index] @@ -2428,9 +2705,10 @@ def calculate_side_set_field(self, expression, side_set_ids='all'): new_values[time_index][member_index] = value except (SyntaxError, NameError): self._error_evaluating_expression( - "%s = %s" % (new_name, eval_expression), var) + "%s = %s" % (new_name, eval_expression), var + ) - def calculate_element_field(self, expression, element_block_ids='all'): + def calculate_element_field(self, expression, element_block_ids="all"): """ Store an element field calculated from the given expression. @@ -2444,14 +2722,14 @@ def calculate_element_field(self, expression, element_block_ids='all'): ... 'stress_yy + stress_zz) / -3') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - if '=' not in expression: + element_block_ids = self._format_element_block_id_list(element_block_ids) + if "=" not in expression: self._error( - 'Invalid expression', + "Invalid expression", 'A "=" sign must be present in the expression but ' - 'was not found.\n\nExpression: %s' % expression) - (name, expression) = expression.split('=', 1) + "was not found.\n\nExpression: %s" % expression, + ) + (name, expression) = expression.split("=", 1) new_name = name.strip() # for each element block for element_block_id in element_block_ids: @@ -2460,17 +2738,18 @@ def calculate_element_field(self, expression, element_block_ids='all'): element_count = self.get_element_count(element_block_id) new_values = fields[new_name] # create list of variable names and modify them in the expression - variable_names = set(['time']) + variable_names = set(["time"]) variable_names.update(self.get_global_variable_names()) variable_names.update(list(fields.keys())) eval_expression = self._transform_eval_expression( - expression, variable_names) - function = eval('lambda var: ' + eval_expression) + expression, variable_names + ) + function = eval("lambda var: " + eval_expression) var = dict() try: for time_index, time in enumerate(self.timesteps): # set time - var['time'] = time + var["time"] = time # set global variables for name, values in list(self.global_variables.items()): var[name] = values[time_index] @@ -2483,7 +2762,8 @@ def calculate_element_field(self, expression, element_block_ids='all'): new_values[time_index][index] = value except (SyntaxError, NameError): self._error_evaluating_expression( - "%s = %s" % (new_name, eval_expression), var) + "%s = %s" % (new_name, eval_expression), var + ) def to_lowercase(self): """ @@ -2524,44 +2804,50 @@ def _translate_element_blocks(self, element_block_translation_list): """ # validity check the inputs valid_element_block_translation_list = [] - for (id_, new_element_type) in element_block_translation_list: + for id_, new_element_type in element_block_translation_list: # check if element block exists if not self.element_block_exists(id_): - self._missing_warning(id_, 'element block') + self._missing_warning(id_, "element block") continue old_element_type = self._get_standard_element_type( - self._get_element_type(id_)) + self._get_element_type(id_) + ) # check if any schemes exist for this element block if old_element_type not in self.ELEMENT_CONVERSIONS: self._error( - 'No element conversion schemes', - 'There are no element conversion schemes to ' + "No element conversion schemes", + "There are no element conversion schemes to " 'convert elements of type "%s" into any other ' - 'element type.' % (old_element_type)) + "element type." % (old_element_type), + ) continue # check if the given scheme exists for this element block conversions = self.ELEMENT_CONVERSIONS[old_element_type] if new_element_type not in conversions: self._error( - 'Invalid target element type', - 'There are no element conversion schemes to ' + "Invalid target element type", + "There are no element conversion schemes to " 'convert elements of type "%s" into elements of ' 'type "%s". Conversions are available to the ' - 'following element types: "%s".' % - (old_element_type, new_element_type, '", "'.join( - list(conversions.keys())))) + 'following element types: "%s".' + % ( + old_element_type, + new_element_type, + '", "'.join(list(conversions.keys())), + ), + ) continue # all is good, keep this one on the list - valid_element_block_translation_list.append( - [id_, new_element_type]) + valid_element_block_translation_list.append([id_, new_element_type]) # if we have nothing to do, just exit if not valid_element_block_translation_list: return # now we need to find the new nodes to create, if any averaged_nodes = set() - for (id_, new_element_type) in valid_element_block_translation_list: + for id_, new_element_type in valid_element_block_translation_list: old_element_type = self._get_standard_element_type( - self._get_element_type(id_)) + self._get_element_type(id_) + ) scheme = self.ELEMENT_CONVERSIONS[old_element_type] scheme = scheme[new_element_type] # find new nodes which need created @@ -2579,8 +2865,8 @@ def _translate_element_blocks(self, element_block_translation_list): nodes_per_element = self.get_nodes_per_element(id_) # iterate over each element for local_node in [ - connectivity[x:x + nodes_per_element] - for x in range(0, len(connectivity), nodes_per_element) + connectivity[x: x + nodes_per_element] + for x in range(0, len(connectivity), nodes_per_element) ]: # iterate over each new averaged node formula for formula in averaged_node_list: @@ -2588,15 +2874,16 @@ def _translate_element_blocks(self, element_block_translation_list): averaged_nodes.add(node_list) # create the averaged node mapping averaged_nodes = sorted(averaged_nodes) - averaged_node_map = dict((x, len(self.nodes) + index) - for index, x in enumerate(averaged_nodes)) + averaged_node_map = dict( + (x, len(self.nodes) + index) for index, x in enumerate(averaged_nodes) + ) # create new averaged nodes self._create_averaged_nodes(averaged_nodes, []) # now create the new element blocks - for (element_block_id, - new_element_type) in valid_element_block_translation_list: + for element_block_id, new_element_type in valid_element_block_translation_list: old_element_type = self._get_standard_element_type( - self._get_element_type(element_block_id)) + self._get_element_type(element_block_id) + ) scheme = self.ELEMENT_CONVERSIONS[old_element_type] scheme = scheme[new_element_type] # rename some things @@ -2605,37 +2892,42 @@ def _translate_element_blocks(self, element_block_translation_list): # create the connectivity for the new element block new_connectivity = [] for local_node in [ - connectivity[x:x + nodes_per_element] - for x in range(0, len(connectivity), nodes_per_element) + connectivity[x: x + nodes_per_element] + for x in range(0, len(connectivity), nodes_per_element) ]: for new_element in scheme: for new_node in new_element: if isinstance(new_node, int): new_connectivity.append(local_node[new_node]) else: - node_list = tuple( - sorted(local_node[x] for x in new_node)) - new_connectivity.append( - averaged_node_map[node_list]) + node_list = tuple(sorted(local_node[x] for x in new_node)) + new_connectivity.append(averaged_node_map[node_list]) # create a temporary element block temporary_element_block_id = self._new_element_block_id() new_nodes_per_element = self.NODES_PER_ELEMENT[new_element_type] - self.create_element_block(temporary_element_block_id, [ - new_element_type, - len(new_connectivity) // new_nodes_per_element, - new_nodes_per_element, 0 - ], new_connectivity) + self.create_element_block( + temporary_element_block_id, + [ + new_element_type, + len(new_connectivity) // new_nodes_per_element, + new_nodes_per_element, + 0, + ], + new_connectivity, + ) temporary_fields = self._get_element_block_fields( - temporary_element_block_id) + temporary_element_block_id + ) element_multiplier = len(scheme) # transfer element values fields = self._get_element_block_fields(element_block_id) for field_name in self.get_element_field_names(element_block_id): values = fields[field_name] new_values = [list(x) for x in values] - new_values = [[ - x for x in these_values for _ in range(element_multiplier) - ] for these_values in new_values] + new_values = [ + [x for x in these_values for _ in range(element_multiplier)] + for these_values in new_values + ] temporary_fields[field_name] = new_values # for each face in the old scheme, find all of its nodes old_face_mapping = self._get_face_mapping(old_element_type) @@ -2643,8 +2935,7 @@ def _translate_element_blocks(self, element_block_translation_list): new_face_mapping = self._get_face_mapping(new_element_type) face_translation = [[] for _ in range(len(old_face_nodes))] for new_element_index, new_element in enumerate(scheme): - for new_face_index, ( - _, face_members) in enumerate(new_face_mapping): + for new_face_index, (_, face_members) in enumerate(new_face_mapping): # find all nodes used by this new face used_nodes = set() for face_member in face_members: @@ -2653,25 +2944,29 @@ def _translate_element_blocks(self, element_block_translation_list): else: used_nodes.update(new_element[face_member]) # see if these are a subset of nodes in the old set - for (old_face_index, - old_members) in enumerate(old_face_nodes): + for old_face_index, old_members in enumerate(old_face_nodes): if used_nodes <= old_members: face_translation[old_face_index].append( - (new_element_index, new_face_index)) + (new_element_index, new_face_index) + ) # update self.side_sets for id_ in self.get_side_set_ids(): members = self.get_side_set_members(id_) fields = self._get_side_set_fields(id_) old_members = list(members) - for member_index, (block_id, element_index, - face_index) in enumerate(old_members): + for member_index, (block_id, element_index, face_index) in enumerate( + old_members + ): if block_id == element_block_id: # add some new faces for new_faces in face_translation[face_index]: members.append( - (temporary_element_block_id, - element_index * len(scheme) + new_faces[0], - new_faces[1])) + ( + temporary_element_block_id, + element_index * len(scheme) + new_faces[0], + new_faces[1], + ) + ) # add values for the new faces for all_values in list(fields.values()): for values in all_values: @@ -2680,16 +2975,13 @@ def _translate_element_blocks(self, element_block_translation_list): # delete the old block self.delete_element_block(element_block_id) # rename the temporary element block - self.rename_element_block(temporary_element_block_id, - element_block_id) + self.rename_element_block(temporary_element_block_id, element_block_id) def convert_element_blocks(self, element_block_ids, new_element_type): """Convert elements within a block to a new element type.""" - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # form the conversion list - conversion_list = [(id_, new_element_type) - for id_ in element_block_ids] + conversion_list = [(id_, new_element_type) for id_ in element_block_ids] # convert each block self._translate_element_blocks(conversion_list) @@ -2703,21 +2995,20 @@ def _change_element_order(self, element_block_ids, target_order): the fewest nodes. """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # find all element types we need to convert element_types = set() for element_block_id in element_block_ids: element_types.add(self._get_element_type(element_block_id)) element_types = sorted( - self._get_standard_element_type(x) for x in element_types) + self._get_standard_element_type(x) for x in element_types + ) # ignore non-standard element types - element_types = [ - x for x in element_types if x in self.STANDARD_ELEMENT_TYPES - ] + element_types = [x for x in element_types if x in self.STANDARD_ELEMENT_TYPES] # find all elements of the target order target_element_types = [ - x for x in self.STANDARD_ELEMENT_TYPES + x + for x in self.STANDARD_ELEMENT_TYPES if self.ELEMENT_ORDER[x] == target_order ] # for each element type, find the optimal target type @@ -2729,26 +3020,29 @@ def _change_element_order(self, element_block_ids, target_order): if self.ELEMENT_ORDER[element_type] == target_order: continue self._error( - 'Unable to convert', - 'There is no valid scheme to convert elements ' + "Unable to convert", + "There is no valid scheme to convert elements " 'of type "%s" to an element type of order ' - '%d.' % (element_type, target_order)) + "%d." % (element_type, target_order), + ) scheme = self.ELEMENT_CONVERSIONS[element_type] - possible_types = set( - scheme.keys()).intersection(target_element_types) + possible_types = set(scheme.keys()).intersection(target_element_types) if not possible_types: # if element type is already the desired order, no warning if self.ELEMENT_ORDER[element_type] == target_order: continue self._error( - 'Unable to convert', - 'There is no valid scheme to convert elements ' + "Unable to convert", + "There is no valid scheme to convert elements " 'of type "%s" to an element type of order ' - '%d.' % (element_type, target_order)) + "%d." % (element_type, target_order), + ) # out of the given options, choose the one that first creates the # least number of elements, and secondly the least number of nodes - ranking = [(len(scheme[x]), len(scheme[x]) * len(scheme[x][0]), x) - for x in possible_types] + ranking = [ + (len(scheme[x]), len(scheme[x]) * len(scheme[x][0]), x) + for x in possible_types + ] ranking = sorted(ranking) element_type_map[element_type] = ranking[0][-1] # create the conversion list @@ -2758,11 +3052,12 @@ def _change_element_order(self, element_block_ids, target_order): element_type = self._get_standard_element_type(element_type) if element_type in element_type_map: conversion_list.append( - (element_block_id, element_type_map[element_type])) + (element_block_id, element_type_map[element_type]) + ) # now translate the elements self._translate_element_blocks(conversion_list) - def make_elements_linear(self, element_block_ids='all'): + def make_elements_linear(self, element_block_ids="all"): """ Convert elements in one or more element blocks to a linear type. @@ -2774,7 +3069,7 @@ def make_elements_linear(self, element_block_ids='all'): """ self._change_element_order(element_block_ids, 1) - def make_elements_quadratic(self, element_block_ids='all'): + def make_elements_quadratic(self, element_block_ids="all"): """ Convert elements in one or more element blocks to a quadratic type. @@ -2786,13 +3081,14 @@ def make_elements_quadratic(self, element_block_ids='all'): """ self._change_element_order(element_block_ids, 2) - def _translate_element_type(self, element_block_id, new_element_type, - scheme): + def _translate_element_type(self, element_block_id, new_element_type, scheme): """Convert elements within a block to a new type.""" [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) old_element_type = self._get_standard_element_type( - self._get_element_type(element_block_id)) + self._get_element_type(element_block_id) + ) new_element_type = self._get_standard_element_type(new_element_type) old_nodes_per_element = self.NODES_PER_ELEMENT[old_element_type] new_nodes_per_element = self.NODES_PER_ELEMENT[new_element_type] @@ -2805,17 +3101,17 @@ def _translate_element_type(self, element_block_id, new_element_type, connectivity = self.get_connectivity(element_block_id) element_count = self.get_element_count(element_block_id) for element_index in range(element_count): - local_node = connectivity[element_index * - old_nodes_per_element:(element_index + - 1) * - old_nodes_per_element] + local_node = connectivity[ + element_index + * old_nodes_per_element: (element_index + 1) + * old_nodes_per_element + ] for new_element in scheme: for new_node in new_element: if isinstance(new_node, int): duplicate_nodes.add(local_node[new_node]) else: - averaged_nodes.add( - tuple(local_node[x] for x in new_node)) + averaged_nodes.add(tuple(local_node[x] for x in new_node)) # create new nodes next_node_index = len(self.nodes) duplicate_nodes = sorted(duplicate_nodes) @@ -2823,43 +3119,53 @@ def _translate_element_type(self, element_block_id, new_element_type, self._duplicate_nodes(duplicate_nodes, []) self._create_averaged_nodes(averaged_nodes, []) # assign node indices - duplicate_nodes = dict((x, next_node_index + index) - for index, x in enumerate(duplicate_nodes)) + duplicate_nodes = dict( + (x, next_node_index + index) for index, x in enumerate(duplicate_nodes) + ) next_node_index += len(duplicate_nodes) - averaged_nodes = dict((x, next_node_index + index) - for index, x in enumerate(averaged_nodes)) + averaged_nodes = dict( + (x, next_node_index + index) for index, x in enumerate(averaged_nodes) + ) # create the connectivity for the new element block new_connectivity = [] for element_index in range(element_count): - local_node = connectivity[element_index * - old_nodes_per_element:(element_index + - 1) * - old_nodes_per_element] + local_node = connectivity[ + element_index + * old_nodes_per_element: (element_index + 1) + * old_nodes_per_element + ] for new_element in scheme: for new_node in new_element: if isinstance(new_node, int): - new_connectivity.append( - duplicate_nodes[local_node[new_node]]) + new_connectivity.append(duplicate_nodes[local_node[new_node]]) else: - new_connectivity.append(averaged_nodes[tuple( - local_node[x] for x in new_node)]) + new_connectivity.append( + averaged_nodes[tuple(local_node[x] for x in new_node)] + ) # create the new block temporary_element_block_id = self._new_element_block_id() - self.create_element_block(temporary_element_block_id, [ - new_element_type, - len(new_connectivity) // new_nodes_per_element, - new_nodes_per_element, 0 - ], new_connectivity) + self.create_element_block( + temporary_element_block_id, + [ + new_element_type, + len(new_connectivity) // new_nodes_per_element, + new_nodes_per_element, + 0, + ], + new_connectivity, + ) temporary_element_fields = self._get_element_block_fields( - temporary_element_block_id) + temporary_element_block_id + ) # transfer element values fields = self._get_element_block_fields(element_block_id) for field_name in self.get_element_field_names(element_block_id): values = fields[field_name] new_values = [list(x) for x in values] - new_values = [[ - x for x in these_values for _ in range(element_multiplier) - ] for these_values in new_values] + new_values = [ + [x for x in these_values for _ in range(element_multiplier)] + for these_values in new_values + ] temporary_element_fields[field_name] = new_values # for each face in the old scheme, find all of its nodes old_face_mapping = self._get_face_mapping(old_element_type) @@ -2867,8 +3173,7 @@ def _translate_element_type(self, element_block_id, new_element_type, new_face_mapping = self._get_face_mapping(new_element_type) face_translation = [[] for _ in range(len(old_face_nodes))] for new_element_index, new_element in enumerate(scheme): - for new_face_index, (_, - face_members) in enumerate(new_face_mapping): + for new_face_index, (_, face_members) in enumerate(new_face_mapping): # find all nodes used by this new face used_nodes = set() for face_member in face_members: @@ -2880,21 +3185,26 @@ def _translate_element_type(self, element_block_id, new_element_type, for old_face_index, old_members in enumerate(old_face_nodes): if used_nodes <= old_members: face_translation[old_face_index].append( - (new_element_index, new_face_index)) + (new_element_index, new_face_index) + ) # update self.side_sets for side_set_id in self.get_side_set_ids(): members = self.get_side_set_members(side_set_id) fields = self._get_side_set_fields(side_set_id) old_members = list(members) - for member_index, (block_id, element_index, - face_index) in enumerate(old_members): + for member_index, (block_id, element_index, face_index) in enumerate( + old_members + ): if block_id == element_block_id: # add some new faces for new_faces in face_translation[face_index]: members.append( - (temporary_element_block_id, - element_index * len(scheme) + new_faces[0], - new_faces[1])) + ( + temporary_element_block_id, + element_index * len(scheme) + new_faces[0], + new_faces[1], + ) + ) # add values for the new faces for all_values in list(fields.values()): for values in all_values: @@ -2904,9 +3214,7 @@ def _translate_element_type(self, element_block_id, new_element_type, self.delete_element_block(element_block_id) self.rename_element_block(temporary_element_block_id, element_block_id) - def convert_hex8_block_to_tet4_block(self, - element_block_id, - scheme='hex24tet'): + def convert_hex8_block_to_tet4_block(self, element_block_id, scheme="hex24tet"): """ Convert a block of 'hex8' elements to a block of 'tet4' elements. @@ -2922,32 +3230,40 @@ def convert_hex8_block_to_tet4_block(self, """ [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) # ensure source block is actually hex8 source_element_type = self._get_standard_element_type( - self._get_element_type(element_block_id)) - if source_element_type != 'hex8': + self._get_element_type(element_block_id) + ) + if source_element_type != "hex8": self._error( - 'Incompatible element type.', - 'We were expecting an element block composed of ' + "Incompatible element type.", + "We were expecting an element block composed of " '"hex8" element but instead encountered one with "%s" ' - 'elements.' % source_element_type) + "elements." % source_element_type, + ) # get the chosen scheme - if scheme != 'hex24tet': - self._error('Unsupported scheme.', - 'The scheme "%s" was not recognized.' % scheme) + if scheme != "hex24tet": + self._error( + "Unsupported scheme.", 'The scheme "%s" was not recognized.' % scheme + ) # create the scheme scheme = [] - for _, face in self._get_face_mapping('hex8'): + for _, face in self._get_face_mapping("hex8"): for index in range(4): scheme.append( - tuple([ - face[(index + 1) % 4], face[index], - tuple(sorted(face)), - tuple(range(8)) - ])) + tuple( + [ + face[(index + 1) % 4], + face[index], + tuple(sorted(face)), + tuple(range(8)), + ] + ) + ) # apply it - self._translate_element_type(element_block_id, 'tet4', scheme) + self._translate_element_type(element_block_id, "tet4", scheme) def displacement_field_exists(self): """ @@ -2958,9 +3274,11 @@ def displacement_field_exists(self): """ prefix = self._get_displacement_field_prefix() - return (self.node_field_exists(prefix + '_x') - and self.node_field_exists(prefix + '_y') - and self.node_field_exists(prefix + '_z')) + return ( + self.node_field_exists(prefix + "_x") + and self.node_field_exists(prefix + "_y") + and self.node_field_exists(prefix + "_z") + ) def create_displacement_field(self): """ @@ -2971,8 +3289,8 @@ def create_displacement_field(self): """ prefix = self._get_displacement_field_prefix() - for component in ['x', 'y', 'z']: - this_name = prefix + '_' + component + for component in ["x", "y", "z"]: + this_name = prefix + "_" + component if not self.node_field_exists(this_name): self.create_node_field(this_name) @@ -2986,12 +3304,12 @@ def _get_displacement_field_values(self): self.create_displacement_field() prefix = self._get_displacement_field_prefix() displacement_field_list = [] - for component in ['x', 'y', 'z']: - this_name = prefix + '_' + component + for component in ["x", "y", "z"]: + this_name = prefix + "_" + component displacement_field_list.append(self.node_fields[this_name]) return displacement_field_list - def _apply_displacements(self, timestep='last', scale_factor=1.0): + def _apply_displacements(self, timestep="last", scale_factor=1.0): """ Apply the displacements to each node. @@ -3005,13 +3323,13 @@ def _apply_displacements(self, timestep='last', scale_factor=1.0): is unchanged. """ - timestep = self._format_id_list(timestep, self.get_timesteps(), - 'timestep') + timestep = self._format_id_list(timestep, self.get_timesteps(), "timestep") if len(timestep) > 1: self._error( - 'Ambiguous timestep.', - 'More than one timestep was specified. We expected ' - 'one or zero timesteps.') + "Ambiguous timestep.", + "More than one timestep was specified. We expected " + "one or zero timesteps.", + ) if not timestep: return [tuple(x) for x in self.nodes] timestep_index = self.timesteps.index(timestep[0]) @@ -3019,13 +3337,12 @@ def _apply_displacements(self, timestep='last', scale_factor=1.0): x[timestep_index] for x in self._get_displacement_field_values() ] new_nodes = [ - (x + dx * scale_factor, y + dy * scale_factor, - z + dz * scale_factor) + (x + dx * scale_factor, y + dy * scale_factor, z + dz * scale_factor) for (x, y, z), dx, dy, dz in zip(self.nodes, *displacement_values) ] self.nodes = new_nodes - def _get_local_index(self, this_id, id_list, entity='entity'): + def _get_local_index(self, this_id, id_list, entity="entity"): """ Return the local index corresponding to the given id. @@ -3038,33 +3355,35 @@ def _get_local_index(self, this_id, id_list, entity='entity'): 10 """ - if this_id == 'first': + if this_id == "first": if not id_list: self._error( - 'Undefined %s reference.' % entity, - 'A reference to the first %s was encountered but ' - 'no %ss are defined.' % (entity, entity)) + "Undefined %s reference." % entity, + "A reference to the first %s was encountered but " + "no %ss are defined." % (entity, entity), + ) return 0 - if this_id == 'last': + if this_id == "last": if not id_list: self._error( - 'Undefined %s reference.' % entity, - 'A reference to the last %s was encountered but ' - 'no %ss are defined.' % (entity, entity)) + "Undefined %s reference." % entity, + "A reference to the last %s was encountered but " + "no %ss are defined." % (entity, entity), + ) return len(id_list) - 1 if this_id not in id_list: - entity_list = ', '.join([str(x) for x in id_list]) + entity_list = ", ".join([str(x) for x in id_list]) self._error( - 'Reference to undefined %s.' % entity, + "Reference to undefined %s." % entity, 'A reference to %s "%s" was encountered but is not ' - 'defined in the model. There are %d defined %ss: %s' % - (entity, str(this_id), len(id_list), entity, entity_list)) + "defined in the model. There are %d defined %ss: %s" + % (entity, str(this_id), len(id_list), entity, entity_list), + ) return id_list.index(this_id) - def get_element_field_values(self, - element_field_name, - element_block_id='auto', - timestep='last'): + def get_element_field_values( + self, element_field_name, element_block_id="auto", timestep="last" + ): """ Return the list of element field values. @@ -3082,25 +3401,26 @@ def get_element_field_values(self, [element_field_name] = self._format_id_list( [element_field_name], self.get_element_field_names(), - 'element field', - single=True) + "element field", + single=True, + ) [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + [element_block_id], single=True + ) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) timestep_index = self._get_internal_timestep_index(timestep) if not self.element_field_exists(element_field_name, element_block_id): - self._missing_on_entity_error(element_field_name, 'element field', - element_block_id, 'element block') + self._missing_on_entity_error( + element_field_name, "element field", element_block_id, "element block" + ) fields = self._get_element_block_fields(element_block_id) return fields[element_field_name][timestep_index] - def get_side_set_field_values(self, - side_set_field_name, - side_set_id='auto', - timestep='last'): + def get_side_set_field_values( + self, side_set_field_name, side_set_id="auto", timestep="last" + ): """ Return the list of side set field values. @@ -3119,24 +3439,23 @@ def get_side_set_field_values(self, [side_set_field_name] = self._format_id_list( [side_set_field_name], self.get_side_set_field_names(), - 'side set field', - single=True) - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + "side set field", + single=True, + ) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) timestep_index = self._get_internal_timestep_index(timestep) if not self.side_set_field_exists(side_set_field_name, side_set_id): - self._missing_on_entity_error(side_set_field_name, - 'side set field', side_set_id, - 'side set') + self._missing_on_entity_error( + side_set_field_name, "side set field", side_set_id, "side set" + ) fields = self._get_side_set_fields(side_set_id) return fields[side_set_field_name][timestep_index] - def get_node_set_field_values(self, - node_set_field_name, - node_set_id='auto', - timestep='last'): + def get_node_set_field_values( + self, node_set_field_name, node_set_id="auto", timestep="last" + ): """ Return the list of node set field values. @@ -3155,17 +3474,17 @@ def get_node_set_field_values(self, [node_set_field_name] = self._format_id_list( [node_set_field_name], self.get_node_set_field_names(), - 'node set field', - single=True) - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + "node set field", + single=True, + ) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) timestep_index = self._get_internal_timestep_index(timestep) if not self.node_set_field_exists(node_set_field_name, node_set_id): - self._missing_on_entity_error(node_set_field_name, - 'node set field', node_set_id, - 'node set') + self._missing_on_entity_error( + node_set_field_name, "node set field", node_set_id, "node set" + ) fields = self._get_node_set_fields(node_set_id) return fields[node_set_field_name][timestep_index] @@ -3193,7 +3512,8 @@ def get_element_block_name(self, element_block_id): """ [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) return self.element_blocks[element_block_id][0] def get_all_element_block_names(self): @@ -3215,7 +3535,8 @@ def _get_standard_element_block_ids(self): """ return [ - x for x in self.get_element_block_ids() + x + for x in self.get_element_block_ids() if self._is_standard_element_type(self._get_element_type(x)) ] @@ -3249,7 +3570,7 @@ def get_node_field_names(self): """ return self._sort_field_names(list(self.node_fields.keys())) - def get_node_set_field_names(self, node_set_ids='all'): + def get_node_set_field_names(self, node_set_ids="all"): """ Return a list of all node set field names. @@ -3268,7 +3589,7 @@ def get_node_set_field_names(self, node_set_ids='all'): names.update(list(self.node_sets[id_][-1].keys())) return self._sort_field_names(list(names)) - def get_side_set_field_names(self, side_set_ids='all'): + def get_side_set_field_names(self, side_set_ids="all"): """ Return a list of all side set field names. @@ -3287,7 +3608,7 @@ def get_side_set_field_names(self, side_set_ids='all'): names.update(list(self._get_side_set_fields(id_).keys())) return self._sort_field_names(list(names)) - def get_element_field_names(self, element_block_ids='all'): + def get_element_field_names(self, element_block_ids="all"): """ Return a list of all element field names. @@ -3300,8 +3621,7 @@ def get_element_field_names(self, element_block_ids='all'): >>> model.get_element_field_names(1) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) names = set() for id_ in element_block_ids: names.update(list(self.element_blocks[id_][-1].keys())) @@ -3329,14 +3649,12 @@ def get_timesteps(self): def _get_internal_timestep_index(self, timestep): """Return the local timestep index.""" - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) return self.timesteps.index(timestep) - def _create_element_field_truth_table(self, element_block_ids, - field_names): + def _create_element_field_truth_table(self, element_block_ids, field_names): """ Return the element field truth table. @@ -3367,7 +3685,8 @@ def _create_side_set_field_truth_table(self, side_set_ids, field_names): # go through each case and set values to True if they exist truth_table = [ self.side_set_field_exists(field_name, side_set_id) - for side_set_id in side_set_ids for field_name in field_names + for side_set_id in side_set_ids + for field_name in field_names ] return truth_table @@ -3384,11 +3703,12 @@ def _create_node_set_field_truth_table(self, node_set_ids, field_names): # go through each case and set values to True if they exist truth_table = [ self.node_set_field_exists(field_name, node_set_id) - for node_set_id in node_set_ids for field_name in field_names + for node_set_id in node_set_ids + for field_name in field_names ] return truth_table - def get_connectivity(self, element_block_id='auto'): + def get_connectivity(self, element_block_id="auto"): """ Return the connectivity list of an element block. @@ -3397,10 +3717,11 @@ def get_connectivity(self, element_block_id='auto'): """ [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) return self.element_blocks[element_block_id][2] - def get_element_block_connectivity(self, element_block_id='auto'): + def get_element_block_connectivity(self, element_block_id="auto"): """Alias for 'get_connectivity()'.""" return self.get_connectivity(element_block_id) @@ -3413,21 +3734,22 @@ def get_nodes_in_element_block(self, element_block_ids): >>> model.get_nodes_in_element_block([1, 3]) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) node_list = set() for id_ in element_block_ids: connectivity = self.get_connectivity(id_) node_list.update(connectivity) return sorted(node_list) - def _rotate_nodes(self, - axis, - angle_in_degrees, - node_indices='all', - adjust_displacement_field='auto'): + def _rotate_nodes( + self, + axis, + angle_in_degrees, + node_indices="all", + adjust_displacement_field="auto", + ): """Rotate nodes about an axis by the given angle.""" - if adjust_displacement_field == 'auto': + if adjust_displacement_field == "auto": adjust_displacement_field = self.displacement_field_exists() # Create rotation matrix. # x --> R * x @@ -3451,38 +3773,51 @@ def _rotate_nodes(self, rzy = uz * uy * (1 - cost) + ux * sint rzz = cost + uz * uz * (1 - cost) # Rotate nodes. - if node_indices == 'all': - self.nodes = [[ - rxx * x + rxy * y + rxz * z, ryx * x + ryy * y + ryz * z, - rzx * x + rzy * y + rzz * z - ] for x, y, z in self.nodes] + if node_indices == "all": + self.nodes = [ + [ + rxx * x + rxy * y + rxz * z, + ryx * x + ryy * y + ryz * z, + rzx * x + rzy * y + rzz * z, + ] + for x, y, z in self.nodes + ] else: for index in node_indices: n = self.nodes[index] self.nodes[index] = [ rxx * n[0] + rxy * n[1] + rxz * n[2], ryx * n[0] + ryy * n[1] + ryz * n[2], - rzx * n[0] + rzy * n[1] + rzz * n[2] + rzx * n[0] + rzy * n[1] + rzz * n[2], ] # Rotate the displacement field. if adjust_displacement_field: (disp_x, disp_y, disp_z) = self._get_displacement_field_values() for timestep_index in range(len(self.timesteps)): - if node_indices == 'all': + if node_indices == "all": new_disp_x = [ - rxx * x + rxy * y + rxz * z for x, y, z in zip( - disp_x[timestep_index], disp_y[timestep_index], - disp_z[timestep_index]) + rxx * x + rxy * y + rxz * z + for x, y, z in zip( + disp_x[timestep_index], + disp_y[timestep_index], + disp_z[timestep_index], + ) ] new_disp_y = [ - ryx * x + ryy * y + ryz * z for x, y, z in zip( - disp_x[timestep_index], disp_y[timestep_index], - disp_z[timestep_index]) + ryx * x + ryy * y + ryz * z + for x, y, z in zip( + disp_x[timestep_index], + disp_y[timestep_index], + disp_z[timestep_index], + ) ] new_disp_z = [ - rzx * x + rzy * y + rzz * z for x, y, z in zip( - disp_x[timestep_index], disp_y[timestep_index], - disp_z[timestep_index]) + rzx * x + rzy * y + rzz * z + for x, y, z in zip( + disp_x[timestep_index], + disp_y[timestep_index], + disp_z[timestep_index], + ) ] disp_x[timestep_index] = new_disp_x disp_y[timestep_index] = new_disp_y @@ -3495,16 +3830,16 @@ def _rotate_nodes(self, (x, y, z) = [ rxx * x + rxy * y + rxz * z, ryx * x + ryy * y + ryz * z, - rzx * x + rzy * y + rzz * z + rzx * x + rzy * y + rzz * z, ] disp_x[timestep_index][index] = x disp_y[timestep_index][index] = y disp_z[timestep_index][index] = z - def _translate_nodes(self, offset, node_indices='all'): + def _translate_nodes(self, offset, node_indices="all"): """Translate nodes by the given offset.""" (dx, dy, dz) = [float(x) for x in offset] - if node_indices == 'all': + if node_indices == "all": self.nodes = [[x + dx, y + dy, z + dz] for x, y, z in self.nodes] else: for index in node_indices: @@ -3512,36 +3847,30 @@ def _translate_nodes(self, offset, node_indices='all'): self.nodes[index][1] += dy self.nodes[index][2] += dz - def _scale_nodes(self, - scale_factor, - node_indices='all', - adjust_displacement_field='auto'): + def _scale_nodes( + self, scale_factor, node_indices="all", adjust_displacement_field="auto" + ): """Scale nodes in the list by the given scale factor.""" scale_factor = float(scale_factor) - if adjust_displacement_field == 'auto': + if adjust_displacement_field == "auto": adjust_displacement_field = self.displacement_field_exists() # Scale the nodal coordinates. - if node_indices == 'all': + if node_indices == "all": self.nodes = [[x * scale_factor for x in n] for n in self.nodes] else: for index in node_indices: - self.nodes[index] = [ - x * scale_factor for x in self.nodes[index] - ] + self.nodes[index] = [x * scale_factor for x in self.nodes[index]] # Scale the displacement field. if adjust_displacement_field: for all_values in self._get_displacement_field_values(): for values in all_values: - if node_indices == 'all': + if node_indices == "all": values[:] = [x * scale_factor for x in values] else: for index in node_indices: values[index] *= scale_factor - def rotate_geometry(self, - axis, - angle_in_degrees, - adjust_displacement_field='auto'): + def rotate_geometry(self, axis, angle_in_degrees, adjust_displacement_field="auto"): """ Rotate the model about an axis by the given angle. @@ -3552,9 +3881,9 @@ def rotate_geometry(self, >>> model.rotate_geometry([1, 0, 0], 90) """ - self._rotate_nodes(axis, - angle_in_degrees, - adjust_displacement_field=adjust_displacement_field) + self._rotate_nodes( + axis, angle_in_degrees, adjust_displacement_field=adjust_displacement_field + ) def translate_geometry(self, offset): """ @@ -3566,7 +3895,7 @@ def translate_geometry(self, offset): """ self._translate_nodes(offset) - def scale_geometry(self, scale_factor, adjust_displacement_field='auto'): + def scale_geometry(self, scale_factor, adjust_displacement_field="auto"): """ Scale the model by the given factor. @@ -3577,8 +3906,9 @@ def scale_geometry(self, scale_factor, adjust_displacement_field='auto'): >>> model.scale_geometry(0.0254) """ - self._scale_nodes(scale_factor, - adjust_displacement_field=adjust_displacement_field) + self._scale_nodes( + scale_factor, adjust_displacement_field=adjust_displacement_field + ) def _ensure_no_shared_nodes(self, element_block_ids): """ @@ -3588,34 +3918,33 @@ def _ensure_no_shared_nodes(self, element_block_ids): other element block then an error message is output. """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) affected_nodes = self.get_nodes_in_element_block(element_block_ids) nodes_in_other_blocks = self.get_nodes_in_element_block( - list(set(self.get_element_block_ids()) - set(element_block_ids))) + list(set(self.get_element_block_ids()) - set(element_block_ids)) + ) shared_nodes = sorted( - set.intersection(set(affected_nodes), set(nodes_in_other_blocks))) + set.intersection(set(affected_nodes), set(nodes_in_other_blocks)) + ) if shared_nodes: max_nodes_to_display = 20 - node_list = ', '.join( - [str(x) for x in shared_nodes[:max_nodes_to_display]]) + node_list = ", ".join([str(x) for x in shared_nodes[:max_nodes_to_display]]) if len(shared_nodes) > max_nodes_to_display: - node_list += ', ...' + node_list += ", ..." self._error( - 'Unable to operate on merged nodes.', - 'You are attempting to operate on some element blocks ' - 'while keeping others unaffected. Because some nodes ' - 'are shared between the two groups, this cannot be ' - 'done. Use unmerge_element_blocks() to unmerge the ' - 'blocks if that is desired.\n' - '\n' - 'There are %d shared nodes: %s' % - (len(shared_nodes), node_list)) - - def translate_element_blocks(self, - element_block_ids, - offset, - check_for_merged_nodes=True): + "Unable to operate on merged nodes.", + "You are attempting to operate on some element blocks " + "while keeping others unaffected. Because some nodes " + "are shared between the two groups, this cannot be " + "done. Use unmerge_element_blocks() to unmerge the " + "blocks if that is desired.\n" + "\n" + "There are %d shared nodes: %s" % (len(shared_nodes), node_list), + ) + + def translate_element_blocks( + self, element_block_ids, offset, check_for_merged_nodes=True + ): """ Translate the specified element blocks by the given offset. @@ -3623,19 +3952,20 @@ def translate_element_blocks(self, >>> model.translate_element_blocks(1, [1.0, 2.0, 3.0]) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) if check_for_merged_nodes: self._ensure_no_shared_nodes(element_block_ids) affected_nodes = self.get_nodes_in_element_block(element_block_ids) self._translate_nodes(offset, affected_nodes) - def reflect_element_blocks(self, - element_block_ids, - point, - normal, - check_for_merged_nodes=True, - adjust_displacement_field='auto'): + def reflect_element_blocks( + self, + element_block_ids, + point, + normal, + check_for_merged_nodes=True, + adjust_displacement_field="auto", + ): """ Reflect the specified element blocks about the given plane. @@ -3646,9 +3976,8 @@ def reflect_element_blocks(self, >>> model.reflect_element_blocks(1, [0, 0, 0], [1, 0, 0]) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - if adjust_displacement_field == 'auto': + element_block_ids = self._format_element_block_id_list(element_block_ids) + if adjust_displacement_field == "auto": adjust_displacement_field = self.displacement_field_exists() point = [float(x) for x in point] scale = math.sqrt(sum(x * x for x in normal)) @@ -3658,8 +3987,8 @@ def reflect_element_blocks(self, affected_nodes = self.get_nodes_in_element_block(element_block_ids) for index in affected_nodes: distance = sum( - (a - p) * n - for a, p, n in zip(self.nodes[index], point, normal)) + (a - p) * n for a, p, n in zip(self.nodes[index], point, normal) + ) self.nodes[index] = [ a - 2 * distance * n for a, n in zip(self.nodes[index], normal) ] @@ -3681,11 +4010,13 @@ def reflect_element_blocks(self, # uninvert elements self._invert_element_blocks(element_block_ids) - def scale_element_blocks(self, - element_block_ids, - scale_factor, - check_for_merged_nodes=True, - adjust_displacement_field='auto'): + def scale_element_blocks( + self, + element_block_ids, + scale_factor, + check_for_merged_nodes=True, + adjust_displacement_field="auto", + ): """ Scale all nodes in the given element blocks by the given amount. @@ -3696,23 +4027,26 @@ def scale_element_blocks(self, >>> model.scale_element_blocks(1, 0.0254) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - if adjust_displacement_field == 'auto': + element_block_ids = self._format_element_block_id_list(element_block_ids) + if adjust_displacement_field == "auto": adjust_displacement_field = self.displacement_field_exists() if check_for_merged_nodes: self._ensure_no_shared_nodes(element_block_ids) affected_nodes = self.get_nodes_in_element_block(element_block_ids) - self._scale_nodes(scale_factor, - affected_nodes, - adjust_displacement_field=adjust_displacement_field) - - def rotate_element_blocks(self, - element_block_ids, - axis, - angle_in_degrees, - check_for_merged_nodes=True, - adjust_displacement_field='auto'): + self._scale_nodes( + scale_factor, + affected_nodes, + adjust_displacement_field=adjust_displacement_field, + ) + + def rotate_element_blocks( + self, + element_block_ids, + axis, + angle_in_degrees, + check_for_merged_nodes=True, + adjust_displacement_field="auto", + ): """ Rotate all nodes in the given element blocks by the given amount. @@ -3726,23 +4060,22 @@ def rotate_element_blocks(self, >>> model.rotate_element_blocks(1, [1, 0, 0], 90) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - if adjust_displacement_field == 'auto': + element_block_ids = self._format_element_block_id_list(element_block_ids) + if adjust_displacement_field == "auto": adjust_displacement_field = self.displacement_field_exists() if check_for_merged_nodes: self._ensure_no_shared_nodes(element_block_ids) affected_nodes = self.get_nodes_in_element_block(element_block_ids) - self._rotate_nodes(axis, - angle_in_degrees, - affected_nodes, - adjust_displacement_field=adjust_displacement_field) + self._rotate_nodes( + axis, + angle_in_degrees, + affected_nodes, + adjust_displacement_field=adjust_displacement_field, + ) - def displace_element_blocks(self, - element_block_ids, - offset, - timesteps='all', - check_for_merged_nodes=True): + def displace_element_blocks( + self, element_block_ids, offset, timesteps="all", check_for_merged_nodes=True + ): """ Displace all nodes in the given element blocks. @@ -3755,10 +4088,8 @@ def displace_element_blocks(self, >>> model.displace_element_blocks('all', [1.0, 2.0, 3.0]) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) - timesteps = self._format_id_list(timesteps, self.get_timesteps(), - 'timestep') + element_block_ids = self._format_element_block_id_list(element_block_ids) + timesteps = self._format_id_list(timesteps, self.get_timesteps(), "timestep") if check_for_merged_nodes: self._ensure_no_shared_nodes(element_block_ids) timestep_indices = [self.timesteps.index(x) for x in timesteps] @@ -3766,10 +4097,11 @@ def displace_element_blocks(self, # if no timesteps exist, issue an error if not self.timesteps: self._error( - 'No timesteps defined', - 'A displacement field cannot exist if no timesteps ' - 'are defined. To avoid this error, create a timestep ' - 'before calling this function.') + "No timesteps defined", + "A displacement field cannot exist if no timesteps " + "are defined. To avoid this error, create a timestep " + "before calling this function.", + ) # get displacement field indices displacement_fields = self._get_displacement_field_values() # get affected nodes @@ -3781,39 +4113,46 @@ def displace_element_blocks(self, for index in node_list: values[index] += offset[dimension] - def _rename_field_on_entity(self, field_type, field_name, new_field_name, - field_name_list_function, entity_type, - entity_list, entity_list_function, - entity_objects): + def _rename_field_on_entity( + self, + field_type, + field_name, + new_field_name, + field_name_list_function, + entity_type, + entity_list, + entity_list_function, + entity_objects, + ): """Rename a field defined on an entity.""" - entity_list = self._format_id_list(entity_list, entity_list_function(), - entity_type) + entity_list = self._format_id_list( + entity_list, entity_list_function(), entity_type + ) [field_name] = self._format_id_list( - [field_name], - field_name_list_function(entity_list), - field_type, - single=True) + [field_name], field_name_list_function(entity_list), field_type, single=True + ) for id_ in entity_list: fields = entity_objects[id_][-1] if field_name not in fields: self._warning( - field_type + ' not defined.', 'The given %s "%s" is not ' - 'defined on %s %s. It cannot ' - 'be renamed.' % - (field_type, field_name, entity_type, str(id_))) + field_type + " not defined.", + 'The given %s "%s" is not ' + "defined on %s %s. It cannot " + "be renamed." % (field_type, field_name, entity_type, str(id_)), + ) continue if field_name == new_field_name: continue if new_field_name in fields: - self._exists_on_entity_warning(new_field_name, field_type, id_, - entity_type) + self._exists_on_entity_warning( + new_field_name, field_type, id_, entity_type + ) fields[new_field_name] = fields[field_name] del fields[field_name] - def rename_element_field(self, - element_field_name, - new_element_field_name, - element_block_ids='all'): + def rename_element_field( + self, element_field_name, new_element_field_name, element_block_ids="all" + ): """ Rename an element field. @@ -3821,17 +4160,20 @@ def rename_element_field(self, >>> model.rename_element_field('p', 'pressure') """ - self._rename_field_on_entity('element field', element_field_name, - new_element_field_name, - self.get_element_field_names, - 'element block', element_block_ids, - self.get_element_block_ids, - self.element_blocks) + self._rename_field_on_entity( + "element field", + element_field_name, + new_element_field_name, + self.get_element_field_names, + "element block", + element_block_ids, + self.get_element_block_ids, + self.element_blocks, + ) - def rename_side_set_field(self, - side_set_field_name, - new_side_set_field_name, - side_set_ids='all'): + def rename_side_set_field( + self, side_set_field_name, new_side_set_field_name, side_set_ids="all" + ): """ Rename a side set field. @@ -3839,11 +4181,16 @@ def rename_side_set_field(self, >>> model.rename_side_set_field('cp', 'contact_pressure') """ - self._rename_field_on_entity('side set field', side_set_field_name, - new_side_set_field_name, - self.get_side_set_field_names, 'side set', - side_set_ids, self.get_side_set_ids, - self.side_sets) + self._rename_field_on_entity( + "side set field", + side_set_field_name, + new_side_set_field_name, + self.get_side_set_field_names, + "side set", + side_set_ids, + self.get_side_set_ids, + self.side_sets, + ) def get_side_set_name(self, side_set_id): """Return the name of a side set.""" @@ -3864,10 +4211,9 @@ def _get_side_set_fields(self, side_set_id): [side_set_id] = self._format_side_set_id_list([side_set_id], single=True) return self.side_sets[side_set_id][-1] - def rename_node_set_field(self, - node_set_field_name, - new_node_set_field_name, - node_set_ids='all'): + def rename_node_set_field( + self, node_set_field_name, new_node_set_field_name, node_set_ids="all" + ): """ Rename a node set field. @@ -3875,19 +4221,29 @@ def rename_node_set_field(self, >>> model.rename_node_set_field('cp', 'contact_pressure') """ - self._rename_field_on_entity('node set field', node_set_field_name, - new_node_set_field_name, - self.get_node_set_field_names, 'node set', - node_set_ids, self.get_node_set_ids, - self.node_sets) - - def _rename_entity(self, entity_type, entity_name, new_entity_name, - entity_name_list_function, entity_objects): + self._rename_field_on_entity( + "node set field", + node_set_field_name, + new_node_set_field_name, + self.get_node_set_field_names, + "node set", + node_set_ids, + self.get_node_set_ids, + self.node_sets, + ) + + def _rename_entity( + self, + entity_type, + entity_name, + new_entity_name, + entity_name_list_function, + entity_objects, + ): """Rename an entity.""" - [entity_name] = self._format_id_list([entity_name], - entity_name_list_function(), - entity_type, - single=True) + [entity_name] = self._format_id_list( + [entity_name], entity_name_list_function(), entity_type, single=True + ) if new_entity_name == entity_name: return if new_entity_name in entity_name_list_function(): @@ -3903,11 +4259,15 @@ def rename_node_field(self, node_field_name, new_node_field_name): >>> model.rename_node_field('temp', 'temperature') """ - self._rename_entity('node field', node_field_name, new_node_field_name, - self.get_node_field_names, self.node_fields) + self._rename_entity( + "node field", + node_field_name, + new_node_field_name, + self.get_node_field_names, + self.node_fields, + ) - def rename_global_variable(self, global_variable_name, - new_global_variable_name): + def rename_global_variable(self, global_variable_name, new_global_variable_name): """ Rename a global variable. @@ -3915,10 +4275,13 @@ def rename_global_variable(self, global_variable_name, >>> model.rename_global_variable('ke', 'kinetic_energy') """ - self._rename_entity('global variable', global_variable_name, - new_global_variable_name, - self.get_global_variable_names, - self.global_variables) + self._rename_entity( + "global variable", + global_variable_name, + new_global_variable_name, + self.get_global_variable_names, + self.global_variables, + ) def rename_element_block(self, element_block_id, new_element_block_id): """ @@ -3934,25 +4297,28 @@ def rename_element_block(self, element_block_id, new_element_block_id): """ [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) # if we're just changing the name if isinstance(new_element_block_id, str): # if the same name already, just exit - if (self.element_blocks[element_block_id][0] == - new_element_block_id): + if self.element_blocks[element_block_id][0] == new_element_block_id: return # if the name already exists, issue a warning if self.element_block_exists(new_element_block_id): - self._exists_warning('"' + new_element_block_id + '"', - 'element block') + self._exists_warning('"' + new_element_block_id + '"', "element block") # rename it self.element_blocks[element_block_id][0] = new_element_block_id return assert isinstance(new_element_block_id, int) # rename the block - self._rename_entity('element block', element_block_id, - new_element_block_id, self.get_element_block_ids, - self.element_blocks) + self._rename_entity( + "element block", + element_block_id, + new_element_block_id, + self.get_element_block_ids, + self.element_blocks, + ) # adjust side sets for side_set_id in self.get_side_set_ids(): members = self.get_side_set_members(side_set_id) @@ -3986,13 +4352,18 @@ def rename_node_set(self, node_set_id, new_node_set_id): return # if the name already exists, issue a warning if self.node_set_exists(new_node_set_id): - self._exists_warning('"' + new_node_set_id + '"', 'node set') + self._exists_warning('"' + new_node_set_id + '"', "node set") # rename it self.node_sets[node_set_id][0] = new_node_set_id return # rename it - self._rename_entity('node set', node_set_id, new_node_set_id, - self.get_node_set_ids, self.node_sets) + self._rename_entity( + "node set", + node_set_id, + new_node_set_id, + self.get_node_set_ids, + self.node_sets, + ) def rename_side_set(self, side_set_id, new_side_set_id): """ @@ -4015,31 +4386,36 @@ def rename_side_set(self, side_set_id, new_side_set_id): return # if the name already exists, issue a warning if self.side_set_exists(new_side_set_id): - self._exists_warning('"' + new_side_set_id + '"', 'side set') + self._exists_warning('"' + new_side_set_id + '"', "side set") # rename it self.side_sets[side_set_id][0] = new_side_set_id return - self._rename_entity('side set', side_set_id, new_side_set_id, - self.get_side_set_ids, self.side_sets) + self._rename_entity( + "side set", + side_set_id, + new_side_set_id, + self.get_side_set_ids, + self.side_sets, + ) def _empty_field_warning(self): """Issue a warning if no timesteps exist.""" assert not self.get_timesteps() self._warning( - 'Creating an empty field', - 'No timesteps are defined. Because fields are only ' - 'defined at each timestep, creating a field when no ' - 'timesteps are defined will allow let the field to ' - 'have any values. By default, empty fields are not ' - 'exported.\n' - '\n' - 'To avoid this warning, create a timestep before ' - 'creating a field.') - - def create_element_field(self, - element_field_name, - element_block_ids='all', - value='auto'): + "Creating an empty field", + "No timesteps are defined. Because fields are only " + "defined at each timestep, creating a field when no " + "timesteps are defined will allow let the field to " + "have any values. By default, empty fields are not " + "exported.\n" + "\n" + "To avoid this warning, create a timestep before " + "creating a field.", + ) + + def create_element_field( + self, element_field_name, element_block_ids="all", value="auto" + ): """ Create an element field on one or more element blocks. @@ -4055,19 +4431,20 @@ def create_element_field(self, if not self.get_timesteps(): self._empty_field_warning() # get list of block ids - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # get the value to assign - if value == 'auto': + if value == "auto": value = self._get_default_field_value(element_field_name) # for each block for element_block_id in element_block_ids: # if it exists, no need to do anything if self.element_field_exists(element_field_name, element_block_id): - self._exists_on_entity_warning(element_field_name, - 'element field', - element_block_id, - 'element block') + self._exists_on_entity_warning( + element_field_name, + "element field", + element_block_id, + "element block", + ) # get the element block info element_count = self.get_element_count(element_block_id) # create an empty field @@ -4078,7 +4455,7 @@ def create_element_field(self, fields = self._get_element_block_fields(element_block_id) fields[element_field_name] = values - def create_node_field(self, node_field_name, value='auto'): + def create_node_field(self, node_field_name, value="auto"): """ Create a node field and assign it a default value. @@ -4095,10 +4472,10 @@ def create_node_field(self, node_field_name, value='auto'): self._empty_field_warning() # if it exists, no need to do anything if self.node_field_exists(node_field_name): - self._exists_warning(node_field_name, 'node field') + self._exists_warning(node_field_name, "node field") return # get the value - if value == 'auto': + if value == "auto": value = self._get_default_field_value(node_field_name) # create the new field new_field_values = [] @@ -4106,10 +4483,9 @@ def create_node_field(self, node_field_name, value='auto'): new_field_values.append([value] * len(self.nodes)) self.node_fields[node_field_name] = new_field_values - def create_node_set_field(self, - node_set_field_name, - node_set_ids='all', - value='auto'): + def create_node_set_field( + self, node_set_field_name, node_set_ids="all", value="auto" + ): """ Create a node set field on the given node sets. @@ -4122,7 +4498,7 @@ def create_node_set_field(self, """ node_set_ids = self._format_node_set_id_list(node_set_ids) - if value == 'auto': + if value == "auto": value = self._get_default_field_value(node_set_field_name) for node_set_id in node_set_ids: members = self.get_node_set_members(node_set_id) @@ -4130,19 +4506,18 @@ def create_node_set_field(self, member_count = len(members) # if it exists, warn about overwriting if self.node_set_field_exists(node_set_field_name, [node_set_id]): - self._exists_on_entity_warning(node_set_field_name, - 'node set field', node_set_id, - 'node set') + self._exists_on_entity_warning( + node_set_field_name, "node set field", node_set_id, "node set" + ) # create the new field new_field_values = [] for _ in range(len(self.timesteps)): new_field_values.append([value] * member_count) fields[node_set_field_name] = new_field_values - def create_side_set_field(self, - side_set_field_name, - side_set_ids='all', - value='auto'): + def create_side_set_field( + self, side_set_field_name, side_set_ids="all", value="auto" + ): """ Create a side set field. @@ -4157,7 +4532,7 @@ def create_side_set_field(self, """ side_set_ids = self._format_side_set_id_list(side_set_ids) - if value == 'auto': + if value == "auto": value = self._get_default_field_value(side_set_field_name) for side_set_id in side_set_ids: members = self.get_side_set_members(side_set_id) @@ -4165,9 +4540,9 @@ def create_side_set_field(self, member_count = len(members) # if it exists, warn about overwriting if self.side_set_field_exists(side_set_field_name, side_set_id): - self._exists_on_entity_warning(side_set_field_name, - 'side set field', side_set_id, - 'side set') + self._exists_on_entity_warning( + side_set_field_name, "side set field", side_set_id, "side set" + ) # create the new field new_field_values = [] for _ in range(len(self.timesteps)): @@ -4233,21 +4608,21 @@ def create_node_set(self, node_set_id, node_set_members=None): """ # if it exists, warn that it will be overwritten if self.node_set_exists(node_set_id): - self._exists_warning(node_set_id, 'node set') + self._exists_warning(node_set_id, "node set") # reformat members if necessary if not node_set_members: node_set_members = [] # do not allow duplicates - new_members = self._remove_duplicates(node_set_members, - preserve_order=True) + new_members = self._remove_duplicates(node_set_members, preserve_order=True) if len(new_members) != len(node_set_members): self._warning( - 'Duplicate nodes in set.', - 'The node set member list contains multiple copies ' - 'of some nodes. These nodes will only be added ' - 'once.') + "Duplicate nodes in set.", + "The node set member list contains multiple copies " + "of some nodes. These nodes will only be added " + "once.", + ) # add the new set - self.node_sets[node_set_id] = ['', new_members, {}] + self.node_sets[node_set_id] = ["", new_members, {}] def add_nodes_to_node_set(self, node_set_id, new_node_set_members): """ @@ -4258,23 +4633,26 @@ def add_nodes_to_node_set(self, node_set_id, new_node_set_members): """ if not self.node_set_exists(node_set_id): - self._warning('Node set does not exist.' - 'The specified node set "%s% does not exist. It ' - 'will be created.' % node_set_id) + self._warning( + "Node set does not exist." + 'The specified node set "%s% does not exist. It ' + "will be created." % node_set_id + ) self.create_node_set(node_set_id, new_node_set_members) return members = self.get_node_set_members(node_set_id) fields = self._get_node_set_fields(node_set_id) # Remove duplicate nodes. - new_nodes = self._remove_duplicates(new_node_set_members, - other_list=members, - preserve_order=True) + new_nodes = self._remove_duplicates( + new_node_set_members, other_list=members, preserve_order=True + ) if len(new_nodes) != len(new_node_set_members): self._warning( - 'Duplicates nodes in set', - 'The node set already contains some of the nodes ' - 'in the list. These members will not be ' - 'duplicated.') + "Duplicates nodes in set", + "The node set already contains some of the nodes " + "in the list. These members will not be " + "duplicated.", + ) # Add the members. members.extend(new_nodes) # Add new values to each field. @@ -4292,32 +4670,33 @@ def _transform_expression(self, expression): """ # create transformation dictionary by precedence order transforms = [] - transforms.append(('||', 'min(abs(L), abs(R))')) - transforms.append(('&&', 'max(abs(L), abs(R))')) - transforms.append(('>=', '((L) - (R)) - abs((L) - (R))')) - transforms.append(('>', '((L) - (R)) - abs((L) - (R))')) - transforms.append(('<=', '((R) - (L)) - abs((R) - (L))')) - transforms.append(('<', '((R) - (L)) - abs((R) - (L))')) - transforms.append(('==', 'abs((L) - (R))')) - transforms.append(('=', 'abs((L) - (R))')) + transforms.append(("||", "min(abs(L), abs(R))")) + transforms.append(("&&", "max(abs(L), abs(R))")) + transforms.append((">=", "((L) - (R)) - abs((L) - (R))")) + transforms.append((">", "((L) - (R)) - abs((L) - (R))")) + transforms.append(("<=", "((R) - (L)) - abs((R) - (L))")) + transforms.append(("<", "((R) - (L)) - abs((R) - (L))")) + transforms.append(("==", "abs((L) - (R))")) + transforms.append(("=", "abs((L) - (R))")) # replace occurrences of each transform for separator, transform in transforms: while separator in expression: # ensure parenthesis count is identical - if expression.count('(') != expression.count(')'): + if expression.count("(") != expression.count(")"): self._error( - 'Unbalances parenthesis.', - 'We cannot transform the given expression ' - 'becuase it contains unbalanced ' - 'parenthesis:\n%s' % expression) + "Unbalances parenthesis.", + "We cannot transform the given expression " + "becuase it contains unbalanced " + "parenthesis:\n%s" % expression, + ) # get parenthesis depth on each character next_depth = 0 depth = [] for c in expression: - if c == '(': + if c == "(": depth.append(next_depth) next_depth += 1 - elif c == ')': + elif c == ")": next_depth -= 1 depth.append(next_depth) else: @@ -4327,25 +4706,30 @@ def _transform_expression(self, expression): left_index = separator_index right_index = separator_index + len(separator) while left_index > 0 and ( - depth[left_index - 1] > depth[separator_index] or - (depth[left_index - 1] == depth[separator_index] - and expression[left_index - 1] != ',')): + depth[left_index - 1] > depth[separator_index] + or ( + depth[left_index - 1] == depth[separator_index] + and expression[left_index - 1] != "," + ) + ): left_index -= 1 while right_index < len(expression) and ( - depth[right_index] > depth[separator_index] or - (depth[right_index] == depth[separator_index] - and expression[right_index] != ',')): + depth[right_index] > depth[separator_index] + or ( + depth[right_index] == depth[separator_index] + and expression[right_index] != "," + ) + ): right_index += 1 new_expression = expression[:left_index] - left_expression = expression[left_index:separator_index].strip( - ) - right_expression = expression[separator_index + - len(separator - ):right_index].strip() + left_expression = expression[left_index:separator_index].strip() + right_expression = expression[ + separator_index + len(separator): right_index + ].strip() for c in transform: - if c == 'L': + if c == "L": new_expression += left_expression - elif c == 'R': + elif c == "R": new_expression += right_expression else: new_expression += c @@ -4354,13 +4738,15 @@ def _transform_expression(self, expression): # return the result return expression - def create_side_set_from_expression(self, - side_set_id, - expression, - element_block_ids='all', - tolerance='auto', - timesteps='last_if_any', - zero_member_warning=True): + def create_side_set_from_expression( + self, + side_set_id, + expression, + element_block_ids="all", + tolerance="auto", + timesteps="last_if_any", + zero_member_warning=True, + ): """ Create a side set from faces which satisfy an expression. @@ -4373,41 +4759,40 @@ def create_side_set_from_expression(self, >>> model.create_side_set_from_expression(1, 'Y == 0') """ - timesteps = self._format_id_list(timesteps, self.get_timesteps(), - 'timestep') + timesteps = self._format_id_list(timesteps, self.get_timesteps(), "timestep") if len(timesteps) > 2: self._error( - 'Too many timesteps specified.', - 'We were expecting zero or one timesteps but instead ' - 'found %d specified.' % len(timesteps)) - if tolerance == 'auto': + "Too many timesteps specified.", + "We were expecting zero or one timesteps but instead " + "found %d specified." % len(timesteps), + ) + if tolerance == "auto": tolerance = self.get_length_scale() * 1e-6 if self.side_set_exists(side_set_id): - self._exists_warning(side_set_id, 'side set') + self._exists_warning(side_set_id, "side set") external_faces_by_block = self._order_element_faces_by_block( - self._get_external_element_faces(element_block_ids)) + self._get_external_element_faces(element_block_ids) + ) members = [] # create list of variable names and modify them in the expression - variable_names = set(['X', 'Y', 'Z']) + variable_names = set(["X", "Y", "Z"]) if timesteps: timestep_index = self._get_internal_timestep_index(timesteps[0]) - variable_names.update(['time']) + variable_names.update(["time"]) variable_names.update(self.get_global_variable_names()) variable_names.update(self.get_node_field_names()) expression = self._transform_expression(expression) - eval_expression = self._transform_eval_expression( - expression, variable_names) + eval_expression = self._transform_eval_expression(expression, variable_names) var = dict() - function = eval('lambda var: ' + eval_expression) + function = eval("lambda var: " + eval_expression) if timesteps: - var['time'] = timesteps[0] + var["time"] = timesteps[0] for name, values in list(self.global_variables.items()): var[name] = values[timestep_index] try: for id_, external_faces in list(external_faces_by_block.items()): connectivity = self.get_connectivity(id_) - face_mapping = self._get_face_mapping( - self._get_element_type(id_)) + face_mapping = self._get_face_mapping(self._get_element_type(id_)) nodes_per_element = self.get_nodes_per_element(id_) for element_index, face_index in external_faces: node_indices = [ @@ -4417,9 +4802,9 @@ def create_side_set_from_expression(self, all_passed = True for node_index in node_indices: # set coordinate values - var['X'] = self.nodes[node_index][0] - var['Y'] = self.nodes[node_index][1] - var['Z'] = self.nodes[node_index][2] + var["X"] = self.nodes[node_index][0] + var["Y"] = self.nodes[node_index][1] + var["Z"] = self.nodes[node_index][2] # set node field values if timesteps: for name, values in list(self.node_fields.items()): @@ -4436,9 +4821,10 @@ def create_side_set_from_expression(self, self.create_side_set(side_set_id, members) if zero_member_warning and not members: self._warning( - 'Empty side set.', - 'No external element faces satisfied the given ' - 'expression. An empty side set was created.') + "Empty side set.", + "No external element faces satisfied the given " + "expression. An empty side set was created.", + ) def create_side_set(self, side_set_id, side_set_members=None): """ @@ -4460,16 +4846,16 @@ def create_side_set(self, side_set_id, side_set_members=None): side_set_members = [] # ensure set set id doesn't exist if self.side_set_exists(side_set_id): - self._exists_warning(side_set_id, 'side set') - unique_members = self._remove_duplicates(side_set_members, - preserve_order=True) + self._exists_warning(side_set_id, "side set") + unique_members = self._remove_duplicates(side_set_members, preserve_order=True) if len(unique_members) != len(side_set_members): self._warning( - 'Duplicate faces in set.', - 'The face set member list contains multiple copies ' - 'of some faces. These faces will only be added ' - 'once.') - self.side_sets[side_set_id] = ['', unique_members, {}] + "Duplicate faces in set.", + "The face set member list contains multiple copies " + "of some faces. These faces will only be added " + "once.", + ) + self.side_sets[side_set_id] = ["", unique_members, {}] def add_faces_to_side_set(self, side_set_id, new_side_set_members): """ @@ -4484,23 +4870,26 @@ def add_faces_to_side_set(self, side_set_id, new_side_set_members): """ if not self.side_set_exists(side_set_id): - self._warning('Side set does not exist.' - 'The specified side set "%s% does not exist. It ' - 'will be created.' % side_set_id) + self._warning( + "Side set does not exist." + 'The specified side set "%s% does not exist. It ' + "will be created." % side_set_id + ) self.create_side_set(side_set_id, new_side_set_members) return members = self.get_side_set_members(side_set_id) fields = self._get_side_set_fields(side_set_id) # remove duplicate faces - new_members = self._remove_duplicates(new_side_set_members, - other_list=members, - preserve_order=True) + new_members = self._remove_duplicates( + new_side_set_members, other_list=members, preserve_order=True + ) if len(new_members) != len(new_side_set_members): self._warning( - 'Duplicates faces in set', - 'The node set already contains some nodes of the ' - 'faces in the list to add. These members will not ' - 'be duplicated.') + "Duplicates faces in set", + "The node set already contains some nodes of the " + "faces in the list to add. These members will not " + "be duplicated.", + ) # add the members members.extend(new_members) # add new values to each field @@ -4519,9 +4908,9 @@ def delete_node_field(self, node_field_names): >>> model.delete_node_field('disp_*') """ - node_field_names = self._format_id_list(node_field_names, - self.get_node_field_names(), - 'node field') + node_field_names = self._format_id_list( + node_field_names, self.get_node_field_names(), "node field" + ) for node_field_name in node_field_names: del self.node_fields[node_field_name] @@ -4537,11 +4926,9 @@ def delete_timestep(self, timesteps): >>> model.delete_timestep('all') """ - timesteps = self._format_id_list(timesteps, self.get_timesteps(), - 'timestep') + timesteps = self._format_id_list(timesteps, self.get_timesteps(), "timestep") # get list of deleted indices in descending order - deleted_indices = reversed( - sorted([self.timesteps.index(x) for x in timesteps])) + deleted_indices = reversed(sorted([self.timesteps.index(x) for x in timesteps])) for index in deleted_indices: # process element fields for element_block_id in self.get_element_block_ids(): @@ -4567,9 +4954,7 @@ def delete_timestep(self, timesteps): # delete the timestep del self.timesteps[index] - def delete_element_block(self, - element_block_ids, - delete_orphaned_nodes=True): + def delete_element_block(self, element_block_ids, delete_orphaned_nodes=True): """ Delete one or more element blocks. @@ -4585,8 +4970,7 @@ def delete_element_block(self, >>> model.delete_element_block([1, 3, 4]) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # if we're not deleting anything, skip some computations. if not element_block_ids: return @@ -4618,13 +5002,12 @@ def delete_element_block(self, if delete_orphaned_nodes: new_unreferenced_nodes = self._get_unreferenced_nodes() nodes_to_delete = sorted( - set(new_unreferenced_nodes) - set(unreferenced_nodes)) + set(new_unreferenced_nodes) - set(unreferenced_nodes) + ) if nodes_to_delete: self._delete_nodes(nodes_to_delete) - def delete_element_field(self, - element_field_names, - element_block_ids='all'): + def delete_element_field(self, element_field_names, element_block_ids="all"): """ Delete one or more element fields. @@ -4633,11 +5016,10 @@ def delete_element_field(self, >>> model.delete_element_field('all') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) element_field_names = self._format_id_list( - element_field_names, self.get_element_field_names(), - 'element field') + element_field_names, self.get_element_field_names(), "element field" + ) # for each field for element_field_name in element_field_names: any_deleted = False @@ -4649,12 +5031,13 @@ def delete_element_field(self, del fields[element_field_name] if not any_deleted: self._warning( - 'Element field not defined.', + "Element field not defined.", 'The element field "%s" was not defined on any ' - 'of the given element blocks. It cannot be ' - 'deleted.' % element_field_name) + "of the given element blocks. It cannot be " + "deleted." % element_field_name, + ) - def delete_node_set_field(self, node_set_field_names, node_set_ids='all'): + def delete_node_set_field(self, node_set_field_names, node_set_ids="all"): """ Delete one or more node set fields. @@ -4664,8 +5047,8 @@ def delete_node_set_field(self, node_set_field_names, node_set_ids='all'): """ node_set_ids = self._format_node_set_id_list(node_set_ids) node_set_field_names = self._format_id_list( - node_set_field_names, self.get_node_set_field_names(), - 'node set field') + node_set_field_names, self.get_node_set_field_names(), "node set field" + ) # for each field for name in node_set_field_names: any_deleted = False @@ -4677,12 +5060,13 @@ def delete_node_set_field(self, node_set_field_names, node_set_ids='all'): del fields[name] if not any_deleted: self._warning( - 'Node set field not defined.', + "Node set field not defined.", 'The node set field "%s" was not defined on any ' - 'of the given node sets. It cannot be ' - 'deleted.' % name) + "of the given node sets. It cannot be " + "deleted." % name, + ) - def delete_side_set_field(self, side_set_field_names, side_set_ids='all'): + def delete_side_set_field(self, side_set_field_names, side_set_ids="all"): """ Delete one or more side set fields. @@ -4692,8 +5076,8 @@ def delete_side_set_field(self, side_set_field_names, side_set_ids='all'): """ side_set_ids = self._format_side_set_id_list(side_set_ids) side_set_field_names = self._format_id_list( - side_set_field_names, self.get_side_set_field_names(), - 'side set field') + side_set_field_names, self.get_side_set_field_names(), "side set field" + ) # for each field for name in side_set_field_names: any_deleted = False @@ -4705,10 +5089,11 @@ def delete_side_set_field(self, side_set_field_names, side_set_ids='all'): del fields[name] if not any_deleted: self._warning( - 'Side set field not defined.', + "Side set field not defined.", 'The side set field "%s" was not defined on any ' - 'of the given side sets. It cannot be ' - 'deleted.' % name) + "of the given side sets. It cannot be " + "deleted." % name, + ) def global_variable_exists(self, global_variable_name): """ @@ -4720,7 +5105,7 @@ def global_variable_exists(self, global_variable_name): """ return global_variable_name in self.global_variables - def side_set_field_exists(self, side_set_field_name, side_set_ids='all'): + def side_set_field_exists(self, side_set_field_name, side_set_ids="all"): """ Return 'True' if the side set field exists on the side sets. @@ -4735,7 +5120,7 @@ def side_set_field_exists(self, side_set_field_name, side_set_ids='all'): return False return True - def node_set_field_exists(self, node_set_field_name, node_set_ids='all'): + def node_set_field_exists(self, node_set_field_name, node_set_ids="all"): """ Return 'True' if the node set field is defined on the node sets. @@ -4750,8 +5135,7 @@ def node_set_field_exists(self, node_set_field_name, node_set_ids='all'): return False return True - def element_field_exists(self, element_field_name, - element_block_ids='all'): + def element_field_exists(self, element_field_name, element_block_ids="all"): """ Return 'True' if the element field exists on the element blocks. @@ -4759,8 +5143,7 @@ def element_field_exists(self, element_field_name, >>> model.element_field_exists('eqps') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) for id_ in element_block_ids: fields = self.element_blocks[id_][-1] if element_field_name not in fields: @@ -4826,7 +5209,7 @@ def timestep_exists(self, timestep): """ return timestep in self.timesteps - def get_node_field_values(self, node_field_name, timestep='last'): + def get_node_field_values(self, node_field_name, timestep="last"): """ Return the list of node field values for the given field and timestep. @@ -4838,10 +5221,9 @@ def get_node_field_values(self, node_field_name, timestep='last'): >>> model.get_node_field_values('disp_x', 0.0) """ - [node_field_name] = self._format_id_list([node_field_name], - self.get_node_field_names(), - 'node field', - single=True) + [node_field_name] = self._format_id_list( + [node_field_name], self.get_node_field_names(), "node field", single=True + ) timestep_index = self._get_internal_timestep_index(timestep) return self.node_fields[node_field_name][timestep_index] @@ -4877,20 +5259,22 @@ def _get_face_mapping(self, element_name): element_type = self._get_standard_element_type(element_name) if element_type not in self.FACE_MAPPING: self._error( - 'Undefined face mapping.', - 'The mapping defining which nodes belong to a given ' - 'face has not been defined for the \"%s\" element ' - 'type. This could be because it has not been ' - 'implemented or because the element type is ' - 'invalid. Mappings for the following element types ' - 'are defined: %s' % - (element_name, ', '.join(list(self.FACE_MAPPING.keys())))) + "Undefined face mapping.", + "The mapping defining which nodes belong to a given " + 'face has not been defined for the "%s" element ' + "type. This could be because it has not been " + "implemented or because the element type is " + "invalid. Mappings for the following element types " + "are defined: %s" + % (element_name, ", ".join(list(self.FACE_MAPPING.keys()))), + ) return self.FACE_MAPPING[element_type] def _get_face_mapping_from_id(self, element_block_id): """Return the face mapping from the element block id.""" [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) element_type = self._get_element_type(element_block_id) element_type = self._get_standard_element_type(element_type) return self._get_face_mapping(element_type) @@ -4914,13 +5298,12 @@ def get_nodes_in_side_set(self, side_set_id): if block_id != last_element_block_id or face_mapping is None: last_element_block_id = block_id nodes_per_element = self.get_nodes_per_element(block_id) - face_mapping = self._get_face_mapping( - self._get_element_type(block_id)) + face_mapping = self._get_face_mapping(self._get_element_type(block_id)) connectivity = self.get_connectivity(block_id) for local_index in face_mapping[face_index][1]: included_nodes.append( - connectivity[element_index * nodes_per_element + - local_index]) + connectivity[element_index * nodes_per_element + local_index] + ) # return list after deleting duplicates included_nodes = sorted(set(included_nodes)) return included_nodes @@ -4966,7 +5349,7 @@ def _minimum_face(self, face, face_type): face = self._rotate_face(face, face_type) return best, best_count - def _get_internal_faces(self, element_block_ids='all', set_of_nodes=None): + def _get_internal_faces(self, element_block_ids="all", set_of_nodes=None): """ Return a list of internal element faces. @@ -4976,8 +5359,7 @@ def _get_internal_faces(self, element_block_ids='all', set_of_nodes=None): TODO: Not sure this handles 'element_block_ids' correctly. """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # hold internal faces internal_faces = dict() # hold faces which need matched @@ -4997,12 +5379,12 @@ def _get_internal_faces(self, element_block_ids='all', set_of_nodes=None): element_count = self.get_element_count(id_) nodes_per_element = self.get_nodes_per_element(id_) for element_index in range(element_count): - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] - for face_index, (face_type, - face_mapping) in enumerate(face_mappings): + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] + for face_index, (face_type, face_mapping) in enumerate(face_mappings): this_member = (id_, element_index, face_index) this_face = tuple(local_node[x] for x in face_mapping) # skip the face if no nodes are relevant @@ -5011,7 +5393,8 @@ def _get_internal_faces(self, element_block_ids='all', set_of_nodes=None): continue # transform into lowest form unique_face, unique_offset = self._minimum_face( - this_face, face_type) + this_face, face_type + ) # match if possible match = faces_to_match.pop((face_type, unique_face), None) # if no match, add it @@ -5019,11 +5402,13 @@ def _get_internal_faces(self, element_block_ids='all', set_of_nodes=None): # invert and transform into lowest form inverted_face = self._invert_face(this_face, face_type) inverted_face, inverted_offset = self._minimum_face( - inverted_face, face_type) + inverted_face, face_type + ) # add it and continue - faces_to_match[(face_type, - inverted_face)] = (this_member, - inverted_offset) + faces_to_match[(face_type, inverted_face)] = ( + this_member, + inverted_offset, + ) continue # set first mapping transform = (match[1] - unique_offset) % len(this_face) @@ -5041,8 +5426,7 @@ def _get_face_indices(self, member): This function is slow. """ - face_mapping = self._get_face_mapping(self._get_element_type( - member[0])) + face_mapping = self._get_face_mapping(self._get_element_type(member[0])) nodes_per_element = self.get_nodes_per_element(member[0]) connectivity = self.get_connectivity(member[0]) return [ @@ -5050,8 +5434,7 @@ def _get_face_indices(self, member): for x in face_mapping[member[2]][1] ] - def convert_side_set_to_cohesive_zone(self, side_set_ids, - new_element_block_id): + def convert_side_set_to_cohesive_zone(self, side_set_ids, new_element_block_id): """ Convert the given side sets into a block of cohesive zone elements. @@ -5072,8 +5455,8 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, return # order all faces by element block members_by_block = self._order_element_faces_by_block( - itertools.chain( - *[self.get_side_set_members(x) for x in side_set_ids])) + itertools.chain(*[self.get_side_set_members(x) for x in side_set_ids]) + ) # find face shape face_type = set() element_types = set() @@ -5085,18 +5468,20 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, # ensure single face type if len(face_type) != 1: self._error( - 'Multiple face types', - 'The side set contains multiple types of faces and ' - 'cannot be converted into a cohesive zone.') + "Multiple face types", + "The side set contains multiple types of faces and " + "cannot be converted into a cohesive zone.", + ) # ensure face type is supported face_type = sorted(face_type)[0] if face_type not in self.COHESIVE_FORMULA: self._bug( - 'Unsupported face type', + "Unsupported face type", 'The side set chosen has elements of face type "%s". ' - 'At this time, only the following face types are ' - 'supported:\n* %s' % - (face_type, '\n* '.join(sorted(self.COHESIVE_FORMULA.keys())))) + "At this time, only the following face types are " + "supported:\n* %s" + % (face_type, "\n* ".join(sorted(self.COHESIVE_FORMULA.keys()))), + ) # for each element type, find adjacent faces # (adjacent faces in this context are faces which share one or more # nodes) @@ -5109,7 +5494,8 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, for face_one in range(face_count): for face_two in range(face_count): if set(face_mapping[face_one][1]).intersection( - face_mapping[face_two][1]): + face_mapping[face_two][1] + ): adjacent_face[face_one].append(face_two) adjacent_faces[element_type] = adjacent_face # create a set of all nodes in the side set @@ -5118,7 +5504,8 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, nodes_on_surface.update(self.get_nodes_in_side_set(side_set_id)) # find all relevant internal faces internal_faces = self._get_internal_faces( - list(members_by_block.keys()), set_of_nodes=nodes_on_surface) + list(members_by_block.keys()), set_of_nodes=nodes_on_surface + ) # create a set of all free faces free_faces = set() for id_, members in list(members_by_block.items()): @@ -5128,10 +5515,11 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, matching_face = internal_faces.get(face, None) if not matching_face: self._error( - 'Invalid face', - 'One or more members of the side set are ' - 'external faces which cannot be converted ' - 'to cohesive elements.') + "Invalid face", + "One or more members of the side set are " + "external faces which cannot be converted " + "to cohesive elements.", + ) free_faces.add(matching_face[0]) # count the number of times each node is used node_use_count = [0] * len(self.nodes) @@ -5142,8 +5530,7 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, # hold a list of all nodes to duplicate nodes_to_duplicate = [] for node_index in nodes_on_surface: - nodes_to_duplicate.extend([node_index] * - node_use_count[node_index]) + nodes_to_duplicate.extend([node_index] * node_use_count[node_index]) nodes_to_duplicate.sort() # duplicate nodes first_new_node_index = len(self.nodes) @@ -5156,9 +5543,7 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, next_index[old_index] = new_index # for faster lookup, create a vector to see if a given node # is on the cohesive zone - node_in_zone = [ - x in nodes_on_surface for x in range(first_new_node_index) - ] + node_in_zone = [x in nodes_on_surface for x in range(first_new_node_index)] # for each element, unmerge nodes on the cohesive zone for id_ in self.get_element_block_ids(): connectivity = self.get_connectivity(id_) @@ -5168,8 +5553,7 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, next_index[value] += 1 # find pairs of nodes which need merged node_pairs = set() - for old_face, (new_face, - transform_count) in list(internal_faces.items()): + for old_face, (new_face, transform_count) in list(internal_faces.items()): # since the list is duplicated, only operate on one if old_face > new_face: continue @@ -5182,16 +5566,15 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, original = self._invert_face(original, face_type) for _ in range(transform_count): original = self._rotate_face(original, face_type) - node_pairs.update((min(x, y), max(x, y)) - for x, y in zip(original, target) if x != y) + node_pairs.update( + (min(x, y), max(x, y)) for x, y in zip(original, target) if x != y + ) # merge nodes self._merge_node_pairs(node_pairs) # delete nodes we created that are no longer referenced as well as the # original nodes which are no longer used nodes_to_delete = self._get_unreferenced_nodes() - nodes_to_delete = [ - x for x in nodes_to_delete if x >= first_new_node_index - ] + nodes_to_delete = [x for x in nodes_to_delete if x >= first_new_node_index] nodes_to_delete.extend(nodes_on_surface) self._delete_nodes(nodes_to_delete) # get the formula for converting two faces into a cohesive element @@ -5214,15 +5597,15 @@ def convert_side_set_to_cohesive_zone(self, side_set_ids, # add this element to the connectivity list connectivity.extend(this_connectivity) # create the actual element block - self.create_element_block(new_element_block_id, [ - formula[0], - len(connectivity) // nodes_per_element, nodes_per_element, 0 - ], connectivity) + self.create_element_block( + new_element_block_id, + [formula[0], len(connectivity) // nodes_per_element, nodes_per_element, 0], + connectivity, + ) - def create_averaged_element_field(self, - from_element_field_names, - new_element_field_name, - element_block_ids='all'): + def create_averaged_element_field( + self, from_element_field_names, new_element_field_name, element_block_ids="all" + ): """ Create an element field by averaging the given field values. @@ -5234,10 +5617,9 @@ def create_averaged_element_field(self, """ # format the arguments from_element_field_names = self._format_id_list( - from_element_field_names, self.get_element_field_names(), - 'element field') - element_block_ids = self._format_element_block_id_list( - element_block_ids) + from_element_field_names, self.get_element_field_names(), "element field" + ) + element_block_ids = self._format_element_block_id_list(element_block_ids) # for each timestep for element_block_id in element_block_ids: fields = self._get_element_block_fields(element_block_id) @@ -5249,21 +5631,22 @@ def create_averaged_element_field(self, break if not all_defined: self._warning( - 'Fields not defined.', - 'Not all of the requested element fields are ' - 'defined on element block %s. The averaged ' - 'field will not be created.' % element_block_id) + "Fields not defined.", + "Not all of the requested element fields are " + "defined on element block %s. The averaged " + "field will not be created." % element_block_id, + ) continue # create the field if it doesn't exist - if self.element_field_exists(new_element_field_name, - element_block_id): - self._exists_on_entity_warning(new_element_field_name, - 'element field', - element_block_id, - 'element block') + if self.element_field_exists(new_element_field_name, element_block_id): + self._exists_on_entity_warning( + new_element_field_name, + "element field", + element_block_id, + "element block", + ) else: - self.create_element_field(new_element_field_name, - element_block_id) + self.create_element_field(new_element_field_name, element_block_id) # get lists to average field_list = [] for name in from_element_field_names: @@ -5273,14 +5656,12 @@ def create_averaged_element_field(self, field_count = len(from_element_field_names) for timestep_index in range(len(self.timesteps)): lists_to_average = [x[timestep_index] for x in field_list] - averaged_field = [ - sum(x) / field_count for x in zip(*lists_to_average) - ] + averaged_field = [sum(x) / field_count for x in zip(*lists_to_average)] new_element_field[timestep_index] = averaged_field - def convert_element_field_to_node_field(self, - element_field_name, - node_field_name='auto'): + def convert_element_field_to_node_field( + self, element_field_name, node_field_name="auto" + ): """ Convert an element field to a node field by performing. @@ -5298,10 +5679,11 @@ def convert_element_field_to_node_field(self, [element_field_name] = self._format_id_list( [element_field_name], self.get_element_field_names(), - 'element field', - single=True) + "element field", + single=True, + ) # format the arguments - if node_field_name == 'auto': + if node_field_name == "auto": node_field_name = element_field_name # create the field self.create_node_field(node_field_name) @@ -5317,40 +5699,36 @@ def convert_element_field_to_node_field(self, # for each element block for element_block_id in self.get_element_block_ids(): # if field doesn't exist on this element, skip it - if not self.element_field_exists(element_field_name, - element_block_id): + if not self.element_field_exists(element_field_name, element_block_id): continue # store connectivity connectivity = self.get_connectivity(element_block_id) # for each node within each element fields = self._get_element_block_fields(element_block_id) - element_field_values = fields[element_field_name][ - timestep_index] - nodes_per_element = self.get_nodes_per_element( - element_block_id) + element_field_values = fields[element_field_name][timestep_index] + nodes_per_element = self.get_nodes_per_element(element_block_id) element_count = self.get_element_count(element_block_id) for element_index in range(element_count): for node_index in range(nodes_per_element): - this_node = connectivity[element_index * - nodes_per_element + - node_index] + this_node = connectivity[ + element_index * nodes_per_element + node_index + ] node_field_values[this_node] += element_field_values[ - element_index] + element_index + ] node_field_elements[this_node] += 1 # average each value, or replace with default value for node_index in range(len(self.nodes)): if node_field_elements[node_index] == 0: node_field_values[node_index] = default_value else: - node_field_values[node_index] /= node_field_elements[ - node_index] + node_field_values[node_index] /= node_field_elements[node_index] # replace field values with generated values node_field[timestep_index] = node_field_values - def convert_node_field_to_element_field(self, - node_field_name, - element_field_name='auto', - element_block_ids='all'): + def convert_node_field_to_element_field( + self, node_field_name, element_field_name="auto", element_block_ids="all" + ): """ Convert a node field to an element field. @@ -5361,14 +5739,12 @@ def convert_node_field_to_element_field(self, >>> model.convert_node_field_to_element_field('temperature') """ - [node_field_name] = self._format_id_list([node_field_name], - self.get_node_field_names(), - 'node field', - single=True) - element_block_ids = self._format_element_block_id_list( - element_block_ids) + [node_field_name] = self._format_id_list( + [node_field_name], self.get_node_field_names(), "node field", single=True + ) + element_block_ids = self._format_element_block_id_list(element_block_ids) # format the arguments - if element_field_name == 'auto': + if element_field_name == "auto": element_field_name = node_field_name # store the node field node_field = self.node_fields[node_field_name] @@ -5388,8 +5764,9 @@ def convert_node_field_to_element_field(self, # for each node within each element for connectivity_index, node_index in enumerate(connectivity): element_index = connectivity_index // nodes_per_element - element_field_values[element_index] += node_field[ - timestep_index][node_index] + element_field_values[element_index] += node_field[timestep_index][ + node_index + ] # average each value element_field_values = [ x / float(nodes_per_element) for x in element_field_values @@ -5412,14 +5789,14 @@ def _find_member_indices_to_keep(self, all_members, members_to_delete): invalid_entries = members_to_delete_set - all_members_set if invalid_entries: self._warning( - 'Invalid members', - 'The member list contains entries that were not ' - 'members. There were %d such occurrences. These ' - 'will be ignored.' % (len(invalid_entries))) + "Invalid members", + "The member list contains entries that were not " + "members. There were %d such occurrences. These " + "will be ignored." % (len(invalid_entries)), + ) # find members to delete indices_to_keep = [ - i for i, x in enumerate(all_members) - if x not in members_to_delete_set + i for i, x in enumerate(all_members) if x not in members_to_delete_set ] return indices_to_keep @@ -5437,12 +5814,12 @@ def _delete_side_set_members(self, side_set_id, side_set_members): members = self.get_side_set_members(side_set_id) fields = self._get_side_set_fields(side_set_id) # find members to keep - indices_to_keep = self._find_member_indices_to_keep( - members, side_set_members) + indices_to_keep = self._find_member_indices_to_keep(members, side_set_members) # delete members from node set fields for all_values in list(fields.values()): - all_values[:] = [[values[x] for x in indices_to_keep] - for values in all_values] + all_values[:] = [ + [values[x] for x in indices_to_keep] for values in all_values + ] # delete members members[:] = [members[x] for x in indices_to_keep] @@ -5460,10 +5837,12 @@ def _delete_node_set_members(self, node_set_id, node_set_members): node_set = self.node_sets[node_set_id] # find members to keep indices_to_keep = self._find_member_indices_to_keep( - node_set[0], node_set_members) + node_set[0], node_set_members + ) # delete members from node set fields - node_set[-1] = [[these_values[x] for x in indices_to_keep] - for these_values in node_set[1]] + node_set[-1] = [ + [these_values[x] for x in indices_to_keep] for these_values in node_set[1] + ] # delete members node_set[0] = [node_set[0][x] for x in indices_to_keep] @@ -5501,17 +5880,16 @@ def _delete_nodes(self, node_list): new_connectivity = [node_map[x] for x in connectivity] if None in new_connectivity: self._error( - 'Node still used.', - 'A node in the list of nodes to delete is still ' - 'used by elements in element block %d and cannot ' - 'be deleted.' % element_block_id) + "Node still used.", + "A node in the list of nodes to delete is still " + "used by elements in element block %d and cannot " + "be deleted." % element_block_id, + ) connectivity[:] = new_connectivity # update node fields for field in list(self.node_fields.values()): for timestep_index in range(len(self.timesteps)): - new_values = [ - field[timestep_index][x] for x in reverse_node_map - ] + new_values = [field[timestep_index][x] for x in reverse_node_map] field[timestep_index] = new_values # delete nodes from node sets and fields for node_set_id in self.get_node_set_ids(): @@ -5539,9 +5917,7 @@ def _get_unreferenced_nodes(self): connectivity = self.get_connectivity(id_) for node_index in connectivity: used_node[node_index] = True - unused_nodes = [ - index for index, used in enumerate(used_node) if not used - ] + unused_nodes = [index for index, used in enumerate(used_node) if not used] return unused_nodes def delete_unused_nodes(self): @@ -5568,8 +5944,8 @@ def delete_global_variable(self, global_variable_names): """ global_variable_names = self._format_id_list( - global_variable_names, self.get_global_variable_names(), - 'global variable') + global_variable_names, self.get_global_variable_names(), "global variable" + ) for name in global_variable_names: del self.global_variables[name] @@ -5636,25 +6012,24 @@ def summarize(self): >>> model.summarize() """ - print('The model contains the following:') - print((' %d elements' % (self.get_element_count()))) - print((' %d timesteps' % (len(self.timesteps)))) - print((' %d global variables' % (len(self.global_variables)))) - print((' %d nodes' % (len(self.nodes)))) - print((' %d node fields' % (len(self.node_fields)))) - print((' %d element blocks' % (len(self.element_blocks)))) - print((' %d element fields' % (len(self.get_element_field_names())))) - print((' %d node sets' % (len(self.node_sets)))) - print( - (' %d node set fields' % (len(self.get_node_set_field_names())))) - print((' %d side sets' % (len(self.side_sets)))) - print( - (' %d side set fields' % (len(self.get_side_set_field_names())))) + print("The model contains the following:") + print((" %d elements" % (self.get_element_count()))) + print((" %d timesteps" % (len(self.timesteps)))) + print((" %d global variables" % (len(self.global_variables)))) + print((" %d nodes" % (len(self.nodes)))) + print((" %d node fields" % (len(self.node_fields)))) + print((" %d element blocks" % (len(self.element_blocks)))) + print((" %d element fields" % (len(self.get_element_field_names())))) + print((" %d node sets" % (len(self.node_sets)))) + print((" %d node set fields" % (len(self.get_node_set_field_names())))) + print((" %d side sets" % (len(self.side_sets)))) + print((" %d side set fields" % (len(self.get_side_set_field_names())))) def _get_element_block_fields(self, element_block_id): """Return the dictionary of element block field values.""" [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) return self.element_blocks[element_block_id][-1] def _get_node_set_fields(self, node_set_id): @@ -5662,7 +6037,7 @@ def _get_node_set_fields(self, node_set_id): [node_set_id] = self._format_node_set_id_list([node_set_id], single=True) return self.node_sets[node_set_id][-1] - def get_element_count(self, element_block_ids='all'): + def get_element_count(self, element_block_ids="all"): """ Return the total number of elements in the given element blocks. @@ -5670,11 +6045,10 @@ def get_element_count(self, element_block_ids='all'): >>> print((' %d elements' % (object.get_element_count()))) """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) return int(sum(self.element_blocks[x][1][1] for x in element_block_ids)) - def process_element_fields(self, element_block_ids='all'): + def process_element_fields(self, element_block_ids="all"): """ Process element field information to create node based fields. @@ -5692,42 +6066,37 @@ def process_element_fields(self, element_block_ids='all'): >>> model.process_element_fields() """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # for each element block for block_id in element_block_ids: element_field_names = self.get_element_field_names(block_id) for element_field_name in element_field_names: # if it's the first integration point, count the total number # and process accordingly - if re.match('^.*_1$', element_field_name): + if re.match("^.*_1$", element_field_name): prefix = element_field_name[:-1] points = 1 - while self.element_field_exists(prefix + str(points + 1), - block_id): + while self.element_field_exists(prefix + str(points + 1), block_id): points += 1 if points == 9: - self.rename_element_field(prefix + '1', prefix[:-1], - block_id) + self.rename_element_field(prefix + "1", prefix[:-1], block_id) for i in range(2, 10): - self.delete_element_field(prefix + str(i), - block_id) + self.delete_element_field(prefix + str(i), block_id) elif points == 8: self.create_averaged_element_field( [prefix + str(x) for x in range(1, 9)], - prefix[:-1], block_id) + prefix[:-1], + block_id, + ) for i in range(1, 9): - self.delete_element_field(prefix + str(i), - block_id) + self.delete_element_field(prefix + str(i), block_id) # nodal average all fields for element_field_name in self.get_element_field_names(): self.convert_element_field_to_node_field(element_field_name) # delete element fields - self.delete_element_field('all') + self.delete_element_field("all") - def combine_element_blocks(self, - element_block_ids, - target_element_block_id='auto'): + def combine_element_blocks(self, element_block_ids, target_element_block_id="auto"): """ Combine multiple element blocks into a single block. @@ -5741,35 +6110,39 @@ def combine_element_blocks(self, """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) - if target_element_block_id == 'auto': + element_block_ids, empty_list_okay=False + ) + if target_element_block_id == "auto": target_element_block_id = min(element_block_ids) if len(element_block_ids) == 1: - self.rename_element_block(element_block_ids[0], - target_element_block_id) + self.rename_element_block(element_block_ids[0], target_element_block_id) return # ensure all blocks have the same number of nodes per element nodes_per_element = set( - self.get_nodes_per_element(x) for x in element_block_ids) + self.get_nodes_per_element(x) for x in element_block_ids + ) if len(nodes_per_element) != 1: self._error( - 'Incompatible element types.', - 'The number of nodes per element on each element ' - 'block to be merged must by the same. This is an ' - 'ExodusII file requirement.') + "Incompatible element types.", + "The number of nodes per element on each element " + "block to be merged must by the same. This is an " + "ExodusII file requirement.", + ) # ensure all blocks are the same type element_types = set( self._get_standard_element_type(self._get_element_type(x)) - for x in element_block_ids) + for x in element_block_ids + ) if len(element_types) != 1: self._warning( - 'Element types vary.', - 'The element types of the merged blocks differ. ' - 'This may cause issues.') + "Element types vary.", + "The element types of the merged blocks differ. " + "This may cause issues.", + ) # create new connectivity new_connectivity = list( - itertools.chain( - *[self.get_connectivity(x) for x in element_block_ids])) + itertools.chain(*[self.get_connectivity(x) for x in element_block_ids]) + ) # create new info new_info = list(self._get_block_info(element_block_ids[0])) # set element count to zero @@ -5778,8 +6151,7 @@ def combine_element_blocks(self, temporary_element_block_id = self._new_element_block_id() # create translation list for elements # new_block[old_block_id] = (new_block_id, element_offset) - new_block_info = dict( - (id_, (id_, 0)) for id_ in self.get_element_block_ids()) + new_block_info = dict((id_, (id_, 0)) for id_ in self.get_element_block_ids()) for id_ in element_block_ids: new_block_info[id_] = (temporary_element_block_id, new_info[1]) new_info[1] += self.element_blocks[id_][1][1] @@ -5791,12 +6163,13 @@ def combine_element_blocks(self, if not self.element_field_exists(name, id_): if give_nonexistant_field_warning: self._warning( - 'Inconsistent element fields.', + "Inconsistent element fields.", 'The element field "%s" is not defined ' - 'on all element blocks included in the ' - 'merging operation. It will be ' - 'created. Future warnings of this type ' - 'will be suppressed.' % name) + "on all element blocks included in the " + "merging operation. It will be " + "created. Future warnings of this type " + "will be suppressed." % name, + ) give_nonexistant_field_warning = False self.create_element_field(name, id_) # create new field information @@ -5804,37 +6177,36 @@ def combine_element_blocks(self, for name in element_field_names: new_values = [[] for _ in self.timesteps] for id_ in element_block_ids: - for index, values in enumerate( - self.element_blocks[id_][-1][name]): + for index, values in enumerate(self.element_blocks[id_][-1][name]): new_values[index].extend(values) new_fields[name] = new_values # create new block - self.create_element_block(temporary_element_block_id, new_info, - new_connectivity) + self.create_element_block( + temporary_element_block_id, new_info, new_connectivity + ) self.element_blocks[temporary_element_block_id][-1] = new_fields # translate side set members for side_set_id in self.get_side_set_ids(): members = self.get_side_set_members(side_set_id) new_members = [ - (new_block_info[element_block_id][0], - element_index + new_block_info[element_block_id][1], - face_index) + ( + new_block_info[element_block_id][0], + element_index + new_block_info[element_block_id][1], + face_index, + ) for element_block_id, element_index, face_index in members ] members[:] = new_members # delete old blocks # (nodes can not be orphaned by this procedure) for element_block_id in element_block_ids: - self.delete_element_block(element_block_id, - delete_orphaned_nodes=False) + self.delete_element_block(element_block_id, delete_orphaned_nodes=False) # rename element block - self.rename_element_block(temporary_element_block_id, - target_element_block_id) + self.rename_element_block(temporary_element_block_id, target_element_block_id) - def duplicate_element_block(self, - element_block_id, - new_element_block_id, - duplicate_nodes=True): + def duplicate_element_block( + self, element_block_id, new_element_block_id, duplicate_nodes=True + ): """ Create an duplicate of the given element block. @@ -5846,7 +6218,8 @@ def duplicate_element_block(self, """ [element_block_id] = self._format_element_block_id_list( - [element_block_id], single=True) + [element_block_id], single=True + ) info = list(self._get_block_info(element_block_id)) old_connectivity = self.get_connectivity(element_block_id) # create new nodes @@ -5855,7 +6228,8 @@ def duplicate_element_block(self, new_node_indices = [] self._duplicate_nodes(unique_node_indices, new_node_indices) new_node_indices = dict( - (x, y) for x, y in zip(unique_node_indices, new_node_indices)) + (x, y) for x, y in zip(unique_node_indices, new_node_indices) + ) new_connectivity = [new_node_indices[x] for x in old_connectivity] else: new_connectivity = list(old_connectivity) @@ -5864,7 +6238,8 @@ def duplicate_element_block(self, # copy fields fields = dict() for name, all_values in list( - self._get_element_block_fields(element_block_id).items()): + self._get_element_block_fields(element_block_id).items() + ): fields[name] = [list(x) for x in all_values] self.element_blocks[new_element_block_id][-1] = fields # update side sets and side set fields @@ -5875,8 +6250,7 @@ def duplicate_element_block(self, source_face = [] for index, member in enumerate(members): if member[0] == element_block_id: - new_members.append( - (new_element_block_id, member[1], member[2])) + new_members.append((new_element_block_id, member[1], member[2])) source_face.append(index) members.extend(new_members) for all_values in list(fields.values()): @@ -5889,9 +6263,10 @@ def _get_inverted_connectivity(self, element_type): element_type = self._get_standard_element_type(element_type) if element_type not in self.INVERTED_CONNECTIVITY: self._error( - 'Unknown inversion algorithm.', - 'The required numbering to invert an element of type ' - '"%s" is not defined.' % element_type) + "Unknown inversion algorithm.", + "The required numbering to invert an element of type " + '"%s" is not defined.' % element_type, + ) return self.INVERTED_CONNECTIVITY[element_type] def _get_inverted_face_mapping(self, element_type): @@ -5899,28 +6274,27 @@ def _get_inverted_face_mapping(self, element_type): face_mapping = self._get_face_mapping(element_type) inversion_mapping = self._get_inverted_connectivity(element_type) original_face = [set(face) for _, face in face_mapping] - new_face = [ - set(inversion_mapping[x] for x in face) for _, face in face_mapping - ] + new_face = [set(inversion_mapping[x] for x in face) for _, face in face_mapping] try: new_face = [original_face.index(x) for x in new_face] except ValueError: self._bug( - 'Unable to determine face mapping.', - 'We were unable to determine how to map faces when ' - 'inverting an element of type "%s".' % element_type) + "Unable to determine face mapping.", + "We were unable to determine how to map faces when " + 'inverting an element of type "%s".' % element_type, + ) return new_face def _invert_element_blocks(self, element_block_ids): """Invert all elements within one or more element blocks.""" - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) for id_ in element_block_ids: element_count = self.get_element_count(id_) nodes_per_element = self.get_nodes_per_element(id_) # invert the connectivity inverted_mapping = self._get_inverted_connectivity( - self._get_element_type(id_)) + self._get_element_type(id_) + ) connectivity = self.get_connectivity(id_) new_connectivity = [ connectivity[element_index * nodes_per_element + x] @@ -5930,13 +6304,13 @@ def _invert_element_blocks(self, element_block_ids): connectivity[:] = new_connectivity # adjust side set members new_face_indices = self._get_inverted_face_mapping( - self._get_element_type(id_)) + self._get_element_type(id_) + ) for side_set_id in self.get_side_set_ids(): members = self.get_side_set_members(side_set_id) for index, member in enumerate(members): if member[0] == id_: - members[index] = (id_, member[1], - new_face_indices[member[2]]) + members[index] = (id_, member[1], new_face_indices[member[2]]) def create_element_block(self, element_block_id, info, connectivity=None): """ @@ -5962,12 +6336,12 @@ def create_element_block(self, element_block_id, info, connectivity=None): """ # make sure it doesn't exist already if self.element_block_exists(element_block_id): - self._exists_error(element_block_id, 'element block') + self._exists_error(element_block_id, "element block") # set up an empty connectivity if none is given if not connectivity: connectivity = [] # create the actual block - self.element_blocks[element_block_id] = ['', info, connectivity, {}] + self.element_blocks[element_block_id] = ["", info, connectivity, {}] def create_nodes(self, new_nodes): """ @@ -5992,46 +6366,51 @@ def create_nodes(self, new_nodes): def _exists_error(self, name, entity): """Warn the user something already exists and exit.""" self._error( - entity[0].upper() + entity[1:] + ' already exists.', + entity[0].upper() + entity[1:] + " already exists.", 'The specified %s "%s" already exists. This operation cannot ' - 'be completed.' % (entity, str(name))) + "be completed." % (entity, str(name)), + ) def _exists_warning(self, name, entity): """Warn the user something already exists.""" self._warning( - entity[0].upper() + entity[1:] + ' already exists.', + entity[0].upper() + entity[1:] + " already exists.", 'The specified %s "%s" already exists. Information may be ' - 'overwritten.' % (entity, str(name))) + "overwritten." % (entity, str(name)), + ) def _exists_on_entity_warning(self, name, entity, base_name, base_entity): """Warn the user something already exists on a given entity.""" self._warning( - entity[0].upper() + entity[1:] + ' already exists.', + entity[0].upper() + entity[1:] + " already exists.", 'The specified %s "%s" already exists on %s %s. Information may ' - 'be overwritten.' % - (entity, str(name), base_entity, str(base_name))) + "be overwritten." % (entity, str(name), base_entity, str(base_name)), + ) def _missing_error(self, name, entity): """Tell the user something does not exist and exit.""" self._error( - entity[0].upper() + entity[1:] + ' does not exist.', - 'The specified %s "%s" does not exist.' % (entity, str(name))) + entity[0].upper() + entity[1:] + " does not exist.", + 'The specified %s "%s" does not exist.' % (entity, str(name)), + ) def _missing_warning(self, name, entity): """Warn the user something does not exist.""" self._error( - entity[0].upper() + entity[1:] + ' does not exist.', - 'The specified %s "%s" does not exist and will be ignored.' % - (entity, str(name))) + entity[0].upper() + entity[1:] + " does not exist.", + 'The specified %s "%s" does not exist and will be ignored.' + % (entity, str(name)), + ) def _missing_on_entity_error(self, name, entity, base_name, base_entity): """Tell the user something does not exist on an entity and exit.""" self._error( - entity[0].upper() + entity[1:] + ' does not exist.', - 'The specified %s "%s" does not exist on %s %s.' % - (entity, str(name), base_entity, str(base_name))) + entity[0].upper() + entity[1:] + " does not exist.", + 'The specified %s "%s" does not exist on %s %s.' + % (entity, str(name), base_entity, str(base_name)), + ) - def create_global_variable(self, global_variable_name, value='auto'): + def create_global_variable(self, global_variable_name, value="auto"): """ Create a new global variable. @@ -6040,15 +6419,15 @@ def create_global_variable(self, global_variable_name, value='auto'): """ if self.global_variable_exists(global_variable_name): - self._exists_warning(global_variable_name, 'global variable') - if value == 'auto': + self._exists_warning(global_variable_name, "global variable") + if value == "auto": value = self._get_default_field_value(global_variable_name) values = [value] * len(self.timesteps) self.global_variables[global_variable_name] = values - def calculate_element_centroids(self, - element_field_name_prefix='centroid_', - element_block_ids='all'): + def calculate_element_centroids( + self, element_field_name_prefix="centroid_", element_block_ids="all" + ): """ Calculate and store the centroid of each element. @@ -6065,22 +6444,21 @@ def calculate_element_centroids(self, >>> model.calculate_element_centroids() """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) if not self.timesteps: self.create_timestep(0.0) if isinstance(element_field_name_prefix, str): centroid_field_names = [ - element_field_name_prefix + x for x in ['x', 'y', 'z'] + element_field_name_prefix + x for x in ["x", "y", "z"] ] else: centroid_field_names = element_field_name_prefix for element_block_id in element_block_ids: for name in centroid_field_names: if self.element_field_exists(name, element_block_id): - self._exists_on_entity_warning(name, 'element field', - element_block_id, - 'element block') + self._exists_on_entity_warning( + name, "element field", element_block_id, "element block" + ) # calculate centroids centroid = [[], [], []] element_count = self.get_element_count(element_block_id) @@ -6089,8 +6467,9 @@ def calculate_element_centroids(self, for element_index in range(element_count): this_centroid = [0.0, 0.0, 0.0] for connectivity_index in range(nodes_per_element): - node_index = connectivity[element_index * nodes_per_element - + connectivity_index] + node_index = connectivity[ + element_index * nodes_per_element + connectivity_index + ] for i in range(3): this_centroid[i] += self.nodes[node_index][i] for i in range(3): @@ -6102,9 +6481,9 @@ def calculate_element_centroids(self, values.append(list(centroid[index])) fields[name] = values - def calculate_element_volumes(self, - element_field_name='volume', - element_block_ids='all'): + def calculate_element_volumes( + self, element_field_name="volume", element_block_ids="all" + ): """ Calculate and store the volume of each element. @@ -6119,76 +6498,81 @@ def calculate_element_volumes(self, >>> model.calculate_element_volumes() """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) if not self.timesteps: self.create_timestep(0.0) for element_block_id in element_block_ids: # get the element type element_type = self._get_standard_element_type( - self._get_element_type(element_block_id)) + self._get_element_type(element_block_id) + ) if element_type not in self.VOLUME_FORMULA: self._warning( - 'Unrecognized element type', - 'The formula for calculating the volume of ' + "Unrecognized element type", + "The formula for calculating the volume of " 'element type "%s" is not implemented or not ' - 'known. This block will be skipped.' % (element_type)) + "known. This block will be skipped." % (element_type), + ) continue # warn if field already exists if self.element_field_exists(element_field_name, element_block_id): - self._exists_on_entity_warning(element_field_name, - 'element field', - element_block_id, - 'element block') + self._exists_on_entity_warning( + element_field_name, + "element field", + element_block_id, + "element block", + ) # get the formula formula = self.VOLUME_FORMULA[element_type] if len(formula) == 2: # distance between two points - equation = ('(x[0] ** 2.0 + ' - 'x[1] ** 2.0 + ' - 'x[2] ** 2.0) ** 0.5') + equation = "(x[0] ** 2.0 + " "x[1] ** 2.0 + " "x[2] ** 2.0) ** 0.5" elif len(formula) == 3: # magnitude of cross product - equation = ('((x[0] * x[4] - x[1] * x[3]) ** 2.0 + ' - '(x[2] * x[3] - x[0] * x[5]) ** 2.0 + ' - '(x[1] * x[5] - x[2] * x[4]) ** 2.0) ** 0.5') + equation = ( + "((x[0] * x[4] - x[1] * x[3]) ** 2.0 + " + "(x[2] * x[3] - x[0] * x[5]) ** 2.0 + " + "(x[1] * x[5] - x[2] * x[4]) ** 2.0) ** 0.5" + ) elif len(formula) == 4: # triple product - equation = ('(x[1] * x[5] - x[2] * x[4]) * x[6] + ' - '(x[2] * x[3] - x[0] * x[5]) * x[7] + ' - '(x[0] * x[4] - x[1] * x[3]) * x[8]') + equation = ( + "(x[1] * x[5] - x[2] * x[4]) * x[6] + " + "(x[2] * x[3] - x[0] * x[5]) * x[7] + " + "(x[0] * x[4] - x[1] * x[3]) * x[8]" + ) else: - self._bug('Unknown case') + self._bug("Unknown case") # process the formula to account for averaged nodes transforms = [] for i, rule in enumerate(formula[1:]): for d in range(3): - value = '(' + value = "(" node_list = rule[1] if isinstance(node_list, int): - value += 'n[%d]' % (node_list * 3 + d) + value += "n[%d]" % (node_list * 3 + d) else: - value += '(' - value += 'n[%d]' % (node_list[0] * 3 + d) + value += "(" + value += "n[%d]" % (node_list[0] * 3 + d) for x in node_list[1:]: - value += ' + n[%d]' % (x * 3 + d) - value += ') / %d.0' % len(node_list) - value += ' - ' + value += " + n[%d]" % (x * 3 + d) + value += ") / %d.0" % len(node_list) + value += " - " node_list = rule[0] if isinstance(node_list, int): - value += 'n[%d]' % (node_list * 3 + d) + value += "n[%d]" % (node_list * 3 + d) else: - value += '(' - value += 'n[%d]' % (node_list[0] * 3 + d) + value += "(" + value += "n[%d]" % (node_list[0] * 3 + d) for x in node_list[1:]: - value += ' + n[%d]' % (x * 3 + d) - value += ') / %d.0' % len(node_list) - value += ')' - transforms.append(('x[%d]' % (i * 3 + d), value)) + value += " + n[%d]" % (x * 3 + d) + value += ") / %d.0" % len(node_list) + value += ")" + transforms.append(("x[%d]" % (i * 3 + d), value)) for transform in transforms: equation = equation.replace(transform[0], transform[1]) # store coordinates of nodes into x, y, z lists - function = eval('lambda n: ' + equation) + function = eval("lambda n: " + equation) # store some element block values element_count = self.get_element_count(element_block_id) nodes_per_element = self.get_nodes_per_element(element_block_id) @@ -6196,10 +6580,11 @@ def calculate_element_volumes(self, volumes = [] for element_index in range(int(element_count)): # get local node values - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] # get local coordinates n = [x for i in local_node for x in self.nodes[i]] # add the volume @@ -6210,17 +6595,16 @@ def calculate_element_volumes(self, fields = self._get_element_block_fields(element_block_id) fields[element_field_name] = values - def get_element_block_volume(self, - element_block_ids, - element_volume_field_name=None): + def get_element_block_volume( + self, element_block_ids, element_volume_field_name=None + ): """Return the total volume of the given element blocks. Example: >>> model.get_element_block_volume('all') """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # create a timestep if none exist created_timestep = False if not self.timesteps: @@ -6231,8 +6615,7 @@ def get_element_block_volume(self, if element_volume_field_name is None: created_volume_field = True element_volume_field_name = self._new_element_field_name() - self.calculate_element_volumes(element_volume_field_name, - element_block_ids) + self.calculate_element_volumes(element_volume_field_name, element_block_ids) # add up the volumes volume = 0.0 for id_ in element_block_ids: @@ -6243,14 +6626,15 @@ def get_element_block_volume(self, self.delete_timestep(0.0) # delete the temporary field if created_volume_field: - self.delete_element_field(element_volume_field_name, - element_block_ids) + self.delete_element_field(element_volume_field_name, element_block_ids) return volume - def get_element_block_centroid(self, - element_block_ids, - element_volume_field_name=None, - element_centroid_field_names=None): + def get_element_block_centroid( + self, + element_block_ids, + element_volume_field_name=None, + element_centroid_field_names=None, + ): """Return the centroid of the given element blocks. Example: @@ -6259,8 +6643,7 @@ def get_element_block_centroid(self, """ # format inputs - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # create a timestep if none exist created_timestep = False if not self.timesteps: @@ -6271,30 +6654,27 @@ def get_element_block_centroid(self, if element_volume_field_name is None: created_volume_field = True element_volume_field_name = self._new_element_field_name() - self.calculate_element_volumes(element_volume_field_name, - element_block_ids) + self.calculate_element_volumes(element_volume_field_name, element_block_ids) # calculate temporary field with element centroids created_centroid_fields = False if element_centroid_field_names is None: created_centroid_fields = True element_centroid_field_names = self._new_element_field_name(3) - self.calculate_element_centroids(element_centroid_field_names, - element_block_ids) + self.calculate_element_centroids( + element_centroid_field_names, element_block_ids + ) # calculate the centroid total_volume = 0.0 centroid = [0.0, 0.0, 0.0] for id_ in element_block_ids: fields = self._get_element_block_fields(id_) volumes = fields[element_volume_field_name][0] - centroids = [ - fields[element_centroid_field_names[x]][0] for x in range(3) - ] + centroids = [fields[element_centroid_field_names[x]][0] for x in range(3)] for x in range(3): - centroid[x] += sum(a * b - for a, b in zip(volumes, centroids[x])) + centroid[x] += sum(a * b for a, b in zip(volumes, centroids[x])) total_volume += sum(volumes) if total_volume == 0.0: - centroid = [float('nan')] * 3 + centroid = [float("nan")] * 3 else: centroid = [x / total_volume for x in centroid] # delete the temporary timestep @@ -6302,14 +6682,13 @@ def get_element_block_centroid(self, self.delete_timestep(0.0) # delete the temporary fields if created_volume_field: - self.delete_element_field(element_volume_field_name, - element_block_ids) + self.delete_element_field(element_volume_field_name, element_block_ids) if created_centroid_fields: for name in element_centroid_field_names: self.delete_element_field(name, element_block_ids) return centroid - def create_interpolated_timestep(self, timestep, interpolation='cubic'): + def create_interpolated_timestep(self, timestep, interpolation="cubic"): """ Create a new timestep by interpolating neighboring steps. @@ -6325,26 +6704,31 @@ def create_interpolated_timestep(self, timestep, interpolation='cubic'): """ if timestep in self.timesteps: - self._exists_warning(timestep, 'timestep') + self._exists_warning(timestep, "timestep") return # find neighboring timesteps and how to form the new step steps = self.get_timesteps() # make sure enough steps exist if len(steps) < 2: self._error( - 'Invalid interpolation.', - 'A timestep cannot be interpolated unless 2 or ' - 'more timesteps already exist. There are %d defined ' - 'timesteps: %s' % (len(self.timesteps), ', '.join( - [str(x) for x in self.get_timesteps()]))) + "Invalid interpolation.", + "A timestep cannot be interpolated unless 2 or " + "more timesteps already exist. There are %d defined " + "timesteps: %s" + % ( + len(self.timesteps), + ", ".join([str(x) for x in self.get_timesteps()]), + ), + ) # make sure value lies within time bounds if steps[0] > timestep or steps[-1] < timestep: self._error( - 'Invalid interpolation.', - 'The specified timestep %s does not lie within the ' - 'range of timesteps already defined: [%s, %s].' % - (str(timestep), str(steps[0]), str(steps[-1]))) - if interpolation == 'linear': + "Invalid interpolation.", + "The specified timestep %s does not lie within the " + "range of timesteps already defined: [%s, %s]." + % (str(timestep), str(steps[0]), str(steps[-1])), + ) + if interpolation == "linear": # find two bounding timesteps nearby = min(steps, key=lambda x: abs(x - timestep)) if nearby < timestep: @@ -6354,7 +6738,7 @@ def create_interpolated_timestep(self, timestep, interpolation='cubic'): # find proportion of each one to use phi = (timestep - nearby[0]) / (nearby[1] - nearby[0]) formula = [(nearby[0], 1.0 - phi), (nearby[1], phi)] - elif interpolation == 'cubic': + elif interpolation == "cubic": # find four bounding timesteps # if step is within first or last segment, create # an imaginary point to do the interpolation @@ -6375,8 +6759,10 @@ def create_interpolated_timestep(self, timestep, interpolation='cubic'): four_steps[3] = steps[index + 2] # find interpolation coefficients coefficients = self._cubic_interpolation(timestep, *four_steps) - formula = [[steps[index], coefficients[1]], - [steps[index + 1], coefficients[2]]] + formula = [ + [steps[index], coefficients[1]], + [steps[index + 1], coefficients[2]], + ] if index == 0: formula[0][1] += 2 * coefficients[0] formula[1][1] -= coefficients[0] @@ -6389,20 +6775,22 @@ def create_interpolated_timestep(self, timestep, interpolation='cubic'): formula.append([steps[index + 2], coefficients[3]]) else: self._error( - 'Unknown interpolation technique', + "Unknown interpolation technique", 'The specified interpolation technique "%s" is not ' - 'recognized.' % interpolation) + "recognized." % interpolation, + ) # create the new timestep self.create_timestep(timestep) # use the given formula to create the new step # formula = list of (timestep_index, contribution) - formula = [(self._get_internal_timestep_index(x[0]), x[1]) - for x in formula] + formula = [(self._get_internal_timestep_index(x[0]), x[1]) for x in formula] this_index = self._get_internal_timestep_index(timestep) # element fields, side set fields, node set fields - for thing in itertools.chain(list(self.element_blocks.values()), - list(self.node_sets.values()), - list(self.side_sets.values())): + for thing in itertools.chain( + list(self.element_blocks.values()), + list(self.node_sets.values()), + list(self.side_sets.values()), + ): fields = thing[-1] for values in list(fields.values()): new_values = [0.0] * len(values[0]) @@ -6451,12 +6839,11 @@ def copy_timestep(self, timestep, new_timestep): object.copy_timestep(0.0, 1.0) """ - [timestep] = self._format_id_list([timestep], - self.get_timesteps(), - 'timestep', - single=True) + [timestep] = self._format_id_list( + [timestep], self.get_timesteps(), "timestep", single=True + ) if self.timestep_exists(new_timestep): - self._exists_warning(new_timestep, 'timestep') + self._exists_warning(new_timestep, "timestep") return # find the index at which to insert the new timestep new_index = self._find_new_timestep_index(new_timestep) @@ -6472,9 +6859,11 @@ def copy_timestep(self, timestep, new_timestep): for values in list(self.global_variables.values()): values.insert(new_index, values[old_index]) # adjust self.element_blocks, self.node_sets, self.side_sets - for thing in itertools.chain(list(self.element_blocks.values()), - list(self.node_sets.values()), - list(self.side_sets.values())): + for thing in itertools.chain( + list(self.element_blocks.values()), + list(self.node_sets.values()), + list(self.side_sets.values()), + ): fields = thing[-1] for field in list(fields.values()): field.insert(new_index, list(field[old_index])) @@ -6491,7 +6880,7 @@ def create_timestep(self, timestep): """ timestep = float(timestep) if self.timestep_exists(timestep): - self._exists_warning(timestep, 'timestep') + self._exists_warning(timestep, "timestep") return # find the index at which to to insert this timestep_index = self._find_new_timestep_index(timestep) @@ -6540,16 +6929,18 @@ def _replace_name_case(self, new_list, original_list): original_case = dict((x.lower(), x) for x in original_list) if len(original_case) != len(original_list): self._warning( - 'Ambiguous string case.', - 'There are multiple strings in the list which have ' - 'identical lowercase representations. One will be ' - 'chosen at random.') + "Ambiguous string case.", + "There are multiple strings in the list which have " + "identical lowercase representations. One will be " + "chosen at random.", + ) for item in new_list: - if not item.lower() in original_case: + if item.lower() not in original_case: self._bug( - 'Unrecognized string.', + "Unrecognized string.", 'The string "%s" appears in the new list but ' - 'not in the original list.' % item) + "not in the original list." % item, + ) return [original_case[x.lower()] for x in new_list] def _sort_field_names(self, original_field_names): @@ -6572,55 +6963,58 @@ def _sort_field_names(self, original_field_names): multicomponent_fields = set() for name in field_names: # see if it has an integration point - if re.match('.*_[0-9]+$', name): - (name, integration_point) = name.rsplit('_', 1) + if re.match(".*_[0-9]+$", name): + (name, integration_point) = name.rsplit("_", 1) integration_point = int(integration_point) else: integration_point = None # see if it possibly has a component - if re.match('.*_.+$', name): - component = name.rsplit('_', 1)[1] + if re.match(".*_.+$", name): + component = name.rsplit("_", 1)[1] if component in self.ALL_MULTI_COMPONENT_FIELD_SUBSCRIPTS: - name = name.rsplit('_', 1)[0] - multicomponent_fields.add( - (name, component, integration_point)) + name = name.rsplit("_", 1)[0] + multicomponent_fields.add((name, component, integration_point)) # now sort multi-component fields base_names = set(x for x, _, _ in multicomponent_fields) sorted_field_names = dict() field_names = set(field_names) for base_name in base_names: # find all components of this form - components = set(x for name, x, _ in multicomponent_fields - if name == base_name) + components = set( + x for name, x, _ in multicomponent_fields if name == base_name + ) # find max integration point value - integration_points = set(x for name, _, x in multicomponent_fields - if name == base_name and x is not None) + integration_points = set( + x + for name, _, x in multicomponent_fields + if name == base_name and x is not None + ) if integration_points: integration_point_count = max( - x for name, _, x in multicomponent_fields - if name == base_name and x is not None) + x + for name, _, x in multicomponent_fields + if name == base_name and x is not None + ) else: integration_point_count = None # see if the components match the form of something matching_form = None - for form, included_components in (list( - self.MULTI_COMPONENT_FIELD_SUBSCRIPTS.items())): + for form, included_components in list( + self.MULTI_COMPONENT_FIELD_SUBSCRIPTS.items() + ): if set(included_components) == components: matching_form = form if not matching_form: continue # see if all components and integration points are present mid = [ - '_' + x - for x in self.MULTI_COMPONENT_FIELD_SUBSCRIPTS[matching_form] + "_" + x for x in self.MULTI_COMPONENT_FIELD_SUBSCRIPTS[matching_form] ] if integration_point_count is None: - last = [''] + last = [""] else: - last = [ - '_' + str(x + 1) for x in range(integration_point_count) - ] + last = ["_" + str(x + 1) for x in range(integration_point_count)] all_names = [base_name + m + s for s in last for m in mid] if set(all_names).issubset(field_names): sorted_field_names[all_names[0]] = all_names @@ -6755,19 +7149,18 @@ def get_input_deck(self): first_word = None for line in self.info_records: if not continuation: - first_word = line.strip().split(' ', 1)[0].lower() - if not continuation and first_word == 'begin': + first_word = line.strip().split(" ", 1)[0].lower() + if not continuation and first_word == "begin": begin_depth += 1 if begin_depth > 0: if continuation: input_deck[-1] = input_deck[-1][:-1] + line else: input_deck.append(line) - continuation = (begin_depth > 0 and len(line) == 80 - and line[-1] == '\\') - if not continuation and first_word == 'end': + continuation = begin_depth > 0 and len(line) == 80 and line[-1] == "\\" + if not continuation and first_word == "end": begin_depth -= 1 - return '\n'.join(input_deck) + return "\n".join(input_deck) def get_length_scale(self): """ @@ -6812,16 +7205,20 @@ def _dot(vector_one, vector_two): @staticmethod def _distance_squared_between(point_one, point_two): """Return the distance squared between two three-dimensional points.""" - return ((point_two[0] - point_one[0])**2 + - (point_two[1] - point_one[1])**2 + - (point_two[2] - point_one[2])**2) + return ( + (point_two[0] - point_one[0]) ** 2 + + (point_two[1] - point_one[1]) ** 2 + + (point_two[2] - point_one[2]) ** 2 + ) @staticmethod def _distance_between(point_one, point_two): """Return the distance between two three-dimensional points.""" - return math.sqrt((point_two[0] - point_one[0])**2 + - (point_two[1] - point_one[1])**2 + - (point_two[2] - point_one[2])**2) + return math.sqrt( + (point_two[0] - point_one[0]) ** 2 + + (point_two[1] - point_one[1]) ** 2 + + (point_two[2] - point_one[2]) ** 2 + ) @staticmethod def _values_match(value, list_of_values): @@ -6868,31 +7265,34 @@ def _merge_node_groups(self, node_groups, suppress_warnings=False): for index in slaves: if index in duplicated_slave_nodes: problem_groups[master] = slaves - groups = '\n '.join( - str(x) + ': ' + str(y) - for x, y in list(problem_groups.items())) + groups = "\n ".join( + str(x) + ": " + str(y) for x, y in list(problem_groups.items()) + ) self._bug( - 'Invalid merged node groups.', - 'Slaves nodes were found in multiple merged groups. ' - 'Conflicting merged node groups:\n %s' % (groups)) + "Invalid merged node groups.", + "Slaves nodes were found in multiple merged groups. " + "Conflicting merged node groups:\n %s" % (groups), + ) # ensure validity of input # slave nodes are not repeated # master nodes are never slave nodes master_nodes = sorted(node_groups.keys()) - slave_nodes = sorted(list( - itertools.chain(*list(node_groups.values())))) + slave_nodes = sorted(list(itertools.chain(*list(node_groups.values())))) slave_nodes_set = set(slave_nodes) # ensure master nodes are not slave nodes for master in master_nodes: if master in slave_nodes_set: self._bug( - 'Invalid merged node groups.', - 'The master node %d is also found in a slave node ' - 'group.' % (master)) + "Invalid merged node groups.", + "The master node %d is also found in a slave node " + "group." % (master), + ) # ensure slave nodes are not in multiple groups if not sorted(slave_nodes_set) == slave_nodes: - self._bug('Invalid merged node groups.', - 'Slave nodes are duplicated in multiple groups.') + self._bug( + "Invalid merged node groups.", + "Slave nodes are duplicated in multiple groups.", + ) # First, remap all nodes such that slave nodes appear at the very # end. next_master_index = 0 @@ -6904,8 +7304,7 @@ def _merge_node_groups(self, node_groups, suppress_warnings=False): if slave_node != index: count = slave_node - index assert count > 0 - node_map.extend( - range(next_master_index, next_master_index + count)) + node_map.extend(range(next_master_index, next_master_index + count)) index += count next_master_index += count node_map.append(next_slave_index) @@ -6922,8 +7321,10 @@ def _merge_node_groups(self, node_groups, suppress_warnings=False): # apply this node map self._apply_node_map(node_map) # apply the mapping to node_groups - node_groups = dict((node_map[key], [node_map[x] for x in values]) - for key, values in list(node_groups.items())) + node_groups = dict( + (node_map[key], [node_map[x] for x in values]) + for key, values in list(node_groups.items()) + ) for master, slaves in list(node_groups.items()): assert master < first_slave_index assert min(slaves) >= first_slave_index @@ -6944,19 +7345,20 @@ def _merge_node_groups(self, node_groups, suppress_warnings=False): master_value = values[master] slave_values = [values[x] for x in slaves] if not self._values_match(master_value, slave_values): - if (not node_field_value_warnings - and not suppress_warnings): + if not node_field_value_warnings and not suppress_warnings: self._warning( - 'Node field values do not match.', - 'Nodes are being merged but values at these ' + "Node field values do not match.", + "Nodes are being merged but values at these " 'nodes for node field "%s" do not match. An ' - 'averaged value will be used.\n' - '\n' - 'Future warnings of this type will be ' - 'suppressed.' % (name)) + "averaged value will be used.\n" + "\n" + "Future warnings of this type will be " + "suppressed." % (name), + ) node_field_value_warnings += 1 - values[master] = (values[master] + sum(slave_values) - ) / float(1 + len(slaves)) + values[master] = (values[master] + sum(slave_values)) / float( + 1 + len(slaves) + ) del values[first_slave_index:] # change self.node_sets node_set_member_warnings = 0 @@ -6981,13 +7383,14 @@ def _merge_node_groups(self, node_groups, suppress_warnings=False): if not master_included or slaves_not_included: if not node_set_member_warnings and not suppress_warnings: self._warning( - 'Ambiguous merge of nodes.', - 'Node are being merged, but only some of these ' - 'nodes belong to a given node set. The operation ' - 'is therefore ambiguous on whether or not to ' - 'include the merged node in the set. The merged ' - 'node will be included in the set.\n\nFuture ' - 'warnings of this type will be suppressed.') + "Ambiguous merge of nodes.", + "Node are being merged, but only some of these " + "nodes belong to a given node set. The operation " + "is therefore ambiguous on whether or not to " + "include the merged node in the set. The merged " + "node will be included in the set.\n\nFuture " + "warnings of this type will be suppressed.", + ) node_set_member_warnings += 1 # if master node is not included, steal the position of a # slave node @@ -7005,20 +7408,20 @@ def _merge_node_groups(self, node_groups, suppress_warnings=False): for name, all_values in list(fields.items()): for values in all_values: slave_values = [values[x] for x in slave_indices] - if not self._values_match(values[master_index], - slave_values): - if (not node_set_value_warnings - and not suppress_warnings): + if not self._values_match(values[master_index], slave_values): + if not node_set_value_warnings and not suppress_warnings: self._warning( - 'Node set field values do not match.', - 'Nodes are being merged but values at ' - 'these nodes for node set field %s do ' - 'not match. An averaged values will ' - 'be used.\n\nFuture warnings of this ' - 'type will be suppressed.' % (name)) + "Node set field values do not match.", + "Nodes are being merged but values at " + "these nodes for node set field %s do " + "not match. An averaged values will " + "be used.\n\nFuture warnings of this " + "type will be suppressed." % (name), + ) node_set_value_warnings += 1 - new_value = (values[master_index] + sum(slave_values) - ) / float(1 + len(slave_indices)) + new_value = (values[master_index] + sum(slave_values)) / float( + 1 + len(slave_indices) + ) values[master_index] = new_value # delete slave members for index in sorted(member_indices_to_delete, reverse=True): @@ -7068,7 +7471,7 @@ def _merge_node_pairs(self, node_pairs): group_to_merge[master] = sorted(set(group) - set([master])) self._merge_node_groups(group_to_merge) - def delete_duplicate_elements(self, element_block_ids='all'): + def delete_duplicate_elements(self, element_block_ids="all"): """ Delete duplicate elements. @@ -7076,8 +7479,7 @@ def delete_duplicate_elements(self, element_block_ids='all'): all of its nodes with another element. """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) # go through each block and delete elements for id_ in element_block_ids: nodes_per_element = self.get_nodes_per_element(id_) @@ -7089,7 +7491,7 @@ def delete_duplicate_elements(self, element_block_ids='all'): duplicates = [] for x in range(0, element_count): start = x * nodes_per_element - element = set(connectivity[start:start + nodes_per_element]) + element = set(connectivity[start: start + nodes_per_element]) element = tuple(sorted(element)) if element in elements: duplicates.append(x) @@ -7121,25 +7523,32 @@ def _find_close_nodes(self, tolerance): scale = math.sqrt(sum([x * x for x in sorting_vector])) sorting_vector = [x / scale for x in sorting_vector] # create a list of node indices sorted by distance along that vector - sorted_nodal_distances = sorted([(self._dot(x, sorting_vector), i) - for i, x in enumerate(self.nodes)]) + sorted_nodal_distances = sorted( + [(self._dot(x, sorting_vector), i) for i, x in enumerate(self.nodes)] + ) # go through the list to find node groups node_count = len(self.nodes) lower_index = 0 upper_index = 1 master_nodes = list(range(len(self.nodes))) while lower_index < node_count: - if (upper_index >= node_count - or sorted_nodal_distances[upper_index][0] - - sorted_nodal_distances[lower_index][0] > tolerance): + if ( + upper_index >= node_count + or sorted_nodal_distances[upper_index][0] + - sorted_nodal_distances[lower_index][0] + > tolerance + ): lower_index += 1 upper_index = lower_index + 1 continue lower_element = sorted_nodal_distances[lower_index] upper_element = sorted_nodal_distances[upper_index] - if self._distance_between( - self.nodes[lower_element[1]], - self.nodes[upper_element[1]]) <= tolerance: + if ( + self._distance_between( + self.nodes[lower_element[1]], self.nodes[upper_element[1]] + ) + <= tolerance + ): one, two = sorted([lower_element[1], upper_element[1]]) master_nodes[two] = one upper_index += 1 @@ -7156,10 +7565,9 @@ def _find_close_nodes(self, tolerance): # return the result return close_node_groups - def merge_nodes(self, - tolerance=1e-6, - relative_tolerance=True, - suppress_warnings=False): + def merge_nodes( + self, tolerance=1e-6, relative_tolerance=True, suppress_warnings=False + ): """ Merge nodes that are closer than the given tolerance. @@ -7180,8 +7588,7 @@ def merge_nodes(self, # find the node groups close_node_groups = self._find_close_nodes(tolerance) # merge these node groups - self._merge_node_groups(close_node_groups, - suppress_warnings=suppress_warnings) + self._merge_node_groups(close_node_groups, suppress_warnings=suppress_warnings) def _duplicate_nodes(self, node_indices, new_node_indices): """ @@ -7192,8 +7599,9 @@ def _duplicate_nodes(self, node_indices, new_node_indices): the node set. """ - new_node_indices[:] = range(len(self.nodes), - len(self.nodes) + len(node_indices)) + new_node_indices[:] = range( + len(self.nodes), len(self.nodes) + len(node_indices) + ) # update self.nodes new_nodes = [list(self.nodes[x]) for x in node_indices] self.create_nodes(new_nodes) @@ -7229,8 +7637,8 @@ def _create_averaged_nodes(self, node_indices, new_node_indices): """ first_node_index = len(self.nodes) new_node_indices[:] = list( - range(len(self.nodes), - len(self.nodes) + len(node_indices))) + range(len(self.nodes), len(self.nodes) + len(node_indices)) + ) # format node_indices such that each value is of the given form: # ((index, weight), (index2, weight2), ...) new_node_indices = [] @@ -7252,16 +7660,16 @@ def _create_averaged_nodes(self, node_indices, new_node_indices): total = sum(x[1] for x in index_list) if abs(total - 1.0) > 1e-14: self._bug( - 'Incorrect weights.', - 'The given node averaging weights do not add up ' - 'to 1.') + "Incorrect weights.", + "The given node averaging weights do not add up " "to 1.", + ) # create the new nodes first_new_node_index = len(self.nodes) new_nodes = [] for index_list in node_indices: this_new_node = [ - sum(weight * self.nodes[index][d] - for index, weight in index_list) for d in range(3) + sum(weight * self.nodes[index][d] for index, weight in index_list) + for d in range(3) ] new_nodes.append(this_new_node) self.create_nodes(new_nodes) @@ -7279,8 +7687,8 @@ def _create_averaged_nodes(self, node_indices, new_node_indices): fields = self._get_node_set_fields(node_set_id) members_set = set(members) index_from_member_index = dict( - (node_index, index) - for index, node_index in enumerate(members)) + (node_index, index) for index, node_index in enumerate(members) + ) for node_index, index_list in enumerate(node_indices): check = set(x in members_set for x, _ in index_list) if False in check: @@ -7290,12 +7698,13 @@ def _create_averaged_nodes(self, node_indices, new_node_indices): # and calculate its value for all fields for all_values in list(fields.values()): for values in all_values: - new_value = sum(weight * - values[index_from_member_index[index]] - for index, weight in index_list) + new_value = sum( + weight * values[index_from_member_index[index]] + for index, weight in index_list + ) values.append(new_value) - def unmerge_element_blocks(self, element_block_ids='all'): + def unmerge_element_blocks(self, element_block_ids="all"): """ Duplicate nodes to unmerge element blocks. @@ -7310,8 +7719,7 @@ def unmerge_element_blocks(self, element_block_ids='all'): >>> model.unmerge_element_blocks() """ - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) if len(element_block_ids) <= 1: return # Separate each pair of blocks. Keep nodes on block id1 the same and @@ -7321,7 +7729,8 @@ def unmerge_element_blocks(self, element_block_ids='all'): for id1, id2 in itertools.combinations(element_block_ids, 2): shared_nodes_set = set.intersection( set(self.get_nodes_in_element_block(id1)), - set(self.get_nodes_in_element_block(id2))) + set(self.get_nodes_in_element_block(id2)), + ) shared_nodes = sorted(shared_nodes_set) if not shared_nodes: continue @@ -7334,24 +7743,28 @@ def unmerge_element_blocks(self, element_block_ids='all'): connectivity = self.get_connectivity(id2) for index, node_index in enumerate(connectivity): if node_index in shared_nodes_set: - connectivity[index] = new_shared_nodes[shared_nodes.index( - node_index)] + connectivity[index] = new_shared_nodes[ + shared_nodes.index(node_index) + ] # blocks should no longer share nodes assert not set.intersection( set(self.get_nodes_in_element_block(id1)), - set(self.get_nodes_in_element_block(id2))) - - def import_model(self, - filename, - element_block_ids='all', - timesteps='all', - node_field_names='all', - element_field_names='all', - side_set_ids='all', - node_set_ids='all', - global_variable_names='all', - node_set_field_names='all', - side_set_field_names='all'): + set(self.get_nodes_in_element_block(id2)), + ) + + def import_model( + self, + filename, + element_block_ids="all", + timesteps="all", + node_field_names="all", + element_field_names="all", + side_set_ids="all", + node_set_ids="all", + global_variable_names="all", + node_set_field_names="all", + side_set_field_names="all", + ): """ Import information from an ExodusII file. @@ -7378,73 +7791,76 @@ def import_model(self, """ # open the file for read if not os.path.isfile(filename): - self._error('File not found', - 'The specified file "%s" was not found.' % filename) + self._error( + "File not found", 'The specified file "%s" was not found.' % filename + ) if SUPPRESS_EXODUS_OUTPUT: save_stdout = sys.stdout sys.stdout = DummyFile() - exodus_file = exodus.exodus(filename, mode='r') + exodus_file = exodus.exodus(filename, mode="r") if SUPPRESS_EXODUS_OUTPUT: sys.stdout = save_stdout # format timesteps to retrieve file_timesteps = list(exodus_file.get_times()) - if timesteps == 'last_if_any': + if timesteps == "last_if_any": if file_timesteps: - timesteps = 'last' + timesteps = "last" else: - timesteps = 'none' - timesteps = self._format_id_list(timesteps, file_timesteps, 'timestep') + timesteps = "none" + timesteps = self._format_id_list(timesteps, file_timesteps, "timestep") # format block id list file_element_block_ids = list(exodus_file.get_elem_blk_ids()) file_element_block_names = [] if file_element_block_ids: file_element_block_names = list(exodus_file.get_elem_blk_names()) element_block_ids = self._format_id_list( - element_block_ids, sorted(file_element_block_ids), 'element block') + element_block_ids, sorted(file_element_block_ids), "element block" + ) # format other id lists node_field_names = self._format_id_list( node_field_names, - sorted(list(exodus_file.get_node_variable_names())), 'node field') - file_element_field_names = list( - exodus_file.get_element_variable_names()) + sorted(list(exodus_file.get_node_variable_names())), + "node field", + ) + file_element_field_names = list(exodus_file.get_element_variable_names()) element_field_names = self._format_id_list( - element_field_names, sorted(file_element_field_names), - 'element field') + element_field_names, sorted(file_element_field_names), "element field" + ) file_side_set_ids = list(exodus_file.get_side_set_ids()) file_side_set_names = [] if file_side_set_ids: file_side_set_names = list(exodus_file.get_side_set_names()) - side_set_ids = self._format_id_list(side_set_ids, - sorted(file_side_set_ids), - 'side set') + side_set_ids = self._format_id_list( + side_set_ids, sorted(file_side_set_ids), "side set" + ) file_node_set_ids = list(exodus_file.get_node_set_ids()) file_node_set_names = [] if file_node_set_ids: file_node_set_names = list(exodus_file.get_node_set_names()) - node_set_ids = self._format_id_list(node_set_ids, - sorted(file_node_set_ids), - 'node set') + node_set_ids = self._format_id_list( + node_set_ids, sorted(file_node_set_ids), "node set" + ) global_variable_names = self._format_id_list( global_variable_names, sorted(list(exodus_file.get_global_variable_names())), - 'global variable') - file_node_set_field_names = list( - exodus_file.get_node_set_variable_names()) + "global variable", + ) + file_node_set_field_names = list(exodus_file.get_node_set_variable_names()) node_set_field_names = self._format_id_list( - node_set_field_names, sorted(file_node_set_field_names), - 'node set field') - file_side_set_field_names = list( - exodus_file.get_side_set_variable_names()) + node_set_field_names, sorted(file_node_set_field_names), "node set field" + ) + file_side_set_field_names = list(exodus_file.get_side_set_variable_names()) side_set_field_names = self._format_id_list( - side_set_field_names, sorted(file_side_set_field_names), - 'node set field') + side_set_field_names, sorted(file_side_set_field_names), "node set field" + ) # ensure element blocks in this file do not already exist for element_block_id in element_block_ids: if self.element_block_exists(element_block_id): self._error( - 'Element block already exists.', - 'Cannot import element block \"%d\" since it already ' - 'exists in the model.' % element_block_id) + "Element block already exists.", + 'Cannot import element block "%d" since it already ' + "exists in the model." % element_block_id, + ) # create new nodes used in this file node_offset = len(self.nodes) # store nodes we are going to import @@ -7459,8 +7875,7 @@ def import_model(self, new_used_nodes = [False] * exodus_file.num_nodes() # add nodes in blocks we are importing for element_block_id in element_block_ids: - connectivity = exodus_file.get_elem_connectivity( - element_block_id)[0] + connectivity = exodus_file.get_elem_connectivity(element_block_id)[0] for i in connectivity: new_used_nodes[i - 1] = True # save indices for nodes we want to import @@ -7497,17 +7912,20 @@ def import_model(self, # create new element blocks for element_block_id in element_block_ids: new_connectivity = list( - exodus_file.get_elem_connectivity(element_block_id))[0] + exodus_file.get_elem_connectivity(element_block_id) + )[0] # apply node map new_connectivity = [node_map[x] for x in new_connectivity] # get the element block name element_block_name = file_element_block_names[ - file_element_block_ids.index(element_block_id)] + file_element_block_ids.index(element_block_id) + ] # create the element block self.create_element_block( element_block_id, list(exodus_file.elem_blk_info(element_block_id)), - connectivity=new_connectivity) + connectivity=new_connectivity, + ) if element_block_name: self.rename_element_block(element_block_id, element_block_name) # get indices of each timestep and create new timesteps @@ -7520,8 +7938,11 @@ def import_model(self, else: duplicate_timesteps = True timestep_indices.append( - (file_timesteps.index(timestep) + 1, - self._get_internal_timestep_index(timestep))) + ( + file_timesteps.index(timestep) + 1, + self._get_internal_timestep_index(timestep), + ) + ) # get list of timestep indices present in the model but not included # in the import included_timestep_indices = [x[1] for x in timestep_indices] @@ -7538,9 +7959,10 @@ def import_model(self, for timestep_index in timestep_indices: file_node_field_values = list( exodus_file.get_node_variable_values( - node_field_name, timestep_index[0])) - model_values = self.node_fields[node_field_name][ - timestep_index[1]] + node_field_name, timestep_index[0] + ) + ) + model_values = self.node_fields[node_field_name][timestep_index[1]] for i in new_used_nodes: model_values[node_map[i]] = file_node_field_values[i - 1] # populate node sets @@ -7556,8 +7978,7 @@ def import_model(self, self.create_node_set(node_set_id, model_node_set_members) else: self.add_nodes_to_node_set(node_set_id, model_node_set_members) - node_set_name = file_node_set_names[file_node_set_ids.index( - node_set_id)] + node_set_name = file_node_set_names[file_node_set_ids.index(node_set_id)] if node_set_name: self.rename_node_set(node_set_id, node_set_name) # populate side sets @@ -7568,16 +7989,18 @@ def import_model(self, for element_index, side_number in zip(*file_side_set_members): if file_block_from_element[element_index] is not None: model_side_set_members.append( - (file_block_from_element[element_index], - file_index_from_element[element_index], - side_number - 1)) + ( + file_block_from_element[element_index], + file_index_from_element[element_index], + side_number - 1, + ) + ) # create the side set or add to an existing set if not self.side_set_exists(side_set_id): self.create_side_set(side_set_id, model_side_set_members) else: self.add_faces_to_side_set(side_set_id, model_side_set_members) - side_set_name = file_side_set_names[file_side_set_ids.index( - side_set_id)] + side_set_name = file_side_set_names[file_side_set_ids.index(side_set_id)] if side_set_name: self.rename_side_set(side_set_id, side_set_name) # store truth table for node set field info @@ -7585,15 +8008,15 @@ def import_model(self, file_node_set_truth_table = [] for file_node_set_id in file_node_set_ids: file_node_set_truth_table.append( - exodus_file.get_node_set_variable_truth_table( - file_node_set_id)) + exodus_file.get_node_set_variable_truth_table(file_node_set_id) + ) # populate node set fields for node_set_field_name in node_set_field_names: for node_set_id in node_set_ids: # don't process if field does not exist in file field_exists = file_node_set_truth_table[ - file_node_set_ids.index(node_set_id)][ - file_node_set_field_names.index(node_set_field_name)] + file_node_set_ids.index(node_set_id) + ][file_node_set_field_names.index(node_set_field_name)] if not field_exists: continue # process each included timestep @@ -7601,13 +8024,13 @@ def import_model(self, for timestep_index in timestep_indices: file_values = list( exodus_file.get_node_set_variable_values( - node_set_id, node_set_field_name, - timestep_index[0])) + node_set_id, node_set_field_name, timestep_index[0] + ) + ) model_values[timestep_index[1]] = file_values # add default field value to excluded timestep for timestep_index in excluded_timestep_indices: - default_value = self._get_default_field_value( - node_set_field_name) + default_value = self._get_default_field_value(node_set_field_name) node_count = len(self.get_node_set_members(node_set_id)) field = [default_value] * node_count model_values[timestep_index] = field @@ -7619,15 +8042,15 @@ def import_model(self, file_side_set_truth_table = [] for file_side_set_id in file_side_set_ids: file_side_set_truth_table.append( - exodus_file.get_side_set_variable_truth_table( - file_side_set_id)) + exodus_file.get_side_set_variable_truth_table(file_side_set_id) + ) # populate side set fields for side_set_field_name in side_set_field_names: for side_set_id in side_set_ids: # don't process if field does not exist in file field_exists = file_side_set_truth_table[ - file_side_set_ids.index(side_set_id)][ - file_side_set_field_names.index(side_set_field_name)] + file_side_set_ids.index(side_set_id) + ][file_side_set_field_names.index(side_set_field_name)] if not field_exists: continue # process each included timestep @@ -7635,13 +8058,13 @@ def import_model(self, for timestep_index in timestep_indices: file_values = list( exodus_file.get_side_set_variable_values( - side_set_id, side_set_field_name, - timestep_index[0])) + side_set_id, side_set_field_name, timestep_index[0] + ) + ) model_values[timestep_index[1]] = file_values # add default field value to excluded timestep for timestep_index in excluded_timestep_indices: - default_value = self._get_default_field_value( - side_set_field_name) + default_value = self._get_default_field_value(side_set_field_name) side_count = len(self.get_side_set_members(side_set_id)) field = [default_value] * side_count model_values[timestep_index] = field @@ -7653,15 +8076,15 @@ def import_model(self, file_truth_table = [] for file_element_block_id in file_element_block_ids: file_truth_table.append( - exodus_file.get_element_variable_truth_table( - file_element_block_id)) + exodus_file.get_element_variable_truth_table(file_element_block_id) + ) # populate element fields for element_field_name in element_field_names: for element_block_id in element_block_ids: # don't process if field does not exist in file - field_exists = file_truth_table[file_element_block_ids.index( - element_block_id)][file_element_field_names.index( - element_field_name)] + field_exists = file_truth_table[ + file_element_block_ids.index(element_block_id) + ][file_element_field_names.index(element_field_name)] if not field_exists: continue # process each included timestep @@ -7669,13 +8092,13 @@ def import_model(self, for timestep_index in timestep_indices: file_values = list( exodus_file.get_element_variable_values( - element_block_id, element_field_name, - timestep_index[0])) + element_block_id, element_field_name, timestep_index[0] + ) + ) model_values[timestep_index[1]] = file_values # add default field value to excluded timestep for timestep_index in excluded_timestep_indices: - default_value = self._get_default_field_value( - element_field_name) + default_value = self._get_default_field_value(element_field_name) element_count = self.get_element_count(element_block_id) field = [default_value] * element_count model_values[timestep_index] = field @@ -7689,29 +8112,28 @@ def import_model(self, self.create_global_variable(global_variable_name) else: if duplicate_timesteps: - self._exists_warning(global_variable_name, - 'global variable') + self._exists_warning(global_variable_name, "global variable") # get values model_values = self.global_variables[global_variable_name] for timestep_index in timestep_indices: file_value = exodus_file.get_global_variable_value( - global_variable_name, timestep_index[0]) + global_variable_name, timestep_index[0] + ) model_values[timestep_index[1]] = file_value # add info records - if (exodus_file.num_info_records() > 0): + if exodus_file.num_info_records() > 0: self.info_records += exodus_file.get_info_records() # add qa records - if (exodus_file.num_qa_records() > 0): + if exodus_file.num_qa_records() > 0: self.qa_records += exodus_file.get_qa_records() # add title if one does not already exist # else add it to an info record if not self.title: self.title = exodus_file.title() else: - self.info_records.append('Discarded title from the ' - 'following file:') + self.info_records.append("Discarded title from the " "following file:") # split filename string if filename is larger than 79 characters - filename_wrap_list = textwrap.fill(filename, width=79).split('\n') + filename_wrap_list = textwrap.fill(filename, width=79).split("\n") # append interpreter continuation char "\\" to end of continuation line while splitting for i in range(len(filename_wrap_list) - 1): filename_wrap_list[i] += "\\" @@ -7728,17 +8150,19 @@ def import_model(self, if SUPPRESS_EXODUS_OUTPUT: sys.stdout = save_stdout - def export_model(self, - filename='output_exomerge.e', - element_block_ids='all', - timesteps='all', - side_set_ids='all', - node_set_ids='all', - global_variable_names='auto', - node_field_names='auto', - element_field_names='auto', - side_set_field_names='auto', - node_set_field_names='auto'): + def export_model( + self, + filename="output_exomerge.e", + element_block_ids="all", + timesteps="all", + side_set_ids="all", + node_set_ids="all", + global_variable_names="auto", + node_field_names="auto", + element_field_names="auto", + side_set_field_names="auto", + node_set_field_names="auto", + ): """ Export the current model to an ExodusII file. @@ -7749,78 +8173,81 @@ def export_model(self, # verify information is valid self._verify() # format subset of data to export - element_block_ids = self._format_element_block_id_list( - element_block_ids) + element_block_ids = self._format_element_block_id_list(element_block_ids) side_set_ids = self._format_side_set_id_list(side_set_ids) node_set_ids = self._format_node_set_id_list(node_set_ids) - timesteps = self._format_id_list(timesteps, self.get_timesteps(), - 'timestep') + timesteps = self._format_id_list(timesteps, self.get_timesteps(), "timestep") # If no timesteps are exported, or if no nodes are defined, then no # fields can be exported. - if element_field_names == 'auto': + if element_field_names == "auto": if timesteps: - element_field_names = self.get_element_field_names( - element_block_ids) + element_field_names = self.get_element_field_names(element_block_ids) else: - element_field_names = 'none' - if global_variable_names == 'auto': + element_field_names = "none" + if global_variable_names == "auto": if timesteps: - global_variable_names = 'all' + global_variable_names = "all" else: - global_variable_names = 'none' - if node_field_names == 'auto': + global_variable_names = "none" + if node_field_names == "auto": if timesteps and self.nodes: - node_field_names = 'all' + node_field_names = "all" else: - node_field_names = 'none' - if node_set_field_names == 'auto': + node_field_names = "none" + if node_set_field_names == "auto": if timesteps and self.nodes: - node_set_field_names = self.get_node_set_field_names( - node_set_ids) + node_set_field_names = self.get_node_set_field_names(node_set_ids) else: - node_set_field_names = 'none' - if side_set_field_names == 'auto': + node_set_field_names = "none" + if side_set_field_names == "auto": if timesteps: - side_set_field_names = self.get_side_set_field_names( - side_set_ids) + side_set_field_names = self.get_side_set_field_names(side_set_ids) else: - side_set_field_names = 'none' + side_set_field_names = "none" # format each list global_variable_names = self._format_id_list( - global_variable_names, self.get_global_variable_names(), - 'global variable') + global_variable_names, self.get_global_variable_names(), "global variable" + ) element_field_names = self._format_id_list( - element_field_names, self.get_element_field_names(), - 'element field') - node_field_names = self._format_id_list(node_field_names, - self.get_node_field_names(), - 'node field') + element_field_names, self.get_element_field_names(), "element field" + ) + node_field_names = self._format_id_list( + node_field_names, self.get_node_field_names(), "node field" + ) node_set_field_names = self._format_id_list( - node_set_field_names, self.get_node_set_field_names(), - 'node set field') + node_set_field_names, self.get_node_set_field_names(), "node set field" + ) side_set_field_names = self._format_id_list( - side_set_field_names, self.get_side_set_field_names(), - 'side set field') + side_set_field_names, self.get_side_set_field_names(), "side set field" + ) # delete the file if it exists if os.path.isfile(filename): os.remove(filename) # create file - if self.title == '': - self.title = '' + if self.title == "": + self.title = "" if SUPPRESS_EXODUS_OUTPUT: save_stdout = sys.stdout sys.stdout = DummyFile() - new_file = exodus.exodus(filename, 'w', 'ctype', self.title, 3, - len(self.nodes), - self.get_element_count(element_block_ids), - len(element_block_ids), len(node_set_ids), - len(side_set_ids)) + new_file = exodus.exodus( + filename, + "w", + "ctype", + self.title, + 3, + len(self.nodes), + self.get_element_count(element_block_ids), + len(element_block_ids), + len(node_set_ids), + len(side_set_ids), + ) if SUPPRESS_EXODUS_OUTPUT: sys.stdout = save_stdout # put timesteps into chronological order - timestep_indices = [(self.timesteps.index(x), index + 1) - for index, x in enumerate(timesteps)] + timestep_indices = [ + (self.timesteps.index(x), index + 1) for index, x in enumerate(timesteps) + ] # write times for index, timestep in enumerate(timesteps): new_file.put_time(index + 1, timestep) @@ -7830,20 +8257,24 @@ def export_model(self, new_file.put_global_variable_name(name, index + 1) values = self.global_variables[name] for timestep_index in timestep_indices: - new_file.put_global_variable_value(name, timestep_index[1], - values[timestep_index[0]]) + new_file.put_global_variable_value( + name, timestep_index[1], values[timestep_index[0]] + ) # write nodes - new_file.put_coords([x[0] for x in self.nodes], - [x[1] for x in self.nodes], - [x[2] for x in self.nodes]) + new_file.put_coords( + [x[0] for x in self.nodes], + [x[1] for x in self.nodes], + [x[2] for x in self.nodes], + ) # write node fields new_file.set_node_variable_number(len(node_field_names)) for index, name in enumerate(node_field_names): new_file.put_node_variable_name(name, index + 1) values = self.node_fields[name] for timestep_index in timestep_indices: - new_file.put_node_variable_values(name, timestep_index[1], - values[timestep_index[0]]) + new_file.put_node_variable_values( + name, timestep_index[1], values[timestep_index[0]] + ) # write element blocks for id_ in element_block_ids: name, info, connectivity, fields = self.element_blocks[id_] @@ -7859,7 +8290,8 @@ def export_model(self, new_file.put_element_variable_name(name, index + 1) if element_field_names: truth_table = self._create_element_field_truth_table( - element_block_ids, element_field_names) + element_block_ids, element_field_names + ) new_file.set_element_variable_truth_table(truth_table) for block_id in element_block_ids: fields = self._get_element_block_fields(block_id) @@ -7869,17 +8301,15 @@ def export_model(self, field = fields[name] for timestep_index in timestep_indices: new_file.put_element_variable_values( - block_id, name, timestep_index[1], - field[timestep_index[0]]) + block_id, name, timestep_index[1], field[timestep_index[0]] + ) # get first element in each block - element_count = [ - self.get_element_count(id_) for id_ in element_block_ids - ] - first_element = [ - sum(element_count[:i]) + 1 for i in range(len(element_count)) - ] - first_element = dict((element_block_ids[i], first_element[i]) - for i in range(len(element_block_ids))) + element_count = [self.get_element_count(id_) for id_ in element_block_ids] + first_element = [sum(element_count[:i]) + 1 for i in range(len(element_count))] + first_element = dict( + (element_block_ids[i], first_element[i]) + for i in range(len(element_block_ids)) + ) # write side sets for id_ in side_set_ids: name = self.get_side_set_name(id_) @@ -7887,8 +8317,7 @@ def export_model(self, new_file.put_side_set_params(id_, len(members), 0) if members: elements = [ - first_element[block_id] + index - for block_id, index, _ in members + first_element[block_id] + index for block_id, index, _ in members ] sides = [x[2] + 1 for x in members] new_file.put_side_set(id_, elements, sides) @@ -7900,7 +8329,8 @@ def export_model(self, new_file.put_side_set_variable_name(name, index + 1) if side_set_field_names: truth_table = self._create_side_set_field_truth_table( - side_set_ids, side_set_field_names) + side_set_ids, side_set_field_names + ) new_file.set_side_set_variable_truth_table(truth_table) for side_set_id in side_set_ids: members = self.get_side_set_members(side_set_id) @@ -7913,8 +8343,8 @@ def export_model(self, field = fields[name] for timestep_index in timestep_indices: new_file.put_side_set_variable_values( - side_set_id, name, timestep_index[1], - field[timestep_index[0]]) + side_set_id, name, timestep_index[1], field[timestep_index[0]] + ) # write node sets for id_ in node_set_ids: name = self.get_node_set_name(id_) @@ -7932,7 +8362,8 @@ def export_model(self, new_file.put_node_set_variable_name(name, index + 1) if node_set_field_names: truth_table = self._create_node_set_field_truth_table( - node_set_ids, node_set_field_names) + node_set_ids, node_set_field_names + ) new_file.set_node_set_variable_truth_table(truth_table) for node_set_id in node_set_ids: members = self.get_node_set_members(node_set_id) @@ -7945,8 +8376,8 @@ def export_model(self, field = fields[name] for timestep_index in timestep_indices: new_file.put_node_set_variable_values( - node_set_id, name, timestep_index[1], - field[timestep_index[0]]) + node_set_id, name, timestep_index[1], field[timestep_index[0]] + ) # write info records new_file.put_info_records(self.info_records) # write qa records (and append one for this program) @@ -7987,7 +8418,7 @@ def _get_thickness_from_volume_and_area(self, volume, area): # max phi (for a sphere) is 6^(-1/3) * pi^(-1/6) phi = math.pow(volume, 1 / 3.0) / math.pow(area, 1 / 2.0) # find a solution, if possible - max_alpha = math.pi**(-1.0 / 6) * 6.0**(-1.0 / 3) + max_alpha = math.pi ** (-1.0 / 6) * 6.0 ** (-1.0 / 3) low = 0.0 high = max_alpha a = 1.0 @@ -8005,9 +8436,9 @@ def _get_thickness_from_volume_and_area(self, volume, area): low = mid # in the case this fails, return NaN if low == 0 or high == max_alpha: - return float('nan') + return float("nan") alpha = (low + high) / 2.0 - height = (volume * 4 * alpha**2 / math.pi)**(1.0 / 3) + height = (volume * 4 * alpha**2 / math.pi) ** (1.0 / 3) return height def _calculate_element_block_thickness(self, element_block_ids): @@ -8020,15 +8451,17 @@ def _calculate_element_block_thickness(self, element_block_ids): """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) + element_block_ids, empty_list_okay=False + ) # delete any element blocks which are not of dimension 3 new_ids = [] for id_ in element_block_ids: if self.get_element_block_dimension(id_) != 3: self._warning( - 'Unexpected element block dimension', - 'Element blocks used to determine element edge ' - 'length are expected to be of dimension 3.') + "Unexpected element block dimension", + "Element blocks used to determine element edge " + "length are expected to be of dimension 3.", + ) else: new_ids.append(id_) # get the volume @@ -8042,7 +8475,7 @@ def _calculate_element_block_thickness(self, element_block_ids): self.delete_side_set(side_set_id) return self._get_thickness_from_volume_and_area(volume, area) - def get_element_block_extents(self, element_block_ids='all'): + def get_element_block_extents(self, element_block_ids="all"): """ Return the extents of the element blocks as a list. @@ -8051,17 +8484,21 @@ def get_element_block_extents(self, element_block_ids='all'): """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) + element_block_ids, empty_list_okay=False + ) # get a set of all nodes within the given element blocks all_nodes = set() for id_ in element_block_ids: connectivity = self.get_connectivity(id_) all_nodes.update(set(connectivity)) # find the extents of that set - extents = [[ - min(self.nodes[x][d] for x in all_nodes), - max(self.nodes[x][d] for x in all_nodes) - ] for d in range(3)] + extents = [ + [ + min(self.nodes[x][d] for x in all_nodes), + max(self.nodes[x][d] for x in all_nodes), + ] + for d in range(3) + ] return extents def _create_element_blocks_from_side_sets(self, side_set_ids): @@ -8083,19 +8520,20 @@ def _create_element_blocks_from_side_sets(self, side_set_ids): these_members = self._order_element_faces_by_block(members) for element_block_id, members in list(these_members.items()): connectivity = self.get_connectivity(element_block_id) - nodes_per_element = self.get_nodes_per_element( - element_block_id) + nodes_per_element = self.get_nodes_per_element(element_block_id) face_mapping = self._get_face_mapping_from_id(element_block_id) for element_index, face_index in members: face_type = face_mapping[face_index][0] if face_type not in new_elements: new_elements[face_type] = [] - local_node = connectivity[element_index * - nodes_per_element: - (element_index + 1) * - nodes_per_element] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] new_elements[face_type].extend( - [local_node[x] for x in face_mapping[face_index][1]]) + [local_node[x] for x in face_mapping[face_index][1]] + ) # now that we have the face elements in a local format, we create # the elements new_block_ids = [] @@ -8105,7 +8543,9 @@ def _create_element_blocks_from_side_sets(self, side_set_ids): nodes_per_element = self.NODES_PER_ELEMENT[element_type] info = [ element_type, - len(connectivity) // nodes_per_element, nodes_per_element, 0 + len(connectivity) // nodes_per_element, + nodes_per_element, + 0, ] self.create_element_block(new_id, info, connectivity) new_block_ids.append(new_id) @@ -8127,9 +8567,7 @@ def _get_element_edge_indices(self, element_type): return [] # create a mock element elements = dict() - elements[element_type] = [ - list(range(self.NODES_PER_ELEMENT[element_type])) - ] + elements[element_type] = [list(range(self.NODES_PER_ELEMENT[element_type]))] iterations = self._get_dimension(element_type) - 1 # iterate until dimensions are zero for _ in range(iterations): @@ -8141,7 +8579,8 @@ def _get_element_edge_indices(self, element_type): new_elements[face_type] = [] for local_nodes in connectivities: new_elements[face_type].append( - [local_nodes[x] for x in indices]) + [local_nodes[x] for x in indices] + ) elements = new_elements # now find the endpoints using the volume formula edges = [] @@ -8155,7 +8594,7 @@ def _get_element_edge_indices(self, element_type): unique_edges = set(tuple(sorted(x)) for x in edges) return unique_edges - def get_element_edge_length_info(self, element_block_ids='all'): + def get_element_edge_length_info(self, element_block_ids="all"): """ Return the minimum and average element edge lengths. @@ -8166,33 +8605,36 @@ def get_element_edge_length_info(self, element_block_ids='all'): """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) + element_block_ids, empty_list_okay=False + ) minimum = sys.float_info.max total = 0.0 edge_count = 0 for element_block_id in element_block_ids: # get the edge endpoint info endpoints = self._get_element_edge_indices( - self._get_element_type(element_block_id)) + self._get_element_type(element_block_id) + ) # form all element edges element_count = self.get_element_count(element_block_id) connectivity = self.get_connectivity(element_block_id) nodes_per_element = self.get_nodes_per_element(element_block_id) edge_count += element_count * len(endpoints) for element_index in range(element_count): - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] for edge in endpoints: this_distance = self._distance_between( - self.nodes[local_node[edge[0]]], - self.nodes[local_node[edge[1]]]) + self.nodes[local_node[edge[0]]], self.nodes[local_node[edge[1]]] + ) total += this_distance if this_distance < minimum: minimum = this_distance if edge_count == 0: - return [float('nan')] * 2 + return [float("nan")] * 2 return [minimum, total / edge_count] def _get_closest_point_distance_brute(self, points): @@ -8218,32 +8660,34 @@ def _get_closest_point_distance(self, points, sorting_coord=0, trials=0): if low == mid or mid == high: if trials >= 2: return self._get_closest_point_distance_brute(points) - return self._get_closest_point_distance(points, - (sorting_coord + 1) % 3, - trials + 1) + return self._get_closest_point_distance( + points, (sorting_coord + 1) % 3, trials + 1 + ) # sort into two lists low_points = [x for x in points if x[sorting_coord] <= mid] high_points = [x for x in points if x[sorting_coord] > mid] assert len(low_points) < point_count assert len(high_points) < point_count # find closest pair within each set - dist = min(self._get_closest_point_distance(low_points), - self._get_closest_point_distance(high_points)) + dist = min( + self._get_closest_point_distance(low_points), + self._get_closest_point_distance(high_points), + ) del low_points del high_points # find points sufficiently close to centerline mid_low = mid - dist mid_high = mid - dist mid_points = [ - x for x in points + x + for x in points if x[sorting_coord] >= mid_low and x[sorting_coord] <= mid_high ] if len(mid_points) == point_count: return self._get_closest_point_distance_brute(points) dist = min( - dist, - self._get_closest_point_distance(mid_points, - (sorting_coord + 1) % 3)) + dist, self._get_closest_point_distance(mid_points, (sorting_coord + 1) % 3) + ) return dist def get_closest_node_distance(self): @@ -8260,19 +8704,20 @@ def _input_check_error(self, argument, arg_format): places. """ - argument_string = '%s' % argument + argument_string = "%s" % argument if len(argument_string) > 50: - argument_string = argument_string[:47] + '...' - format_string = '%s' % arg_format + argument_string = argument_string[:47] + "..." + format_string = "%s" % arg_format if len(format_string) > 50: - format_string = format_string[:47] + '...' + format_string = format_string[:47] + "..." self._error( - 'Unexpected argument type', - 'The argument to a function failed an input check. This ' - 'is most likely due to passing an invalid argument to ' - 'the function.\n\n' - 'Argument: %s\n' - 'Expected type: %s' % (argument_string, format_string)) + "Unexpected argument type", + "The argument to a function failed an input check. This " + "is most likely due to passing an invalid argument to " + "the function.\n\n" + "Argument: %s\n" + "Expected type: %s" % (argument_string, format_string), + ) def _input_check(self, argument, arg_format): """ @@ -8318,10 +8763,7 @@ def _input_check(self, argument, arg_format): if not isinstance(argument, arg_format[0]): self._input_check_error(argument, arg_format) - def build_hex8_cube(self, - element_block_id='auto', - extents=1.0, - divisions=3): + def build_hex8_cube(self, element_block_id="auto", extents=1.0, divisions=3): """ Create an element block in the shape of a cuboid. @@ -8337,7 +8779,7 @@ def build_hex8_cube(self, """ # process shortcuts on arguments - if element_block_id == 'auto': + if element_block_id == "auto": element_block_id = self._new_element_block_id() if not isinstance(extents, list): self._input_check(extents, [float]) @@ -8380,11 +8822,13 @@ def build_hex8_cube(self, # now create the actual nodes self.create_nodes(new_nodes) # now create the actual block - self.create_element_block(element_block_id, - ['hex8', dimx * dimy * dimz, 8, 0], - connectivity=connectivity) + self.create_element_block( + element_block_id, + ["hex8", dimx * dimy * dimz, 8, 0], + connectivity=connectivity, + ) - def count_degenerate_elements(self, element_block_ids='all'): + def count_degenerate_elements(self, element_block_ids="all"): """ Return the number of degenerate elements in the given element blocks. @@ -8393,22 +8837,24 @@ def count_degenerate_elements(self, element_block_ids='all'): """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) + element_block_ids, empty_list_okay=False + ) degenerate_element_count = 0 for element_block_id in element_block_ids: _, _, connectivity, _ = self.element_blocks[element_block_id] nodes_per_element = self.get_nodes_per_element(element_block_id) element_count = len(connectivity) // nodes_per_element for element_index in range(element_count): - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element + ] if len(set(local_node)) != nodes_per_element: degenerate_element_count += 1 return degenerate_element_count - def count_disconnected_blocks(self, element_block_ids='all'): + def count_disconnected_blocks(self, element_block_ids="all"): """ Return the number of disconnected blocks. @@ -8417,7 +8863,8 @@ def count_disconnected_blocks(self, element_block_ids='all'): """ element_block_ids = self._format_element_block_id_list( - element_block_ids, empty_list_okay=False) + element_block_ids, empty_list_okay=False + ) nodes = self.get_nodes_in_element_block(element_block_ids) # for each node, find the lowest index node that it's connected to master = list(range(len(self.nodes))) @@ -8426,8 +8873,9 @@ def count_disconnected_blocks(self, element_block_ids='all'): nodes_per_element = self.get_nodes_per_element(element_block_id) element_count = self.get_element_count(element_block_id) for i in range(element_count): - local_node = connectivity[i * nodes_per_element:(i + 1) * - nodes_per_element] + local_node = connectivity[ + i * nodes_per_element: (i + 1) * nodes_per_element + ] # find lowest index master out of these low = min(local_node) for x in local_node: @@ -8460,10 +8908,8 @@ def _get_mating_faces(self, side_set_members_one, side_set_members_two): """ # order by element block - members_one_by_block = self._order_element_faces_by_block( - side_set_members_one) - members_two_by_block = self._order_element_faces_by_block( - side_set_members_two) + members_one_by_block = self._order_element_faces_by_block(side_set_members_one) + members_two_by_block = self._order_element_faces_by_block(side_set_members_two) # find the nodes within set two and create a set of them faces_to_match = set() for id_, members in list(members_two_by_block.items()): @@ -8471,13 +8917,12 @@ def _get_mating_faces(self, side_set_members_one, side_set_members_two): connectivity = self.get_connectivity(id_) face_mapping = self._get_face_mapping_from_id(id_) for element_index, face_index in members: - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] - face_nodes = [ - local_node[x] for x in face_mapping[face_index][1] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element ] + face_nodes = [local_node[x] for x in face_mapping[face_index][1]] faces_to_match.add(tuple(sorted(face_nodes))) # now look through the original list for duplicates mating_faces = [] @@ -8486,13 +8931,12 @@ def _get_mating_faces(self, side_set_members_one, side_set_members_two): connectivity = self.get_connectivity(id_) face_mapping = self._get_face_mapping_from_id(id_) for element_index, face_index in members: - local_node = connectivity[element_index * - nodes_per_element:(element_index + - 1) * - nodes_per_element] - face_nodes = [ - local_node[x] for x in face_mapping[face_index][1] + local_node = connectivity[ + element_index + * nodes_per_element: (element_index + 1) + * nodes_per_element ] + face_nodes = [local_node[x] for x in face_mapping[face_index][1]] if tuple(sorted(face_nodes)) in faces_to_match: mating_faces.append((id_, element_index, face_index)) return mating_faces @@ -8508,12 +8952,16 @@ def _detailed_summary(self): timestep_created = True self.create_timestep(0.0) # print out general info - print('\nMODEL SUMMARY\n') + print("\nMODEL SUMMARY\n") ids = self.get_element_block_ids() element_block_count = len(ids) element_count = self.get_element_count(ids) - print(('- Model contains %d element blocks and %d elements' % - (element_block_count, element_count))) + print( + ( + "- Model contains %d element blocks and %d elements" + % (element_block_count, element_count) + ) + ) # if any elements exist... if element_count: # calculate element volume field @@ -8525,93 +8973,112 @@ def _detailed_summary(self): # print out element block info if element_count: extents = self.get_element_block_extents(ids) - print('- Extents are:') + print("- Extents are:") for d in range(3): - print((' - %s: %g to %g, range of %g' % - ('XYZ' [d], extents[d][0], extents[d][1], - extents[d][1] - extents[d][0]))) + print( + ( + " - %s: %g to %g, range of %g" + % ( + "XYZ"[d], + extents[d][0], + extents[d][1], + extents[d][1] - extents[d][0], + ) + ) + ) # print center of mass - cg = self.get_element_block_centroid(ids, - element_volume_field_name, - element_centroid_field_names) - cg = ['%g' % x for x in cg] - print(('- Center of volume is at [%s]' % (', '.join(cg)))) + cg = self.get_element_block_centroid( + ids, element_volume_field_name, element_centroid_field_names + ) + cg = ["%g" % x for x in cg] + print(("- Center of volume is at [%s]" % (", ".join(cg)))) # print total volume - volume = self.get_element_block_volume(ids, - element_volume_field_name) - print(('- Total volume is %g' % volume)) + volume = self.get_element_block_volume(ids, element_volume_field_name) + print(("- Total volume is %g" % volume)) # print total surface area side_set_id = self._new_side_set_id() - self.create_side_set(side_set_id, - self._get_external_element_faces(ids)) + self.create_side_set(side_set_id, self._get_external_element_faces(ids)) area = self.get_side_set_area(side_set_id) self.delete_side_set(side_set_id) - print(('- Total surface area is %d' % area)) + print(("- Total surface area is %d" % area)) # print number of disconnected blocks - connected_blocks = self.count_disconnected_blocks('all') - print(('- Contains %d disconnected blocks' % (connected_blocks))) + connected_blocks = self.count_disconnected_blocks("all") + print(("- Contains %d disconnected blocks" % (connected_blocks))) # print element edge length stats minimum, average = self.get_element_edge_length_info(ids) - print(('- Average element edge length is %g' % (average))) - print(('- Smallest element edge length is %g' % (minimum))) + print(("- Average element edge length is %g" % (average))) + print(("- Smallest element edge length is %g" % (minimum))) if self.nodes: node_distance = self.get_closest_node_distance() - print(('- The closest node pair is %g apart' % (node_distance))) + print(("- The closest node pair is %g apart" % (node_distance))) print() - print('ELEMENT BLOCK INFO') + print("ELEMENT BLOCK INFO") # find external faces for each element block if element_count: - external_faces = dict((id_, self._get_external_element_faces(id_)) - for id_ in self.get_element_block_ids()) + external_faces = dict( + (id_, self._get_external_element_faces(id_)) + for id_ in self.get_element_block_ids() + ) # print info on each element block for id_ in self.get_element_block_ids(): print() name = self.get_element_block_name(id_) - print(('Element block ID %d%s:' % (id_, (' "%s"' % - (name)) if name else ''))) + print( + ("Element block ID %d%s:" % (id_, (' "%s"' % (name)) if name else "")) + ) dim = self.get_element_block_dimension(id_) element_count = self.get_element_count(id_) element_type = self._get_element_type(id_) - dim_name = ' %d-dimensional' % dim if dim != -1 else '' - print(('- Contains %d "%s"%s elements' % - (element_count, element_type, dim_name))) + dim_name = " %d-dimensional" % dim if dim != -1 else "" + print( + ( + '- Contains %d "%s"%s elements' + % (element_count, element_type, dim_name) + ) + ) # if no elements, skip detailed info on this block if not element_count: continue extents = self.get_element_block_extents(id_) - print('- Extents are:') + print("- Extents are:") for d in range(3): - print((' - %s: %g to %g, range of %g' % - ('XYZ' [d], extents[d][0], extents[d][1], - extents[d][1] - extents[d][0]))) + print( + ( + " - %s: %g to %g, range of %g" + % ( + "XYZ"[d], + extents[d][0], + extents[d][1], + extents[d][1] - extents[d][0], + ) + ) + ) # print center of mass - cg = self.get_element_block_centroid(id_, - element_volume_field_name, - element_centroid_field_names) - cg = ['%g' % x for x in cg] - print(('- Center of volume is at [%s]' % (', '.join(cg)))) + cg = self.get_element_block_centroid( + id_, element_volume_field_name, element_centroid_field_names + ) + cg = ["%g" % x for x in cg] + print(("- Center of volume is at [%s]" % (", ".join(cg)))) # print total volume - volume = self.get_element_block_volume(id_, - element_volume_field_name) - print(('- Total volume is %g' % (volume))) + volume = self.get_element_block_volume(id_, element_volume_field_name) + print(("- Total volume is %g" % (volume))) # print total surface area side_set_id = self._new_side_set_id() self.create_side_set(side_set_id, external_faces[id_]) area = self.get_side_set_area(side_set_id) self.delete_side_set(side_set_id) - print(('- Total surface area is %g' % (area))) + print(("- Total surface area is %g" % (area))) # print number of disconnected blocks connected_blocks = self.count_disconnected_blocks(id_) - print(('- Contains %d disconnected blocks' % (connected_blocks))) + print(("- Contains %d disconnected blocks" % (connected_blocks))) # print element edge length stats if dim == 3: minimum, average = self.get_element_edge_length_info(id_) - print(('- Average element edge length is %g' % (average))) - print(('- Smallest element edge length is %g' % (minimum))) + print(("- Average element edge length is %g" % (average))) + print(("- Smallest element edge length is %g" % (minimum))) # print thickness - thickness = self._get_thickness_from_volume_and_area( - volume, area) - print(('- Approximate thickness is %g' % (thickness))) + thickness = self._get_thickness_from_volume_and_area(volume, area) + print(("- Approximate thickness is %g" % (thickness))) # print surface connectivity to other blocks # find faces connected to other blocks remaining_faces = set(external_faces[id_]) @@ -8619,8 +9086,9 @@ def _detailed_summary(self): for other_id in self.get_element_block_ids(): if other_id == id_: continue - mating_faces = self._get_mating_faces(external_faces[id_], - external_faces[other_id]) + mating_faces = self._get_mating_faces( + external_faces[id_], external_faces[other_id] + ) if mating_faces: remaining_faces -= set(mating_faces) side_set_id = self._new_side_set_id() @@ -8628,69 +9096,73 @@ def _detailed_summary(self): area = self.get_side_set_area(side_set_id) self.delete_side_set(side_set_id) if not header_output: - print('- Connected to the following element blocks:') + print("- Connected to the following element blocks:") header_output = True print( - (' - To element block %d though %d faces ' - '(area of %g)' % (other_id, len(mating_faces), area))) + ( + " - To element block %d though %d faces " + "(area of %g)" % (other_id, len(mating_faces), area) + ) + ) if header_output and remaining_faces: remaining_faces = list(remaining_faces) side_set_id = self._new_side_set_id() self.create_side_set(side_set_id, remaining_faces) area = self.get_side_set_area(side_set_id) self.delete_side_set(side_set_id) - print((' - To the outside through %d faces ' - '(area of %g)' % (len(remaining_faces), area))) + print( + ( + " - To the outside through %d faces " + "(area of %g)" % (len(remaining_faces), area) + ) + ) if not header_output: - print('- Not connected to any element blocks') + print("- Not connected to any element blocks") # print node set info - print('\nNODE SET INFO\n') + print("\nNODE SET INFO\n") ids = self.get_node_set_ids() - print(('There are %d node sets defined.' % (len(ids)))) + print(("There are %d node sets defined." % (len(ids)))) for id_ in ids: print() name = self.get_node_set_name(id_) - print(('Node set ID %d%s:' % (id_, - (' "%s"' % (name)) if name else ''))) - print(('- Contains %d members' % - (len(self.get_node_set_members(id_))))) + print(("Node set ID %d%s:" % (id_, (' "%s"' % (name)) if name else ""))) + print(("- Contains %d members" % (len(self.get_node_set_members(id_))))) field_names = self.get_node_set_field_names(id_) if field_names: - print(('- Has %d fields defined:' % (len(field_names)))) + print(("- Has %d fields defined:" % (len(field_names)))) for name in field_names: print((' - "%s"' % (name))) # print node set info - print('\nSIDE SET INFO\n') + print("\nSIDE SET INFO\n") ids = self.get_side_set_ids() - print(('There are %d side sets defined.' % (len(ids)))) + print(("There are %d side sets defined." % (len(ids)))) for id_ in ids: print() name = self.get_side_set_name(id_) - print(('Side set ID %d%s:' % (id_, - (' "%s"' % (name)) if name else ''))) + print(("Side set ID %d%s:" % (id_, (' "%s"' % (name)) if name else ""))) members = self.get_side_set_members(id_) member_count = len(members) - print(('- Contains %d members' % (member_count))) + print(("- Contains %d members" % (member_count))) parent_blocks = sorted(set(x[0] for x in members)) - parent_string = ', '.join('%s' % (x) for x in parent_blocks) - print(('- Parent element block IDs: %s' % (parent_string))) + parent_string = ", ".join("%s" % (x) for x in parent_blocks) + print(("- Parent element block IDs: %s" % (parent_string))) face_types = [] members_by_block = self._order_element_faces_by_block(members) for block_id, these_members in list(members_by_block.items()): element_type = self._get_element_type(block_id) if not self._is_standard_element_type(element_type): - face_types.append('unknown') + face_types.append("unknown") continue face_mapping = self._get_face_mapping_from_id(block_id) face_indices = set(x[1] for x in these_members) face_types.extend(face_mapping[x][0] for x in face_indices) face_types = sorted(set(face_types)) - print(('- Face types: %s' % (', '.join(face_types)))) + print(("- Face types: %s" % (", ".join(face_types)))) area = self.get_side_set_area(id_) - print(('- Total area of %g' % (area))) + print(("- Total area of %g" % (area))) field_names = self.get_side_set_field_names(id_) if field_names: - print(('- Has %d fields defined:' % (len(field_names)))) + print(("- Has %d fields defined:" % (len(field_names)))) for name in field_names: print((' - "%s"' % (name))) # delete temporary timestep if created diff --git a/packages/seacas/scripts/tests/exomerge_unit_test.py b/packages/seacas/scripts/tests/exomerge_unit_test.py index 4720a1d4ee..70cbd4f33a 100755 --- a/packages/seacas/scripts/tests/exomerge_unit_test.py +++ b/packages/seacas/scripts/tests/exomerge_unit_test.py @@ -2,10 +2,11 @@ """ This file performs unit tests of functions within Exomerge. -Copyright 2018, 2021, 2022 National Technology and Engineering Solutions of Sandia. Under -the terms of Contract DE-NA-0003525, there is a non-exclusive license for use -of this work by or on behalf of the U.S. Government. Export of this program -may require a license from the United States Government. +Copyright 2018, 2021, 2022 National Technology and Engineering +Solutions of Sandia. Under the terms of Contract DE-NA-0003525, there +is a non-exclusive license for use of this work by or on behalf of the +U.S. Government. Export of this program may require a license from +the United States Government. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -114,7 +115,7 @@ def compares_equal_with_nan(one, two): floats. They can be nested. """ - if type(one) != type(two): + if type(one) is not type(two): return False if isinstance(one, dict): if sorted(one.keys()) != sorted(two.keys()): @@ -918,7 +919,9 @@ def _test_merge_nodes(self): if not self.model.nodes: return False x = len(self.model.nodes) - self.model._duplicate_nodes(_random_subset(list(range(len(self.model.nodes))), 1), []) + self.model._duplicate_nodes( + _random_subset(list(range(len(self.model.nodes))), 1), [] + ) self.model.merge_nodes(suppress_warnings=True) assert len(self.model.nodes) <= x @@ -1765,9 +1768,7 @@ def test(self): # get a list of all public functions in exomerge public_functions = [] - for (function, _) in inspect.getmembers( - exomerge.ExodusModel, inspect.isfunction - ): + for function, _ in inspect.getmembers(exomerge.ExodusModel, inspect.isfunction): if not function.startswith("_"): public_functions.append(function) print( @@ -1783,7 +1784,7 @@ def test(self): matched_unit_tests = [] for unit_test in unit_tests: (test, _) = unit_test - if not test[6:] in public_functions: + if test[6:] not in public_functions: unmatched.append(test) else: matched_unit_tests.append(unit_test) @@ -1803,7 +1804,7 @@ def test(self): unmatched = [] unit_test_names = [x[0] for x in unit_tests] for name in public_functions: - if not "_test_" + name in unit_test_names: + if "_test_" + name not in unit_test_names: unmatched.append(name) if unmatched: print( @@ -1860,7 +1861,7 @@ def test(self): # if some tests did not successfully run, not that if len(passed_tests) != len(unit_tests): untested = [] - for (x, _) in unit_tests: + for x, _ in unit_tests: if x not in passed_tests: untested.append(x) print( diff --git a/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h b/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h index 8012dba2c0..06b5313366 100644 --- a/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h +++ b/packages/zoltan/siMPI/pyMPI/siMPI/mpi.h @@ -12,13 +12,14 @@ /* FILE *********** mpi.h ********************/ /******************************************************************/ /* Author : Lisa Alano June 18 2002 */ -/* Copyright (c) 2002 University of California Regents */ +/* Copyright (c) 2002, 2023 University of California Regents */ /******************************************************************/ #ifndef _MPI_H #define _MPI_H #ifdef __cplusplus + // NOLINTBEGIN extern "C" { #endif @@ -294,6 +295,7 @@ SKIP FOR NOW FORTRAN: EXTERNAL MPI_DUP_FN #ifdef __cplusplus + // NOLINTEND } #endif diff --git a/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h b/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h index 962bec0a06..157093cbd7 100644 --- a/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h +++ b/packages/zoltan/siMPI/pyMPI/siMPI/mpi_implementation.h @@ -9,13 +9,14 @@ /* FILE *********** mpi_implementation.h ********************/ /******************************************************************/ /* Author : Lisa Alano June 18 2002 */ -/* Copyright (c) 2002 University of California Regents */ +/* Copyright (c) 2002, 2023 University of California Regents */ /******************************************************************/ #ifndef _MPI_IMPL_H #define _MPI_IMPL_H #ifdef __cplusplus + // NOLINTBEGIN extern "C" { #endif @@ -257,6 +258,7 @@ int _MPI_Find_free (void); #ifdef __cplusplus } + // NOLINTEND #endif #endif diff --git a/packages/zoltan/src/include/zoltan.h b/packages/zoltan/src/include/zoltan.h index 3a077248d8..6bb2712a0c 100644 --- a/packages/zoltan/src/include/zoltan.h +++ b/packages/zoltan/src/include/zoltan.h @@ -4,7 +4,7 @@ * *********************************************************************** * * Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring - * Copyright 2012 Sandia Corporation + * Copyright 2012, 2023 Sandia Corporation * * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, * the U.S. Government retains certain rights in this software. @@ -63,6 +63,7 @@ typedef void ZOLTAN_VOID_FN(void); #ifdef __cplusplus /* if C++, define the rest of this header file as extern C */ + // NOLINTBEGIN extern "C" { #endif @@ -3431,6 +3432,7 @@ extern int Zoltan_Deserialize( #ifdef __cplusplus } /* closing bracket for extern "C" */ + // NOLINTEND #endif #endif /* !__ZOLTAN_H */ diff --git a/packages/zoltan/src/include/zoltan_cpp.h b/packages/zoltan/src/include/zoltan_cpp.h index 72b049f615..74a65e9f63 100644 --- a/packages/zoltan/src/include/zoltan_cpp.h +++ b/packages/zoltan/src/include/zoltan_cpp.h @@ -4,7 +4,7 @@ * *********************************************************************** * * Zoltan Toolkit for Load-balancing, Partitioning, Ordering and Coloring - * Copyright 2012 Sandia Corporation + * Copyright 2012, 2023 Sandia Corporation * * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, * the U.S. Government retains certain rights in this software. @@ -275,7 +275,7 @@ class Zoltan { int Set_Fn ( const ZOLTAN_FN_TYPE &fn_type, void (*fn_ptr)(), - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Fn( ZZ_Ptr, fn_type, fn_ptr, data ); } @@ -284,257 +284,257 @@ class Zoltan { ///-------------------------- int Set_Part_Multi_Fn ( ZOLTAN_PART_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Part_Fn ( ZOLTAN_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Edges_Multi_Fn ( ZOLTAN_NUM_EDGES_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Edges_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Edges_Fn ( ZOLTAN_NUM_EDGES_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Edges_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Edge_List_Multi_Fn ( ZOLTAN_EDGE_LIST_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Edge_List_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Edge_List_Fn ( ZOLTAN_EDGE_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Edge_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Geom_Fn ( ZOLTAN_NUM_GEOM_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Geom_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Geom_Multi_Fn ( ZOLTAN_GEOM_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Geom_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Geom_Fn ( ZOLTAN_GEOM_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Geom_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Obj_Fn ( ZOLTAN_NUM_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Obj_List_Fn ( ZOLTAN_OBJ_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Obj_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_First_Obj_Fn ( ZOLTAN_FIRST_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_First_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Next_Obj_Fn ( ZOLTAN_NEXT_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Next_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Coarse_Obj_Fn ( ZOLTAN_NUM_COARSE_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Coarse_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Coarse_Obj_List_Fn ( ZOLTAN_COARSE_OBJ_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Coarse_Obj_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_First_Coarse_Obj_Fn( ZOLTAN_FIRST_COARSE_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_First_Coarse_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Next_Coarse_Obj_Fn ( ZOLTAN_NEXT_COARSE_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Next_Coarse_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Child_Fn ( ZOLTAN_NUM_CHILD_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Child_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Child_List_Fn ( ZOLTAN_CHILD_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Child_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Child_Weight_Fn ( ZOLTAN_CHILD_WEIGHT_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Child_Weight_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_Size_CS_Fn ( ZOLTAN_HG_SIZE_CS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_Size_CS_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_CS_Fn ( ZOLTAN_HG_CS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_CS_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_Size_Edge_Wts_Fn ( ZOLTAN_HG_SIZE_EDGE_WTS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_Size_Edge_Wts_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_HG_Edge_Wts_Fn ( ZOLTAN_HG_EDGE_WTS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_HG_Edge_Wts_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Num_Levels_Fn( ZOLTAN_HIER_NUM_LEVELS_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Num_Levels_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Part_Fn( ZOLTAN_HIER_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Part_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Method_Fn( ZOLTAN_HIER_METHOD_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Method_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Num_Fixed_Obj_Fn ( ZOLTAN_NUM_FIXED_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Num_Fixed_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Fixed_Obj_List_Fn ( ZOLTAN_FIXED_OBJ_LIST_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Fixed_Obj_List_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Pre_Migrate_PP_Fn ( ZOLTAN_PRE_MIGRATE_PP_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Pre_Migrate_PP_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Mid_Migrate_PP_Fn ( ZOLTAN_MID_MIGRATE_PP_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Mid_Migrate_PP_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Post_Migrate_PP_Fn ( ZOLTAN_POST_MIGRATE_PP_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Post_Migrate_PP_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Obj_Size_Multi_Fn ( ZOLTAN_OBJ_SIZE_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Obj_Size_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Obj_Size_Fn ( ZOLTAN_OBJ_SIZE_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Obj_Size_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Pack_Obj_Multi_Fn ( ZOLTAN_PACK_OBJ_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Pack_Obj_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Pack_Obj_Fn ( ZOLTAN_PACK_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Pack_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Unpack_Obj_Multi_Fn( ZOLTAN_UNPACK_OBJ_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Unpack_Obj_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Unpack_Obj_Fn ( ZOLTAN_UNPACK_OBJ_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Unpack_Obj_Fn( ZZ_Ptr, fn_ptr, data ); } @@ -542,21 +542,21 @@ class Zoltan { /// Backward compatibility with v3.0 ///-------------------------- int Set_Partition_Multi_Fn ( ZOLTAN_PART_MULTI_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Multi_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Partition_Fn ( ZOLTAN_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Part_Fn( ZZ_Ptr, fn_ptr, data ); } ///-------------------------- int Set_Hier_Partition_Fn( ZOLTAN_HIER_PART_FN * fn_ptr, - void * data = 0 ) + void * data = nullptr ) { return Zoltan_Set_Hier_Part_Fn( ZZ_Ptr, fn_ptr, data ); }