Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lurpi/ogsPW
  • steffenbeese/ogs
  • HBShaoUFZ/ogs
  • vehling/ogs
  • kuateric/ogs
  • heinzej/ogs
  • MostafaMollaali/dynamic
  • GuanglinDu/ogs
  • katakurgyis/ogs
  • felikskiszkurno/ogs
  • aachaudhry/ogs
  • friederl/ogs
  • fparisio/ogs
  • Scinopode/ogs
  • MaxDoe/ogs
  • nagelt/ogs
  • zhangning737/ogs
  • ogs/ogs
  • bilke/ogs
  • montoyav/ogs
  • TomFischer/ogs
  • wenqing/ogs
  • renchao-lu/ogs
  • ChaofanChen/ogs
  • rinkk/ogs
  • WanlongCai/ogs
  • dominik-kern/ogs
  • Yonghui56/ogs
  • endJunction/ogs
  • VinayGK/ogs
  • AlirezaBGE/ogs
  • SebasTouristTrophyF/ogs
  • tengfeideng/ogs
  • joergbuchwald/ogs
  • KeitaYoshioka/ogs
  • hhutyou/debug-petsc-large
  • ThieJan/ogs
  • ArashPartow/ogs
  • skai95/ogs
  • yezhigangzju/ogs
  • PhilippSelzer/ogs
  • MartinBinder/ogs
  • MehranGhasabeh/ogs-mg
  • MManicaM/ogs
  • TobiasMeisel/ogs
  • norihiro-w/ogs
  • garibay-j/ogs
  • Christopher-McDermott/ogs
  • loewenzahm/ogs
  • aheinri5/ogs
  • RichardScottOZ/ogs
  • lagraviereScience/ogs
  • tcajuhi/ogs
  • jrandow/ogs
  • cbsilver/ogs
  • reza-taherdangkoo/ogs
  • joboog/ogs
  • basakz/ogs
  • ropaoleon/ogs
  • ShuangChen88/ogs
  • cguevaramorel/ogs
  • boyanmeng/ogs
  • XRuiWang/ogs
  • grubbymoon/ogs
  • yUHaOLiu-tj/ogs
  • FZill/ogs
  • michaelpitz/ogs
  • hhutyou/ogs
  • Lifan97/ogs
  • mattschy/ogs
  • Mojtaba-abdolkhani/ogs
  • kristofkessler/ogs
  • ozgurozansen/ogs
  • eike-radeisen/ogs-gitlab
  • DStafford/ogs
  • Max_Jaeschke/ogs
  • fwitte/ogs
  • LionAhrendt/ogs
  • emadnrz/ogs
  • laubry/ogs
  • HailongS/ogs
  • noorhasan/ogs
  • WenjieXuZJU/ogs
  • suresh199824/ogs
