findRefCells.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016,2025 OpenCFD Ltd.
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 "findRefCell.H"
30 #include "regionSplit.H"
31 
32 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
33 
35 (
36  const volScalarField& field,
37  const volScalarField& fieldRef,
38  const dictionary& dict,
39  boolList& regionNeedReference,
40  labelList& regionRefCells,
41  scalarField& regionRefValues,
42  const bool forceReference
43 )
44 {
45  const regionSplit& regions = regionSplit::New(field.mesh());
46 
47  regionNeedReference.setSize(regions.nRegions(), true);
48  regionRefCells.setSize(regions.nRegions(), -1);
49  regionRefValues.setSize(regions.nRegions(), 0);
50 
51  if (!forceReference)
52  {
53  const volScalarField::GeometricBoundaryField& bfld =
54  fieldRef.boundaryField();
55 
56  forAll(bfld, patchI)
57  {
58  if (bfld[patchI].fixesValue())
59  {
60  // Unmark all regions
61 
62  const labelUList& fc = bfld[patchI].patch().patch().faceCells();
63 
64  forAll(fc, faceI)
65  {
66  regionNeedReference[regions[fc[faceI]]] = false;
67  }
68  }
69  }
70 
71  Pstream::listCombineReduce(regionNeedReference, orEqOp<bool>());
72  }
73 
74 
75  label nRefs = 0;
76  forAll(regionNeedReference, regionI)
77  {
78  if (regionNeedReference[regionI])
79  {
80  nRefs++;
81  }
82  }
83 
84  if (nRefs == 0)
85  {
86  return;
87  }
88 
89  // Get the reference cells for all the regions
90 
91  word refCellName = field.name() + "RefCells";
92  word refPointName = field.name() + "RefPoints";
93  word refValueName = field.name() + "RefValues";
94 
95 
96  // (per region!) does region have reference cell?
97  labelList hasRef(regionNeedReference.size(), Zero);
98 
99 
100  const labelList refValues(dict.lookup(refValueName));
101 
102 
103  if (dict.found(refCellName))
104  {
105  // Have specified reference cells (on master!)
106 
107  if (Pstream::master())
108  {
109  labelList refCells(dict.lookup(refCellName));
110 
111  if (refCells.size() != regionNeedReference.size())
112  {
114  << "Number of refCells " << refCells.size()
115  << " does not correspond to number of regions "
116  << regionNeedReference.size()
117  << exit(FatalIOError);
118  }
119 
120  forAll(refCells, i)
121  {
122  label regionI = regions[refCells[i]];
123 
124  if (regionNeedReference[regionI])
125  {
126  regionRefCells[regionI] = refCells[i];
127  regionRefValues[regionI] = refValues[i];
128  }
129  }
130 
131 
132  forAll(regionNeedReference, regionI)
133  {
134  if
135  (
136  regionNeedReference[regionI]
137  && regionRefCells[regionI] == -1
138  )
139  {
141  << "Have no reference cell for region " << regionI
142  << nl
143  << "Overall per-region reference cells "
144  << regionRefCells
145  << exit(FatalIOError);
146  }
147  }
148  }
149  }
150  else if (dict.found(refPointName))
151  {
152  pointField refPoints(dict.lookup(refPointName));
153 
154  if (refPoints.size() != regionNeedReference.size())
155  {
157  << "Number of refPoints " << refPoints.size()
158  << " does not correspond to number of regions "
159  << regionNeedReference.size()
160  << exit(FatalIOError);
161  }
162 
163  labelList hasRef(refPoints.size(), Zero);
164 
165  forAll(refPoints, i)
166  {
167  // Note: find reference cell using facePlanes to avoid constructing
168  // face decomposition structure. Most likely the reference
169  // cell is an undistorted one so this should not be a
170  // problem.
171 
172  label celli = field.mesh().findCell
173  (
174  refPoints[i],
175  polyMesh::FACEPLANES
176  );
177 
178  if (celli >= 0)
179  {
180  Pout<< "Found point " << refPoints[i]
181  << " in reference cell " << celli
182  << " at " << field.mesh().cellCentres()[celli]
183  << " for region " << regions[celli]
184  << endl;
185 
186  regionRefCells[regions[celli]] = celli;
187  hasRef[regions[celli]] = 1;
188  }
189  }
190 
191  Pstream::listReduce(hasRef, sumOp<label>());
192 
193  forAll(hasRef, regionI)
194  {
195  if (hasRef[regionI] != 1)
196  {
198  << "Unable to set reference cell for field " << field.name()
199  << nl
200  << " Reference points " << refPointName
201  << " " << refPoints
202  << nl << " For region " << regionI
203  << " found on " << hasRef[regionI]
204  << " domains (should be one)"
205  << nl << exit(FatalIOError);
206  }
207  }
208  }
209  else
210  {
212  << "Unable to set reference cell for field " << field.name()
213  << nl
214  << " Please supply either " << refCellName
215  << " or " << refPointName << nl << exit(FatalIOError);
216  }
217 }
218 
219 
220 // ************************************************************************* //
dictionary dict
rDeltaTY field()
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:518
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
Find the reference cell nearest (in index) to the given cell but which is not on a cyclic...
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:72
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void setRefCells(const volScalarField &field, const volScalarField &fieldRef, const dictionary &dict, const label refCelli, const scalar refValue, boolList &needReference, labelList &refCells, scalarField &refValues, const bool forceReference=false)
Set reference cells for multi-region domains. Returns per region:
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:681
List< label > labelList
A List of labels.
Definition: List.H:61
List< bool > boolList
A List of bools.
Definition: List.H:59
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127