diff --git a/partitioned-heat-conduction-mixedbc/clean-tutorial.sh b/partitioned-heat-conduction-mixedbc/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/0/T b/partitioned-heat-conduction-mixedbc/openfoam-left/0/T new file mode 100644 index 000000000..08d5408e5 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/0/T @@ -0,0 +1,86 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + + +internalField #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + #}; + + codeLibs + #{ + -lmeshTools \ + -lfiniteVolume + #}; + + code + + #{ + const IOdictionary& d = static_cast(dict); + const fvMesh& mesh = refCast(d.db()); + const vectorField& CC = mesh.C(); // cell center + + // assign values + scalarField T(mesh.nCells()); + forAll(CC, cellI) + { + scalar x = CC[cellI].x(); + scalar y = CC[cellI].y(); + + T[cellI] = 1 + pow(x, 2) + (3 * pow(y, 2)); // t is zero for initial conditions + } + T.writeEntry("", os); + #}; +}; + +boundaryField +{ + interface + { + type mixed; + refValue uniform 2; + refGradient uniform 2; + valueFraction uniform 1.0; + } + + DirichletBoundary + { + type codedFixedValue; + value uniform 1; + name DirichletBoundary; + code + #{ + const vectorField& Cf = patch().Cf(); + const scalar t = this->db().time().value(); + + scalarField& field = *this; + forAll(Cf, faceI) + { + const scalar x = Cf[faceI].x(); + const scalar y = Cf[faceI].y(); + + field[faceI] = 1 + pow(x, 2) + (3 * pow(y, 2)) + 1.2 * t; + } + #}; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/clean.sh b/partitioned-heat-conduction-mixedbc/openfoam-left/clean.sh new file mode 100755 index 000000000..db233c8e4 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/clean.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +set -e + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/constant/transportProperties b/partitioned-heat-conduction-mixedbc/openfoam-left/constant/transportProperties new file mode 100644 index 000000000..3ce99aead --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/constant/transportProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/run.sh b/partitioned-heat-conduction-mixedbc/openfoam-left/run.sh new file mode 100755 index 000000000..8f55fbfa5 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/system/blockMeshDict b/partitioned-heat-conduction-mixedbc/openfoam-left/system/blockMeshDict new file mode 100644 index 000000000..33357badb --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/system/blockMeshDict @@ -0,0 +1,50 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + + (0 0 0) + (1 0 0) + (1 1 0) + (0 1 0) + + (0 0 .1) + (1 0 .1) + (1 1 .1) + (0 1 .1) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (100 100 1) simpleGrading (1 1 1) +); + +boundary +( + + interface + { + type patch; + faces + ( + (1 2 6 5) + ); + } + + DirichletBoundary + { + type patch; + faces + ( + (4 7 3 0) + (7 6 2 3) + (4 0 1 5) + ); + } +); diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/system/controlDict b/partitioned-heat-conduction-mixedbc/openfoam-left/system/controlDict new file mode 100644 index 000000000..27aac31a9 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/system/controlDict @@ -0,0 +1,52 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +// Make sure you build the solver located +// in ../../solver-openfoam/ before running +// the case +application heatTransfer; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +// Write data only at the end of each coupling time window +// Intermediate time step results correspond to the first coupling iteration and are not converged. +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + errors strict; // Available since OpenFOAM v2012 + } +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/system/decomposeParDict b/partitioned-heat-conduction-mixedbc/openfoam-left/system/decomposeParDict new file mode 100644 index 000000000..ad99cf6c5 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/system/fvSchemes b/partitioned-heat-conduction-mixedbc/openfoam-left/system/fvSchemes new file mode 100644 index 000000000..6719e4491 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(T) Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(DT,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/system/fvSolution b/partitioned-heat-conduction-mixedbc/openfoam-left/system/fvSolution new file mode 100644 index 000000000..0505de916 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/system/fvSolution @@ -0,0 +1,23 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + T + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } +} + +SIMPLE +{ + nNonOrthogonalCorrectors 0; +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-left/system/preciceDict b/partitioned-heat-conduction-mixedbc/openfoam-left/system/preciceDict new file mode 100644 index 000000000..d65a3a43c --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-left/system/preciceDict @@ -0,0 +1,43 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Left; + +modules (generic); + +interfaces +{ + Interface1 + { + mesh Left-Mesh; + patches (interface); + + readData + ( + Sink-Temp + { + name Temperature-Right; + solver_name T; + operation ref-value; + } + ); + + writeData + ( + Write-Grad + { + name Gradient-Left; + solver_name T; + operation surface-normal-gradient; + } + ); + }; +}; diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/0/T b/partitioned-heat-conduction-mixedbc/openfoam-right/0/T new file mode 100644 index 000000000..bba8891ff --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/0/T @@ -0,0 +1,86 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + + +internalField #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + #}; + + codeLibs + #{ + -lmeshTools \ + -lfiniteVolume + #}; + + code + + #{ + const IOdictionary& d = static_cast(dict); + const fvMesh& mesh = refCast(d.db()); + const vectorField& CC = mesh.C(); // cell center + + // assign values + scalarField T(mesh.nCells()); + forAll(CC, cellI) + { + scalar x = CC[cellI].x(); + scalar y = CC[cellI].y(); + + T[cellI] = 1 + pow(x, 2) + (3 * pow(y, 2)); // t is zero for initial conditions + } + T.writeEntry("", os); + #}; +}; + +boundaryField +{ + interface + { + type mixed; + refValue uniform 2; + refGradient uniform 2; + valueFraction uniform 0.0; + } + + DirichletBoundary + { + type codedFixedValue; + value uniform 1; + name DirichletBoundary; + code + #{ + const vectorField& Cf = patch().Cf(); + const scalar t = this->db().time().value(); + + scalarField& field = *this; + forAll(Cf, faceI) + { + const scalar x = Cf[faceI].x(); + const scalar y = Cf[faceI].y(); + + field[faceI] = 1 + pow(x, 2) + (3 * pow(y, 2)) + 1.2 * t; + } + #}; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/clean.sh b/partitioned-heat-conduction-mixedbc/openfoam-right/clean.sh new file mode 100755 index 000000000..db233c8e4 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/clean.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +set -e + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/constant/transportProperties b/partitioned-heat-conduction-mixedbc/openfoam-right/constant/transportProperties new file mode 100644 index 000000000..3ce99aead --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/constant/transportProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/run.sh b/partitioned-heat-conduction-mixedbc/openfoam-right/run.sh new file mode 100755 index 000000000..8f55fbfa5 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/system/blockMeshDict b/partitioned-heat-conduction-mixedbc/openfoam-right/system/blockMeshDict new file mode 100644 index 000000000..972d11103 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/system/blockMeshDict @@ -0,0 +1,53 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 1; + +vertices +( + + (1 0 0) + (2 0 0) + (2 1 0) + (1 1 0) + + (1 0 .1) + (2 0 .1) + (2 1 .1) + (1 1 .1) + +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (100 100 1) simpleGrading (1 1 1) +); + +boundary +( + + interface + { + type patch; + faces + ( + (4 7 3 0) + ); + } + + DirichletBoundary + { + type patch; + faces + ( + (1 2 6 5) + (4 0 1 5) + (7 6 2 3) + ); + } +); diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/system/controlDict b/partitioned-heat-conduction-mixedbc/openfoam-right/system/controlDict new file mode 100644 index 000000000..27aac31a9 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/system/controlDict @@ -0,0 +1,52 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +// Make sure you build the solver located +// in ../../solver-openfoam/ before running +// the case +application heatTransfer; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +// Write data only at the end of each coupling time window +// Intermediate time step results correspond to the first coupling iteration and are not converged. +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + errors strict; // Available since OpenFOAM v2012 + } +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/system/fvSchemes b/partitioned-heat-conduction-mixedbc/openfoam-right/system/fvSchemes new file mode 100644 index 000000000..113863ee9 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default none; + grad(T) Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(DT,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/system/fvSolution b/partitioned-heat-conduction-mixedbc/openfoam-right/system/fvSolution new file mode 100644 index 000000000..0505de916 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/system/fvSolution @@ -0,0 +1,23 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + T + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } +} + +SIMPLE +{ + nNonOrthogonalCorrectors 0; +} diff --git a/partitioned-heat-conduction-mixedbc/openfoam-right/system/preciceDict b/partitioned-heat-conduction-mixedbc/openfoam-right/system/preciceDict new file mode 100644 index 000000000..98462891b --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/openfoam-right/system/preciceDict @@ -0,0 +1,44 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Right; + +modules (generic); + +interfaces +{ + Interface1 + { + mesh Right-Mesh; + patches (interface); + + readData + ( + HTC + { + name Gradient-Left; + solver_name T; + operation ref-gradient; + flip-normal true; + } + ); + + writeData + ( + Write-Temp + { + name Temperature-Right; + solver_name T; + operation value; + } + ); + }; +}; diff --git a/partitioned-heat-conduction-mixedbc/precice-config.xml b/partitioned-heat-conduction-mixedbc/precice-config.xml new file mode 100644 index 000000000..f4656c822 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/precice-config.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/.clang-format b/partitioned-heat-conduction-mixedbc/solver-openfoam/.clang-format new file mode 100644 index 000000000..8284a6189 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/.clang-format @@ -0,0 +1,176 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +# +# Proposed clang-format-11 style for OpenFOAM, trying to follow the OpenFOAM style guide: +# https://gitlab.com/openfoam/core/openfoam/-/wikis/coding/style/style +# Configuration developed for the OpenFOAM-preCICE adapter code: +# https://github.com/precice/openfoam-adapter +# Contribute to the discussion at the respective OpenFOAM issue: +# https://develop.openfoam.com/Development/openfoam/-/issues/1634 (archived) +# https://gitlab.com/openfoam/core/openfoam/-/issues/1634 +# +# Keep `public:` at the first indentation level +AccessModifierOffset: -4 +# Undocumented guideline: align arguments after an open bracket. +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +# Align operands after operators (+,*,<<) (see BreakBeforeBinaryOperators) +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLoopsOnASingleLine: false +# Guideline: Splitting return type and function name +# (this guideline is apparently not strictly followed in OpenFOAM) +# AlwaysBreakAfterReturnType: All +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +# Covered by "BreakBeforeBraces" +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: true + BeforeWhile: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +# Guideline (almost): Splitting long lines at an = sign. Indent after split. +# Guideline (almost): Splitting formulae over several lines. +BreakBeforeBinaryOperators: NonAssignment +# Always break before braces: if, for, functions, classes, etc. +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +# Guideline (almost): Splitting logical tests over several lines. +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +# Undocumented guideline (almost): Have the initializer : in a new line. +BreakConstructorInitializers: BeforeColon +BreakStringLiterals: true +# Here we could set the 80 charactes limit, but that would lead to more aggressive changes. +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +# Undocumented guideline: add line after "public:" etc (since clang-format 12) +# EmptyLineAfterAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +# Guideline: Macro loops are like for loops, but without a space. +ForEachMacros: + - forAllIters + - forAllConstIters + - forAllReverseIters + - forAllConstReverseIters + - forAll + - forAllReverse + - forAllIter + - forAllConstIter +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +# Guideline: The normal indentation is 4 spaces per logical level. +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +# Required to not change code following the guidelines +# "Leave two empty lines between sections" and +# "Use two empty lines between functions" +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +# Do not change the order of include statements (could be catastrophic for OpenFOAM) +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +# No "template " (guideline already used, but not documented) +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +# No a{1} (no guideline) +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +# Guideline: Spaces in "if ()", "for ()", but not "forAll ()". +SpaceBeforeParens: ControlStatementsExceptForEachMacros +# Guideline: Range-based for should have a space surrounding the ':'. +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +# No "arr[3] = [ 1, 2, 3 ]" (no guideline). +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +# Treat the code as C++11 or later +Standard: Latest +StatementMacros: +TabWidth: 4 +UseCRLF: false +# Guideline: No tab characters - only use spaces for indentation. +UseTab: Never +WhitespaceSensitiveMacros: +... + diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/.gitignore b/partitioned-heat-conduction-mixedbc/solver-openfoam/.gitignore new file mode 100644 index 000000000..1729c7850 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/.gitignore @@ -0,0 +1,4 @@ +Make/* +!Make/files +!Make/options +lnInclude/ diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/Make/files b/partitioned-heat-conduction-mixedbc/solver-openfoam/Make/files new file mode 100644 index 000000000..5721e3a21 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/Make/files @@ -0,0 +1,3 @@ +heatTransfer.C + +EXE = $(FOAM_USER_APPBIN)/heatTransfer diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/Make/options b/partitioned-heat-conduction-mixedbc/solver-openfoam/Make/options new file mode 100644 index 000000000..04ef6c148 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/Make/options @@ -0,0 +1,8 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lfvOptions \ + -lmeshTools diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/clean.sh b/partitioned-heat-conduction-mixedbc/solver-openfoam/clean.sh new file mode 100755 index 000000000..2ca6224c6 --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/clean.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +set -e -u + +wclean diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/createFields.H b/partitioned-heat-conduction-mixedbc/solver-openfoam/createFields.H new file mode 100644 index 000000000..aa377a95d --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/createFields.H @@ -0,0 +1,38 @@ +Info << "Reading field T\n" + << endl; + +volScalarField T( + IOobject( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE), + mesh); + +Info << "Reading diffusivity DT\n" + << endl; + +volScalarField DT( + IOobject( + "DT", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE), + mesh, + dimensionedScalar(dimViscosity, Zero)); + +if (!DT.headerOk()) +{ + IOdictionary transportProperties( + IOobject( + "transportProperties", + runTime.constant(), + mesh, + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE)); + DT = dimensionedScalar("DT", dimViscosity, transportProperties); +} + +#include "createFvOptions.H" diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/heatTransfer.C b/partitioned-heat-conduction-mixedbc/solver-openfoam/heatTransfer.C new file mode 100644 index 000000000..96515fc3c --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/heatTransfer.C @@ -0,0 +1,173 @@ +// This solver is based on previous work of OpenCFD Ltd. In particular, major code +// parts are part of the laplacianFoam solver of OpenFOAM 2012, which served as a +// basis for this solver. +// ------------------------------------------------------------------------------- +// Application +// heatTransfer +// +// Group +// grpBasicSolvers +// +// Description +// Modified version of the Laplace equation solver for a scalar quantity with +// a non-zero RHS. +// +// \heading Solver details +// The solver is applicable to, e.g. for thermal diffusion in a solid. The +// equation is given by: +// +// \f[ +// \ddt{T} = \div \left( D_T \grad T \right) + F +// \f] +// +// Where: +// \vartable +// T | Scalar field which is solved for, e.g. temperature +// D_T | Diffusion coefficient +// F | The RHS which is defined as: beta - 2 - 2 * alpha +// \endvartable +// +// \heading Required fields +// \plaintable +// T | Scalar field which is solved for, e.g. temperature +// \endplaintable + +#include "fvCFD.H" +#include "fvOptions.H" +#include "simpleControl.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Some helper functions in order to investigate this case +namespace Functions +{ +double get_rhs(const double x, const double y, const double alpha, const double beta) +{ + return beta - 2 - 2 * alpha; +} +double get_solution(const double x, const double y, const double alpha, const double beta, const double time) +{ + return 1 + std::pow(x, 2) + (alpha * std::pow(y, 2)) + (beta * time); +} + +void compute_and_print_errors(const Foam::fvMesh& mesh, const double alpha, const double beta, const double time) +{ + double error = 0; + const Foam::volScalarField* T_(&mesh.lookupObject("T")); + + double max_error = std::numeric_limits::min(); + + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + unsigned int numDataLocations = CellCenters.size(); + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, time); + const auto result = (exact_solution - T_->internalField()[i]) * (exact_solution - T_->internalField()[i]); + error += result; + max_error = std::max(result, max_error); + } + + Info << "\nError metrics at t = " << time << "s:\n"; + Info << "l2 error (sqrt(sum(err^2)/n)):\t\t" << std::sqrt(error / numDataLocations) << endl; + Info << "Maximum absolute error (max(err)):\t" << std::sqrt(max_error) << endl; + Info << "Global absolute error (sum(err^2)):\t" << error << "\n"; + Info << endl; +} +} // namespace Functions + +int main(int argc, char* argv[]) +{ + argList::addNote( + "Laplace equation solver for a scalar quantity."); + +#include "postProcess.H" + +#include "addCheckCaseOptions.H" +#include "setRootCaseLists.H" +#include "createTime.H" +#include "createMesh.H" + + simpleControl simple(mesh); + +#include "createFields.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating temperature distribution\n" + << endl; + + const double alpha = 3; + const double beta = 1.2; + + // Initialize the RHS with zero + volScalarField f( + IOobject( + "RHS", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE), + mesh, + dimensionedScalar( + "Tdim", + dimensionSet(0, 0, -1, 1, 0, 0, 0), + Foam::scalar(0))); + + // Now assign the respective values to the RHS + //(strictly speaking not required here, only for space-dependent RHS functions) + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + f.ref()[i] = Functions::get_rhs(coord_x, coord_y, alpha, beta); + } + + for (int j = 0; j < mesh.boundaryMesh().size() - 1; ++j) + { + // Get the face centers of the current patch + const vectorField faceCenters = + mesh.boundaryMesh()[j].faceCentres(); + + // Assign the (x,y,z) locations to the vertices + for (int i = 0; i < faceCenters.size(); i++) + { + const double coord_x = faceCenters[i].x(); + const double coord_y = faceCenters[i].y(); + f.boundaryFieldRef()[j][i] = Functions::get_rhs(coord_x, coord_y, alpha, beta); + } + } + + Functions::compute_and_print_errors(mesh, alpha, beta, runTime.value()); + + while (simple.loop()) + { + Info << "Time = " << runTime.timeName() << nl << endl; + + // We need to update the coded boundary conditions before solving to account for its time dependency properly + T.correctBoundaryConditions(); + while (simple.correctNonOrthogonal()) + { + fvScalarMatrix TEqn( + fvm::ddt(T) - fvm::laplacian(DT, T) - fvm::Su(f, T) + == fvOptions(T)); + + fvOptions.constrain(TEqn); + TEqn.solve(); + fvOptions.correct(T); + } + +#include "write.H" + + runTime.printExecutionTime(Info); + } + + Info << "End\n" + << endl; + + return 0; +} +// ************************************************************************* // diff --git a/partitioned-heat-conduction-mixedbc/solver-openfoam/write.H b/partitioned-heat-conduction-mixedbc/solver-openfoam/write.H new file mode 100644 index 000000000..70014da3e --- /dev/null +++ b/partitioned-heat-conduction-mixedbc/solver-openfoam/write.H @@ -0,0 +1,89 @@ +// We need to disable the runTime.writeTime if condition for implicit coupling +// as the condition only returns true in the very first coupling iteration +// if (runTime.writeTime()) +{ + volVectorField gradT(fvc::grad(T)); + + volScalarField gradTx( + IOobject( + "gradTx", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::X)); + + volScalarField gradTy( + IOobject( + "gradTy", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::Y)); + + volScalarField gradTz( + IOobject( + "gradTz", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::Z)); + + volVectorField DTgradT( + IOobject( + "flux", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + DT * gradT); + volScalarField error_total( + IOobject( + "error", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + DT * 0); + + // Print error metrics + Functions::compute_and_print_errors(mesh, alpha, beta, runTime.value()); + + // compute and store the error also in a paraView field + { + const Foam::volScalarField* T_(&mesh.lookupObject("T")); + + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, runTime.value()); + + error_total.ref()[i] = std::abs((exact_solution - T_->internalField()[i])); + } + + T.correctBoundaryConditions(); + for (int j = 0; j < mesh.boundaryMesh().size() - 1; ++j) + { + // Get the face centers of the current patch + const vectorField faceCenters = + mesh.boundaryMesh()[j].faceCentres(); + + // Assign the (x,y,z) locations to the vertices + for (int i = 0; i < faceCenters.size(); i++) + { + const double coord_x = faceCenters[i].x(); + const double coord_y = faceCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, runTime.value()); + error_total.boundaryFieldRef()[j][i] = std::abs(exact_solution - T_->boundaryField()[j][i]); + } + } + } + + runTime.write(); +} diff --git a/partitioned-heat-conduction-robin/clean-tutorial.sh b/partitioned-heat-conduction-robin/clean-tutorial.sh new file mode 120000 index 000000000..4713f5092 --- /dev/null +++ b/partitioned-heat-conduction-robin/clean-tutorial.sh @@ -0,0 +1 @@ +../tools/clean-tutorial-base.sh \ No newline at end of file diff --git a/partitioned-heat-conduction-robin/openfoam-left/0/T b/partitioned-heat-conduction-robin/openfoam-left/0/T new file mode 100644 index 000000000..5805c0e0b --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/0/T @@ -0,0 +1,86 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + + +internalField #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + #}; + + codeLibs + #{ + -lmeshTools \ + -lfiniteVolume + #}; + + code + + #{ + const IOdictionary& d = static_cast(dict); + const fvMesh& mesh = refCast(d.db()); + const vectorField& CC = mesh.C(); // cell center + + // assign values + scalarField T(mesh.nCells()); + forAll(CC, cellI) + { + scalar x = CC[cellI].x(); + scalar y = CC[cellI].y(); + + T[cellI] = 1 + pow(x, 2) + (3 * pow(y, 2)); // t is zero for initial conditions + } + T.writeEntry("", os); + #}; +}; + +boundaryField +{ + interface + { + type mixed; + refValue uniform 2; + refGradient uniform -2; + valueFraction uniform 0.5; + } + + DirichletBoundary + { + type codedFixedValue; + value uniform 1; + name DirichletBoundary; + code + #{ + const vectorField& Cf = patch().Cf(); + const scalar t = this->db().time().value(); + + scalarField& field = *this; + forAll(Cf, faceI) + { + const scalar x = Cf[faceI].x(); + const scalar y = Cf[faceI].y(); + + field[faceI] = 1 + pow(x, 2) + (3 * pow(y, 2)) + 1.2 * t; + } + #}; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction-robin/openfoam-left/clean.sh b/partitioned-heat-conduction-robin/openfoam-left/clean.sh new file mode 100755 index 000000000..b64fc5101 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/clean.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/partitioned-heat-conduction-robin/openfoam-left/constant/transportProperties b/partitioned-heat-conduction-robin/openfoam-left/constant/transportProperties new file mode 100644 index 000000000..3ce99aead --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/constant/transportProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/partitioned-heat-conduction-robin/openfoam-left/run.sh b/partitioned-heat-conduction-robin/openfoam-left/run.sh new file mode 100755 index 000000000..8f55fbfa5 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-heat-conduction-robin/openfoam-left/system/blockMeshDict b/partitioned-heat-conduction-robin/openfoam-left/system/blockMeshDict new file mode 100644 index 000000000..33357badb --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/system/blockMeshDict @@ -0,0 +1,50 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + + (0 0 0) + (1 0 0) + (1 1 0) + (0 1 0) + + (0 0 .1) + (1 0 .1) + (1 1 .1) + (0 1 .1) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (100 100 1) simpleGrading (1 1 1) +); + +boundary +( + + interface + { + type patch; + faces + ( + (1 2 6 5) + ); + } + + DirichletBoundary + { + type patch; + faces + ( + (4 7 3 0) + (7 6 2 3) + (4 0 1 5) + ); + } +); diff --git a/partitioned-heat-conduction-robin/openfoam-left/system/controlDict b/partitioned-heat-conduction-robin/openfoam-left/system/controlDict new file mode 100644 index 000000000..27aac31a9 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/system/controlDict @@ -0,0 +1,52 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +// Make sure you build the solver located +// in ../../solver-openfoam/ before running +// the case +application heatTransfer; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +// Write data only at the end of each coupling time window +// Intermediate time step results correspond to the first coupling iteration and are not converged. +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + errors strict; // Available since OpenFOAM v2012 + } +} diff --git a/partitioned-heat-conduction-robin/openfoam-left/system/decomposeParDict b/partitioned-heat-conduction-robin/openfoam-left/system/decomposeParDict new file mode 100644 index 000000000..ad99cf6c5 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/system/decomposeParDict @@ -0,0 +1,16 @@ +FoamFile { + version 2.0; + class dictionary; + object decomposeParDict; + format ascii; +} + +numberOfSubdomains 2; + +method simple; + +simpleCoeffs +{ + n (2 1 1); + delta 0.001; +} diff --git a/partitioned-heat-conduction-robin/openfoam-left/system/fvSchemes b/partitioned-heat-conduction-robin/openfoam-left/system/fvSchemes new file mode 100644 index 000000000..6719e4491 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; + grad(T) Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(DT,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-heat-conduction-robin/openfoam-left/system/fvSolution b/partitioned-heat-conduction-robin/openfoam-left/system/fvSolution new file mode 100644 index 000000000..0505de916 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/system/fvSolution @@ -0,0 +1,23 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + T + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } +} + +SIMPLE +{ + nNonOrthogonalCorrectors 0; +} diff --git a/partitioned-heat-conduction-robin/openfoam-left/system/preciceDict b/partitioned-heat-conduction-robin/openfoam-left/system/preciceDict new file mode 100644 index 000000000..5685ed151 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-left/system/preciceDict @@ -0,0 +1,56 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Left; + +modules (generic); + +interfaces +{ + Interface1 + { + mesh Left-Mesh; + patches (interface); + + readData + ( + Sink-Temp + { + name Temperature-Right; + solver_name T; + operation ref-value; + } + HTC + { + name Gradient-Right; + solver_name T; + operation ref-gradient; + flip-normal true; + } + ); + + writeData + ( + Write-Temp + { + name Temperature-Left; + solver_name T; + operation value; + } + Write-Grad + { + name Gradient-Left; + solver_name T; + operation surface-normal-gradient; + } + ); + }; +}; diff --git a/partitioned-heat-conduction-robin/openfoam-right/0/T b/partitioned-heat-conduction-robin/openfoam-right/0/T new file mode 100644 index 000000000..98ee1d76a --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/0/T @@ -0,0 +1,86 @@ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object T; +} + +dimensions [0 0 0 1 0 0 0]; + + +internalField #codeStream +{ + codeInclude + #{ + #include "fvCFD.H" + #}; + + codeOptions + #{ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + #}; + + codeLibs + #{ + -lmeshTools \ + -lfiniteVolume + #}; + + code + + #{ + const IOdictionary& d = static_cast(dict); + const fvMesh& mesh = refCast(d.db()); + const vectorField& CC = mesh.C(); // cell center + + // assign values + scalarField T(mesh.nCells()); + forAll(CC, cellI) + { + scalar x = CC[cellI].x(); + scalar y = CC[cellI].y(); + + T[cellI] = 1 + pow(x, 2) + (3 * pow(y, 2)); // t is zero for initial conditions + } + T.writeEntry("", os); + #}; +}; + +boundaryField +{ + interface + { + type mixed; + refValue uniform 2; + refGradient uniform 2; + valueFraction uniform 0.5; + } + + DirichletBoundary + { + type codedFixedValue; + value uniform 1; + name DirichletBoundary; + code + #{ + const vectorField& Cf = patch().Cf(); + const scalar t = this->db().time().value(); + + scalarField& field = *this; + forAll(Cf, faceI) + { + const scalar x = Cf[faceI].x(); + const scalar y = Cf[faceI].y(); + + field[faceI] = 1 + pow(x, 2) + (3 * pow(y, 2)) + 1.2 * t; + } + #}; + } + + defaultFaces + { + type empty; + } +} diff --git a/partitioned-heat-conduction-robin/openfoam-right/clean.sh b/partitioned-heat-conduction-robin/openfoam-right/clean.sh new file mode 100755 index 000000000..b64fc5101 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/clean.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +set -e -u + +. ../../tools/cleaning-tools.sh + +clean_openfoam . diff --git a/partitioned-heat-conduction-robin/openfoam-right/constant/transportProperties b/partitioned-heat-conduction-robin/openfoam-right/constant/transportProperties new file mode 100644 index 000000000..3ce99aead --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/constant/transportProperties @@ -0,0 +1,9 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object transportProperties; +} + +DT DT [ 0 2 -1 0 0 0 0 ] 1; diff --git a/partitioned-heat-conduction-robin/openfoam-right/run.sh b/partitioned-heat-conduction-robin/openfoam-right/run.sh new file mode 100755 index 000000000..8f55fbfa5 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e -u + +. ../../tools/log.sh +exec > >(tee --append "$LOGFILE") 2>&1 + +blockMesh + +../../tools/run-openfoam.sh "$@" +. ../../tools/openfoam-remove-empty-dirs.sh && openfoam_remove_empty_dirs + +close_log diff --git a/partitioned-heat-conduction-robin/openfoam-right/system/blockMeshDict b/partitioned-heat-conduction-robin/openfoam-right/system/blockMeshDict new file mode 100644 index 000000000..972d11103 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/system/blockMeshDict @@ -0,0 +1,53 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +convertToMeters 1; + +vertices +( + + (1 0 0) + (2 0 0) + (2 1 0) + (1 1 0) + + (1 0 .1) + (2 0 .1) + (2 1 .1) + (1 1 .1) + +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (100 100 1) simpleGrading (1 1 1) +); + +boundary +( + + interface + { + type patch; + faces + ( + (4 7 3 0) + ); + } + + DirichletBoundary + { + type patch; + faces + ( + (1 2 6 5) + (4 0 1 5) + (7 6 2 3) + ); + } +); diff --git a/partitioned-heat-conduction-robin/openfoam-right/system/controlDict b/partitioned-heat-conduction-robin/openfoam-right/system/controlDict new file mode 100644 index 000000000..27aac31a9 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/system/controlDict @@ -0,0 +1,52 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object controlDict; +} + +// Make sure you build the solver located +// in ../../solver-openfoam/ before running +// the case +application heatTransfer; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1; + +deltaT 0.01; + +writeControl runTime; + +// Write data only at the end of each coupling time window +// Intermediate time step results correspond to the first coupling iteration and are not converged. +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable false; + +libs ("libpreciceAdapterFunctionObject.so"); +functions +{ + preCICE_Adapter + { + type preciceAdapterFunctionObject; + errors strict; // Available since OpenFOAM v2012 + } +} diff --git a/partitioned-heat-conduction-robin/openfoam-right/system/fvSchemes b/partitioned-heat-conduction-robin/openfoam-right/system/fvSchemes new file mode 100644 index 000000000..113863ee9 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/system/fvSchemes @@ -0,0 +1,39 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSchemes; +} + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default none; + grad(T) Gauss linear; +} + +divSchemes +{ + default none; +} + +laplacianSchemes +{ + default none; + laplacian(DT,T) Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} diff --git a/partitioned-heat-conduction-robin/openfoam-right/system/fvSolution b/partitioned-heat-conduction-robin/openfoam-right/system/fvSolution new file mode 100644 index 000000000..0505de916 --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/system/fvSolution @@ -0,0 +1,23 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object fvSolution; +} + +solvers +{ + T + { + solver PCG; + preconditioner DIC; + tolerance 1e-10; + relTol 0; + } +} + +SIMPLE +{ + nNonOrthogonalCorrectors 0; +} diff --git a/partitioned-heat-conduction-robin/openfoam-right/system/preciceDict b/partitioned-heat-conduction-robin/openfoam-right/system/preciceDict new file mode 100644 index 000000000..91f5fe82f --- /dev/null +++ b/partitioned-heat-conduction-robin/openfoam-right/system/preciceDict @@ -0,0 +1,56 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object preciceDict; +} + +preciceConfig "../precice-config.xml"; + +participant Right; + +modules (generic); + +interfaces +{ + Interface1 + { + mesh Right-Mesh; + patches (interface); + + readData + ( + Sink-Temp + { + name Temperature-Left; + solver_name T; + operation ref-value; + } + HTC + { + name Gradient-Left; + solver_name T; + operation ref-gradient; + flip-normal true; + } + ); + + writeData + ( + Write-Temp + { + name Temperature-Right; + solver_name T; + operation value; + } + Write-Grad + { + name Gradient-Right; + solver_name T; + operation surface-normal-gradient; + } + ); + }; +}; diff --git a/partitioned-heat-conduction-robin/precice-config.xml b/partitioned-heat-conduction-robin/precice-config.xml new file mode 100644 index 000000000..d24072448 --- /dev/null +++ b/partitioned-heat-conduction-robin/precice-config.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/partitioned-heat-conduction-robin/solver-openfoam/.clang-format b/partitioned-heat-conduction-robin/solver-openfoam/.clang-format new file mode 100644 index 000000000..8284a6189 --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/.clang-format @@ -0,0 +1,176 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +# +# Proposed clang-format-11 style for OpenFOAM, trying to follow the OpenFOAM style guide: +# https://gitlab.com/openfoam/core/openfoam/-/wikis/coding/style/style +# Configuration developed for the OpenFOAM-preCICE adapter code: +# https://github.com/precice/openfoam-adapter +# Contribute to the discussion at the respective OpenFOAM issue: +# https://develop.openfoam.com/Development/openfoam/-/issues/1634 (archived) +# https://gitlab.com/openfoam/core/openfoam/-/issues/1634 +# +# Keep `public:` at the first indentation level +AccessModifierOffset: -4 +# Undocumented guideline: align arguments after an open bracket. +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +# Align operands after operators (+,*,<<) (see BreakBeforeBinaryOperators) +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLoopsOnASingleLine: false +# Guideline: Splitting return type and function name +# (this guideline is apparently not strictly followed in OpenFOAM) +# AlwaysBreakAfterReturnType: All +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +# Covered by "BreakBeforeBraces" +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: true + BeforeWhile: true + IndentBraces: true + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +# Guideline (almost): Splitting long lines at an = sign. Indent after split. +# Guideline (almost): Splitting formulae over several lines. +BreakBeforeBinaryOperators: NonAssignment +# Always break before braces: if, for, functions, classes, etc. +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +# Guideline (almost): Splitting logical tests over several lines. +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +# Undocumented guideline (almost): Have the initializer : in a new line. +BreakConstructorInitializers: BeforeColon +BreakStringLiterals: true +# Here we could set the 80 charactes limit, but that would lead to more aggressive changes. +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +# Undocumented guideline: add line after "public:" etc (since clang-format 12) +# EmptyLineAfterAccessModifier: Always +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +# Guideline: Macro loops are like for loops, but without a space. +ForEachMacros: + - forAllIters + - forAllConstIters + - forAllReverseIters + - forAllConstReverseIters + - forAll + - forAllReverse + - forAllIter + - forAllConstIter +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +# Guideline: The normal indentation is 4 spaces per logical level. +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +# Required to not change code following the guidelines +# "Leave two empty lines between sections" and +# "Use two empty lines between functions" +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +# Do not change the order of include statements (could be catastrophic for OpenFOAM) +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +# No "template " (guideline already used, but not documented) +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +# No a{1} (no guideline) +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +# Guideline: Spaces in "if ()", "for ()", but not "forAll ()". +SpaceBeforeParens: ControlStatementsExceptForEachMacros +# Guideline: Range-based for should have a space surrounding the ':'. +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +# No "arr[3] = [ 1, 2, 3 ]" (no guideline). +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +# Treat the code as C++11 or later +Standard: Latest +StatementMacros: +TabWidth: 4 +UseCRLF: false +# Guideline: No tab characters - only use spaces for indentation. +UseTab: Never +WhitespaceSensitiveMacros: +... + diff --git a/partitioned-heat-conduction-robin/solver-openfoam/.gitignore b/partitioned-heat-conduction-robin/solver-openfoam/.gitignore new file mode 100644 index 000000000..1729c7850 --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/.gitignore @@ -0,0 +1,4 @@ +Make/* +!Make/files +!Make/options +lnInclude/ diff --git a/partitioned-heat-conduction-robin/solver-openfoam/Make/files b/partitioned-heat-conduction-robin/solver-openfoam/Make/files new file mode 100644 index 000000000..5721e3a21 --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/Make/files @@ -0,0 +1,3 @@ +heatTransfer.C + +EXE = $(FOAM_USER_APPBIN)/heatTransfer diff --git a/partitioned-heat-conduction-robin/solver-openfoam/Make/options b/partitioned-heat-conduction-robin/solver-openfoam/Make/options new file mode 100644 index 000000000..04ef6c148 --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/Make/options @@ -0,0 +1,8 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lfvOptions \ + -lmeshTools diff --git a/partitioned-heat-conduction-robin/solver-openfoam/clean.sh b/partitioned-heat-conduction-robin/solver-openfoam/clean.sh new file mode 100755 index 000000000..2ca6224c6 --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/clean.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +set -e -u + +wclean diff --git a/partitioned-heat-conduction-robin/solver-openfoam/createFields.H b/partitioned-heat-conduction-robin/solver-openfoam/createFields.H new file mode 100644 index 000000000..aa377a95d --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/createFields.H @@ -0,0 +1,38 @@ +Info << "Reading field T\n" + << endl; + +volScalarField T( + IOobject( + "T", + runTime.timeName(), + mesh, + IOobject::MUST_READ, + IOobject::AUTO_WRITE), + mesh); + +Info << "Reading diffusivity DT\n" + << endl; + +volScalarField DT( + IOobject( + "DT", + runTime.timeName(), + mesh, + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE), + mesh, + dimensionedScalar(dimViscosity, Zero)); + +if (!DT.headerOk()) +{ + IOdictionary transportProperties( + IOobject( + "transportProperties", + runTime.constant(), + mesh, + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE)); + DT = dimensionedScalar("DT", dimViscosity, transportProperties); +} + +#include "createFvOptions.H" diff --git a/partitioned-heat-conduction-robin/solver-openfoam/heatTransfer.C b/partitioned-heat-conduction-robin/solver-openfoam/heatTransfer.C new file mode 100644 index 000000000..96515fc3c --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/heatTransfer.C @@ -0,0 +1,173 @@ +// This solver is based on previous work of OpenCFD Ltd. In particular, major code +// parts are part of the laplacianFoam solver of OpenFOAM 2012, which served as a +// basis for this solver. +// ------------------------------------------------------------------------------- +// Application +// heatTransfer +// +// Group +// grpBasicSolvers +// +// Description +// Modified version of the Laplace equation solver for a scalar quantity with +// a non-zero RHS. +// +// \heading Solver details +// The solver is applicable to, e.g. for thermal diffusion in a solid. The +// equation is given by: +// +// \f[ +// \ddt{T} = \div \left( D_T \grad T \right) + F +// \f] +// +// Where: +// \vartable +// T | Scalar field which is solved for, e.g. temperature +// D_T | Diffusion coefficient +// F | The RHS which is defined as: beta - 2 - 2 * alpha +// \endvartable +// +// \heading Required fields +// \plaintable +// T | Scalar field which is solved for, e.g. temperature +// \endplaintable + +#include "fvCFD.H" +#include "fvOptions.H" +#include "simpleControl.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Some helper functions in order to investigate this case +namespace Functions +{ +double get_rhs(const double x, const double y, const double alpha, const double beta) +{ + return beta - 2 - 2 * alpha; +} +double get_solution(const double x, const double y, const double alpha, const double beta, const double time) +{ + return 1 + std::pow(x, 2) + (alpha * std::pow(y, 2)) + (beta * time); +} + +void compute_and_print_errors(const Foam::fvMesh& mesh, const double alpha, const double beta, const double time) +{ + double error = 0; + const Foam::volScalarField* T_(&mesh.lookupObject("T")); + + double max_error = std::numeric_limits::min(); + + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + unsigned int numDataLocations = CellCenters.size(); + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, time); + const auto result = (exact_solution - T_->internalField()[i]) * (exact_solution - T_->internalField()[i]); + error += result; + max_error = std::max(result, max_error); + } + + Info << "\nError metrics at t = " << time << "s:\n"; + Info << "l2 error (sqrt(sum(err^2)/n)):\t\t" << std::sqrt(error / numDataLocations) << endl; + Info << "Maximum absolute error (max(err)):\t" << std::sqrt(max_error) << endl; + Info << "Global absolute error (sum(err^2)):\t" << error << "\n"; + Info << endl; +} +} // namespace Functions + +int main(int argc, char* argv[]) +{ + argList::addNote( + "Laplace equation solver for a scalar quantity."); + +#include "postProcess.H" + +#include "addCheckCaseOptions.H" +#include "setRootCaseLists.H" +#include "createTime.H" +#include "createMesh.H" + + simpleControl simple(mesh); + +#include "createFields.H" + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + Info << "\nCalculating temperature distribution\n" + << endl; + + const double alpha = 3; + const double beta = 1.2; + + // Initialize the RHS with zero + volScalarField f( + IOobject( + "RHS", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::NO_WRITE), + mesh, + dimensionedScalar( + "Tdim", + dimensionSet(0, 0, -1, 1, 0, 0, 0), + Foam::scalar(0))); + + // Now assign the respective values to the RHS + //(strictly speaking not required here, only for space-dependent RHS functions) + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + f.ref()[i] = Functions::get_rhs(coord_x, coord_y, alpha, beta); + } + + for (int j = 0; j < mesh.boundaryMesh().size() - 1; ++j) + { + // Get the face centers of the current patch + const vectorField faceCenters = + mesh.boundaryMesh()[j].faceCentres(); + + // Assign the (x,y,z) locations to the vertices + for (int i = 0; i < faceCenters.size(); i++) + { + const double coord_x = faceCenters[i].x(); + const double coord_y = faceCenters[i].y(); + f.boundaryFieldRef()[j][i] = Functions::get_rhs(coord_x, coord_y, alpha, beta); + } + } + + Functions::compute_and_print_errors(mesh, alpha, beta, runTime.value()); + + while (simple.loop()) + { + Info << "Time = " << runTime.timeName() << nl << endl; + + // We need to update the coded boundary conditions before solving to account for its time dependency properly + T.correctBoundaryConditions(); + while (simple.correctNonOrthogonal()) + { + fvScalarMatrix TEqn( + fvm::ddt(T) - fvm::laplacian(DT, T) - fvm::Su(f, T) + == fvOptions(T)); + + fvOptions.constrain(TEqn); + TEqn.solve(); + fvOptions.correct(T); + } + +#include "write.H" + + runTime.printExecutionTime(Info); + } + + Info << "End\n" + << endl; + + return 0; +} +// ************************************************************************* // diff --git a/partitioned-heat-conduction-robin/solver-openfoam/write.H b/partitioned-heat-conduction-robin/solver-openfoam/write.H new file mode 100644 index 000000000..70014da3e --- /dev/null +++ b/partitioned-heat-conduction-robin/solver-openfoam/write.H @@ -0,0 +1,89 @@ +// We need to disable the runTime.writeTime if condition for implicit coupling +// as the condition only returns true in the very first coupling iteration +// if (runTime.writeTime()) +{ + volVectorField gradT(fvc::grad(T)); + + volScalarField gradTx( + IOobject( + "gradTx", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::X)); + + volScalarField gradTy( + IOobject( + "gradTy", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::Y)); + + volScalarField gradTz( + IOobject( + "gradTz", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + gradT.component(vector::Z)); + + volVectorField DTgradT( + IOobject( + "flux", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + DT * gradT); + volScalarField error_total( + IOobject( + "error", + runTime.timeName(), + mesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE), + DT * 0); + + // Print error metrics + Functions::compute_and_print_errors(mesh, alpha, beta, runTime.value()); + + // compute and store the error also in a paraView field + { + const Foam::volScalarField* T_(&mesh.lookupObject("T")); + + // Get the locations of the volume centered mesh vertices + const vectorField& CellCenters = mesh.C(); + + for (int i = 0; i < CellCenters.size(); i++) + { + const double coord_x = CellCenters[i].x(); + const double coord_y = CellCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, runTime.value()); + + error_total.ref()[i] = std::abs((exact_solution - T_->internalField()[i])); + } + + T.correctBoundaryConditions(); + for (int j = 0; j < mesh.boundaryMesh().size() - 1; ++j) + { + // Get the face centers of the current patch + const vectorField faceCenters = + mesh.boundaryMesh()[j].faceCentres(); + + // Assign the (x,y,z) locations to the vertices + for (int i = 0; i < faceCenters.size(); i++) + { + const double coord_x = faceCenters[i].x(); + const double coord_y = faceCenters[i].y(); + const double exact_solution = Functions::get_solution(coord_x, coord_y, alpha, beta, runTime.value()); + error_total.boundaryFieldRef()[j][i] = std::abs(exact_solution - T_->boundaryField()[j][i]); + } + } + } + + runTime.write(); +}