anisotropic.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2022-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "anisotropic.H"
27 #include "fvmLaplacian.H"
28 #include "fvcLaplacian.H"
29 #include "fvcSnGrad.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<class SolidThermophysicalTransportModel>
37 setZonesPatchFaces() const
38 {
39  if (!zoneCoordinateSystems_.size()) return;
40 
41  // Find all the patch faces adjacent to zones
42 
43  const fvMesh& mesh = this->thermo().mesh();
44  const fvBoundaryMesh& patches = mesh.boundary();
45  const labelList& own = mesh.faceOwner();
46 
47  zonesPatchFaces_.setSize(zoneCoordinateSystems_.size());
48  label zonei = 0;
49 
51  (
52  PtrDictionary<coordinateSystem>,
53  zoneCoordinateSystems_,
54  iter
55  )
56  {
57  zonesPatchFaces_[zonei].setSize(patches.size());
58 
59  const labelList& zoneCells = mesh.cellZones()[iter().name()];
60 
61  // Cell in zone
62  boolList cellInZone(mesh.nCells(), false);
63 
64  forAll(zoneCells, i)
65  {
66  cellInZone[zoneCells[i]] = true;
67  }
68 
70  {
71  const fvPatch& pp = patches[patchi];
72 
73  zonesPatchFaces_[zonei][patchi].setSize(pp.size());
74 
75  label nZonePatchFaces = 0;
76 
77  forAll(pp, patchFacei)
78  {
79  const label facei = pp.start() + patchFacei;
80 
81  if (cellInZone[own[facei]])
82  {
83  zonesPatchFaces_[zonei][patchi][nZonePatchFaces++] =
84  patchFacei;
85  }
86  }
87 
88  zonesPatchFaces_[zonei][patchi].setSize(nZonePatchFaces);
89  }
90 
91  zonei++;
92  }
93 }
94 
95 
96 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
97 
98 template<class SolidThermophysicalTransportModel>
101 (
102  const alphaField& alpha,
103  const solidThermo& thermo,
104  const word& type
105 )
106 :
107  SolidThermophysicalTransportModel(type, alpha, thermo),
109  coordinateSystem_
110  (
111  coordinateSystem::New(thermo.mesh(), this->typeDict(type))
112  ),
113  boundaryAligned_
114  (
115  this->typeDict(type).template lookupOrDefault<Switch>
116  (
117  "boundaryAligned",
118  false
119  )
120  ),
121  aligned_(thermo.mesh().boundary().size(), true)
122 {
123  if (this->typeDict(type).found("zones"))
124  {
125  const dictionary& zonesDict(this->typeDict(type).subDict("zones"));
126 
127  Info<< " Reading coordinate system for zones:" << endl;
128 
129  forAllConstIter(dictionary, zonesDict, iter)
130  {
131  if (iter().isDict())
132  {
133  const word& zoneName = iter().keyword();
134  const dictionary& dict = iter().dict();
135 
136  Info<< " " << zoneName << endl;
137 
138  zoneCoordinateSystems_.insert
139  (
140  zoneName,
141  coordinateSystem::New(zoneName, dict).ptr()
142  );
143  }
144  }
145 
146  // Find all the patch faces adjacent to zones
147  setZonesPatchFaces();
148  }
149 
150  const fvMesh& mesh = thermo.mesh();
151  const fvBoundaryMesh& bMesh = mesh.boundary();
152 
153  bool aligned = true;
154 
156  {
157  if
158  (
159  !bMesh[patchi].coupled()
160  && returnReduce(bMesh[patchi].size(), sumOp<label>())
161  )
162  {
163  const vectorField n(bMesh[patchi].nf());
164  const vectorField nKappa(n & Kappa(patchi));
165 
166  // Calculate a patch alignment factor for Kappa
167  const scalar alignmentFactor =
168  gSum
169  (
171  *mag(nKappa - n*(nKappa & n))
172  )/gSum(mesh.magSf().boundaryField()[patchi]*mag(nKappa));
173 
174  if (alignmentFactor > 1e-3)
175  {
176  aligned_[patchi] = false;
177  aligned = false;
178 
179  Info<< " Kappa is not aligned with patch "
180  << bMesh[patchi].name()
181  << " by an alignment factor of " << alignmentFactor
182  << " (0=aligned, 1=unaligned)" << nl
183  << " heat-flux correction will be applied." << endl;
184  }
185  }
186  }
187 
188  if (!aligned && boundaryAligned_)
189  {
190  aligned_ = true;
191  aligned = true;
192 
193  Info<<
194  " boundaryAligned is set true, "
195  "boundary alignment of kappa will be enforced." << endl;
196  }
197 
198  // If Kappa is not aligned with any patch enable grad(T) caching
199  // because the patch grad(T) will be required for the heat-flux correction
200  if (!aligned)
201  {
202  mesh.solution().enableCache("grad(T)");
203  }
204 
205  Info << endl;
206 
207  mesh.schemes().setFluxRequired(thermo.T().name());
208 }
209 
210 
211 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
212 
213 template<class SolidThermophysicalTransportModel>
216 {
217 
218  return true;
219 }
220 
221 
222 template<class SolidThermophysicalTransportModel>
226 {
227  const solidThermo& thermo = this->thermo();
228  const fvMesh& mesh = thermo.mesh();
229 
230  const volVectorField& materialKappa = thermo.Kappa();
231 
233  (
235  (
236  "Kappa",
237  mesh,
238  dimensionedSymmTensor(materialKappa.dimensions(), Zero)
239  )
240  );
241  volSymmTensorField& Kappa = tKappa.ref();
242 
243  Kappa.primitiveFieldRef() =
244  coordinateSystem_.R(mesh.C()).transformDiagTensor(materialKappa);
245 
246  forAll(Kappa.boundaryField(), patchi)
247  {
248  Kappa.boundaryFieldRef()[patchi] =
249  coordinateSystem_.R(mesh.boundary()[patchi].Cf())
250  .transformDiagTensor(materialKappa.boundaryField()[patchi]);
251  }
252 
253  label zonei = 0;
254 
256  (
258  zoneCoordinateSystems_,
259  iter
260  )
261  {
262  const labelList& zoneCells = mesh.cellZones()[iter().name()];
263  const coordinateSystem& cs = iter();
264 
265  symmTensorField& KappaIf = Kappa;
266 
267  forAll(zoneCells, i)
268  {
269  const label celli = zoneCells[i];
270 
271  KappaIf[celli] =
273  (
274  mesh.C()[celli],
275  materialKappa[celli]
276  );
277  }
278 
279  forAll(zonesPatchFaces_[zonei], patchi)
280  {
281  symmTensorField& KappaPf = Kappa.boundaryFieldRef()[patchi];
282 
283  const vectorField& materialKappaPf =
284  materialKappa.boundaryField()[patchi];
285 
286  const vectorField& CPf = mesh.boundary()[patchi].Cf();
287 
288  forAll(zonesPatchFaces_[zonei][patchi], zonePatchFacei)
289  {
290  const label patchFacei =
291  zonesPatchFaces_[zonei][patchi][zonePatchFacei];
292 
293  KappaPf[patchFacei] =
295  (
296  CPf[patchFacei],
297  materialKappaPf[patchFacei]
298  );
299  }
300  }
301 
302  zonei++;
303  }
304 
305  return tKappa;
306 }
307 
308 
309 template<class SolidThermophysicalTransportModel>
313 (
314  const label patchi
315 ) const
316 {
317  const solidThermo& thermo = this->thermo();
318  const vectorField& CPf = thermo.mesh().boundary()[patchi].Cf();
319 
320  const vectorField& materialKappaPf(thermo.Kappa().boundaryField()[patchi]);
321 
322  tmp<symmTensorField> tKappa
323  (
324  coordinateSystem_.R(CPf).transformDiagTensor(materialKappaPf)
325  );
326  symmTensorField& KappaPf = tKappa.ref();
327 
328  label zonei = 0;
329 
331  (
332  PtrDictionary<coordinateSystem>,
333  zoneCoordinateSystems_,
334  iter
335  )
336  {
337  const coordinateSystem& cs = iter();
338 
339  forAll(zonesPatchFaces_[zonei][patchi], zonePatchFacei)
340  {
341  const label patchFacei =
342  zonesPatchFaces_[zonei][patchi][zonePatchFacei];
343 
344  KappaPf[patchFacei] =
345  cs.R().transformDiagTensor
346  (
347  CPf[patchFacei],
348  materialKappaPf[patchFacei]
349  );
350  }
351 
352  zonei++;
353  }
354 
355  return tKappa;
356 }
357 
358 
359 template<class SolidThermophysicalTransportModel>
363 {
365  return tmp<volScalarField>(nullptr);
366 }
367 
368 
369 template<class SolidThermophysicalTransportModel>
373 (
374  const label patchi
375 ) const
376 {
377  const vectorField n(this->thermo().mesh().boundary()[patchi].nf());
378  return n & Kappa(patchi) & n;
379 }
380 
381 
382 template<class SolidThermophysicalTransportModel>
386 {
387  const solidThermo& thermo = this->thermo();
388  const fvMesh& mesh = thermo.mesh();
389 
391  (
392  "q",
393  -fvm::laplacian(this->alpha()*Kappa(), thermo.T())().flux()/mesh.magSf()
394  );
395 }
396 
397 
398 template<class SolidThermophysicalTransportModel>
402 {
404  return tmp<scalarField>(nullptr);
405 }
406 
407 
408 template<class SolidThermophysicalTransportModel>
412 (
413  const label patchi
414 ) const
415 {
416  if (!aligned_[patchi])
417  {
418  tmp<volVectorField> gradT(fvc::grad(this->thermo().T()));
419 
420  const vectorField n(this->thermo().mesh().boundary()[patchi].nf());
421  const vectorField nKappa(n & Kappa(patchi));
422 
423  return
424  -(
425  this->alpha().boundaryField()[patchi]
426  *((nKappa - n*(nKappa & n)) & gradT().boundaryField()[patchi])
427  );
428  }
429  else
430  {
431  return tmp<scalarField>(nullptr);
432  }
433 }
434 
435 
436 template<class SolidThermophysicalTransportModel>
440 (
442 ) const
443 {
444  const solidThermo& thermo = this->thermo();
445  const volSymmTensorField Kappa(this->Kappa());
446  const surfaceVectorField& Sf = thermo.mesh().Sf();
447  const surfaceScalarField& magSf = thermo.mesh().magSf();
448 
449  // Return heat flux source as an implicit energy correction
450  // to the temperature gradient flux
451  return
452  -fvc::laplacian(this->alpha()*Kappa, thermo.T())
454  (
455  (Sf & fvc::interpolate(this->alpha()*Kappa/thermo.Cv()) & Sf)
456  /sqr(magSf),
457  e
458  );
459 }
460 
461 
462 template<class SolidThermophysicalTransportModel>
465 {
466  SolidThermophysicalTransportModel::predict();
467 
468  // Recalculate zonesPatchFaces if they have been deleted
469  // following mesh changes
470  if (!zonesPatchFaces_.size())
471  {
472  setZonesPatchFaces();
473  }
474 }
475 
476 
477 template<class SolidThermophysicalTransportModel>
480 {
481  return true;
482 }
483 
484 
485 template<class SolidThermophysicalTransportModel>
488 (
489  const polyTopoChangeMap& map
490 )
491 {
492  // Delete the cached zonesPatchFaces, will be re-created in predict
493  zonesPatchFaces_.clear();
494 }
495 
496 
497 template<class SolidThermophysicalTransportModel>
500 (
501  const polyMeshMap& map
502 )
503 {
504  // Delete the cached zonesPatchFaces, will be re-created in predict
505  zonesPatchFaces_.clear();
506 }
507 
508 
509 template<class SolidThermophysicalTransportModel>
512 (
513  const polyDistributionMap& map
514 )
515 {
516  // Delete the cached zonesPatchFaces, will be re-created in predict
517  zonesPatchFaces_.clear();
518 }
519 
520 
521 // ************************************************************************* //
bool found
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
Macros for easy insertion into run-time selection tables.
void insert(const word &, T *)
Add at head of dictionary.
const dimensionSet & dimensions() const
Return dimensions.
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Internal::FieldType & primitiveFieldRef()
Return a reference to the primitive field.
Boundary & boundaryFieldRef()
Return a reference to the boundary field.
static tmp< GeometricField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Internal &, const PtrList< Patch > &, const HashPtrTable< Source > &=HashPtrTable< Source >())
Return a temporary field constructed from name,.
void setSize(const label)
Reset size of List.
Definition: List.C:281
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:61
virtual symmTensor transformDiagTensor(const vector &p, const vector &v) const =0
Transform diagTensor masquerading as a vector using transformation.
Base class for other coordinate system specifications.
static autoPtr< coordinateSystem > New(const objectRegistry &obr, const dictionary &dict)
Select constructed from dictionary and objectRegistry.
const coordinateRotation & R() const
Return const reference to co-ordinate rotation.
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Foam::fvBoundaryMesh.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
const volVectorField & C() const
Return cell centres.
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:932
const fvSchemes & schemes() const
Return the fvSchemes.
Definition: fvMesh.C:1792
const fvSolution & solution() const
Return the fvSolution.
Definition: fvMesh.C:1803
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
void setFluxRequired(const word &name) const
Definition: fvSchemes.C:434
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
const cellZoneList & cellZones() const
Return cell zones.
Definition: polyMesh.H:438
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1321
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
label nCells() const
Base-class for solid thermodynamic properties.
Definition: solidThermo.H:59
Solid thermophysical transport model for anisotropic thermal conductivity.
Definition: anisotropic.H:121
virtual bool movePoints()
Update for mesh motion.
Definition: anisotropic.C:479
anisotropic(const alphaField &alpha, const solidThermo &thermo, const word &type=typeName)
Construct from solid thermophysical properties.
Definition: anisotropic.C:101
SolidThermophysicalTransportModel::alphaField alphaField
Definition: anisotropic.H:154
virtual tmp< scalarField > qCorr(const label patchi) const
Return the patch heat flux correction [W/m^2].
Definition: anisotropic.C:412
virtual void predict()
Correct the anisotropic viscosity.
Definition: anisotropic.C:464
virtual void mapMesh(const polyMeshMap &map)
Update from another mesh using the given map.
Definition: anisotropic.C:500
virtual void distribute(const polyDistributionMap &map)
Redistribute or update using the given distribution map.
Definition: anisotropic.C:512
virtual tmp< volScalarField > kappa() const
Thermal conductivity [W/m/K].
Definition: anisotropic.C:362
virtual tmp< surfaceScalarField > q() const
Return the heat flux [W/m^2].
Definition: anisotropic.C:385
virtual void topoChange(const polyTopoChangeMap &map)
Update topology using the given map.
Definition: anisotropic.C:488
virtual bool read()
Read thermophysicalTransport dictionary.
Definition: anisotropic.C:215
virtual tmp< fvScalarMatrix > divq(volScalarField &he) const
Return the source term for the energy equation.
Definition: anisotropic.C:440
void enableCache(const word &name) const
Enable caching of the given field.
Definition: solution.C:137
A class for managing temporary objects.
Definition: tmp.H:55
A class for handling words, derived from string.
Definition: word.H:63
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:381
Calculate the laplacian of the given field.
Calculate the snGrad of the given volField.
Calculate the matrix for the laplacian of the field.
const polyBoundaryMesh & bMesh
label patchi
const fvPatchList & patches
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
tmp< VolField< Type > > laplacian(const VolField< Type > &vf, const word &name)
Definition: fvcLaplacian.C:45
tmp< VolField< typename outerProduct< vector, Type >::type > > grad(const SurfaceField< Type > &ssf)
Definition: fvcGrad.C:46
tmp< fvMatrix< Type > > laplacian(const VolField< Type > &vf, const word &name)
Definition: fvmLaplacian.C:47
tmp< fvMatrix< Type > > laplacianCorrection(const VolField< scalar > &gamma, const VolField< Type > &vf)
Definition: fvmLaplacian.C:340
static const zero Zero
Definition: zero.H:97
const doubleScalar e
Definition: doubleScalar.H:106
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
messageStream Info
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
Type gSum(const UList< Type > &f, const label comm)
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< symmTensor > dimensionedSymmTensor
Dimensioned tensor obtained from generic dimensioned type.
Field< vector > vectorField
Specialisation of Field<T> for vector.
Field< symmTensor > symmTensorField
Specialisation of Field<T> for symmTensor.
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
void T(GeometricField< Type, GeoMesh, PrimitiveField1 > &gf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf1)
static const char nl
Definition: Ostream.H:297
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
faceListList boundary(nPatches)
dictionary dict
fluidMulticomponentThermo & thermo
Definition: createFields.H:15