cellsToCellsStabilisation.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) 2023 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 
27 #include "syncTools.H"
28 #include "wallPoint.H"
29 #include "WallLocationData.H"
30 #include "WallInfo.H"
31 #include "FaceCellWave.H"
32 #include "globalIndex.H"
33 #include "OBJstream.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
40 }
41 
42 
43 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 
46 :
47  stabilisation_(false),
48  localStabilisationCells_(),
49  stabilisationMapPtr_(nullptr)
50 {}
51 
52 
53 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
54 
56 {}
57 
58 
59 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
60 
62 (
63  const polyMesh& mesh,
64  const PackedBoolList& cellCoupleds
65 )
66 {
67  // Determine whether or not stabilisation is necessary
68  stabilisation_ = false;
69  forAll(cellCoupleds, celli)
70  {
71  if (!cellCoupleds[celli])
72  {
73  stabilisation_ = true;
74  break;
75  }
76  }
77  reduce(stabilisation_, orOp<bool>());
78 
79  // Quick return if nothing is to be done
80  if (!stabilisation_) return;
81 
82  // Get some information regarding the cells on the other side of couplings
83  List<remote> bFaceNbrProcCells(mesh.nFaces() - mesh.nInternalFaces());
84  boolList bFaceNbrIsCoupled(mesh.nFaces() - mesh.nInternalFaces());
85  forAll(bFaceNbrIsCoupled, bFacei)
86  {
87  const label owni = mesh.faceOwner()[bFacei + mesh.nInternalFaces()];
88  bFaceNbrProcCells[bFacei] = remote(Pstream::myProcNo(), owni);
89  bFaceNbrIsCoupled[bFacei] = cellCoupleds[owni];
90  }
91  syncTools::swapBoundaryFaceList(mesh, bFaceNbrProcCells);
92  syncTools::swapBoundaryFaceList(mesh, bFaceNbrIsCoupled);
93 
94  // Determine the "cut" faces that separate coupled and un-coupled cellS
96  DynamicList<label> cutFaces;
97  DynamicList<info> cutFaceInfos;
98  for (label facei = 0; facei < mesh.nFaces(); ++ facei)
99  {
100  const label owni = mesh.faceOwner()[facei];
101  const bool ownIsCoupled = cellCoupleds[owni];
102 
103  if (facei < mesh.nInternalFaces())
104  {
105  const label nbri = mesh.faceNeighbour()[facei];
106  const bool nbrIsCoupled = cellCoupleds[nbri];
107 
108  if (ownIsCoupled != nbrIsCoupled)
109  {
110  const label celli = ownIsCoupled ? owni : nbri;
111 
112  cutFaces.append(facei);
113  cutFaceInfos.append
114  (
115  info
116  (
117  remote(Pstream::myProcNo(), celli),
118  mesh.faceCentres()[facei],
119  0
120  )
121  );
122  }
123  }
124  else
125  {
126  const label bFacei = facei - mesh.nInternalFaces();
127 
128  const bool nbrIsCoupled = bFaceNbrIsCoupled[bFacei];
129 
130  if (!ownIsCoupled && nbrIsCoupled)
131  {
132  cutFaces.append(facei);
133  cutFaceInfos.append
134  (
135  info
136  (
137  bFaceNbrProcCells[bFacei],
138  mesh.faceCentres()[facei],
139  0
140  )
141  );
142  }
143  }
144  }
145 
146  // Wave the information about the cut faces' connected coupled cells into
147  // the un-coupled cells. Base this wave on distance to the cut face.
148  // Initialise coupled cells to have a distance of zero, so that we do not
149  // waste time waving into coupled regions of the mesh.
150  List<info> faceInfos(mesh.nFaces()), cellInfos(mesh.nCells());
151  forAll(cellCoupleds, celli)
152  {
153  if (cellCoupleds[celli])
154  {
155  cellInfos[celli] =
156  info
157  (
158  remote(Pstream::myProcNo(), celli),
159  mesh.cellCentres()[celli],
160  0
161  );
162  }
163  }
165  (
166  mesh,
167  cutFaces,
168  cutFaceInfos,
169  faceInfos,
170  cellInfos,
171  mesh.globalData().nTotalCells() + 1 // max iterations
172  );
173 
174  // Check that the wave connected to all un-coupled cells
175  forAll(cellCoupleds, celli)
176  {
177  if (!cellCoupleds[celli] && !cellInfos[celli].valid(wave.data()))
178  {
180  << "Un-coupled cell " << celli << " of mesh " << mesh.name()
181  << " on processor " << Pstream::myProcNo() << " with centre "
182  << "at " << mesh.cellCentres()[celli] << " was not connected "
183  << "to a coupled cell by the stabilisation wave. This "
184  << "indicates that an entire non-contiguous region of mesh "
185  << "lies outside of the other mesh being mapped to. This is "
186  << "not recoverable." << exit(FatalError);
187  }
188  }
189 
190  // Construct the cell to local stabilisation cell map
191  const globalIndex cellGlobalIndex(mesh.nCells());
192  localStabilisationCells_.resize(mesh.nCells());
193  forAll(cellCoupleds, celli)
194  {
195  const remote& r = cellInfos[celli].data();
196  localStabilisationCells_[celli] =
197  cellCoupleds[celli]
198  ? cellGlobalIndex.toGlobal(celli)
199  : cellGlobalIndex.toGlobal(r.proci, r.elementi);
200  }
201 
202  // Construct the distribution map, if necessary
203  if (Pstream::parRun())
204  {
205  List<Map<label>> compactMap;
206  stabilisationMapPtr_.reset
207  (
208  new distributionMap
209  (
210  cellGlobalIndex,
211  localStabilisationCells_,
212  compactMap
213  )
214  );
215  }
216 
217  // Write out stabilisation connections
218  if (debug)
219  {
220  OBJstream obj
221  (
222  typeName + "_" + mesh.name()
223  + (Pstream::parRun() ? "_proc" + name(Pstream::myProcNo()) : "")
224  + "_connections.obj"
225  );
226 
227  pointField ccs(mesh.cellCentres());
228  stabilise(ccs);
229 
230  forAll(ccs, celli)
231  {
232  const point& c = mesh.cellCentres()[celli];
233  if (magSqr(c - ccs[celli]) == 0) continue;
234  obj.write(linePointRef(ccs[celli], c));
235  }
236  }
237 }
238 
239 
240 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:79
const word & name() const
Return name.
Definition: IOobject.H:310
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
OFstream which keeps track of vertices.
Definition: OBJstream.H:56
virtual Ostream & write(const char)
Write character.
Definition: OBJstream.C:81
A bit-packed bool list.
T * data()
Return a pointer to the first data element,.
Definition: UListI.H:149
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
Holds information regarding nearest wall point. Used in wall distance calculation.
Definition: WallInfo.H:58
Stabilisation data and routines for cell-to-cell interpolations.
void update(const polyMesh &mesh, const PackedBoolList &cellCoupleds)
Compute the stabilisation addressing if necessary.
Class containing processor-to-processor mapping information.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
label toGlobal(const label i) const
From local to global.
Definition: globalIndexI.H:82
label nTotalCells() const
Return total number of cells in decomposed mesh.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1387
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1563
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1393
label nCells() const
const vectorField & faceCentres() const
const vectorField & cellCentres() const
label nInternalFaces() const
label nFaces() const
Struct for keeping processor, element (cell, face, point) index.
Definition: remote.H:57
label elementi
Element index.
Definition: remote.H:66
label proci
Processor index.
Definition: remote.H:63
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled boundary face values.
Definition: syncTools.H:436
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
bool valid(const PtrList< ModelType > &l)
const dimensionedScalar c
Speed of light in a vacuum.
label wave(const fvMesh &mesh, const List< labelPair > &changedPatchAndFaces, const label nCorrections, GeometricField< scalar, PatchField, GeoMesh > &distance, TrackingData &td, GeometricField< DataType, PatchField, GeoMesh > &... data)
Wave distance (and maybe additional) data from faces. If nCorrections is.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
tmp< DimensionedField< scalar, GeoMesh > > stabilise(const DimensionedField< scalar, GeoMesh > &dsf, const dimensioned< scalar > &ds)
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
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
defineTypeNameAndDebug(combustionModel, 0)
error FatalError
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
dimensioned< scalar > magSqr(const dimensioned< Type > &)