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 -------------------------------------------------------------------------------
11 License
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 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(Helmholtz, 1);
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);
65  dimensionedScalar one("1", dimless, 1.);
66  // Smoothed field
67  volScalarField bTilda
68  (
69  IOobject
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 
157 Foam::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  {
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 " << gMin(result) << " " << gMax(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 // ************************************************************************* //
Base class for selecting the regulatisation radius.
dictionary dict
fvMatrix< scalar > fvScalarMatrix
Definition: fvMatricesFwd.H:37
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
virtual void addRegularisationTerm(fvScalarMatrix &matrix, bool isTopoField) const =0
Term including the regulatisation of the field.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:70
Base class for selecting the regulatisation PDE.
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
Macros for easy insertion into run-time selection tables.
A regulatisation PDE based on a Helmholtz filter.
Definition: Helmholtz.H:49
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition: HashOps.H:164
dynamicFvMesh & mesh
const cellShapeList & cells
void setValues(fvScalarMatrix &bTildaEqn, const bool isTopoField, const scalar minSetValue=Zero)
Set fixed bTilda values.
zeroField Sp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
scalar wallValue_
Fixed value at wall boundaries. Defaults to 1.
Definition: Helmholtz.H:82
const Mesh & mesh() const noexcept
Return mesh.
Bound the given scalar field if it has gone unbounded.
defineTypeNameAndDebug(combustionModel, 0)
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
void rmap(const UList< Type > &mapF, const labelUList &mapAddressing)
1 to 1 reverse-map from the given field
Definition: Field.C:529
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Nothing to be read.
loopControl iters(runTime, aMesh.solutionDict(), "solution")
const std::string patch
OpenFOAM patch number as a std::string.
messageStream Info
Information stream (stdout output on master, null elsewhere)
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...
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
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 growFromWalls_
Whether to apply a fixedValue BC or zeroGradient one to alphaTilda, when regularisation is performed...
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:56
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127