mapFields.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 | Copyright (C) 2011-2015 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 Application
25  mapFields
26 
27 Description
28  Maps volume fields from one mesh to another, reading and
29  interpolating all fields present in the time directory of both cases.
30 
31  Parallel and non-parallel cases are handled without the need to reconstruct
32  them first.
33 
34 \*---------------------------------------------------------------------------*/
35 
36 #include "fvCFD.H"
37 #include "meshToMesh0.H"
38 #include "processorFvPatch.H"
39 #include "MapMeshes.H"
40 #include "decompositionModel.H"
41 
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 
44 int readNumProcs
45 (
46  const argList& args,
47  const word& optionName,
48  const Time& runTime
49 )
50 {
51  fileName dictFile;
52  if (args.optionReadIfPresent(optionName, dictFile))
53  {
54  if (isDir(dictFile))
55  {
56  dictFile = dictFile/"decomposeParDict";
57  }
58  }
59 
60  return readInt
61  (
62  IOdictionary
63  (
64  decompositionModel::selectIO
65  (
66  IOobject
67  (
68  "decomposeParDict",
69  runTime.system(),
70  runTime,
71  IOobject::MUST_READ_IF_MODIFIED,
72  IOobject::NO_WRITE,
73  false
74  ),
75  dictFile
76  )
77  ).lookup("numberOfSubdomains")
78  );
79 }
80 
81 
82 void mapConsistentMesh
83 (
84  const fvMesh& meshSource,
85  const fvMesh& meshTarget,
86  const meshToMesh0::order& mapOrder,
87  const bool subtract
88 )
89 {
90  if (subtract)
91  {
92  MapConsistentMesh<minusEqOp>
93  (
94  meshSource,
95  meshTarget,
96  mapOrder
97  );
98  }
99  else
100  {
101  MapConsistentMesh<eqOp>
102  (
103  meshSource,
104  meshTarget,
105  mapOrder
106  );
107  }
108 }
109 
110 
111 void mapSubMesh
112 (
113  const fvMesh& meshSource,
114  const fvMesh& meshTarget,
115  const HashTable<word>& patchMap,
116  const wordList& cuttingPatches,
117  const meshToMesh0::order& mapOrder,
118  const bool subtract
119 )
120 {
121  if (subtract)
122  {
123  MapSubMesh<minusEqOp>
124  (
125  meshSource,
126  meshTarget,
127  patchMap,
128  cuttingPatches,
129  mapOrder
130  );
131  }
132  else
133  {
134  MapSubMesh<eqOp>
135  (
136  meshSource,
137  meshTarget,
138  patchMap,
139  cuttingPatches,
140  mapOrder
141  );
142  }
143 }
144 
145 
146 void mapConsistentSubMesh
147 (
148  const fvMesh& meshSource,
149  const fvMesh& meshTarget,
150  const meshToMesh0::order& mapOrder,
151  const bool subtract
152 )
153 {
154  if (subtract)
155  {
156  MapConsistentSubMesh<minusEqOp>
157  (
158  meshSource,
159  meshTarget,
160  mapOrder
161  );
162  }
163  else
164  {
165  MapConsistentSubMesh<eqOp>
166  (
167  meshSource,
168  meshTarget,
169  mapOrder
170  );
171  }
172 }
173 
174 
175 wordList addProcessorPatches
176 (
177  const fvMesh& meshTarget,
178  const wordList& cuttingPatches
179 )
180 {
181  // Add the processor patches to the cutting list
182  HashTable<label> cuttingPatchTable;
183  forAll(cuttingPatches, i)
184  {
185  cuttingPatchTable.insert(cuttingPatches[i], i);
186  }
187 
188  forAll(meshTarget.boundary(), patchi)
189  {
190  if (isA<processorFvPatch>(meshTarget.boundary()[patchi]))
191  {
192  if
193  (
194  !cuttingPatchTable.found
195  (
196  meshTarget.boundaryMesh()[patchi].name()
197  )
198  )
199  {
200  cuttingPatchTable.insert
201  (
202  meshTarget.boundaryMesh()[patchi].name(),
203  -1
204  );
205  }
206  }
207  }
208 
209  return cuttingPatchTable.toc();
210 }
211 
212 
213 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
214 
215 int main(int argc, char *argv[])
216 {
217  argList::addNote
218  (
219  "map volume fields from one mesh to another"
220  );
221  argList::noParallel();
222  argList::validArgs.append("sourceCase");
223 
224  argList::addOption
225  (
226  "sourceTime",
227  "scalar|'latestTime'",
228  "specify the source time"
229  );
230  argList::addOption
231  (
232  "sourceRegion",
233  "word",
234  "specify the source region"
235  );
236  argList::addOption
237  (
238  "targetRegion",
239  "word",
240  "specify the target region"
241  );
242  argList::addBoolOption
243  (
244  "parallelSource",
245  "the source is decomposed"
246  );
247  argList::addBoolOption
248  (
249  "parallelTarget",
250  "the target is decomposed"
251  );
252  argList::addBoolOption
253  (
254  "consistent",
255  "source and target geometry and boundary conditions identical"
256  );
257  argList::addOption
258  (
259  "mapMethod",
260  "word",
261  "specify the mapping method"
262  );
263  argList::addBoolOption
264  (
265  "subtract",
266  "subtract mapped source from target"
267  );
268  argList::addOption
269  (
270  "sourceDecomposeParDict",
271  "file",
272  "read decomposePar dictionary from specified location"
273  );
274  argList::addOption
275  (
276  "targetDecomposeParDict",
277  "file",
278  "read decomposePar dictionary from specified location"
279  );
280 
281 
282  argList args(argc, argv);
283 
284  if (!args.check())
285  {
286  FatalError.exit();
287  }
288 
289  fileName rootDirTarget(args.rootPath());
290  fileName caseDirTarget(args.globalCaseName());
291 
292  const fileName casePath = args[1];
293  const fileName rootDirSource = casePath.path();
294  const fileName caseDirSource = casePath.name();
295 
296  Info<< "Source: " << rootDirSource << " " << caseDirSource << endl;
297  word sourceRegion = fvMesh::defaultRegion;
298  if (args.optionFound("sourceRegion"))
299  {
300  sourceRegion = args["sourceRegion"];
301  Info<< "Source region: " << sourceRegion << endl;
302  }
303 
304  Info<< "Target: " << rootDirTarget << " " << caseDirTarget << endl;
305  word targetRegion = fvMesh::defaultRegion;
306  if (args.optionFound("targetRegion"))
307  {
308  targetRegion = args["targetRegion"];
309  Info<< "Target region: " << targetRegion << endl;
310  }
311 
312  const bool parallelSource = args.optionFound("parallelSource");
313  const bool parallelTarget = args.optionFound("parallelTarget");
314  const bool consistent = args.optionFound("consistent");
315 
316  meshToMesh0::order mapOrder = meshToMesh0::INTERPOLATE;
317  if (args.optionFound("mapMethod"))
318  {
319  const word mapMethod(args["mapMethod"]);
320  if (mapMethod == "mapNearest")
321  {
322  mapOrder = meshToMesh0::MAP;
323  }
324  else if (mapMethod == "interpolate")
325  {
326  mapOrder = meshToMesh0::INTERPOLATE;
327  }
328  else if (mapMethod == "cellPointInterpolate")
329  {
330  mapOrder = meshToMesh0::CELL_POINT_INTERPOLATE;
331  }
332  else
333  {
335  << "Unknown mapMethod " << mapMethod << ". Valid options are: "
336  << "mapNearest, interpolate and cellPointInterpolate"
337  << exit(FatalError);
338  }
339 
340  Info<< "Mapping method: " << mapMethod << endl;
341  }
342 
343  const bool subtract = args.optionFound("subtract");
344  if (subtract)
345  {
346  Info<< "Subtracting mapped source field from target" << endl;
347  }
348 
349 
350  #include "createTimes.H"
351 
352  HashTable<word> patchMap;
353  wordList cuttingPatches;
354 
355  if (!consistent)
356  {
357  IOdictionary mapFieldsDict
358  (
359  IOobject
360  (
361  "mapFieldsDict",
362  runTimeTarget.system(),
364  IOobject::MUST_READ_IF_MODIFIED,
365  IOobject::NO_WRITE,
366  false
367  )
368  );
369 
370  mapFieldsDict.lookup("patchMap") >> patchMap;
371  mapFieldsDict.lookup("cuttingPatches") >> cuttingPatches;
372  }
373 
374  if (parallelSource && !parallelTarget)
375  {
376  int nProcs = readNumProcs
377  (
378  args,
379  "sourceDecomposeParDict",
381  );
382 
383  Info<< "Create target mesh\n" << endl;
384 
385  fvMesh meshTarget
386  (
387  IOobject
388  (
389  targetRegion,
390  runTimeTarget.timeName(),
392  )
393  );
394 
395  Info<< "Target mesh size: " << meshTarget.nCells() << endl;
396 
397  for (int procI=0; procI<nProcs; procI++)
398  {
399  Info<< nl << "Source processor " << procI << endl;
400 
401  Time runTimeSource
402  (
403  Time::controlDictName,
404  rootDirSource,
405  caseDirSource/fileName(word("processor") + name(procI))
406  );
407 
408  #include "setTimeIndex.H"
409 
410  fvMesh meshSource
411  (
412  IOobject
413  (
414  sourceRegion,
415  runTimeSource.timeName(),
417  )
418  );
419 
420  Info<< "mesh size: " << meshSource.nCells() << endl;
421 
422  if (consistent)
423  {
424  mapConsistentSubMesh
425  (
426  meshSource,
427  meshTarget,
428  mapOrder,
429  subtract
430  );
431  }
432  else
433  {
434  mapSubMesh
435  (
436  meshSource,
437  meshTarget,
438  patchMap,
439  cuttingPatches,
440  mapOrder,
441  subtract
442  );
443  }
444  }
445  }
446  else if (!parallelSource && parallelTarget)
447  {
448  int nProcs = readNumProcs
449  (
450  args,
451  "targetDecomposeParDict",
453  );
454 
455 
456  Info<< "Create source mesh\n" << endl;
457 
458  #include "setTimeIndex.H"
459 
460  fvMesh meshSource
461  (
462  IOobject
463  (
464  sourceRegion,
465  runTimeSource.timeName(),
467  )
468  );
469 
470  Info<< "Source mesh size: " << meshSource.nCells() << endl;
471 
472  for (int procI=0; procI<nProcs; procI++)
473  {
474  Info<< nl << "Target processor " << procI << endl;
475 
476  Time runTimeTarget
477  (
478  Time::controlDictName,
479  rootDirTarget,
480  caseDirTarget/fileName(word("processor") + name(procI))
481  );
482 
483  fvMesh meshTarget
484  (
485  IOobject
486  (
487  targetRegion,
488  runTimeTarget.timeName(),
490  )
491  );
492 
493  Info<< "mesh size: " << meshTarget.nCells() << endl;
494 
495  if (consistent)
496  {
497  mapConsistentSubMesh
498  (
499  meshSource,
500  meshTarget,
501  mapOrder,
502  subtract
503  );
504  }
505  else
506  {
507  mapSubMesh
508  (
509  meshSource,
510  meshTarget,
511  patchMap,
512  addProcessorPatches(meshTarget, cuttingPatches),
513  mapOrder,
514  subtract
515  );
516  }
517  }
518  }
519  else if (parallelSource && parallelTarget)
520  {
521  int nProcsSource = readNumProcs
522  (
523  args,
524  "sourceDecomposeParDict",
526  );
527  int nProcsTarget = readNumProcs
528  (
529  args,
530  "targetDecomposeParDict",
532  );
533 
534  List<boundBox> bbsTarget(nProcsTarget);
535  List<bool> bbsTargetSet(nProcsTarget, false);
536 
537  for (int procISource=0; procISource<nProcsSource; procISource++)
538  {
539  Info<< nl << "Source processor " << procISource << endl;
540 
541  Time runTimeSource
542  (
543  Time::controlDictName,
544  rootDirSource,
545  caseDirSource/fileName(word("processor") + name(procISource))
546  );
547 
548  #include "setTimeIndex.H"
549 
550  fvMesh meshSource
551  (
552  IOobject
553  (
554  sourceRegion,
555  runTimeSource.timeName(),
557  )
558  );
559 
560  Info<< "mesh size: " << meshSource.nCells() << endl;
561 
562  boundBox bbSource(meshSource.bounds());
563 
564  for (int procITarget=0; procITarget<nProcsTarget; procITarget++)
565  {
566  if
567  (
568  !bbsTargetSet[procITarget]
569  || (
570  bbsTargetSet[procITarget]
571  && bbsTarget[procITarget].overlaps(bbSource)
572  )
573  )
574  {
575  Info<< nl << "Target processor " << procITarget << endl;
576 
577  Time runTimeTarget
578  (
579  Time::controlDictName,
580  rootDirTarget,
581  caseDirTarget/fileName(word("processor")
582  + name(procITarget))
583  );
584 
585  fvMesh meshTarget
586  (
587  IOobject
588  (
589  targetRegion,
590  runTimeTarget.timeName(),
592  )
593  );
594 
595  Info<< "mesh size: " << meshTarget.nCells() << endl;
596 
597  bbsTarget[procITarget] = meshTarget.bounds();
598  bbsTargetSet[procITarget] = true;
599 
600  if (bbsTarget[procITarget].overlaps(bbSource))
601  {
602  if (consistent)
603  {
604  mapConsistentSubMesh
605  (
606  meshSource,
607  meshTarget,
608  mapOrder,
609  subtract
610  );
611  }
612  else
613  {
614  mapSubMesh
615  (
616  meshSource,
617  meshTarget,
618  patchMap,
619  addProcessorPatches(meshTarget, cuttingPatches),
620  mapOrder,
621  subtract
622  );
623  }
624  }
625  }
626  }
627  }
628  }
629  else
630  {
631  #include "setTimeIndex.H"
632 
633  Info<< "Create meshes\n" << endl;
634 
635  fvMesh meshSource
636  (
637  IOobject
638  (
639  sourceRegion,
640  runTimeSource.timeName(),
642  )
643  );
644 
645  fvMesh meshTarget
646  (
647  IOobject
648  (
649  targetRegion,
650  runTimeTarget.timeName(),
652  )
653  );
654 
655  Info<< "Source mesh size: " << meshSource.nCells() << tab
656  << "Target mesh size: " << meshTarget.nCells() << nl << endl;
657 
658  if (consistent)
659  {
660  mapConsistentMesh(meshSource, meshTarget, mapOrder, subtract);
661  }
662  else
663  {
664  mapSubMesh
665  (
666  meshSource,
667  meshTarget,
668  patchMap,
669  cuttingPatches,
670  mapOrder,
671  subtract
672  );
673  }
674  }
675 
676  Info<< "\nEnd\n" << endl;
677 
678  return 0;
679 }
680 
681 
682 // ************************************************************************* //
Foam::subtract
void subtract(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:871
processorFvPatch.H
meshToMesh0.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::argList::rootPath
const fileName & rootPath() const
Return root path.
Definition: argListI.H:36
Foam::fileName::name
word name() const
Return file name (part beyond last /)
Definition: fileName.C:212
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:54
Foam::readInt
int readInt(Istream &)
Definition: intIO.C:31
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
main
int main(int argc, char *argv[])
Definition: postCalc.C:54
Foam::argList::path
fileName path() const
Return the path to the caseName.
Definition: argListI.H:60
Foam::FatalError
error FatalError
Foam::isDir
bool isDir(const fileName &)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:615
Foam::error::exit
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
Definition: error.C:165
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::tab
static const char tab
Definition: Ostream.H:259
patchi
label patchi
Definition: getPatchFieldScalar.H:1
runTimeSource
Time runTimeSource(Time::controlDictName, argsSrc)
Foam::argList::optionFound
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
fvCFD.H
decompositionModel.H
List
Definition: Test.C:19
args
Foam::argList args(argc, argv)
runTimeTarget
Time runTimeTarget(Time::controlDictName, args)
Foam::argList::optionReadIfPresent
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:198
Foam::argList::globalCaseName
const fileName & globalCaseName() const
Return case name.
Definition: argListI.H:48
Foam::argList::check
bool check(bool checkArgs=true, bool checkOpts=true) const
Check argument list.
Definition: argList.C:1184
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47