mapLagrangian.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-2017 OpenFOAM Foundation
9  Copyright (C) 2018-2019 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 "MapLagrangianFields.H"
30 #include "passiveParticleCloud.H"
31 #include "meshSearch.H"
32 
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37 
38 static const scalar perturbFactor = 1e-6;
39 
40 
41 // Special version of findCell that generates a cell guaranteed to be
42 // compatible with tracking.
43 static label findCell(const Cloud<passiveParticle>& cloud, const point& pt)
44 {
45  label celli = -1;
46  label tetFacei = -1;
47  label tetPtI = -1;
48 
49  const polyMesh& mesh = cloud.pMesh();
50 
51  mesh.findCellFacePt(pt, celli, tetFacei, tetPtI);
52 
53  if (celli >= 0)
54  {
55  return celli;
56  }
57  else
58  {
59  // See if particle on face by finding nearest face and shifting
60  // particle.
61 
62  meshSearch meshSearcher
63  (
64  mesh,
65  polyMesh::FACE_PLANES // no decomposition needed
66  );
67 
68  label facei = meshSearcher.findNearestBoundaryFace(pt);
69 
70  if (facei >= 0)
71  {
72  const point& cc = mesh.cellCentres()[mesh.faceOwner()[facei]];
73 
74  const point perturbPt = (1-perturbFactor)*pt+perturbFactor*cc;
75 
76  mesh.findCellFacePt(perturbPt, celli, tetFacei, tetPtI);
77 
78  return celli;
79  }
80  }
81 
82  return -1;
83 }
84 
85 
86 void mapLagrangian(const meshToMesh& interp)
87 {
88  // Determine which particles are in meshTarget
89  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
90 
91  const polyMesh& meshSource = interp.srcRegion();
92  const polyMesh& meshTarget = interp.tgtRegion();
93  const labelListList& sourceToTarget = interp.srcToTgtCellAddr();
94 
95  const fileNameList cloudDirs
96  (
97  readDir
98  (
99  meshSource.time().timePath()/cloud::prefix,
101  )
102  );
103 
104  for (const fileName& cloudDir : cloudDirs)
105  {
106  // Search for list of lagrangian objects for this time
107  IOobjectList objects
108  (
109  meshSource,
110  meshSource.time().timeName(),
111  cloud::prefix/cloudDir
112  );
113 
114  if
115  (
117  (
118  (objects.found("coordinates") || objects.found("positions")),
119  orOp<bool>()
120  )
121  )
122  {
123  // Has coordinates/positions - so must be a valid cloud
124  Info<< nl << " processing cloud " << cloudDir << endl;
125 
126  // Read positions & cell
127  passiveParticleCloud sourceParcels
128  (
129  meshSource,
130  cloudDir,
131  false
132  );
133  Info<< " read " << sourceParcels.size()
134  << " parcels from source mesh." << endl;
135 
136  // Construct empty target cloud
137  passiveParticleCloud targetParcels
138  (
139  meshTarget,
140  cloudDir,
141  IDLList<passiveParticle>()
142  );
143 
144  passiveParticle::trackingData td(targetParcels);
145 
146  label sourceParticleI = 0;
147 
148  // Indices of source particles that get added to targetParcels
149  DynamicList<label> addParticles(sourceParcels.size());
150 
151  // Unmapped particles
152  labelHashSet unmappedSource(sourceParcels.size());
153 
154 
155  // Initial: track from fine-mesh cell centre to particle position
156  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157  // This requires there to be no boundary in the way.
158 
159 
160  for (const passiveParticle& p : sourceParcels)
161  {
162  bool foundCell = false;
163 
164  // Assume that cell from read parcel is the correct one...
165  if (p.cell() >= 0)
166  {
167  const labelList& targetCells =
168  sourceToTarget[p.cell()];
169 
170  // Particle probably in one of the targetcells. Try
171  // all by tracking from their cell centre to the parcel
172  // position.
173 
174  for (const label targetCell : targetCells)
175  {
176  // Track from its cellcentre to position to make sure.
177  autoPtr<passiveParticle> newPtr
178  (
179  new passiveParticle
180  (
181  meshTarget,
182  barycentric(1, 0, 0, 0),
183  targetCell,
184  meshTarget.cells()[targetCell][0],
185  1
186  )
187  );
188  passiveParticle& newP = newPtr();
189 
190  newP.track(p.position() - newP.position(), 0);
191 
192  if (!newP.onFace())
193  {
194  // Hit position.
195  foundCell = true;
196  addParticles.append(sourceParticleI);
197  targetParcels.addParticle(newPtr.ptr());
198  break;
199  }
200  }
201  }
202 
203  if (!foundCell)
204  {
205  // Store for closer analysis
206  unmappedSource.insert(sourceParticleI);
207  }
208 
209  sourceParticleI++;
210  }
211 
212  Info<< " after meshToMesh addressing found "
213  << targetParcels.size()
214  << " parcels in target mesh." << endl;
215 
216 
217  // Do closer inspection for unmapped particles
218  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219 
220  if (unmappedSource.size())
221  {
222  sourceParticleI = 0;
223 
224  for (passiveParticle& p : sourceParcels)
225  {
226  if (unmappedSource.found(sourceParticleI))
227  {
228  const label targetCell =
229  findCell(targetParcels, p.position());
230 
231  if (targetCell >= 0)
232  {
233  unmappedSource.erase(sourceParticleI);
234  addParticles.append(sourceParticleI);
235  targetParcels.addParticle
236  (
237  new passiveParticle
238  (
239  meshTarget,
240  p.position(),
241  targetCell
242  )
243  );
244  sourceParcels.remove(&p);
245  }
246  }
247  sourceParticleI++;
248  }
249  }
250  addParticles.shrink();
251 
252  Info<< " after additional mesh searching found "
253  << targetParcels.size() << " parcels in target mesh." << endl;
254 
255  if (addParticles.size())
256  {
257  IOPosition<passiveParticleCloud>(targetParcels).write();
258 
259  // addParticles now contains the indices of the sourceMesh
260  // particles that were appended to the target mesh.
261 
262  // Map lagrangian fields
263  // ~~~~~~~~~~~~~~~~~~~~~
264 
265  MapLagrangianFields<label>
266  (
267  cloudDir,
268  objects,
269  meshTarget,
270  addParticles
271  );
272  MapLagrangianFields<scalar>
273  (
274  cloudDir,
275  objects,
276  meshTarget,
277  addParticles
278  );
279  MapLagrangianFields<vector>
280  (
281  cloudDir,
282  objects,
283  meshTarget,
284  addParticles
285  );
286  MapLagrangianFields<sphericalTensor>
287  (
288  cloudDir,
289  objects,
290  meshTarget,
291  addParticles
292  );
293  MapLagrangianFields<symmTensor>
294  (
295  cloudDir,
296  objects,
297  meshTarget,
298  addParticles
299  );
300  MapLagrangianFields<tensor>
301  (
302  cloudDir,
303  objects,
304  meshTarget,
305  addParticles
306  );
307  }
308  }
309  }
310 }
311 
312 
313 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
314 
315 } // End namespace Foam
316 
317 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::cloud::prefix
static const word prefix
The prefix to local: lagrangian.
Definition: cloud.H:87
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
Foam::polyMesh::findCellFacePt
void findCellFacePt(const point &p, label &celli, label &tetFacei, label &tetPti) const
Find the cell, tetFacei and tetPti for point p.
Definition: polyMesh.C:1356
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::fileNameList
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:58
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:84
meshSearch.H
Foam::nl
constexpr char nl
Definition: Ostream.H:404
passiveParticleCloud.H
Foam::mapLagrangian
void mapLagrangian(const meshToMesh0 &meshToMesh0Interp)
Maps lagrangian positions and fields.
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::fileName::DIRECTORY
A directory.
Definition: fileName.H:84
Foam::polyMesh::FACE_PLANES
Definition: polyMesh.H:102
Foam::barycentric
Barycentric< scalar > barycentric
A scalar version of the templated Barycentric.
Definition: barycentric.H:47
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
Foam::readDir
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: MSwindows.C:707