84 results
Show changes
Showing
with 2808 additions and 631 deletions
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
Alireza Hassanzadegan <a.hassanzadegan@gmail.com> AlirezaBGE <a.hassanzadegan@gmail.com>
Aqeel Chaudhry <Aqeel.Chaudhry@ifgt.tu-freiberg.de> aachaudhry <aqeel318@gmail.com>
Carolin Helbig <carolin.helbig@ufz.de>
Chaofan Chen <chaofan.chen@ufz.de>
Chaofan Chen <chaofan.chen@ufz.de> <cchaofan1311@gmail.com>
Christian Silbermann <christian.silbermann@ifgt.tu-freiberg.de> cbsilver <christian.silbermann@ifgt.tu-freiberg.de>
Christoph Lehmann <christoph.lehmann@ufz.de> <chleh@users.noreply.github.com>
Dmitri Naumov <dmitri-jurievic.naumov@ifgt.tu-freiberg.de> <github@naumov.de>
Dmitri Naumov <dmitri-jurievic.naumov@ifgt.tu-freiberg.de> Dmitrij Naumov <dmitrij@naumov.de>
Dmitri Naumov <dmitri-jurievic.naumov@ifgt.tu-freiberg.de> Dmitry Yu. Naumov <dmitri.naumov@ufz.de>
Dmitri Naumov <dmitri-jurievic.naumov@ifgt.tu-freiberg.de> <dmitri.naumov@ufz.de>
Dmitri Naumov <dmitri-jurievic.naumov@ifgt.tu-freiberg.de> <Dmitri-Jurievic.Naumov@ifgt.tu-freiberg.de>
Dominik Kern <dominik.kern1@ifgt.tu-freiberg.de> <dominik.kern.ifgt@gmail.com>
Eric Simo <eric.simo@bge.de> ericsimo <kuateric>
Florian Zill <florian.zill@ufz.de> Florian Krupsack <florian.krupsack@ufz.de>
Florian Zill <florian.zill@ufz.de> FZill <48240078+FZill@users.noreply.github.com>
Florian Zill <florian.zill@ufz.de> FZill <florian.zill@ufz.de>
Francesco Parisio <francesco.parisio@ufz.de> <francesco.parisio@protonmail.com>
Haibing Shao <haibing.shao@ufz.de> <36633245+HBShaoUFZ@users.noreply.github.com>
Haibing Shao <haibing.shao@ufz.de> HBShaoUFZ
Jaime Garibay <jaimegaribay.1@gmail.com> garibay-j <jaimegaribay.1@gmail.com>
Jan Thiedau <jan.thiedau@bgr.de> <44462589+ThieJan@users.noreply.github.com>
Jan Thiedau <jan.thiedau@bgr.de> Jan Thiedau <Jan.Thiedau@bgr.de>
Jan Thiedau <jan.thiedau@bgr.de> ThieJan <jan.thiedau@bgr.de>
Jasper Bathmann <jasper.bathmann@ufz.de>
Jeremie Lagraviere <jeremie.lagraviere@gmail.com>
Johannes Boog <johannes.boog@ufz.de> <johannesboog@yahoo.de>
Jörg Buchwald <joerg.buchwald@ufz.de> joerg <joerg.buchwald@ufz.de>
Jörg Buchwald <joerg.buchwald@ufz.de> joerg <joerg@debian>
Jörg Buchwald <joerg.buchwald@ufz.de> joergbuchwald <44933043+joergbuchwald@users.noreply.github.com>
Jörg Buchwald <joerg.buchwald@ufz.de> joergbuchwald <joerg.buchwald@ufz.de>
Karsten Rink <karsten.rink@ufz.de>
Keita Yoshioka <keita.yoshioka@ufz.de>
Keita Yoshioka <keita.yoshioka@ufz.de> <32516139+KeitaYoshioka@users.noreply.github.com>
Lars Bilke <lars.bilke@ufz.de> <bilke@users.noreply.github.com> <lars@bilke.info>
Lars Bilke <lars.bilke@ufz.de> Lars Bilke <lars@bilke.info>
Lars Bilke <lars.bilke@ufz.de> Lars Bilke <larsbilke83@googlemail.com>
Marc Walther <marc.walther@ufz.de>
Mostafa Mollaali <mostafa.mollaali@ufz.de> MostafaMollaali <m.molaali@gmail.com>
Myles English <mylesenglish@gmail.com>
Norbert Grunwald <norbert.grunwald@ufz.de> <n.g.boettcher@gmail.com>
Norbert Grunwald <norbert.grunwald@ufz.de> <Norbert.Grunwald@ufz.de>
Norihiro Watanabe <norihiro.watanabe@ufz.de> <norihiro.watanabe@aist.go.jp>
Norihiro Watanabe <norihiro.watanabe@ufz.de> <norihiro.w@gmail.com>
OGS Bot[bot] <no-email> git@dev2 <lars.bilke@ufz.de>
OGS Bot[bot] <no-email> GitLab Runner <ci@opengeosys.org>
OGS Bot[bot] <no-email> OGS Bot <larsbilke@web.de>
OGS Bot[bot] <no-email> OGS Bot <larsbilke@web.de>
OGS Bot[bot] <no-email> ogsbot <larsbilke@web.de>
Renchao Lu <renchao.lu@ufz.de> <renchao.lu@gmail.com>
Renchao Lu <renchao.lu@ufz.de> <lur@modmon128.intranet.ufz.de>
Renchao Lu <renchao.lu@ufz.de> renchao.lu <renchao.lu@ufz.de>
Reza Taher Dang Koo <reza.taherdangkoo@ifgt.tu-freiberg.de> rezataherdangkoo <reza.taherdangkoo@gmail.com>
Shuang Chen <shuang.chen@bgr.de> <gechenshuang88@gmail.com>
Shuang Chen <shuang.chen@bgr.de> Shuang Chen <shuang.chen@ufz.de>
Tengfei Deng <Tengfei.Deng@doktorand.tu-freiberg.de> tengfeideng <54792615+tengfeideng@users.noreply.github.com>
Tengfei Deng <Tengfei.Deng@doktorand.tu-freiberg.de> tengfeideng <dengtengfei2016@hotmail.com>
Thomas Fischer <thomas.fischer@ufz.de> <123_tom_dabei@web.de> <Thomas.Fischer@ufz.de>
Thomas Fischer <thomas.fischer@ufz.de> <Thomas.Fischer@ufz.de>
Thomas Kalbacher <thomas.kalbacher@ufz.de> Thomas-TK <thomas.kalbacher@ufz.de>
Thomas Nagel <thomas.nagel@ufz.de> <nagelt@tcd.ie>
Thomas Nagel <thomas.nagel@ufz.de> nagelt <thomas.nagel@ufz.de>
Thomas Nagel <thomas.nagel@ufz.de> tnagel <thomas.nagel@ufz.de>
Thomas Nagel <thomas.nagel@ufz.de> <thomas.nagel@ifgt.tu-freiberg.de>
Tianyuan Zheng <ichbinzty@gmail.com>
Tobias Meisel <tobias.meisel@ufz.de> <tobias.meisel@web.de>
Tobias Meisel <tobias.meisel@ufz.de>
Tuanny Cajuhi <Tuanny.Cajuhi@bgr.de> tcajuhi <trmcajuhi@gmail.com>
Vanessa Montoya <vanessa.montoya@ufz.de> montoyag <vanemonto@hotmail.com>
Vanessa Montoya <vanessa.montoya@ufz.de> montoyav <vanessa.montoya@ufz.de>
Wanlong Cai <cccwl828@gmail.com> Wanlong <cccwl828@gmail.com>
Wanlong Cai <cccwl828@gmail.com> WanlongCai <wanlong.cai@ufz.de>
Wenqing Wang <wenqing.wang@ufz.de>
Xing-Yuan Miao <miaoxingyuan@live.cn> <xing-yuan.miao@ufz.de>
Xing-Yuan Miao <miaoxingyuan@live.cn> xingyuanmiao <xingyuanmiao@users.noreply.github.com>
Xing-Yuan Miao <miaoxingyuan@live.cn> xymiao
Yonghui Huang <huangyh56@gmail.com>
Yonghui Huang <huangyh56@gmail.com> Yonghui <huangyh56@gmial.com>
Yonghui Huang <huangyh56@gmail.com> Yonghui56 <huangyh56@gmail.com>
Zhang Ning <zhangning737@gmail.com> Rooney <43574869+zhangning737@users.noreply.github.com>
Zhang Ning <zhangning737@gmail.com> zhangning737 <zhangning737@gmail.com>
dependabot[bot] <no-email> dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dependabot[bot] <no-email> dependabot[bot] <dependabot[bot]@users.noreply.github.com>
Robert Habel <Robert.Habel@student.tu-freiberg.de> Robert Habel <robert.habel@student.tu-freiberg.de>
Linda Günther <linda.guenther@student.tu-freiberg.de> Linda Günther <Linda.Guenther@student.tu-freiberg.de>
Sophia Einspänner <sophia.einspaenner@student.tu-freiberg.de> Sophia Einspänner <Sophia.Einspaenner@student.tu-freiberg.de>
Jakob Randow <jakob.randow@web.de> jrandow <jakob.randow@htwk-leipzig.de>
Jakob Randow <jakob.randow@web.de> jrandow <jakob.randow@web.de>
Olaf Kolditz <olaf.kolditz@ufz.de>
Falko Vehling <falko.vehling@ufz.de>
Julian Heinze <julian.heinze@ufz.de>
Tao You <hhutyou@126.com>
Matthes Kantzenbach <m.kantzenbach@outlook.de>
Feliks K. Kiszkurno <feliks-kuba.kiszkurno@ufz.de>
Philipp Selzer <philipp.selzer@ufz.de>
Philipp Selzer <philipp.selzer@ufz.de> <Philipp.Selzer@gmx.net>
Joy Brato Shil <joybroto6@gmail.com>
Frieder Loer <frieder.loer@ufz.de>
Eike Radeisen <eike.radeisen@bgr.de>
Maximilian Dörnbrack <maximilian.doernbrack@ufz.de> <maximlian.doernbrack@ufz.de>
Kristof Kessler <kristof.kessler@bgr.de> <mail@kristofkessler.com>
\ No newline at end of file
comment: OpenGeoSys rules
default: true
line-length: false
no-inline-html: false
no-duplicate-heading: false
first-line-h1: false
no-bare-urls: false
web/content/releases/
web/content/docs/devguide/packages/mfront/index.md
Documentation/.vale/
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md, --markdown-linebreak-ext=pandoc]
# Tests/Python/res/test_docu_scripts/ contain improper white spaces on
# purpose: such whitespace errors should be tested, there.
exclude: "^Tests/Data/.*|^Tests/Python/res/test_docu_scripts/|^web/static|^Documentation/.vale/.*|.*\\.patch"
- id: check-added-large-files
args: [--maxkb 1024]
- id: check-merge-conflict
- id: check-xml
exclude: '^Tests/Data/.*\.xml'
- id: check-yaml
exclude: "^scripts/ci/.*|.cmake-format.yaml"
- id: check-toml
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: check-json
- id: fix-byte-order-marker
exclude: "^Documentation/.vale/.*"
- id: mixed-line-ending
exclude: ".*\\.vtu|.*@@"
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
exclude: "LinearMFront/generate_ref.py"
# Run black on markdown notebooks
- repo: https://github.com/nbQA-dev/nbQA
rev: 1.7.0
hooks:
- id: nbqa-black
additional_dependencies: [jupytext, black==23.1.0]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.2
hooks:
- id: codespell
exclude: 'Tests/Data/.*|.*\.ya?ml|.*\.bib|^web/content/imprint.md|^GeoLib/IO/XmlIO/OpenGeoSysSTN.xsd|^Applications/FileIO/Legacy/OGSIOVer4.cpp|^scripts/cmake/CPM.cmake|Documentation/.vale/.*|.*\.ipynb|.*\.svg|^GeoLib/predicates.c'
- repo: https://github.com/cheshirekow/cmake-format-precommit
rev: v0.6.13
hooks:
- id: cmake-format
additional_dependencies: ["cmakelang[YAML]"]
args: [--config=.cmake-format.yaml]
exclude: "CPM.cmake|FindFilesystem.cmake|FindMKL.cmake|JSONParser.cmake|Tests.cmake|FindTFEL.cmake|FindMFrontGenericInterface.cmake"
- id: cmake-lint
additional_dependencies: ["cmakelang[YAML]"]
exclude: "CPM.cmake|FindFilesystem.cmake|FindMKL.cmake|JSONParser.cmake|BuildExternalProject.cmake|FindTFEL.cmake|FindMFrontGenericInterface.cmake"
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.42.0
hooks:
- id: markdownlint
language_version: 22.11.0
- repo: local
hooks:
- id: git-diff-check
name: Run git diff --check
entry: git diff --check --cached -- ':!*.md' ':!*.pandoc' ':!*.asc' ':!*.dat' ':!*.ts'
language: system
exclude: "Tests/Data/.*|web/static/images/xsd"
stages: [pre-commit, manual]
- id: file-extensions
name: Check file extensions
entry: scripts/hooks/pre-commit-file-extensions.sh
language: system
files: '.*\.cpp'
stages: [pre-commit, manual]
- id: git-clang-format
name: git-clang-format
entry: bash -c 'if command -v git-clang-format &> /dev/null; then git clang-format; else exit 0; fi'
language: system
pass_filenames: false
files: \.(h|cpp)$
- repo: https://github.com/errata-ai/vale
rev: v2.24.4
hooks:
- id: vale
name: vale sync
pass_filenames: false
args: [sync]
- id: vale
args: [--output=line, --minAlertLevel=error]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.9.9"
hooks:
- id: ruff
types_or: [python, pyi, jupyter]
args: [--output-format=full]
# A variant of the ruff hook above that automatically applies proposed fixes.
# Runs only manually.
# Run this hook (and all other manual hooks if any) with:
# pre-commit run --hook-stage manual
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.9.9"
hooks:
- id: ruff
types_or: [python, pyi, jupyter]
args: [--output-format=full, --fix, --exit-non-zero-on-fix]
stages: [manual]
# Enable on demand, run with
# pre-commit run --all-files clang-format
#
# - repo: https://github.com/pocc/pre-commit-hooks
# rev: master
# hooks:
# - id: clang-format
# args: ["-i"]
sudo: false
language: cpp
compiler:
- gcc
- clang
addons:
apt:
sources:
- boost-latest
- ubuntu-toolchain-r-test
# TODO: feelpp/petsc
packages:
- g++-4.8
- libeigen3-dev
- libboost1.55-dev
- libboost-date-time1.55-dev
- libboost-filesystem1.55-dev
- libboost-program-options1.55-dev
- libboost-system1.55-dev
- qt4-dev-tools
- libxt-dev
# TODO
# - libpetsc3.4.2-dev
# Not allowed yet:
# - numdiff
# - libshp-dev
# - libgeotiff-dev
cache:
directories:
- $HOME/cmake-3.1.1-Linux-x86_64
- $HOME/VTK-Install
env:
global:
- VTK_DIR=VTK-Install/lib/cmake/vtk-6.1
matrix:
- CASE=CLI CMAKE_ARGS="-DOGS_BUILD_GUI=OFF -DOGS_BUILD_UTILS=ON -DVTK_DIR=$HOME/$VTK_DIR"
# - CASE=CLI_PETSC CMAKE_ARGS="-DOGS_BUILD_GUI=OFF -DOGS_BUILD_UTILS=OFF -DOGS_USE_PETSC=ON -DPETSC_DIR=/usr/lib/petscdir/3.4.2/"
- CASE=GUI CMAKE_ARGS="-DOGS_BUILD_GUI=ON -DOGS_BUILD_CLI=OFF -DOGS_BUILD_TESTS=OFF -DVTK_DIR=$HOME/$VTK_DIR"
before_install:
- bash scripts/travis/cmake.sh
- bash scripts/travis/vtk.sh
before_script:
- export PATH=$HOME/cmake-3.1.1-Linux-x86_64/bin:$PATH
- export CXX=g++-4.8 CC=gcc-4.8
script:
- mkdir build
- cd build
- cmake $CMAKE_ARGS ..
- make -j 2
- if [[ "$CASE" == "CLI" ]]; then make tests; fi
# PetSc
#- if [[ "$CASE" == "CLI_PETSC" ]]; then make tests_mpi; fi
notifications:
hipchat:
rooms:
secure: kmLyt50IGFuK96xbD+VzWRRzF6UU6SdVpsn1bolKQaTCCj1rz4H1np1iUML0jeGn86DAkkHPWmFXaS2JN0EoX8L74HavJSkUfIa49cegk0je986fxucaUV1fnhFIRh6EGkpqvqE+uXs/wKHkzrkYbpHaRvJgmxQSV9kR4yRuAmw=
# Vale configuration file.
#
# For more information, see https://vale.sh/docs/topics/config
StylesPath = Documentation/.vale
Vocab = ogs
MinAlertLevel = suggestion
Packages = Hugo
[*.md]
BasedOnStyles = Vale, write-good, ogs
Vale.Spelling = None
write-good.ThereIs = None
write-good.Passive = None
write-good.TooWordy = None
write-good.Weasel = None
write-good.E-Prime = None
TokenIgnores = \
(\{\{[%<][^>]+[%>]\}\}), \
(.*?\{\{[%<]?/.*[%>]\}\}), \
; (\\ref\s\S+(\s"\S*")?), \
; (\\subpage\s\S*), \
; (\\copydoc\s\S*), \
(\$[^\n$]+\$), \
(\\\S*|\{\S*\}), \
(\w*\set\sal), \
({{<\s?(rel)?ref (.*)>}})
# https://regex101.com/r/QWLhgT/1 helped me generating this one:
BlockIgnores = (?s) *(\$\$.*?\$\$)
# Source files # Source files
set(LIB_SOURCES ProjectData.cpp) get_source_files(SOURCES_APPLICATIONSLIB)
set(LIB_SOURCES ${SOURCES_APPLICATIONSLIB})
# Library # Library
add_library(ApplicationsLib STATIC ${LIB_SOURCES}) ogs_add_library(ApplicationsLib ${LIB_SOURCES})
target_link_libraries(ApplicationsLib INTERFACE target_link_libraries(
GeoLib ApplicationsLib
MeshGeoToolsLib PUBLIC
ProcessLib BaseLib
${CATALYST_LIBRARIES} GeoLib
logog NumLib
$<$<AND:$<BOOL:${OGS_USE_PETSC}>,$<TARGET_EXISTS:VTK::ParallelMPI>>:VTK::ParallelMPI>
$<$<AND:$<NOT:$<BOOL:${OGS_BUILD_WHEEL}>>,$<BOOL:${OGS_BUILD_CLI}>>:ogs_embedded_python>
PRIVATE CMakeInfoLib
MathLib
MeshLib
MeshGeoToolsLib
MeshToolsLib
$<$<BOOL:${OGS_USE_PETSC}>:PkgConfig::PETSC>
pybind11::module
) )
ADD_CATALYST_DEPENDENCY(ApplicationsLib)
if(OGS_BUILD_GUI) if(OGS_BUILD_CLI OR OGS_BUILD_UTILS OR OGS_BUILD_TESTING)
target_link_libraries(ApplicationsLib PUBLIC Qt4::QtCore) target_link_libraries(
ApplicationsLib PUBLIC Processes PRIVATE ParameterLib ProcessLib
)
elseif(OGS_BUILD_GUI)
target_link_libraries(
ApplicationsLib PRIVATE MeshToolsLib nlohmann_json::nlohmann_json
)
endif()
if(OGS_USE_LIS)
target_include_directories(ApplicationsLib PUBLIC ${LIS_INCLUDE_DIR})
endif() endif()
if(TARGET Eigen) target_compile_definitions(
add_dependencies(ApplicationsLib Eigen) ApplicationsLib PUBLIC $<$<BOOL:${USE_LIS}>:USE_LIS>
PRIVATE $<$<BOOL:${OGS_USE_INSITU}>:OGS_USE_INSITU>
)
# ~~~
# Prevent warning:
# warning: ‘ProjectData’ declared with greater visibility than the type of its field ‘ProjectData::_py_scoped_interpreter’
# see https://pybind11.readthedocs.io/en/stable/faq.html#someclass-declared-with-greater-visibility-than-the-type-of-its-field-someclass-member-wattributes
# ~~~
if(NOT OGS_BUILD_WHEEL AND OGS_BUILD_CLI)
set_target_properties(
ApplicationsLib PROPERTIES CXX_VISIBILITY_PRESET hidden
)
endif() endif()
# Set cpp definitions if the cmake option is enabled for the given process.
foreach(process ${_enabled_processes})
string(TOUPPER "OGS_BUILD_PROCESS_${process}" EnableProcess)
set_property(
TARGET ApplicationsLib APPEND PROPERTY COMPILE_DEFINITIONS
${EnableProcess}
)
endforeach()
target_precompile_headers(
ApplicationsLib PRIVATE [["BaseLib/Error.h"]] [["BaseLib/ConfigTree.h"]]
[["BaseLib/Logging.h"]]
)
/**
* \file
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
/// The LinearSolverLibrarySetup takes care of proper initialization and
/// shutting down of an external linear solver library. The concrete
/// implementation is chosen by the build system.
/// An object of this class must be created at the beginning of the scope where
/// it is used. When the scope closes (or the object is destroyed explicitly)
/// library shutting down functions are automatically called.
/// The default implementation is empty providing polymorphic behaviour when
/// using this class.
#include "BaseLib/MPI.h"
#include "NumLib/DOF/GlobalMatrixProviders.h"
#if defined(USE_PETSC)
#include <petsc.h>
#include <mpi.h>
namespace ApplicationsLib
{
struct LinearSolverLibrarySetup final
{
LinearSolverLibrarySetup(int argc, char* argv[]) : mpi_setup(argc, argv)
{
char help[] = "ogs6 with PETSc \n";
PetscInitialize(&argc, &argv, nullptr, help);
MPI_Comm_set_errhandler(PETSC_COMM_WORLD, MPI_ERRORS_RETURN);
}
~LinearSolverLibrarySetup()
{
NumLib::cleanupGlobalMatrixProviders();
PetscFinalize();
}
BaseLib::MPI::Setup mpi_setup;
};
} // ApplicationsLib
#elif defined(USE_LIS)
#include <lis.h>
namespace ApplicationsLib
{
struct LinearSolverLibrarySetup final
{
LinearSolverLibrarySetup(int argc, char* argv[])
{
lis_initialize(&argc, &argv);
}
~LinearSolverLibrarySetup()
{
NumLib::cleanupGlobalMatrixProviders();
lis_finalize();
}
};
} // ApplicationsLib
#else
namespace ApplicationsLib
{
struct LinearSolverLibrarySetup final
{
LinearSolverLibrarySetup(int /*argc*/, char* /*argv*/[])
{
#ifdef _OPENMP
const char* omp_num_threads_env = std::getenv("OMP_NUM_THREADS");
if (omp_num_threads_env)
{
INFO("OMP_NUM_THREADS is set to: {:s}", omp_num_threads_env);
}
else
{
WARN("OMP_NUM_THREADS is not set, falling back to: {:d}",
omp_get_max_threads());
}
#endif
INFO("Eigen use {:d} threads", Eigen::nbThreads());
}
~LinearSolverLibrarySetup()
{
NumLib::cleanupGlobalMatrixProviders();
}
};
} // namespace ApplicationsLib
#endif
/** /**
* \file
* \author Karsten Rink * \author Karsten Rink
* \date 2010-08-25 * \date 2010-08-25
* \brief Implementation of the project data class. * \brief Implementation of the project data class.
* *
* \copyright * \copyright
* Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org) * Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License. * Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or * See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license * http://www.opengeosys.org/project/license
...@@ -13,210 +14,1440 @@ ...@@ -13,210 +14,1440 @@
#include "ProjectData.h" #include "ProjectData.h"
#include <algorithm> #include <pybind11/eval.h>
// ThirdParty/logog #include <algorithm>
#include "logog/include/logog.hpp" #include <boost/algorithm/string/predicate.hpp>
#include <cctype>
#include <range/v3/action/sort.hpp>
#include <range/v3/action/unique.hpp>
#include <range/v3/algorithm/contains.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/adjacent_remove_if.hpp>
#include <set>
#include "BaseLib/Algorithm.h"
#include "BaseLib/ConfigTree.h"
#include "BaseLib/FileTools.h" #include "BaseLib/FileTools.h"
#include "BaseLib/Logging.h"
#include "BaseLib/StringTools.h"
#include "GeoLib/GEOObjects.h"
#include "GeoLib/IO/AsciiRasterInterface.h"
#include "GeoLib/IO/NetCDFRasterReader.h"
#include "GeoLib/Raster.h"
#include "InfoLib/CMakeInfo.h"
#include "MaterialLib/MPL/CreateMedium.h"
#include "MaterialLib/Utils/MediaCreation.h"
#include "MathLib/Curve/CreatePiecewiseLinearCurve.h"
#if defined(USE_LIS)
#include "MathLib/LinAlg/EigenLis/LinearSolverOptionsParser.h"
#elif defined(USE_PETSC)
#include "MathLib/LinAlg/PETSc/LinearSolverOptionsParser.h"
#else
#include "MathLib/LinAlg/Eigen/LinearSolverOptionsParser.h"
#endif
#include "MeshGeoToolsLib/ConstructMeshesFromGeometries.h"
#include "MeshGeoToolsLib/CreateSearchLength.h"
#include "MeshGeoToolsLib/SearchLength.h"
#include "MeshLib/Mesh.h" #include "MeshLib/Mesh.h"
#include "MeshLib/Utils/SetMeshSpaceDimension.h"
#include "MeshToolsLib/ZeroMeshFieldDataByMaterialIDs.h"
#include "NumLib/ODESolver/ConvergenceCriterion.h"
#include "ProcessLib/CreateJacobianAssembler.h"
#include "ProcessLib/DeactivatedSubdomain.h"
// FileIO // FileIO
#include "FileIO/XmlIO/Boost/BoostXmlGmlInterface.h" #include "GeoLib/IO/XmlIO/Boost/BoostXmlGmlInterface.h"
#include "FileIO/readMeshFromFile.h" #include "MeshLib/IO/readMeshFromFile.h"
#include "ParameterLib/ConstantParameter.h"
#include "ParameterLib/CreateCoordinateSystem.h"
#include "ParameterLib/Utils.h"
#include "ProcessLib/CreateTimeLoop.h"
#include "ProcessLib/TimeLoop.h"
#ifdef OGS_EMBED_PYTHON_INTERPRETER
#include "Applications/CLI/ogs_embedded_python.h"
#endif
#ifdef OGS_BUILD_PROCESS_COMPONENTTRANSPORT
#include "ChemistryLib/CreateChemicalSolverInterface.h"
#include "ProcessLib/ComponentTransport/CreateComponentTransportProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_STEADYSTATEDIFFUSION
#include "ProcessLib/SteadyStateDiffusion/CreateSteadyStateDiffusion.h"
#endif
#ifdef OGS_BUILD_PROCESS_HT
#include "ProcessLib/HT/CreateHTProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_HEATCONDUCTION
#include "ProcessLib/HeatConduction/CreateHeatConductionProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_HEATTRANSPORTBHE
#include "ProcessLib/HeatTransportBHE/CreateHeatTransportBHEProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_WELLBORESIMULATOR
#include "ProcessLib/WellboreSimulator/CreateWellboreSimulatorProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_HYDROMECHANICS
#include "ProcessLib/HydroMechanics/CreateHydroMechanicsProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_LARGEDEFORMATION
#include "ProcessLib/LargeDeformation/CreateLargeDeformationProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_LIE_M
#include "ProcessLib/LIE/SmallDeformation/CreateSmallDeformationProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_LIE_HM
#include "ProcessLib/LIE/HydroMechanics/CreateHydroMechanicsProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_LIQUIDFLOW
#include "ProcessLib/LiquidFlow/CreateLiquidFlowProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_STOKESFLOW
#include "ProcessLib/StokesFlow/CreateStokesFlowProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_THERMORICHARDSMECHANICS
#include "ProcessLib/ThermoRichardsMechanics/CreateThermoRichardsMechanicsProcess.h"
#endif
namespace detail #ifdef OGS_BUILD_PROCESS_PHASEFIELD
#include "ProcessLib/PhaseField/CreatePhaseFieldProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_HMPHASEFIELD
#include "ProcessLib/HMPhaseField/CreateHMPhaseFieldProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_RICHARDSCOMPONENTTRANSPORT
#include "ProcessLib/RichardsComponentTransport/CreateRichardsComponentTransportProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_RICHARDSFLOW
#include "ProcessLib/RichardsFlow/CreateRichardsFlowProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_RICHARDSMECHANICS
#include "ProcessLib/RichardsMechanics/CreateRichardsMechanicsProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_SMALLDEFORMATION
#include "ProcessLib/SmallDeformation/CreateSmallDeformationProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_SMALLDEFORMATIONNONLOCAL
#include "ProcessLib/SmallDeformationNonlocal/CreateSmallDeformationNonlocalProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_TES
#include "ProcessLib/TES/CreateTESProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_TH2M
#include "ProcessLib/TH2M/CreateTH2MProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_THERMALTWOPHASEFLOWWITHPP
#include "ProcessLib/ThermalTwoPhaseFlowWithPP/CreateThermalTwoPhaseFlowWithPPProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_THERMOHYDROMECHANICS
#include "ProcessLib/ThermoHydroMechanics/CreateThermoHydroMechanicsProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_THERMOMECHANICALPHASEFIELD
#include "ProcessLib/ThermoMechanicalPhaseField/CreateThermoMechanicalPhaseFieldProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_THERMOMECHANICS
#include "ProcessLib/ThermoMechanics/CreateThermoMechanicsProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_THERMORICHARDSFLOW
#include "ProcessLib/ThermoRichardsFlow/CreateThermoRichardsFlowProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_TWOPHASEFLOWWITHPP
#include "ProcessLib/TwoPhaseFlowWithPP/CreateTwoPhaseFlowWithPPProcess.h"
#endif
#ifdef OGS_BUILD_PROCESS_TWOPHASEFLOWWITHPRHO
#include "ProcessLib/TwoPhaseFlowWithPrho/CreateTwoPhaseFlowWithPrhoProcess.h"
#endif
namespace
{ {
static void readGeometry(std::string const& fname, GeoLib::GEOObjects& geo_objects,
void readGeometry(std::string const& fname, GeoLib::GEOObjects & geo_objects) std::string const& dir_first, std::string const& dir_second)
{ {
DBUG("Reading geometry file \'%s\'.", fname.c_str()); DBUG("Reading geometry file '{:s}'.", fname);
FileIO::BoostXmlGmlInterface gml_reader(geo_objects); GeoLib::IO::BoostXmlGmlInterface gml_reader(geo_objects);
gml_reader.readFile(fname); std::string geometry_file = BaseLib::joinPaths(dir_first, fname);
if (!BaseLib::IsFileExisting(geometry_file))
{
// Fallback to reading gml from prj-file directory
geometry_file = BaseLib::joinPaths(dir_second, fname);
WARN("File {:s} not found in {:s}! Trying reading from {:s}.", fname,
dir_first, dir_second);
if (!BaseLib::IsFileExisting(geometry_file))
{
OGS_FATAL("Could not read geometry file {:s} in {:s}.", fname,
dir_second);
}
}
gml_reader.readFile(geometry_file);
} }
std::unique_ptr<MeshLib::Mesh> readSingleMesh(
BaseLib::ConfigTree const& mesh_config_parameter,
std::string const& directory)
{
std::string const mesh_file = BaseLib::joinPaths(
directory, mesh_config_parameter.getValue<std::string>());
DBUG("Reading mesh file '{:s}'.", mesh_file);
auto mesh = std::unique_ptr<MeshLib::Mesh>(MeshLib::IO::readMeshFromFile(
mesh_file, true /* compute_element_neighbors */));
if (!mesh)
{
std::filesystem::path abspath{mesh_file};
try
{
abspath = std::filesystem::absolute(mesh_file);
}
catch (std::filesystem::filesystem_error const& e)
{
ERR("Determining the absolute path of '{}' failed: {}", mesh_file,
e.what());
}
OGS_FATAL("Could not read mesh from '{:s}' file. No mesh added.",
abspath.string());
}
#ifdef DOXYGEN_DOCU_ONLY
//! \ogs_file_attr{prj__meshes__mesh__axially_symmetric}
mesh_config_parameter.getConfigAttributeOptional<bool>("axially_symmetric");
#endif // DOXYGEN_DOCU_ONLY
if (auto const axially_symmetric =
//! \ogs_file_attr{prj__mesh__axially_symmetric}
mesh_config_parameter.getConfigAttributeOptional<bool>(
"axially_symmetric"))
{
mesh->setAxiallySymmetric(*axially_symmetric);
if (mesh->getDimension() == 3 && mesh->isAxiallySymmetric())
{
OGS_FATAL("3D mesh cannot be axially symmetric.");
}
}
return mesh;
} }
ProjectData::ProjectData(ConfigTree const& project_config, std::vector<std::unique_ptr<MeshLib::Mesh>> readMeshes(
std::string const& path) BaseLib::ConfigTree const& config, std::string const& directory,
std::string const& project_directory)
{ {
// geometry std::vector<std::unique_ptr<MeshLib::Mesh>> meshes;
std::string const geometry_file = BaseLib::copyPathToFileName(
project_config.get<std::string>("geometry"), path GeoLib::GEOObjects geoObjects;
);
detail::readGeometry(geometry_file, *_geoObjects); //! \ogs_file_param{prj__meshes}
auto optional_meshes = config.getConfigSubtreeOptional("meshes");
if (optional_meshes)
{
DBUG("Reading multiple meshes.");
//! \ogs_file_param{prj__meshes__mesh}
auto const configs = optional_meshes->getConfigParameterList("mesh");
std::transform(configs.begin(), configs.end(),
std::back_inserter(meshes),
[&directory](auto const& mesh_config)
{ return readSingleMesh(mesh_config, directory); });
if (auto const geometry_file_name =
//! \ogs_file_param{prj__geometry}
config.getConfigParameterOptional<std::string>("geometry"))
{
readGeometry(*geometry_file_name, geoObjects, directory,
project_directory);
}
}
else
{ // Read single mesh with geometry.
meshes.push_back(
//! \ogs_file_param{prj__mesh}
readSingleMesh(config.getConfigParameter("mesh"), directory));
auto const geometry_file_name =
//! \ogs_file_param{prj__geometry}
config.getConfigParameter<std::string>("geometry");
readGeometry(geometry_file_name, geoObjects, directory,
project_directory);
}
if (!geoObjects.getPoints().empty() || !geoObjects.getPolylines().empty() ||
!geoObjects.getSurfaces().empty())
{ // generate meshes from geometries
std::unique_ptr<MeshGeoToolsLib::SearchLength> search_length_algorithm =
MeshGeoToolsLib::createSearchLengthAlgorithm(config, *meshes[0]);
bool const multiple_nodes_allowed = false;
auto additional_meshes =
MeshGeoToolsLib::constructAdditionalMeshesFromGeoObjects(
geoObjects, *meshes[0], std::move(search_length_algorithm),
multiple_nodes_allowed);
// mesh std::move(begin(additional_meshes), end(additional_meshes),
std::string const mesh_file = BaseLib::copyPathToFileName( std::back_inserter(meshes));
project_config.get<std::string>("mesh"), path }
);
MeshLib::Mesh* const mesh = FileIO::readMeshFromFile(mesh_file); auto mesh_names = MeshLib::views::names | ranges::to<std::vector>() |
if (!mesh) ranges::actions::sort;
ERR("Could not read mesh from \'%s\' file. No mesh added.", auto const sorted_names = meshes | mesh_names;
mesh_file.c_str()); auto const unique_names = meshes | mesh_names | ranges::actions::unique;
_mesh_vec.push_back(mesh); if (unique_names.size() < sorted_names.size())
{
WARN(
"Mesh names aren't unique. From project file read mesh names are:");
for (auto const& name : meshes | MeshLib::views::names)
{
INFO("- {}", name);
}
}
// process variables auto const zero_mesh_field_data_by_material_ids =
parseProcessVariables(project_config.get_child("process_variables")); //! \ogs_file_param{prj__zero_mesh_field_data_by_material_ids}
config.getConfigParameterOptional<std::vector<int>>(
"zero_mesh_field_data_by_material_ids");
if (zero_mesh_field_data_by_material_ids)
{
WARN(
"Tag 'zero_mesh_field_data_by_material_ids` is experimental. Its "
"name may be changed, or it may be removed due to its "
"corresponding feature becomes a single tool. Please use it with "
"care!");
MeshToolsLib::zeroMeshFieldDataByMaterialIDs(
*meshes[0], *zero_mesh_field_data_by_material_ids);
}
// processes MeshLib::setMeshSpaceDimension(meshes);
parseProcesses(project_config.get_child("processes"));
// output return meshes;
parseOutput(project_config.get_child("output"), path);
} }
ProjectData::~ProjectData() std::vector<GeoLib::NamedRaster> readRasters(
BaseLib::ConfigTree const& config, std::string const& raster_directory,
GeoLib::MinMaxPoints const& min_max_points)
{ {
delete _geoObjects; INFO("readRasters ...");
std::vector<GeoLib::NamedRaster> named_rasters;
for(ProcessLib::Process* p : _processes) //! \ogs_file_param{prj__rasters}
delete p; auto optional_rasters = config.getConfigSubtreeOptional("rasters");
if (optional_rasters)
for (MeshLib::Mesh* m : _mesh_vec) {
delete m; //! \ogs_file_param{prj__rasters__raster}
auto const configs = optional_rasters->getConfigSubtreeList("raster");
std::transform(
configs.begin(), configs.end(), std::back_inserter(named_rasters),
[&raster_directory, &min_max_points](auto const& raster_config)
{
return GeoLib::IO::readRaster(raster_config, raster_directory,
min_max_points);
});
}
INFO("readRasters done");
return named_rasters;
} }
void ProjectData::addMesh(MeshLib::Mesh* mesh) // for debugging raster reading implementation
// void writeRasters(std::vector<GeoLib::NamedRaster> const& named_rasters,
// std::string const& output_directory)
//{
// for (auto const& named_raster : named_rasters)
// {
// #if defined(USE_PETSC)
// int my_mpi_rank;
// MPI_Comm_rank(MPI_COMM_WORLD, &my_mpi_rank);
// #endif
// FileIO::AsciiRasterInterface::writeRasterAsASC(
// named_raster.raster, output_directory + "/" +
// named_raster.raster_name +
// #if defined(USE_PETSC)
// "_" + std::to_string(my_mpi_rank) +
// #endif
// ".asc");
// }
//}
} // namespace
ProjectData::ProjectData() = default;
ProjectData::ProjectData(BaseLib::ConfigTree const& project_config,
std::string const& project_directory,
std::string const& output_directory,
std::string const& mesh_directory,
[[maybe_unused]] std::string const& script_directory)
: _mesh_vec(readMeshes(project_config, mesh_directory, project_directory)),
_named_rasters(readRasters(project_config, project_directory,
GeoLib::AABB(_mesh_vec[0]->getNodes().begin(),
_mesh_vec[0]->getNodes().end())
.getMinMaxPoints()))
{ {
std::string name = mesh->getName(); // for debugging raster reading implementation
isMeshNameUniqueAndProvideUniqueName(name); // writeRasters(_named_rasters, output_directory);
mesh->setName(name); if (auto const python_script =
_mesh_vec.push_back(mesh); //! \ogs_file_param{prj__python_script}
project_config.getConfigParameterOptional<std::string>("python_script"))
{
namespace py = pybind11;
#ifdef OGS_EMBED_PYTHON_INTERPRETER
_py_scoped_interpreter.emplace(ApplicationsLib::setupEmbeddedPython());
#endif
// Append to python's module search path
auto py_path = py::module::import("sys").attr("path");
py_path.attr("append")(script_directory); // .prj or -s directory
auto const script_path =
BaseLib::joinPaths(script_directory, *python_script);
// Evaluate in scope of main module
py::object scope = py::module::import("__main__").attr("__dict__");
// add (global) variables
auto globals = py::dict(scope);
globals["ogs_prj_directory"] = project_directory;
globals["ogs_mesh_directory"] = mesh_directory;
globals["ogs_script_directory"] = script_directory;
try
{
py::eval_file(script_path, scope);
}
catch (py::error_already_set const& e)
{
OGS_FATAL("Error evaluating python script {}: {}", script_path,
e.what());
}
}
//! \ogs_file_param{prj__curves}
parseCurves(project_config.getConfigSubtreeOptional("curves"));
auto parameter_names_for_transformation =
//! \ogs_file_param{prj__parameters}
parseParameters(project_config.getConfigSubtree("parameters"));
_local_coordinate_system = ParameterLib::createCoordinateSystem(
//! \ogs_file_param{prj__local_coordinate_system}
project_config.getConfigSubtreeOptional("local_coordinate_system"),
_parameters);
for (auto& parameter : _parameters)
{
if (std::find(begin(parameter_names_for_transformation),
end(parameter_names_for_transformation),
parameter->name) !=
end(parameter_names_for_transformation))
{
if (!_local_coordinate_system)
{
OGS_FATAL(
"The parameter '{:s}' is using the local coordinate system "
"but no local coordinate system was provided.",
parameter->name);
}
parameter->setCoordinateSystem(*_local_coordinate_system);
}
parameter->initialize(_parameters);
}
//! \ogs_file_param{prj__process_variables}
parseProcessVariables(project_config.getConfigSubtree("process_variables"));
//! \ogs_file_param{prj__media}
parseMedia(project_config.getConfigSubtreeOptional("media"));
//! \ogs_file_param{prj__linear_solvers}
parseLinearSolvers(project_config.getConfigSubtree("linear_solvers"));
auto chemical_solver_interface = parseChemicalSolverInterface(
//! \ogs_file_param{prj__chemical_system}
project_config.getConfigSubtreeOptional("chemical_system"),
output_directory);
//! \ogs_file_param{prj__processes}
parseProcesses(project_config.getConfigSubtree("processes"),
project_directory, output_directory,
std::move(chemical_solver_interface));
//! \ogs_file_param{prj__nonlinear_solvers}
parseNonlinearSolvers(project_config.getConfigSubtree("nonlinear_solvers"));
//! \ogs_file_param{prj__time_loop}
parseTimeLoop(project_config.getConfigSubtree("time_loop"),
output_directory);
} }
std::vector<MeshLib::Mesh*>::const_iterator ProjectData::findMeshByName( void ProjectData::parseProcessVariables(
std::string const& name) const BaseLib::ConfigTree const& process_variables_config)
{ {
return const_cast<ProjectData&>(*this).findMeshByName(name); DBUG("Parse process variables:");
std::set<std::string> names;
for (auto var_config
//! \ogs_file_param{prj__process_variables__process_variable}
: process_variables_config.getConfigSubtreeList("process_variable"))
{
// Either the mesh name is given, or the first mesh's name will be
// taken. Taking the first mesh's value is deprecated.
auto const mesh_name =
//! \ogs_file_param{prj__process_variables__process_variable__mesh}
var_config.getConfigParameter<std::string>("mesh",
_mesh_vec[0]->getName());
auto& mesh = MeshLib::findMeshByName(_mesh_vec, mesh_name);
auto pv = ProcessLib::ProcessVariable{var_config, mesh, _mesh_vec,
_parameters, _curves};
if (!names.insert(pv.getName()).second)
{
OGS_FATAL("A process variable with name `{:s}' already exists.",
pv.getName());
}
_process_variables.push_back(std::move(pv));
}
} }
std::vector<MeshLib::Mesh*>::iterator ProjectData::findMeshByName( std::vector<std::string> ProjectData::parseParameters(
std::string const& name) BaseLib::ConfigTree const& parameters_config)
{ {
return std::find_if(_mesh_vec.begin(), _mesh_vec.end(), using namespace ProcessLib;
[&name](MeshLib::Mesh* mesh)
{ std::set<std::string> names;
return mesh && (name == mesh->getName()); std::vector<std::string> parameter_names_for_transformation;
});
DBUG("Reading parameters:");
for (auto parameter_config :
//! \ogs_file_param{prj__parameters__parameter}
parameters_config.getConfigSubtreeList("parameter"))
{
auto p = ParameterLib::createParameter(parameter_config, _mesh_vec,
_named_rasters, _curves);
if (!names.insert(p->name).second)
{
OGS_FATAL("A parameter with name `{:s}' already exists.", p->name);
}
auto const use_local_coordinate_system =
//! \ogs_file_param{prj__parameters__parameter__use_local_coordinate_system}
parameter_config.getConfigParameterOptional<bool>(
"use_local_coordinate_system");
if (!!use_local_coordinate_system && *use_local_coordinate_system)
{
parameter_names_for_transformation.push_back(p->name);
}
_parameters.push_back(std::move(p));
}
_parameters.push_back(
std::make_unique<ParameterLib::ConstantParameter<double>>(
ProcessLib::DeactivatedSubdomain::zero_parameter_name, 0.0));
_parameters.push_back(
std::make_unique<ParameterLib::ConstantParameter<double>>(
ProcessLib::Process::constant_one_parameter_name, 1.0));
return parameter_names_for_transformation;
} }
const MeshLib::Mesh* ProjectData::getMesh(const std::string &name) const void ProjectData::parseMedia(
std::optional<BaseLib::ConfigTree> const& media_config)
{ {
std::vector<MeshLib::Mesh*>::const_iterator it = findMeshByName(name); if (!media_config)
return (it == _mesh_vec.end() ? nullptr : *it); {
return;
}
DBUG("Reading media:");
if (_mesh_vec.empty() || _mesh_vec[0] == nullptr)
{
ERR("A mesh is required to define medium materials.");
return;
}
for (auto const& medium_config :
//! \ogs_file_param{prj__media__medium}
media_config->getConfigSubtreeList("medium"))
{
auto create_medium = [dim = _mesh_vec[0]->getDimension(),
&medium_config, this](int const id)
{
return MaterialPropertyLib::createMedium(
id, _mesh_vec[0]->getDimension(), medium_config, _parameters,
_local_coordinate_system ? &*_local_coordinate_system : nullptr,
_curves);
};
auto const material_id_string =
//! \ogs_file_attr{prj__media__medium__id}
medium_config.getConfigAttribute<std::string>("id", "0");
std::vector<int> const material_ids_of_this_medium =
MaterialLib::parseMaterialIdString(material_id_string,
materialIDs(*_mesh_vec[0]));
for (auto const& id : material_ids_of_this_medium)
{
MaterialLib::createMediumForId(
id, _media, material_ids_of_this_medium, create_medium);
}
}
if (_media.empty())
{
OGS_FATAL("No entity is found inside <media>.");
}
} }
bool ProjectData::removeMesh(const std::string &name) std::unique_ptr<ChemistryLib::ChemicalSolverInterface>
{ ProjectData::parseChemicalSolverInterface(
bool mesh_found = false; std::optional<BaseLib::ConfigTree> const& config,
std::vector<MeshLib::Mesh*>::iterator it = findMeshByName(name); std::string const& output_directory)
while (it != _mesh_vec.end()) {
{ if (!config)
delete *it; {
*it = nullptr; return nullptr;
it = findMeshByName(name); }
mesh_found = true;
} std::unique_ptr<ChemistryLib::ChemicalSolverInterface>
chemical_solver_interface;
_mesh_vec.erase(std::remove(_mesh_vec.begin(), _mesh_vec.end(), nullptr), #ifdef OGS_BUILD_PROCESS_COMPONENTTRANSPORT
_mesh_vec.end()); INFO(
return mesh_found; "Ready for initializing interface to a chemical solver for water "
"chemistry calculation.");
auto const chemical_solver =
//! \ogs_file_attr{prj__chemical_system__chemical_solver}
config->getConfigAttribute<std::string>("chemical_solver");
if (boost::iequals(chemical_solver, "Phreeqc"))
{
INFO(
"Configuring phreeqc interface for water chemistry calculation "
"using file-based approach.");
chemical_solver_interface = ChemistryLib::createChemicalSolverInterface<
ChemistryLib::ChemicalSolver::Phreeqc>(_mesh_vec, _linear_solvers,
*config, output_directory);
}
else if (boost::iequals(chemical_solver, "PhreeqcKernel"))
{
OGS_FATAL(
"The chemical solver option of PhreeqcKernel is not accessible for "
"the time being. Please set 'Phreeqc'' as the chemical solver for "
"reactive transport modeling.");
}
else if (boost::iequals(chemical_solver, "SelfContained"))
{
INFO(
"Use self-contained chemical solver for water chemistry "
"calculation.");
chemical_solver_interface = ChemistryLib::createChemicalSolverInterface<
ChemistryLib::ChemicalSolver::SelfContained>(
_mesh_vec, _linear_solvers, *config, output_directory);
}
else
{
OGS_FATAL(
"Unknown chemical solver. Please specify either Phreeqc or "
"PhreeqcKernel as the solver for water chemistry calculation "
"instead.");
}
#else
(void)output_directory;
OGS_FATAL(
"Found the type of the process to be solved is not component transport "
"process. Please specify the process type to ComponentTransport. At "
"the present, water chemistry calculation is only available for "
"component transport process.");
#endif
return chemical_solver_interface;
} }
bool ProjectData::meshExists(const std::string &name) const void ProjectData::parseProcesses(
BaseLib::ConfigTree const& processes_config,
std::string const& project_directory,
std::string const& output_directory,
[[maybe_unused]] std::unique_ptr<ChemistryLib::ChemicalSolverInterface>&&
chemical_solver_interface)
{ {
return findMeshByName(name) != _mesh_vec.end(); (void)project_directory; // to avoid compilation warning
(void)output_directory; // to avoid compilation warning
DBUG("Reading processes:");
//! \ogs_file_param{prj__processes__process}
for (auto process_config : processes_config.getConfigSubtreeList("process"))
{
auto const type =
//! \ogs_file_param{prj__processes__process__type}
process_config.peekConfigParameter<std::string>("type");
auto const name =
//! \ogs_file_param{prj__processes__process__name}
process_config.getConfigParameter<std::string>("name");
[[maybe_unused]] auto const integration_order =
//! \ogs_file_param{prj__processes__process__integration_order}
process_config.getConfigParameter<int>("integration_order");
std::unique_ptr<ProcessLib::Process> process;
auto jacobian_assembler = ProcessLib::createJacobianAssembler(
//! \ogs_file_param{prj__processes__process__jacobian_assembler}
process_config.getConfigSubtreeOptional("jacobian_assembler"));
#ifdef OGS_BUILD_PROCESS_STEADYSTATEDIFFUSION
if (type == "STEADY_STATE_DIFFUSION")
{
// The existence check of the in the configuration referenced
// process variables is checked in the physical process.
// TODO at the moment we have only one mesh, later there can be
// several meshes. Then we have to assign the referenced mesh
// here.
process =
ProcessLib::SteadyStateDiffusion::createSteadyStateDiffusion(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _mesh_vec, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_LIQUIDFLOW
if (type == "LIQUID_FLOW")
{
process = ProcessLib::LiquidFlow::createLiquidFlowProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _mesh_vec, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_STOKESFLOW
if (type == "StokesFlow")
{
WARN(
"The StokesFlow process is deprecated and will be removed in "
"OGS-6.5.5.");
switch (_mesh_vec[0]->getDimension())
{
case 2:
process =
ProcessLib::StokesFlow::createStokesFlowProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
break;
default:
OGS_FATAL(
"StokesFlow process does not support given "
"dimension {:d}",
_mesh_vec[0]->getDimension());
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_TES
if (type == "TES")
{
WARN(
"The TES process is deprecated and will be removed in "
"OGS-6.5.5.");
process = ProcessLib::TES::createTESProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_TH2M
if (type == "TH2M")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::TH2M::createTH2MProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::TH2M::createTH2MProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
default:
OGS_FATAL("TH2M process does not support given dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_HEATCONDUCTION
if (type == "HEAT_CONDUCTION")
{
process = ProcessLib::HeatConduction::createHeatConductionProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_HEATTRANSPORTBHE
if (type == "HEAT_TRANSPORT_BHE")
{
if (_mesh_vec[0]->getDimension() != 3)
{
OGS_FATAL(
"HEAT_TRANSPORT_BHE can only work with a 3-dimensional "
"mesh! ");
}
process =
ProcessLib::HeatTransportBHE::createHeatTransportBHEProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _curves, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_WELLBORESIMULATOR
if (type == "WELLBORE_SIMULATOR")
{
if (_mesh_vec[0]->getDimension() != 1)
{
OGS_FATAL(
"WELLBORE_SIMULATOR can only work with a 1-dimensional "
"mesh!");
}
process =
ProcessLib::WellboreSimulator::createWellboreSimulatorProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_HYDROMECHANICS
if (type == "HYDRO_MECHANICS")
{
if ( //! \ogs_file_param{prj__processes__process__HYDRO_MECHANICS__dimension}
process_config.getConfigParameterOptional<int>("dimension"))
{
OGS_FATAL(
"The 'dimension' tag has been removed in the merge-request "
"!4766. The dimension is now taken from the main mesh and "
"the tag must be removed. There is a python script in the "
"merge-request description for automatic conversion.");
}
switch (_mesh_vec[0]->getDimension())
{
case 2:
process =
ProcessLib::HydroMechanics::createHydroMechanicsProcess<
2>(name, *_mesh_vec[0],
std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process =
ProcessLib::HydroMechanics::createHydroMechanicsProcess<
3>(name, *_mesh_vec[0],
std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
default:
OGS_FATAL(
"HYDRO_MECHANICS process does not support given "
"dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_LARGEDEFORMATION
if (type == "LARGE_DEFORMATION")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::LargeDeformation::
createLargeDeformationProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::LargeDeformation::
createLargeDeformationProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
default:
OGS_FATAL(
"LARGE_DEFORMATION process does not support given "
"dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_LIE_HM
if (type == "HYDRO_MECHANICS_WITH_LIE")
{
if ( //! \ogs_file_param{prj__processes__process__HYDRO_MECHANICS_WITH_LIE__dimension}
process_config.getConfigParameterOptional<int>("dimension"))
{
OGS_FATAL(
"The 'dimension' tag has been removed in the merge-request "
"!4766."
"The dimension is now taken from the main mesh and the tag "
"must be"
"removed. There is a python script in the merge-request "
"description"
"for automatic conversion.");
}
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::LIE::HydroMechanics::
createHydroMechanicsProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::LIE::HydroMechanics::
createHydroMechanicsProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
default:
OGS_FATAL(
"HYDRO_MECHANICS_WITH_LIE process does not support "
"given dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_HT
if (type == "HT")
{
process = ProcessLib::HT::createHTProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _mesh_vec, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_COMPONENTTRANSPORT
if (type == "ComponentTransport")
{
process =
ProcessLib::ComponentTransport::createComponentTransportProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _mesh_vec, _media,
std::move(chemical_solver_interface));
}
else
#endif
#ifdef OGS_BUILD_PROCESS_PHASEFIELD
if (type == "PHASE_FIELD")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process =
ProcessLib::PhaseField::createPhaseFieldProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
case 3:
process =
ProcessLib::PhaseField::createPhaseFieldProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_HMPHASEFIELD
if (type == "HM_PHASE_FIELD")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process =
ProcessLib::HMPhaseField::createHMPhaseFieldProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process =
ProcessLib::HMPhaseField::createHMPhaseFieldProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_RICHARDSCOMPONENTTRANSPORT
if (type == "RichardsComponentTransport")
{
process = ProcessLib::RichardsComponentTransport::
createRichardsComponentTransportProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_SMALLDEFORMATION
if (type == "SMALL_DEFORMATION")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::SmallDeformation::
createSmallDeformationProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::SmallDeformation::
createSmallDeformationProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
default:
OGS_FATAL(
"SMALL_DEFORMATION process does not support given "
"dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_SMALLDEFORMATIONNONLOCAL
if (type == "SMALL_DEFORMATION_NONLOCAL")
{
WARN(
"The SMALL_DEFORMATION_NONLOCAL process is deprecated and will "
"be removed in OGS-6.5.5.");
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::SmallDeformationNonlocal::
createSmallDeformationNonlocalProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
case 3:
process = ProcessLib::SmallDeformationNonlocal::
createSmallDeformationNonlocalProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
default:
OGS_FATAL(
"SMALL_DEFORMATION_NONLOCAL process does not support "
"given dimension {:d}",
_mesh_vec[0]->getDimension());
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_LIE_M
if (type == "SMALL_DEFORMATION_WITH_LIE")
{
if ( //! \ogs_file_param{prj__processes__process__SMALL_DEFORMATION_WITH_LIE__dimension}
process_config.getConfigParameterOptional<int>("dimension"))
{
OGS_FATAL(
"The 'dimension' tag has been removed in the merge-request "
"!4766."
"The dimension is now taken from the main mesh and the tag "
"must be"
"removed. There is a python script in the merge-request "
"description"
"for automatic conversion.");
}
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::LIE::SmallDeformation::
createSmallDeformationProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
case 3:
process = ProcessLib::LIE::SmallDeformation::
createSmallDeformationProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
default:
OGS_FATAL(
"SMALL_DEFORMATION_WITH_LIE process does not support "
"given dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_THERMOHYDROMECHANICS
if (type == "THERMO_HYDRO_MECHANICS")
{
if ( //! \ogs_file_param{prj__processes__process__THERMO_HYDRO_MECHANICS__dimension}
process_config.getConfigParameterOptional<int>("dimension"))
{
OGS_FATAL(
"The 'dimension' tag has been removed in the merge-request "
"!4766."
"The dimension is now taken from the main mesh and the tag "
"must be"
"removed. There is a python script in the merge-request "
"description"
"for automatic conversion.");
}
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::ThermoHydroMechanics::
createThermoHydroMechanicsProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::ThermoHydroMechanics::
createThermoHydroMechanicsProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
default:
OGS_FATAL(
"THERMO_HYDRO_MECHANICS process does not support given "
"dimension");
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_THERMOMECHANICALPHASEFIELD
if (type == "THERMO_MECHANICAL_PHASE_FIELD")
{
WARN(
"The THERMO_MECHANICAL_PHASE_FIELD process is deprecated and "
"will be removed in OGS-6.5.5.");
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::ThermoMechanicalPhaseField::
createThermoMechanicalPhaseFieldProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
case 3:
process = ProcessLib::ThermoMechanicalPhaseField::
createThermoMechanicalPhaseFieldProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config);
break;
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_THERMOMECHANICS
if (type == "THERMO_MECHANICS")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::ThermoMechanics::
createThermoMechanicsProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::ThermoMechanics::
createThermoMechanicsProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_RICHARDSFLOW
if (type == "RICHARDS_FLOW")
{
process = ProcessLib::RichardsFlow::createRichardsFlowProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_RICHARDSMECHANICS
if (type == "RICHARDS_MECHANICS")
{
if ( //! \ogs_file_param{prj__processes__process__RICHARDS_MECHANICS__dimension}
process_config.getConfigParameterOptional<int>("dimension"))
{
OGS_FATAL(
"The 'dimension' tag has been removed in the merge-request "
"!4766."
"The dimension is now taken from the main mesh and the tag "
"must be"
"removed. There is a python script in the merge-request "
"description"
"for automatic conversion.");
}
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::RichardsMechanics::
createRichardsMechanicsProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::RichardsMechanics::
createRichardsMechanicsProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_THERMORICHARDSFLOW
if (type == "THERMO_RICHARDS_FLOW")
{
process =
ProcessLib::ThermoRichardsFlow::createThermoRichardsFlowProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_THERMORICHARDSMECHANICS
if (type == "THERMO_RICHARDS_MECHANICS")
{
switch (_mesh_vec[0]->getDimension())
{
case 2:
process = ProcessLib::ThermoRichardsMechanics::
createThermoRichardsMechanicsProcess<2>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
case 3:
process = ProcessLib::ThermoRichardsMechanics::
createThermoRichardsMechanicsProcess<3>(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters,
_local_coordinate_system, integration_order,
process_config, _media);
break;
}
}
else
#endif
#ifdef OGS_BUILD_PROCESS_TWOPHASEFLOWWITHPP
if (type == "TWOPHASE_FLOW_PP")
{
process =
ProcessLib::TwoPhaseFlowWithPP::createTwoPhaseFlowWithPPProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_TWOPHASEFLOWWITHPRHO
if (type == "TWOPHASE_FLOW_PRHO")
{
WARN(
"The TWOPHASE_FLOW_PRHO process is deprecated and will be "
"removed in OGS-6.5.5.");
process = ProcessLib::TwoPhaseFlowWithPrho::
createTwoPhaseFlowWithPrhoProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
#ifdef OGS_BUILD_PROCESS_THERMALTWOPHASEFLOWWITHPP
if (type == "THERMAL_TWOPHASE_WITH_PP")
{
process = ProcessLib::ThermalTwoPhaseFlowWithPP::
createThermalTwoPhaseFlowWithPPProcess(
name, *_mesh_vec[0], std::move(jacobian_assembler),
_process_variables, _parameters, integration_order,
process_config, _media);
}
else
#endif
{
OGS_FATAL("Unknown process type: {:s}", type);
}
if (ranges::contains(_processes, name,
[](std::unique_ptr<ProcessLib::Process> const& p)
{ return p->name; }))
{
OGS_FATAL("The process name '{:s}' is not unique.", name);
}
_processes.push_back(std::move(process));
}
} }
bool ProjectData::isMeshNameUniqueAndProvideUniqueName(std::string &name) const void ProjectData::parseTimeLoop(BaseLib::ConfigTree const& config,
{ std::string const& output_directory)
int count(0); {
bool isUnique(false); DBUG("Reading time loop configuration.");
std::string cpName;
bool const compensate_non_equilibrium_initial_residuum = std::any_of(
while (!isUnique) std::begin(_process_variables),
{ std::end(_process_variables),
isUnique = true; [](auto const& process_variable)
cpName = name; { return process_variable.compensateNonEquilibriumInitialResiduum(); });
count++; _time_loop = ProcessLib::createTimeLoop(
// If the original name already exists we start to add numbers to name for config, output_directory, _processes, _nonlinear_solvers, _mesh_vec,
// as long as it takes to make the name unique. compensate_non_equilibrium_initial_residuum);
if (count > 1)
cpName = cpName + "-" + std::to_string(count); if (!_time_loop)
{
for (std::vector<MeshLib::Mesh*>::const_iterator it = _mesh_vec.begin(); OGS_FATAL("Initialization of time loop failed.");
it != _mesh_vec.end(); ++it) }
if ( cpName.compare((*it)->getName()) == 0 )
isUnique = false;
}
// At this point cpName is a unique name and isUnique is true.
// If cpName is not the original name, "name" is changed and isUnique is set to false,
// indicating that a vector with the original name already exists.
if (count > 1)
{
isUnique = false;
name = cpName;
}
return isUnique;
} }
void ProjectData::parseProcessVariables( void ProjectData::parseLinearSolvers(BaseLib::ConfigTree const& config)
ConfigTree const& process_variables_config) {
{ DBUG("Reading linear solver configuration.");
DBUG("Parse process variables:")
if (_geoObjects == nullptr) { //! \ogs_file_param{prj__linear_solvers__linear_solver}
ERR("Geometric objects are required to define process variables."); for (auto conf : config.getConfigSubtreeList("linear_solver"))
ERR("No geometric objects present."); {
return; //! \ogs_file_param{prj__linear_solvers__linear_solver__name}
} auto const name = conf.getConfigParameter<std::string>("name");
auto const linear_solver_parser =
// TODO at the moment we have only one mesh, later there MathLib::LinearSolverOptionsParser<GlobalLinearSolver>{};
// can be several meshes. Then we have to check for correct mesh here and auto const solver_options =
// assign the referenced mesh below. linear_solver_parser.parseNameAndOptions("", &conf);
if (_mesh_vec.empty() || _mesh_vec[0] == nullptr) {
ERR("A mesh is required to define process variables."); BaseLib::insertIfKeyUniqueElseError(
return; _linear_solvers,
} name,
std::make_unique<GlobalLinearSolver>(std::get<0>(solver_options),
for (auto it : process_variables_config) { std::get<1>(solver_options)),
ConfigTree const& var_config = it.second; "The linear solver name is not unique");
// TODO Extend to referenced meshes. }
_process_variables.emplace_back(var_config,*_mesh_vec[0],*_geoObjects);
}
} }
void ProjectData::parseProcesses(ConfigTree const& processes_config) void ProjectData::parseNonlinearSolvers(BaseLib::ConfigTree const& config)
{ {
DBUG("Reading processes:"); DBUG("Reading non-linear solver configuration.");
for (auto pc_it : processes_config) {
ConfigTree const& process_config = pc_it.second; //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver}
for (auto conf : config.getConfigSubtreeList("nonlinear_solver"))
{
auto const ls_name =
//! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__linear_solver}
conf.getConfigParameter<std::string>("linear_solver");
auto const& linear_solver = BaseLib::getOrError(
_linear_solvers, ls_name,
"A linear solver with the given name does not exist.");
// Check if the process type is specified. //! \ogs_file_param{prj__nonlinear_solvers__nonlinear_solver__name}
if (!process_config.get_optional<std::string>("type")) { auto const name = conf.getConfigParameter<std::string>("name");
ERR("The process config does not provide a type tag."); BaseLib::insertIfKeyUniqueElseError(
ERR(" Ignoring this process config."); _nonlinear_solvers,
continue; name,
} NumLib::createNonlinearSolver(*linear_solver, conf).first,
_process_configs.push_back(process_config); "The nonlinear solver name is not unique");
} }
} }
void ProjectData::parseOutput(ConfigTree const& output_config, void ProjectData::parseCurves(std::optional<BaseLib::ConfigTree> const& config)
std::string const& path)
{ {
DBUG("Parse output configuration:"); if (!config)
{
return;
}
auto const file = output_config.get_optional<std::string>("file"); DBUG("Reading curves configuration.");
if (!file) {
ERR("The output config does not provide a file tag.");
ERR(" Output file not set.");
return;
}
_output_file_prefix = path + *file; //! \ogs_file_param{prj__curves__curve}
for (auto conf : config->getConfigSubtreeList("curve"))
{
//! \ogs_file_param{prj__curves__curve__name}
auto const name = conf.getConfigParameter<std::string>("name");
BaseLib::insertIfKeyUniqueElseError(
_curves,
name,
MathLib::createPiecewiseLinearCurve<
MathLib::PiecewiseLinearInterpolation>(conf),
"The curve name is not unique.");
}
}
MeshLib::Mesh& ProjectData::getMesh(std::string const& mesh_name) const
{
return MeshLib::findMeshByName(_mesh_vec, mesh_name);
} }
/** /**
* \file
* \author Karsten Rink * \author Karsten Rink
* \date 2010-08-25 * \date 2010-08-25
* *
* \copyright * \copyright
* Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org) * Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License. * Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or * See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license * http://www.opengeosys.org/project/license
* *
*/ */
#ifndef PROJECTDATA_H_ #pragma once
#define PROJECTDATA_H_
#include <boost/property_tree/ptree.hpp> #include <map>
#include <memory>
#include <optional>
#include <string>
#ifdef OGS_BUILD_GUI #include "BaseLib/ConfigTree-fwd.h"
#include "Applications/DataExplorer/DataView/GEOModels.h" #include "BaseLib/ExportSymbol.h"
#else #include "ChemistryLib/ChemicalSolverInterface.h"
#include "GeoLib/GEOObjects.h" #include "MaterialLib/MPL/Medium.h"
#include "MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h"
#include "ParameterLib/CoordinateSystem.h"
#include "ParameterLib/Parameter.h"
#include "ProcessLib/Process.h"
#include "ProcessLib/ProcessVariable.h"
#ifdef OGS_EMBED_PYTHON_INTERPRETER
#include <pybind11/embed.h>
#endif #endif
#include "ProcessLib/ProcessVariable.h" namespace GeoLib
#include "ProcessLib/Process.h" {
struct NamedRaster;
}
namespace MeshLib { namespace MeshLib
class Mesh; {
class Mesh;
}
namespace NumLib
{
class NonlinearSolverBase;
}
namespace ProcessLib
{
class TimeLoop;
} }
/** /**
* The ProjectData Object contains all the data needed for a certain project, i.e. all * The ProjectData Object contains all the data needed for a certain project,
* geometric data (stored in a GEOObjects-object), all the meshes, processes, * i.e. all geometric data (stored in a GEOObjects-object), all the meshes,
* and process variables. * processes, and process variables.
*/ */
class ProjectData class ProjectData final
{ {
using ConfigTree = boost::property_tree::ptree;
public: public:
/// The empty constructor used in the gui, for example, when the project's /// The empty constructor used in the gui, for example, when the project's
/// configuration is not loaded yet. /// configuration is not loaded yet.
ProjectData() = default; ProjectData();
/// Constructs project data by parsing provided configuration. /// Constructs project data by parsing provided configuration.
/// The additional path is used to find files referenced in the ///
/// configuration. /// \param project_config Configuration as read from the prj file.
ProjectData(ConfigTree const& config_tree, std::string const& path); /// \param project_directory Where to look for files referenced in the
/// \c config_tree.
ProjectData(ProjectData&) = delete; /// \param output_directory Where to write simulation output files to.
virtual ~ProjectData(); /// \param mesh_directory Directory where meshes are read from.
/// \param script_directory Directory where scripts (e.g. Python BCs) are
/// Returns the GEOObjects containing all points, polylines and surfaces. /// read from.
GeoLib::GEOObjects* getGEOObjects() ProjectData(BaseLib::ConfigTree const& project_config,
{ std::string const& project_directory,
return _geoObjects; std::string const& output_directory,
} std::string const& mesh_directory,
[[maybe_unused]] std::string const& script_directory);
/// Adds a new mesh under a (possibly new) unique name.
/// \attention This might change the given mesh's name. ProjectData(ProjectData&) = delete;
void addMesh(MeshLib::Mesh* mesh);
//
/// Returns the mesh with the given name or a \c nullptr if the mesh was not // Process interface
/// found. //
const MeshLib::Mesh* getMesh(const std::string &name) const;
/// Provides read access to the process container.
/// Returns all the meshes with their respective names std::vector<std::unique_ptr<ProcessLib::Process>> const& getProcesses()
/// \attention This method should be used only by methods garanteeing const
/// read-only access to the meshes. {
/// \todo This method breaks encapsulation. return _processes;
const std::vector<MeshLib::Mesh*>& getMeshObjects() const }
{
return _mesh_vec; ProcessLib::TimeLoop& getTimeLoop() { return *_time_loop; }
}
MeshLib::Mesh& getMesh(std::string const& mesh_name) const;
/// Deletes all meshes with the given name and removes them from the list of
/// saved meshes. If any mesh was found for removal, true is returned and std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const&
/// false otherwise. getMedia() const
bool removeMesh(const std::string &name); {
return _media;
// }
// Process interface
//
/// Builder for processes. The supplied template defines the types of global
/// vectors and matrices, and the global executor. These types are passed to
/// every of the constructed processes.
template <typename GlobalSetupType>
void buildProcesses()
{
for (auto pc : _process_configs)
{
if (pc.get<std::string>("type") == "GROUNDWATER_FLOW") {
// The existence check of the in the configuration referenced
// process variables is checked in the physical process.
// TODO at the moment we have only one mesh, later there can be
// several meshes. Then we have to assign the referenced mesh
// here.
_processes.push_back(
new ProcessLib::GroundwaterFlowProcess<GlobalSetupType>(
*_mesh_vec[0], _process_variables, pc));
}
}
}
/// Iterator access for processes.
/// Provides read access to the process container.
std::vector<ProcessLib::Process*>::const_iterator
processesBegin() const
{
return _processes.begin();
}
/// Iterator access for processes as in processesBegin().
std::vector<ProcessLib::Process*>::const_iterator
processesEnd() const
{
return _processes.end();
}
std::string const&
getOutputFilePrefix() const
{
return _output_file_prefix;
}
private: private:
/// Checks if a mesh with the same name exists and provides a unique name in /// Parses the process variables configuration and creates new variables for
/// case of already existing mesh. Returns true if the mesh name is unique. /// each variable entry passing the corresponding subtree to the process
/// Returns false and changes the provided name to a unique name otherwise. /// variable constructor.
bool isMeshNameUniqueAndProvideUniqueName(std::string &name) const; void parseProcessVariables(
BaseLib::ConfigTree const& process_variables_config);
/// Returns true if a mesh with the same name exists and false otherwise. /// Parses the parameters configuration and saves them.
bool meshExists(const std::string &name) const; /// Checks for double parameters' names. Returns names of vectors which are
/// to be transformed using local coordinate system.
std::vector<std::string> parseParameters(
BaseLib::ConfigTree const& parameters_config);
/// Parses media configuration and saves them in an object.
void parseMedia(std::optional<BaseLib::ConfigTree> const& media_config);
/// Returns an iterator to the first found mesh with the given name. /// Parses the processes configuration and creates new processes for each
std::vector<MeshLib::Mesh*>::const_iterator findMeshByName( /// process entry passing the corresponding subtree to the process
std::string const& name) const; /// constructor.
std::vector<MeshLib::Mesh*>::iterator findMeshByName( void parseProcesses(BaseLib::ConfigTree const& processes_config,
std::string const& name); std::string const& project_directory,
std::string const& output_directory,
std::unique_ptr<ChemistryLib::ChemicalSolverInterface>&&
chemical_solver_interface);
/// Parses the process variables configuration and creates new variables for /// Parses the time loop configuration.
/// each variable entry passing the corresponding subtree to the process void parseTimeLoop(BaseLib::ConfigTree const& config,
/// variable constructor. const std::string& output_directory);
void parseProcessVariables(ConfigTree const& process_variables_config);
/// Parses the processes configuration and creates new processes for each void parseLinearSolvers(BaseLib::ConfigTree const& config);
/// process entry passing the corresponding subtree to the process
/// constructor.
void parseProcesses(ConfigTree const& process_config);
/// Parses the output configuration. void parseNonlinearSolvers(BaseLib::ConfigTree const& config);
/// Parses the file tag and sets output file prefix.
void parseOutput(ConfigTree const& output_config, std::string const& path);
private: void parseCurves(std::optional<BaseLib::ConfigTree> const& config);
#ifdef OGS_BUILD_GUI
GEOModels *_geoObjects = new GEOModels();
#else
GeoLib::GEOObjects *_geoObjects = new GeoLib::GEOObjects();
#endif
std::vector<MeshLib::Mesh*> _mesh_vec;
std::vector<ProcessLib::Process*> _processes;
std::vector<ProcessLib::ProcessVariable> _process_variables;
/// Buffer for each process' config used in the process building function. std::unique_ptr<ChemistryLib::ChemicalSolverInterface>
std::vector<ConfigTree> _process_configs; parseChemicalSolverInterface(
std::optional<BaseLib::ConfigTree> const& config,
const std::string& output_directory);
/// Output file path with project prefix. std::vector<std::unique_ptr<MeshLib::Mesh>> _mesh_vec;
std::string _output_file_prefix; std::vector<GeoLib::NamedRaster> _named_rasters;
}; std::vector<std::unique_ptr<ProcessLib::Process>> _processes;
std::vector<ProcessLib::ProcessVariable> _process_variables;
/// Buffer for each parameter config passed to the process.
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> _parameters;
std::optional<ParameterLib::CoordinateSystem> _local_coordinate_system;
#endif //PROJECTDATA_H_ std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> _media;
/// The time loop used to solve this project's processes.
std::unique_ptr<ProcessLib::TimeLoop> _time_loop;
std::map<std::string, std::unique_ptr<GlobalLinearSolver>> _linear_solvers;
std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>>
_nonlinear_solvers;
std::map<std::string,
std::unique_ptr<MathLib::PiecewiseLinearInterpolation>>
_curves;
#ifdef OGS_EMBED_PYTHON_INTERPRETER
std::optional<pybind11::scoped_interpreter> _py_scoped_interpreter;
#endif
};
/**
* \file
* \brief Implementation of class Simulation
*
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "Simulation.h"
#include <spdlog/spdlog.h>
#include "Applications/ApplicationsLib/LinearSolverLibrarySetup.h"
#include "Applications/ApplicationsLib/ProjectData.h"
#include "Applications/ApplicationsLib/TestDefinition.h"
#include "Applications/InSituLib/Adaptor.h"
#include "BaseLib/ConfigTreeUtil.h"
#include "BaseLib/FileTools.h"
#include "BaseLib/PrjProcessing.h"
#include "MeshLib/Mesh.h"
#include "NumLib/NumericsConfig.h"
#include "ProcessLib/TimeLoop.h"
Simulation::Simulation(int argc, char* argv[])
: linear_solver_library_setup(argc, argv),
#if defined(USE_PETSC)
controller(vtkSmartPointer<vtkMPIController>::New()),
#endif
test_definition{std::nullopt}
{
#if defined(USE_PETSC)
controller->Initialize(&argc, &argv, 1);
vtkMPIController::SetGlobalController(controller);
{ // Can be called only after MPI_INIT.
int mpi_rank;
MPI_Comm_rank(PETSC_COMM_WORLD, &mpi_rank);
spdlog::set_pattern(fmt::format("[{}] %^%l:%$ %v", mpi_rank));
}
#endif
}
void Simulation::initializeDataStructures(
std::string const& project,
std::vector<std::string> const& xml_patch_file_names,
bool const reference_path_is_set, std::string const& reference_path,
bool const nonfatal, std::string const& outdir, std::string const& mesh_dir,
std::string const& script_dir, bool const write_prj)
{
INFO("Reading project file {}.",
std::filesystem::absolute(project).string());
std::stringstream prj_stream;
BaseLib::prepareProjectFile(prj_stream, project, xml_patch_file_names,
write_prj, outdir);
auto project_config = BaseLib::makeConfigTree(
project, !nonfatal, "OpenGeoSysProject", prj_stream);
if (!reference_path_is_set)
{ // Ignore the test_definition section.
project_config.ignoreConfigParameter("test_definition");
}
else
{
test_definition = ApplicationsLib::TestDefinition(
//! \ogs_file_param{prj__test_definition}
project_config.getConfigSubtree("test_definition"), reference_path,
outdir);
if (test_definition->numberOfTests() == 0)
{
OGS_FATAL(
"No tests were constructed from the test definitions, "
"but reference solutions path was given.");
}
INFO("Cleanup possible output files before running ogs.");
BaseLib::removeFiles(test_definition->getOutputFiles());
}
#ifdef OGS_USE_INSITU
//! \ogs_file_param{prj__insitu}
if (auto t = project_config.getConfigSubtreeOptional("insitu"))
{
InSituLib::Initialize(
//! \ogs_file_param{prj__insitu__scripts}
t->getConfigSubtree("scripts"),
BaseLib::extractPath(project));
isInsituConfigured = true;
}
#else
project_config.ignoreConfigParameter("insitu");
#endif
project_data = std::make_unique<ProjectData>(project_config,
BaseLib::getProjectDirectory(),
outdir, mesh_dir, script_dir);
INFO("Initialize processes.");
for (auto& p : project_data->getProcesses())
{
p->initialize(project_data->getMedia());
}
// Check intermediately that config parsing went fine.
checkAndInvalidate(project_config);
BaseLib::ConfigTree::assertNoSwallowedErrors();
auto& time_loop = project_data->getTimeLoop();
time_loop.initialize();
}
double Simulation::currentTime() const
{
auto const& time_loop = project_data->getTimeLoop();
return time_loop.currentTime()();
}
double Simulation::endTime() const
{
auto const& time_loop = project_data->getTimeLoop();
return time_loop.endTime()();
}
bool Simulation::executeTimeStep()
{
auto& time_loop = project_data->getTimeLoop();
if (time_loop.currentTime() < time_loop.endTime())
{
auto const result = time_loop.executeTimeStep();
if (time_loop.calculateNextTimeStep())
{
time_loop.outputLastTimeStep();
}
return result;
}
return false;
}
MeshLib::Mesh& Simulation::getMesh(std::string const& name)
{
return project_data->getMesh(name);
}
bool Simulation::executeSimulation()
{
INFO("Solve processes.");
auto& time_loop = project_data->getTimeLoop();
while (time_loop.currentTime() < time_loop.endTime())
{
time_loop.executeTimeStep();
if (!time_loop.calculateNextTimeStep())
{
break;
}
}
return time_loop.successful_time_step;
}
void Simulation::outputLastTimeStep() const
{
auto const& time_loop = project_data->getTimeLoop();
time_loop.outputLastTimeStep();
}
std::optional<ApplicationsLib::TestDefinition> Simulation::getTestDefinition()
const
{
return test_definition;
}
Simulation::~Simulation()
{
#ifdef OGS_USE_INSITU
if (isInsituConfigured)
{
InSituLib::Finalize();
}
#endif
#if defined(USE_PETSC)
controller->Finalize(1);
#endif
}
/**
* \file
* \brief Declaration of class Simulation
*
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include <optional>
#ifdef USE_PETSC
#include <vtkMPIController.h>
#include <vtkSmartPointer.h>
#endif
#include "Applications/ApplicationsLib/LinearSolverLibrarySetup.h"
#include "Applications/ApplicationsLib/TestDefinition.h"
#include "BaseLib/ExportSymbol.h"
class ProjectData;
namespace MeshLib
{
class Mesh;
}
class Simulation final
{
public:
OGS_EXPORT_SYMBOL Simulation(int argc, char* argv[]);
OGS_EXPORT_SYMBOL void initializeDataStructures(
std::string const& project,
std::vector<std::string> const& xml_patch_file_names,
bool reference_path_is_set, std::string const& reference_path,
bool nonfatal, std::string const& outdir, std::string const& mesh_dir,
std::string const& script_dir, bool write_prj);
OGS_EXPORT_SYMBOL double currentTime() const;
OGS_EXPORT_SYMBOL double endTime() const;
OGS_EXPORT_SYMBOL bool executeTimeStep();
OGS_EXPORT_SYMBOL bool executeSimulation();
OGS_EXPORT_SYMBOL void outputLastTimeStep() const;
OGS_EXPORT_SYMBOL MeshLib::Mesh& getMesh(std::string const& name);
OGS_EXPORT_SYMBOL std::optional<ApplicationsLib::TestDefinition>
getTestDefinition() const;
OGS_EXPORT_SYMBOL ~Simulation();
private:
ApplicationsLib::LinearSolverLibrarySetup linear_solver_library_setup;
#if defined(USE_PETSC)
vtkSmartPointer<vtkMPIController> controller;
#endif
std::unique_ptr<ProjectData> project_data;
std::optional<ApplicationsLib::TestDefinition> test_definition;
#if defined(OGS_USE_INSITU)
bool isInsituConfigured = false;
#endif
};
/**
* \file
*
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "TestDefinition.h"
#include <cmath>
#include <cstdlib>
#include <filesystem>
#include <regex>
#include <vector>
#include "BaseLib/ConfigTree.h"
#include "BaseLib/Error.h"
#include "BaseLib/FileTools.h"
#include "BaseLib/MPI.h"
#ifdef USE_PETSC
#include "MeshLib/IO/VtkIO/VtuInterface.h" // For petsc file name conversion.
#endif
namespace
{
/// Test if the given string is convertible to a valid double value, not a NaN.
bool isConvertibleToDouble(std::string const& s)
{
std::size_t pos = 0;
double value;
try
{
value = std::stod(s, &pos);
}
catch (...)
{
ERR("The given string '{:s}' is not convertible to double.", s);
return false;
}
if (pos != s.size())
{
ERR("Only {:d} characters were used for double conversion of string "
"'{:s}'",
pos, s);
return false;
}
if (std::isnan(value))
{
ERR("The given string '{:s}' results in a NaN value.", s);
return false;
}
return true;
}
/// Wraps a string into double ticks.
std::string safeString(std::string const& s)
{
std::stringstream ss;
ss << std::quoted(s);
return ss.str();
}
/// Tries to find a vtkdiff executable by testing 'path/vtkdiff --version' calls
/// for various paths.
std::string findVtkdiff()
{
// Try to read the VTKDIFF_EXE environment variable.
if (const char* vtkdiff_exe_environment_variable =
std::getenv("VTKDIFF_EXE"))
{
std::string const vtkdiff_exe{vtkdiff_exe_environment_variable};
DBUG("VTKDIFF_EXE set to {:s}.", vtkdiff_exe);
//
// Sanity checks.
//
{ // The base name is 'vtkdiff'
auto const& base_name =
BaseLib::extractBaseNameWithoutExtension(vtkdiff_exe);
if (base_name != "vtkdiff")
{
OGS_FATAL(
"The VTKDIFF_EXE environment variable does not point to "
"'vtkdiff'. VTKDIFF_EXE='{:s}'",
vtkdiff_exe);
}
}
{ // vtkdiff must exist.
if (!BaseLib::IsFileExisting(vtkdiff_exe))
{
OGS_FATAL(
"The VTKDIFF_EXE points to a non-existing file. "
"VTKDIFF_EXE='{:s}'",
vtkdiff_exe);
}
}
//
// Test the actual call.
//
int const return_value =
// TODO (naumov) replace system call with output consuming call
// (fork + execl seems to be more safe), and extract the vtkdiff
// call to common function. Also properly escape all strings in
// command lines.
// Reference for POSIX and Windows:
// https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152177
// Take care when using fork, which might copy resources.
std::system((vtkdiff_exe + " --version").c_str());
if (return_value == 0)
{
return vtkdiff_exe;
}
WARN(
"Calling {:s} from the VTKDIFF_EXE environment variable didn't "
"work as expected. Return value was {:d}.",
vtkdiff_exe, return_value);
}
std::string const vtkdiff_exe{"vtkdiff"};
std::vector<std::string> const paths = {"", "bin"};
auto const path =
find_if(begin(paths), end(paths),
[&vtkdiff_exe](std::string const& path)
{
int const return_value =
// TODO (naumov) replace system call with output
// consuming call as in an above todo comment.
std::system((BaseLib::joinPaths(path, vtkdiff_exe) +
" --version")
.c_str());
return return_value == 0;
});
if (path == end(paths))
{
OGS_FATAL("vtkdiff not found.");
}
return BaseLib::joinPaths(*path, vtkdiff_exe);
}
} // namespace
namespace ApplicationsLib
{
TestDefinition::TestDefinition(BaseLib::ConfigTree const& config_tree,
std::string const& reference_path,
std::string const& output_directory)
{
if (reference_path.empty())
{
OGS_FATAL(
"Reference path containing expected result files can not be "
"empty.");
}
std::string const vtkdiff = findVtkdiff();
// Construct command lines for each entry.
//! \ogs_file_param{prj__test_definition__vtkdiff}
auto const& vtkdiff_configs = config_tree.getConfigSubtreeList("vtkdiff");
_command_lines.reserve(vtkdiff_configs.size());
for (auto const& vtkdiff_config : vtkdiff_configs)
{
std::string const& field_name =
//! \ogs_file_param{prj__test_definition__vtkdiff__field}
vtkdiff_config.getConfigParameter<std::string>("field");
DBUG("vtkdiff will compare field '{:s}'.", field_name);
std::vector<std::string> filenames;
if (auto const regex_string =
//! \ogs_file_param{prj__test_definition__vtkdiff__regex}
vtkdiff_config.getConfigParameterOptional<std::string>("regex"))
{
// TODO: insert rank into regex for mpi case
DBUG("vtkdiff regex is '{}'.", *regex_string);
auto const regex = std::regex(*regex_string);
for (auto const& p : std::filesystem::directory_iterator(
std::filesystem::path(reference_path)))
{
auto const filename = p.path().filename().string();
if (std::regex_match(filename, regex))
{
DBUG(" -> matched '{}'", filename);
filenames.push_back(filename);
}
}
}
else
{
std::string filename =
//! \ogs_file_param{prj__test_definition__vtkdiff__file}
vtkdiff_config.getConfigParameter<std::string>("file");
#ifdef USE_PETSC
BaseLib::MPI::Mpi mpi;
if (mpi.size > 1)
{
filename =
MeshLib::IO::getVtuFileNameForPetscOutputWithoutExtension(
filename) +
"_" + std::to_string(mpi.rank) + ".vtu";
}
#endif // OGS_USE_PETSC
filenames.push_back(filename);
}
if (empty(filenames))
{
OGS_FATAL(
"No files from test definitions were added for tests but {} "
"{:s} specified.",
std::size(vtkdiff_configs),
(std::size(vtkdiff_configs) == 1 ? "test was" : "tests were"));
}
auto const absolute_tolerance =
//! \ogs_file_param{prj__test_definition__vtkdiff__absolute_tolerance}
vtkdiff_config.getConfigParameter<std::string>("absolute_tolerance",
"");
if (!absolute_tolerance.empty() &&
!isConvertibleToDouble(absolute_tolerance))
{
OGS_FATAL(
"The absolute tolerance value '{:s}' is not convertible to "
"double.",
absolute_tolerance);
}
std::string const absolute_tolerance_parameter =
"--abs " + absolute_tolerance;
auto const relative_tolerance =
//! \ogs_file_param{prj__test_definition__vtkdiff__relative_tolerance}
vtkdiff_config.getConfigParameter<std::string>("relative_tolerance",
"");
if (!relative_tolerance.empty() &&
!isConvertibleToDouble(relative_tolerance))
{
OGS_FATAL(
"The relative tolerance value '{:s}' is not convertible to "
"double.",
relative_tolerance);
}
std::string const relative_tolerance_parameter =
"--rel " + relative_tolerance;
for (auto const& filename : filenames)
{
std::string output_filename =
BaseLib::joinPaths(output_directory, filename);
_output_files.push_back(output_filename);
std::string reference_filename =
BaseLib::joinPaths(reference_path, filename);
#if _WIN32
// vtk does not handle Windows long paths:
// https://gitlab.kitware.com/vtk/vtk/-/blob/master/Utilities/KWSys/vtksys/SystemTools.cxx#L1519-1521
// workaround is to make path absolute and prefix with a special
// marker and put everything in quotes, see
// https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=powershell
auto const& long_path_indicator = R"(\\?\)";
reference_filename =
std::filesystem::absolute(reference_filename).string();
reference_filename = std::format("\"{}{}\"", long_path_indicator,
reference_filename);
output_filename =
std::filesystem::absolute(output_filename).string();
output_filename =
std::format("\"{}{}\"", long_path_indicator, output_filename);
#else
output_filename = safeString(output_filename);
reference_filename = safeString(reference_filename);
#endif
//
// Construct command line.
//
std::string command_line =
vtkdiff + " -a " + safeString(field_name) + " -b " +
safeString(field_name) + " " + reference_filename + " " +
output_filename + " " + absolute_tolerance_parameter + " " +
relative_tolerance_parameter;
INFO("Will run '{:s}'", command_line);
_command_lines.emplace_back(std::move(command_line));
}
}
}
bool TestDefinition::runTests() const
{
std::vector<int> return_values;
transform(begin(_command_lines), end(_command_lines),
back_inserter(return_values),
[](std::string const& command_line)
{
INFO("---------- vtkdiff begin ----------");
int const return_value = std::system(command_line.c_str());
if (return_value != 0)
{
WARN("Return value {:d} was returned by '{:s}'.",
return_value, command_line);
}
INFO("---------- vtkdiff end ----------\n");
return return_value;
});
return !return_values.empty() &&
all_of(begin(return_values), end(return_values),
[](int const& return_value) { return return_value == 0; });
}
std::vector<std::string> const& TestDefinition::getOutputFiles() const
{
return _output_files;
}
std::size_t TestDefinition::numberOfTests() const
{
return size(_command_lines);
}
} // namespace ApplicationsLib
/**
* \file
*
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "BaseLib/ExportSymbol.h"
namespace BaseLib
{
class ConfigTree;
}
namespace ApplicationsLib
{
class TestDefinition final
{
public:
/// Constructs test definition from the config and reference path
/// essentially constructing the command lines to be run on run() function
/// call.
TestDefinition(BaseLib::ConfigTree const& config_tree,
std::string const& reference_path,
std::string const& output_directory);
OGS_EXPORT_SYMBOL bool runTests() const;
std::vector<std::string> const& getOutputFiles() const;
std::size_t numberOfTests() const;
private:
std::vector<std::string> _command_lines;
std::vector<std::string> _output_files;
};
} // namespace ApplicationsLib
if(OGS_BUILD_WHEEL)
return()
endif()
add_executable(ogs # Troubleshooting: If you get linker errors, such as ogs.cpp:(.text+0xb4):
ogs.cpp # undefined reference to `_Py_ZeroStruct' it could be that OGS is compiled with
) # the wrong Python version. I (Ch. Leh.) observed the following: The symbol
# _Py_ZeroStruct could not be found in /usr/lib/libpython3.6m.so (I intended to
# compile OGS with Python3). It's apparently a Python2 symbol (present in
# /usr/lib/libpython2.7.so) The compiler command-line was the following:
# ~~~
# /usr/bin/g++ ... -DvtkRenderingVolume_AUTOINIT="1(vtkRenderingVolumeOpenGL2)" \
# -I/usr/include/vtk -I/usr/include/python2.7 -I/usr/include/freetype2 \
# -I/usr/include/libxml2 ... -I/.../BaseLib ... \
# -isystem /usr/include/python3.6m ... -o CMakeFiles/ogs.dir/ogs.cpp.o \
# -c /.../Applications/CLI/ogs.cpp
# ~~~
# In particular, the Python2 include path comes before the Python3 include path.
# Compiling OGS with Python2 solved the issue. I assume (this is only a guess!)
# that VTK pulls in Python2 dependencies (on my system). I assume that this is
# related to https://github.com/ufz/ogs/pull/2158. Workaround: Always make sure
# that OGS is compiled with the same Python version as VTK. The error described
# above should be detected automatically by cmake and an appropriate message
# should be presented. The note is kept for the case that the automatic
# detection does not work due to whatever reason.
target_link_libraries(ogs # TODO: Make this work in python interpreters,
ApplicationsLib # see https://github.com/pybind/pybind11/discussions/5079
FileIO ogs_add_library(ogs_embedded_python ogs_embedded_python.cpp)
)
if(OGS_BUILD_GUI) # Performance warning from
target_link_libraries(ogs # https://github.com/pybind/pybind11/blob/master/docs/compiling.rst: Since
QtDataView # pybind11 is a metatemplate library, it is crucial that certain compiler flags
QtStratView # are provided to ensure high quality code generation. In contrast to the
VtkVis # pybind11_add_module() command, the CMake interface library only provides the
vtkInteractionStyle # minimal set of parameters to ensure that the code using pybind11 compiles, but
Qt4::QtCore # it does not pass these extra compiler flags (i.e. this is up to you). TODO:
Qt4::QtGui # Enable further compiler/linker flags.
Qt4::QtXml target_link_libraries(
Qt4::QtNetwork ogs_embedded_python PUBLIC pybind11::embed
) PRIVATE ProcessLibBoundaryConditionAndSourceTermPythonModule
if(CMAKE_CROSSCOMPILING) )
target_link_libraries(ogs target_compile_definitions(
${QT_XML_DEPS_LIBRARIES} ogs_embedded_python
${QT_GUI_DEPS_LIBRARIES} PUBLIC OGS_EMBED_PYTHON_INTERPRETER
${QT_NETWORK_DEPS_LIBRARIES}) # Add macro definition, because static libs make special handling
endif() # necessary s.t. the embedded OpenGeoSys Python module won't be
endif() # removed by the linker.
$<$<BOOL:${BUILD_SHARED_LIBS}>:PRIVATE
OGS_BUILD_SHARED_LIBS>
)
ADD_CATALYST_DEPENDENCY(ogs) ogs_add_executable(ogs ogs.cpp CommandLineArgumentParser.cpp)
if(OGS_USE_PETSC) target_link_libraries(
target_link_libraries(ogs ${PETSC_LIBRARIES}) ogs
endif() PRIVATE
ApplicationsLib
BaseLib
CMakeInfoLib
GitInfoLib
MeshLib
ProcessLib
$<$<AND:$<BOOL:${OGS_USE_PETSC}>,$<TARGET_EXISTS:MPI::MPI_CXX>>:MPI::MPI_CXX>
$<$<TARGET_EXISTS:InSituLib>:InSituLib>
$<$<TARGET_EXISTS:petsc>:petsc>
tclap
)
if(NOT OGS_USE_MPI) # ---- Tests ----
include(Tests.cmake) add_test(NAME ogs_no_args COMMAND ogs)
endif() set_tests_properties(ogs_no_args PROPERTIES WILL_FAIL TRUE LABELS "default")
#################### # ---- Installation ----
### Installation ### install(TARGETS ogs RUNTIME DESTINATION bin)
####################
install(TARGETS ogs RUNTIME DESTINATION bin COMPONENT ogs_cli)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "ogs" "OGS Simulator") set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "ogs"
cpack_add_component(ogs_cli "OGS Simulator"
DISPLAY_NAME "OGS THMC Simulator" )
DESCRIPTION "The command line interface for OpenGeoSys." cpack_add_component(
GROUP Applications ogs_cli
DISPLAY_NAME "OGS THMC Simulator"
DESCRIPTION "The command line interface for OpenGeoSys."
GROUP Applications
) )
include(packaging/InstallDependencies)
InstallDependencies(ogs ogs_cli)
/**
* \file
* \brief Implementation of CommandLineArgumentParser.
*
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "CommandLineArgumentParser.h"
#include <tclap/CmdLine.h>
#include "BaseLib/FileTools.h"
#include "InfoLib/CMakeInfo.h"
#include "InfoLib/GitInfo.h"
CommandLineArguments parseCommandLineArguments(int argc, char* argv[],
bool const exit_on_exception)
{
// Parse CLI arguments.
TCLAP::CmdLine cmd(
"OpenGeoSys-6 software."
"\n"
"Copyright (c) 2012-2025, OpenGeoSys Community "
"(https://www.opengeosys.org) "
"\n"
"Distributed under a Modified BSD License. "
"See accompanying file LICENSE.txt or "
"https://www.opengeosys.org/project/license"
"\n"
"version: " +
GitInfoLib::GitInfo::ogs_version +
"\n"
"CMake arguments: " +
CMakeInfoLib::CMakeInfo::cmake_args,
' ',
GitInfoLib::GitInfo::ogs_version + "\n\n" +
"CMake arguments: " + CMakeInfoLib::CMakeInfo::cmake_args);
cmd.setExceptionHandling(exit_on_exception);
TCLAP::ValueArg<std::string> log_level_arg(
"l", "log-level",
"the verbosity of logging messages: none, error, warn, info, "
"debug, "
"all",
false,
#ifdef NDEBUG
"info",
#else
"all",
#endif
"LOG_LEVEL");
#ifndef _WIN32 // TODO: On windows floating point exceptions are not handled
// currently
TCLAP::SwitchArg enable_fpe_arg("", "enable-fpe",
"enables floating point exceptions");
#endif // _WIN32
TCLAP::SwitchArg unbuffered_cout_arg("", "unbuffered-std-out",
"use unbuffered standard output");
TCLAP::ValueArg<std::string> reference_path_arg(
"r", "reference",
"Run output result comparison after successful simulation "
"comparing to all files in the given path. This requires test "
"definitions to be present in the project file.",
false, "", "PATH");
TCLAP::UnlabeledValueArg<std::string> project_arg(
"project-file",
"Path to the ogs6 project file.",
true,
"",
"PROJECT_FILE");
TCLAP::MultiArg<std::string> xml_patch_files_arg(
"p", "xml-patch",
"the xml patch file(s) which is (are) applied (in the given order) "
"to the PROJECT_FILE",
false, "");
TCLAP::ValueArg<std::string> outdir_arg("o", "output-directory",
"the output directory to write to",
false, "", "PATH");
TCLAP::ValueArg<std::string> mesh_dir_arg(
"m", "mesh-input-directory",
"the directory where the meshes are read from", false, "", "PATH");
TCLAP::ValueArg<std::string> script_dir_arg(
"s", "script-input-directory",
"the directory where script files (e.g. Python BCs) are read from",
false, "", "PATH");
TCLAP::SwitchArg write_prj_arg("",
"write-prj",
"Writes processed project file to output "
"path / [prj_base_name]_processed.prj.");
TCLAP::SwitchArg nonfatal_arg("",
"config-warnings-nonfatal",
"warnings from parsing the configuration "
"file will not trigger program abortion");
cmd.add(reference_path_arg);
cmd.add(project_arg);
cmd.add(xml_patch_files_arg);
cmd.add(outdir_arg);
cmd.add(mesh_dir_arg);
cmd.add(script_dir_arg);
cmd.add(write_prj_arg);
cmd.add(log_level_arg);
cmd.add(nonfatal_arg);
cmd.add(unbuffered_cout_arg);
#ifndef _WIN32 // TODO: On windows floating point exceptions are not handled
// currently
cmd.add(enable_fpe_arg);
#endif // _WIN32
cmd.parse(argc, argv);
CommandLineArguments cli_args;
cli_args.reference_path = reference_path_arg.getValue();
cli_args.reference_path_is_set = reference_path_arg.isSet();
cli_args.project = project_arg.getValue();
BaseLib::setProjectDirectory(BaseLib::extractPath(cli_args.project));
cli_args.xml_patch_file_names = xml_patch_files_arg.getValue();
cli_args.outdir = outdir_arg.getValue();
cli_args.mesh_dir = mesh_dir_arg.getValue().empty()
? BaseLib::getProjectDirectory()
: mesh_dir_arg.getValue();
cli_args.script_dir = script_dir_arg.getValue().empty()
? BaseLib::getProjectDirectory()
: script_dir_arg.getValue();
cli_args.nonfatal = nonfatal_arg.getValue();
cli_args.log_level = log_level_arg.getValue();
cli_args.write_prj = write_prj_arg.getValue();
// deactivate buffer for standard output if specified
if (unbuffered_cout_arg.isSet())
{
std::cout.setf(std::ios::unitbuf);
}
#ifndef _WIN32
cli_args.enable_fpe_is_set = enable_fpe_arg.isSet();
#endif // _WIN32
return cli_args;
}
/**
* \file
* \brief Declaration of CommandLineArgumentParser.
*
* \copyright
* Copyright (c) 2012-2025, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include <string>
#include <vector>
#pragma once
struct CommandLineArguments final
{
std::string reference_path;
std::string project;
std::vector<std::string> xml_patch_file_names;
std::string outdir;
std::string mesh_dir;
std::string script_dir;
std::string log_level;
bool write_prj;
bool nonfatal;
bool reference_path_is_set;
#ifndef _WIN32
bool enable_fpe_is_set;
#endif // _WIN32
};
CommandLineArguments parseCommandLineArguments(
int argc, char* argv[], bool const exit_on_exception = true);
/**
* \copyright
* Copyright (c) 2012-2015, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#ifndef APPLICATIONS_NUMERICSCONFIG_H_
#define APPLICATIONS_NUMERICSCONFIG_H_
#include <type_traits>
/**
* This file provides a configuration of the global matrix/vector and
* corresponding linear solver, and the global executer types.
* The configuration is collected in the GlobalSetupType being a particular
* instantiation of the AssemblerLib::GlobalSetup template.
* The existence of the GlobalSetupType is checked at the end of the file.
*/
//
// Global vector/matrix types and linear solver.
//
#ifdef USE_LIS
#include "MathLib/LinAlg/Lis/LisMatrix.h"
#include "MathLib/LinAlg/Lis/LisVector.h"
#include "MathLib/LinAlg/Lis/LisLinearSolver.h"
namespace detail
{
using GlobalVectorType = MathLib::LisVector;
using GlobalMatrixType = MathLib::LisMatrix;
using LinearSolverType = MathLib::LisLinearSolver;
}
#else // USE_LIS
#ifdef OGS_USE_EIGEN
#include "MathLib/LinAlg/Eigen/EigenVector.h"
#include "MathLib/LinAlg/Eigen/EigenMatrix.h"
#include "MathLib/LinAlg/Eigen/EigenLinearSolver.h"
namespace detail
{
using GlobalVectorType = MathLib::EigenVector;
using GlobalMatrixType = MathLib::EigenMatrix;
using LinearSolverType = MathLib::EigenLinearSolver;
}
#else // OGS_USE_EIGEN
#include "MathLib/LinAlg/Dense/DenseVector.h"
#include "MathLib/LinAlg/Dense/GlobalDenseMatrix.h"
#include "MathLib/LinAlg/Solvers/GaussAlgorithm.h"
namespace detail
{
using GlobalVectorType = MathLib::DenseVector<double>;
using GlobalMatrixType = MathLib::GlobalDenseMatrix<double>;
using LinearSolverType =
MathLib::GaussAlgorithm<GlobalMatrixType, GlobalVectorType>;
}
#endif // USE_LIS
#endif // OGS_USE_EIGEN
//
// Global vector/matrix builder.
//
#include "AssemblerLib/SerialVectorMatrixBuilder.h"
namespace detail
{
using GlobalVectorMatrixBuilderType =
AssemblerLib::SerialVectorMatrixBuilder<
GlobalMatrixType,
GlobalVectorType>;
}
//
// Global executor
//
#include "AssemblerLib/SerialExecutor.h"
namespace detail
{
using GlobalExecutorType = AssemblerLib::SerialExecutor;
}
///
/// Global setup collects the previous configuration in single place.
///
#include "AssemblerLib/GlobalSetup.h"
using GlobalSetupType =
AssemblerLib::GlobalSetup<
detail::GlobalVectorMatrixBuilderType,
detail::GlobalExecutorType,
detail::LinearSolverType>;
//
// Check the configuration
//
static_assert(std::is_class<GlobalSetupType>::value,
"GlobalSetupType was not defined.");
#endif // APPLICATIONS_NUMERICSCONFIG_H_
add_test(NAME ogs_no_args COMMAND ogs)
set_tests_properties(ogs_no_args PROPERTIES WILL_FAIL TRUE)
# CUBE 1x1x1 GROUNDWATER FLOW TESTS
foreach(mesh_size 1e0 1e1 1e2 1e3)
AddTest(
NAME GroundWaterFlowProcess_cube_1x1x1_${mesh_size}
PATH Elliptic/cube_1x1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS cube_${mesh_size}.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA cube_${mesh_size}.vtu Linear_1_to_minus1 Result
DATA cube_${mesh_size}.prj cube_1x1x1_hex_${mesh_size}.vtu cube_1x1x1.gml
)
AddTest(
NAME GroundWaterFlowProcess_cube_1x1x1_Neumann_${mesh_size}
PATH Elliptic/cube_1x1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS cube_${mesh_size}_neumann.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA cube_${mesh_size}_neumann.vtu D1_left_front_N1_right Result
DATA cube_${mesh_size}_neumann.prj cube_1x1x1_hex_${mesh_size}.vtu cube_1x1x1.gml
)
endforeach()
foreach(mesh_size 1e4 2e4 3e4 4e4 5e4 1e5 1e6)
AddTest(
NAME LARGE_GroundWaterFlowProcess_cube_1x1x1_${mesh_size}
PATH Elliptic/cube_1x1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS cube_${mesh_size}.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA cube_${mesh_size}.vtu Linear_1_to_minus1 Result
DATA cube_${mesh_size}.prj cube_1x1x1_hex_${mesh_size}.vtu cube_1x1x1.gml
)
AddTest(
NAME LARGE_GroundWaterFlowProcess_cube_1x1x1_Neumann_${mesh_size}
PATH Elliptic/cube_1x1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS cube_${mesh_size}_neumann.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA cube_${mesh_size}_neumann.vtu D1_left_front_N1_right Result
DATA cube_${mesh_size}_neumann.prj cube_1x1x1_hex_${mesh_size}.vtu cube_1x1x1.gml
)
endforeach()
# SQUARE 1x1 GROUNDWATER FLOW TESTS
foreach(mesh_size 1e0 1e1 1e2 1e3 1e4)
AddTest(
NAME GroundWaterFlowProcess_square_1x1_${mesh_size}
PATH Elliptic/square_1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS square_${mesh_size}.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA square_${mesh_size}.vtu Linear_1_to_minus1 Result
DATA square_${mesh_size}.prj square_1x1_quad_${mesh_size}.vtu square_1x1.gml
)
AddTest(
NAME GroundWaterFlowProcess_square_1x1_Neumann_${mesh_size}
PATH Elliptic/square_1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS square_${mesh_size}_neumann.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA square_${mesh_size}_neumann.vtu D1_left_bottom_N1_right Result
DATA square_${mesh_size}_neumann.prj square_1x1_quad_${mesh_size}.vtu square_1x1.gml
)
endforeach()
foreach(mesh_size 1e5 1e6)
AddTest(
NAME LARGE_GroundWaterFlowProcess_square_1x1_${mesh_size}
PATH Elliptic/square_1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS square_${mesh_size}.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA square_${mesh_size}.vtu Linear_1_to_minus1 Result
DATA square_${mesh_size}.prj square_1x1_quad_${mesh_size}.vtu square_1x1.gml
)
AddTest(
NAME LARGE_GroundWaterFlowProcess_square_1x1_Neumann_${mesh_size}
PATH Elliptic/square_1x1_GroundWaterFlow
EXECUTABLE ogs
EXECUTABLE_ARGS square_${mesh_size}_neumann.prj
WRAPPER time
TESTER vtkdiff
DIFF_DATA square_${mesh_size}_neumann.vtu D1_left_bottom_N1_right Result
DATA square_${mesh_size}_neumann.prj square_1x1_quad_${mesh_size}.vtu square_1x1.gml
)
endforeach()