Loading...
Searching...
No Matches
Helmholtz.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2021-2023 PCOpt/NTUA
9 Copyright (C) 2021-2023 FOSS GP
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "Helmholtz.H"
32#include "wallFvPatch.H"
33#include "DynamicList.H"
34#include "fvMeshSubset.H"
35#include "fvm.H"
36#include "bound.H"
38
39// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40
41namespace Foam
42{
44 addToRunTimeSelectionTable(regularisationPDE, Helmholtz, dictionary);
45}
46
47
48// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
49
51(
52 const volScalarField& aTilda,
53 const scalarField& source,
54 scalarField& result,
55 const bool isTopoField,
56 const regularisationRadius& radius,
57 const scalar minSetValue,
58 const bool fixATildaValues
59)
60{
61 const fvMesh& mesh = aTilda.internalField().mesh();
62 // Convergence criteria
63 const label iters = dict_.getOrDefault<label>("iters", 500);
64 const scalar tolerance = dict_.getOrDefault<scalar>("tolerance", 1.e-06);
66 // Smoothed field
67 volScalarField bTilda
68 (
70 (
71 "bTilda",
72 mesh.time().timeName(),
73 mesh,
76 ),
77 mesh,
79 (
81 fixedValueFvPatchScalarField::typeName :
82 zeroGradientFvPatchScalarField::typeName
83 )
84 );
85 // If solution corresponds to the topology porosity field, modify boundary
86 // conditions accordingly
87 if (isTopoField && growFromWalls_)
88 {
89 // Apply a unit alphaTilda value next to all walls
90 forAll(mesh.boundary(), patchI)
91 {
92 const fvPatch& patch = mesh.boundary()[patchI];
93 if (isA<wallFvPatch>(patch))
94 {
95 bTilda.boundaryFieldRef()[patchI] == wallValue_;
96 }
97 }
98 }
99 // Source field
100 DimensionedField<scalar, volMesh> sourceField
101 (
102 IOobject
103 (
104 "source",
105 mesh.time().timeName(),
106 mesh,
109 ),
110 mesh,
111 dimless,
112 source
113 );
114
115 for (label iter = 0; iter < iters; ++iter)
116 {
117 fvScalarMatrix smoothEqn
118 (
119 fvm::Sp(one, bTilda)
120 ==
121 sourceField
122 );
123 radius.addRegularisationTerm(smoothEqn, isTopoField);
124
125 // Set solution in given zones
126 if (fixATildaValues)
127 {
128 setValues(smoothEqn, isTopoField, minSetValue);
129 }
130
131 const scalar residual(mag(smoothEqn.solve().initialResidual()));
132
133// if (isTopoField)
134// {
135// bound(bTilda, dimensionedScalar(bTilda.dimensions(), minSetValue));
136// }
137
138 // Print execution time
139 mesh.time().printExecutionTime(Info);
140
141 // Check convergence
142 if (residual < tolerance)
143 {
144 Info<< "\n***Reached regularisation equation convergence limit, "
145 "iteration " << iter << "***\n\n";
146 break;
147 }
148 }
149
150 // Replace field with its regularised counterpart
151 result = bTilda.primitiveField();
152}
153
154
155// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
156
157Foam::Helmholtz::Helmholtz
158(
159 const fvMesh& mesh,
160 const dictionary& dict,
161 const topOZones& zones
162)
163:
164 regularisationPDE(mesh, dict, zones),
165 solveOnActiveCells_(dict.getOrDefault<bool>("solveOnActiveCells", false)),
166 wallValue_(dict.getOrDefault<scalar>("wallValue", 1))
167{}
168
169
170// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
171
173(
174 const volScalarField& aTilda,
175 const scalarField& source,
176 scalarField& result,
177 const bool isTopoField,
178 const regularisationRadius& radius,
179 const scalar minSetValue,
180 const bool fixATildaValues
181)
182{
183 // Set values for all constant cells here.
184 // If a subsetMesh is used, cells outside its domain will not be changed,
185 // potentially leading to fixed cells not getting their correct values
186 if (fixATildaValues)
187 {
189 DynamicList<scalar> values(0);
190 setValues(mesh_, cells, values, isTopoField);
191 result.rmap(values, cells);
192 }
193
194 /*
195 // Solve the regularisation equation on a mesh including only the active
196 // cells, if needed
197 if (solveOnActiveCells_)
198 {
199 const labelList& activeZones = zones_.adjointPorousZoneIDs();
200 if (!activeZones.empty())
201 {
202 Info<< "Solving regularisation equation on active cells only"
203 << endl;
204 DynamicList<label> allActiveCells(0);
205 for (const label zI : activeZones)
206 {
207 allActiveCells.append(mesh_.cellZones()[zI]);
208 }
209 fvMeshSubset::exposedPatchType = wallPolyPatch::typeName;
210 fvMeshSubset subSetMesh(mesh_, allActiveCells);
211 fvMesh& subMesh = subSetMesh.subMesh();
212
213 schemesLookup& fvSchemes = static_cast<schemesLookup&>(subMesh);
214 fvSchemes.readOpt() = IOobject::MUST_READ_IF_MODIFIED;
215 fvSchemes.read();
216
217 fvSolution& solution = static_cast<fvSolution&>(subMesh);
218 solution.readOpt(IOobject::MUST_READ_IF_MODIFIED);
219 solution.read();
220
221 const labelList& cellMap = subSetMesh.cellMap();
222 // Map input fields to subSetMesh fields
223 volScalarField aTildaSub(subSetMesh.interpolate(aTilda));
224 scalarField sourceSub(source, cellMap);
225 scalarField resultSub(result, cellMap);
226 // Solve the regularisation equation
227 solveEqn
228 (
229 aTildaSub, sourceSub, resultSub,
230 isTopoField, radius, minSetValue, fixATildaValues
231 );
232 // Map result back to original field
233 result.rmap(resultSub, cellMap);
234 Info<< "min max " << gMinMax(result) << endl;
235 return;
236 }
237 }
238 */
239 solveEqn
240 (
241 aTilda,
242 source,
243 result,
244 isTopoField,
245 radius,
246 minSetValue,
247 fixATildaValues
248 );
249}
250
251
252// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Bound the given scalar field if it has gone unbounded.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
const Mesh & mesh() const noexcept
Return const reference to mesh.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void rmap(const UList< Type > &mapF, const labelUList &mapAddressing)
1 to 1 reverse-map from the given field
Definition Field.C:528
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
A regulatisation PDE based on a Helmholtz filter.
Definition Helmholtz.H:52
scalar wallValue_
Fixed value at wall boundaries. Defaults to 1.
Definition Helmholtz.H:82
void solveEqn(const volScalarField &aTilda, const scalarField &source, scalarField &result, const bool isTopoField, const regularisationRadius &radius, const scalar minSetValue=Zero, const bool fixATildaValues=true)
Solve the regulatisation equation.
Definition Helmholtz.C:44
virtual void regularise(const volScalarField &aTilda, const scalarField &source, scalarField &result, const bool isTopoField, const regularisationRadius &radius, const scalar minSetValue=Zero, const bool fixATildaValues=true)
Regularise field (or sensitivities) using a Laplace PDE.
Definition Helmholtz.C:166
bool solveOnActiveCells_
Solve the regularisationPDE only on a subset mesh made of the active cell zones.
Definition Helmholtz.H:77
@ NO_READ
Nothing to be read.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const Type & initialResidual() const noexcept
Return initial residual.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
SolverPerformance< Type > solve(const dictionary &)
Solve returning the solution statistics.
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition fvPatch.H:71
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition one.H:57
Base class for selecting the regulatisation PDE.
bool growFromWalls_
Whether to apply a fixedValue BC or zeroGradient one to alphaTilda, when regularisation is performed.
void setValues(fvScalarMatrix &bTildaEqn, const bool isTopoField, const scalar minSetValue=Zero)
Set fixed bTilda values.
Base class for selecting the regulatisation radius.
virtual void addRegularisationTerm(fvScalarMatrix &matrix, bool isTopoField) const =0
Term including the regulatisation of the field.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
dynamicFvMesh & mesh
const cellShapeList & cells
zeroField Sp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
Namespace for OpenFOAM.
const dimensionSet dimless
Dimensionless.
fvMatrix< scalar > fvScalarMatrix
GeometricField< scalar, fvPatchField, volMesh > volScalarField
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
loopControl iters(runTime, aMesh.solutionDict(), "solution")
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299