decomposePar.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  decomposePar
26 
27 Description
28  Automatically decomposes a mesh and fields of a case for parallel
29  execution of OpenFOAM.
30 
31 Usage
32 
33  - decomposePar [OPTION]
34 
35  \param -cellDist \n
36  Write the cell distribution as a labelList, for use with 'manual'
37  decomposition method or as a volScalarField for post-processing.
38 
39  \param -region regionName \n
40  Decompose named region. Does not check for existence of processor*.
41 
42  \param -allRegions \n
43  Decompose all regions in regionProperties. Does not check for
44  existence of processor*.
45 
46  \param -copyUniform \n
47  Copy any \a uniform directories too.
48 
49  \param -constant \n
50  \param -time xxx:yyy \n
51  Override controlDict settings and decompose selected times. Does not
52  re-decompose the mesh i.e. does not handle moving mesh or changing
53  mesh cases.
54 
55  \param -fields \n
56  Use existing geometry decomposition and convert fields only.
57 
58  \param -noSets \n
59  Skip decomposing cellSets, faceSets, pointSets.
60 
61  \param -force \n
62  Remove any existing \a processor subdirectories before decomposing the
63  geometry.
64 
65  \param -ifRequired \n
66  Only decompose the geometry if the number of domains has changed from a
67  previous decomposition. No \a processor subdirectories will be removed
68  unless the \a -force option is also specified. This option can be used
69  to avoid redundant geometry decomposition (eg, in scripts), but should
70  be used with caution when the underlying (serial) geometry or the
71  decomposition method etc. have been changed between decompositions.
72 
73 \*---------------------------------------------------------------------------*/
74 
75 #include "OSspecific.H"
76 #include "fvCFD.H"
77 #include "IOobjectList.H"
78 #include "domainDecomposition.H"
79 #include "labelIOField.H"
80 #include "labelFieldIOField.H"
81 #include "scalarIOField.H"
82 #include "scalarFieldIOField.H"
83 #include "vectorIOField.H"
84 #include "vectorFieldIOField.H"
85 #include "sphericalTensorIOField.H"
87 #include "symmTensorIOField.H"
88 #include "symmTensorFieldIOField.H"
89 #include "tensorIOField.H"
90 #include "tensorFieldIOField.H"
91 #include "pointFields.H"
92 #include "regionProperties.H"
93 
94 #include "readFields.H"
95 #include "dimFieldDecomposer.H"
96 #include "fvFieldDecomposer.H"
97 #include "pointFieldDecomposer.H"
98 #include "lagrangianFieldDecomposer.H"
99 #include "decompositionModel.H"
100 
101 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
102 
104 (
105  const PtrList<fvMesh>& procMeshList,
106  const label procI,
107  const word& name,
108  PtrList<labelIOList>& procAddressingList
109 )
110 {
111  const fvMesh& procMesh = procMeshList[procI];
112 
113  if (!procAddressingList.set(procI))
114  {
115  procAddressingList.set
116  (
117  procI,
118  new labelIOList
119  (
120  IOobject
121  (
122  name,
123  procMesh.facesInstance(),
124  procMesh.meshSubDir,
125  procMesh,
126  IOobject::MUST_READ,
127  IOobject::NO_WRITE,
128  false
129  )
130  )
131  );
132  }
133  return procAddressingList[procI];
134 }
135 
136 
137 
138 int main(int argc, char *argv[])
139 {
140  argList::addNote
141  (
142  "decompose a mesh and fields of a case for parallel execution"
143  );
144 
145  argList::noParallel();
146  argList::addOption
147  (
148  "decomposeParDict",
149  "file",
150  "read decomposePar dictionary from specified location"
151  );
152  #include "addRegionOption.H"
153  argList::addBoolOption
154  (
155  "allRegions",
156  "operate on all regions in regionProperties"
157  );
158  argList::addBoolOption
159  (
160  "cellDist",
161  "write cell distribution as a labelList - for use with 'manual' "
162  "decomposition method or as a volScalarField for post-processing."
163  );
164  argList::addBoolOption
165  (
166  "copyUniform",
167  "copy any uniform/ directories too"
168  );
169  argList::addBoolOption
170  (
171  "fields",
172  "use existing geometry decomposition and convert fields only"
173  );
174  argList::addBoolOption
175  (
176  "noSets",
177  "skip decomposing cellSets, faceSets, pointSets"
178  );
179  argList::addBoolOption
180  (
181  "force",
182  "remove existing processor*/ subdirs before decomposing the geometry"
183  );
184  argList::addBoolOption
185  (
186  "ifRequired",
187  "only decompose geometry if the number of domains has changed"
188  );
189 
190  // Include explicit constant options, have zero from time range
191  timeSelector::addOptions(true, false);
192 
193  #include "setRootCase.H"
194 
195  bool allRegions = args.optionFound("allRegions");
196  bool writeCellDist = args.optionFound("cellDist");
197  bool copyUniform = args.optionFound("copyUniform");
198  bool decomposeFieldsOnly = args.optionFound("fields");
199  bool decomposeSets = !args.optionFound("noSets");
200  bool forceOverwrite = args.optionFound("force");
201  bool ifRequiredDecomposition = args.optionFound("ifRequired");
202 
203  // Set time from database
204  #include "createTime.H"
205  // Allow override of time
206  instantList times = timeSelector::selectIfPresent(runTime, args);
207 
208 
209  // Allow override of decomposeParDict location
210  fileName decompDictFile;
211  if (args.optionReadIfPresent("decomposeParDict", decompDictFile))
212  {
213  if (isDir(decompDictFile))
214  {
215  decompDictFile = decompDictFile/"decomposeParDict";
216  }
217  }
218 
219 
220  wordList regionNames;
221  wordList regionDirs;
222  if (allRegions)
223  {
224  Info<< "Decomposing all regions in regionProperties" << nl << endl;
225  regionProperties rp(runTime);
226  forAllConstIter(HashTable<wordList>, rp, iter)
227  {
228  const wordList& regions = iter();
229  forAll(regions, i)
230  {
231  if (findIndex(regionNames, regions[i]) == -1)
232  {
233  regionNames.append(regions[i]);
234  }
235  }
236  }
237  regionDirs = regionNames;
238  }
239  else
240  {
241  word regionName;
242  if (args.optionReadIfPresent("region", regionName))
243  {
244  regionNames = wordList(1, regionName);
245  regionDirs = regionNames;
246  }
247  else
248  {
249  regionNames = wordList(1, fvMesh::defaultRegion);
250  regionDirs = wordList(1, word::null);
251  }
252  }
253 
254 
255 
256  forAll(regionNames, regionI)
257  {
258  const word& regionName = regionNames[regionI];
259  const word& regionDir = regionDirs[regionI];
260 
261  Info<< "\n\nDecomposing mesh " << regionName << nl << endl;
262 
263 
264  // determine the existing processor count directly
265  label nProcs = 0;
266  while
267  (
268  isDir
269  (
270  runTime.path()
271  / (word("processor") + name(nProcs))
272  / runTime.constant()
273  / regionDir
274  / polyMesh::meshSubDir
275  )
276  )
277  {
278  ++nProcs;
279  }
280 
281  // get requested numberOfSubdomains. Note: have no mesh yet so
282  // cannot use decompositionModel::New
283  const label nDomains = readLabel
284  (
285  IOdictionary
286  (
287  decompositionModel::selectIO
288  (
289  IOobject
290  (
291  "decomposeParDict",
292  runTime.time().system(),
293  regionDir, // use region if non-standard
294  runTime,
295  IOobject::MUST_READ_IF_MODIFIED,
296  IOobject::NO_WRITE,
297  false
298  ),
299  decompDictFile
300  )
301 
302  ).lookup("numberOfSubdomains")
303  );
304 
305  if (decomposeFieldsOnly)
306  {
307  // Sanity check on previously decomposed case
308  if (nProcs != nDomains)
309  {
311  << "Specified -fields, but the case was decomposed with "
312  << nProcs << " domains"
313  << nl
314  << "instead of " << nDomains
315  << " domains as specified in decomposeParDict" << nl
316  << exit(FatalError);
317  }
318  }
319  else if (nProcs)
320  {
321  bool procDirsProblem = true;
322 
323  if (ifRequiredDecomposition && nProcs == nDomains)
324  {
325  // we can reuse the decomposition
326  decomposeFieldsOnly = true;
327  procDirsProblem = false;
328  forceOverwrite = false;
329 
330  Info<< "Using existing processor directories" << nl;
331  }
332 
333  if (forceOverwrite)
334  {
335  Info<< "Removing " << nProcs
336  << " existing processor directories" << endl;
337 
338  // remove existing processor dirs
339  // reverse order to avoid gaps if someone interrupts the process
340  for (label procI = nProcs-1; procI >= 0; --procI)
341  {
342  fileName procDir
343  (
344  runTime.path()/(word("processor") + name(procI))
345  );
346 
347  rmDir(procDir);
348  }
349 
350  procDirsProblem = false;
351  }
352 
353  if (procDirsProblem)
354  {
356  << "Case is already decomposed with " << nProcs
357  << " domains, use the -force option or manually" << nl
358  << "remove processor directories before decomposing. e.g.,"
359  << nl
360  << " rm -rf " << runTime.path().c_str() << "/processor*"
361  << nl
362  << exit(FatalError);
363  }
364  }
365 
366  Info<< "Create mesh" << endl;
367  domainDecomposition mesh
368  (
369  IOobject
370  (
371  regionName,
372  runTime.timeName(),
373  runTime,
374  IOobject::NO_READ,
375  IOobject::NO_WRITE,
376  false
377  ),
378  decompDictFile
379  );
380 
381  // Decompose the mesh
382  if (!decomposeFieldsOnly)
383  {
384  mesh.decomposeMesh();
385 
386  mesh.writeDecomposition(decomposeSets);
387 
388  if (writeCellDist)
389  {
390  const labelList& procIds = mesh.cellToProc();
391 
392  // Write the decomposition as labelList for use with 'manual'
393  // decomposition method.
394  labelIOList cellDecomposition
395  (
396  IOobject
397  (
398  "cellDecomposition",
399  mesh.facesInstance(),
400  mesh,
401  IOobject::NO_READ,
402  IOobject::NO_WRITE,
403  false
404  ),
405  procIds
406  );
407  cellDecomposition.write();
408 
409  Info<< nl << "Wrote decomposition to "
410  << cellDecomposition.objectPath()
411  << " for use in manual decomposition." << endl;
412 
413  // Write as volScalarField for postprocessing.
414  volScalarField cellDist
415  (
416  IOobject
417  (
418  "cellDist",
419  runTime.timeName(),
420  mesh,
421  IOobject::NO_READ,
422  IOobject::AUTO_WRITE
423  ),
424  mesh,
425  dimensionedScalar("cellDist", dimless, 0),
426  zeroGradientFvPatchScalarField::typeName
427  );
428 
429  forAll(procIds, celli)
430  {
431  cellDist[celli] = procIds[celli];
432  }
433 
434  cellDist.write();
435 
436  Info<< nl << "Wrote decomposition as volScalarField to "
437  << cellDist.name() << " for use in postprocessing."
438  << endl;
439  }
440  }
441 
442 
443 
444  // Caches
445  // ~~~~~~
446  // Cached processor meshes and maps. These are only preserved if running
447  // with multiple times.
448  PtrList<Time> processorDbList(mesh.nProcs());
449  PtrList<fvMesh> procMeshList(mesh.nProcs());
450  PtrList<labelIOList> faceProcAddressingList(mesh.nProcs());
451  PtrList<labelIOList> cellProcAddressingList(mesh.nProcs());
452  PtrList<labelIOList> boundaryProcAddressingList(mesh.nProcs());
453  PtrList<fvFieldDecomposer> fieldDecomposerList(mesh.nProcs());
454  PtrList<dimFieldDecomposer> dimFieldDecomposerList(mesh.nProcs());
455  PtrList<labelIOList> pointProcAddressingList(mesh.nProcs());
456  PtrList<pointFieldDecomposer> pointFieldDecomposerList(mesh.nProcs());
457 
458 
459 
460  // Loop over all times
461  forAll(times, timeI)
462  {
463  runTime.setTime(times[timeI], timeI);
464 
465  Info<< "Time = " << runTime.timeName() << endl;
466 
467  // Search for list of objects for this time
468  IOobjectList objects(mesh, runTime.timeName());
469 
470 
471  // Construct the vol fields
472  // ~~~~~~~~~~~~~~~~~~~~~~~~
473  PtrList<volScalarField> volScalarFields;
474  readFields(mesh, objects, volScalarFields, false);
475  PtrList<volVectorField> volVectorFields;
476  readFields(mesh, objects, volVectorFields, false);
477  PtrList<volSphericalTensorField> volSphericalTensorFields;
478  readFields(mesh, objects, volSphericalTensorFields, false);
479  PtrList<volSymmTensorField> volSymmTensorFields;
480  readFields(mesh, objects, volSymmTensorFields, false);
481  PtrList<volTensorField> volTensorFields;
482  readFields(mesh, objects, volTensorFields, false);
483 
484 
485  // Construct the dimensioned fields
486  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
487  PtrList<DimensionedField<scalar, volMesh> > dimScalarFields;
488  readFields(mesh, objects, dimScalarFields);
489  PtrList<DimensionedField<vector, volMesh> > dimVectorFields;
490  readFields(mesh, objects, dimVectorFields);
491  PtrList<DimensionedField<sphericalTensor, volMesh> >
492  dimSphericalTensorFields;
493  readFields(mesh, objects, dimSphericalTensorFields);
494  PtrList<DimensionedField<symmTensor, volMesh> > dimSymmTensorFields;
495  readFields(mesh, objects, dimSymmTensorFields);
496  PtrList<DimensionedField<tensor, volMesh> > dimTensorFields;
497  readFields(mesh, objects, dimTensorFields);
498 
499 
500  // Construct the surface fields
501  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
502  PtrList<surfaceScalarField> surfaceScalarFields;
503  readFields(mesh, objects, surfaceScalarFields, false);
504  PtrList<surfaceVectorField> surfaceVectorFields;
505  readFields(mesh, objects, surfaceVectorFields, false);
506  PtrList<surfaceSphericalTensorField> surfaceSphericalTensorFields;
507  readFields(mesh, objects, surfaceSphericalTensorFields, false);
508  PtrList<surfaceSymmTensorField> surfaceSymmTensorFields;
509  readFields(mesh, objects, surfaceSymmTensorFields, false);
510  PtrList<surfaceTensorField> surfaceTensorFields;
511  readFields(mesh, objects, surfaceTensorFields, false);
512 
513 
514  // Construct the point fields
515  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
516  const pointMesh& pMesh = pointMesh::New(mesh);
517 
518  PtrList<pointScalarField> pointScalarFields;
519  readFields(pMesh, objects, pointScalarFields, false);
520  PtrList<pointVectorField> pointVectorFields;
521  readFields(pMesh, objects, pointVectorFields, false);
522  PtrList<pointSphericalTensorField> pointSphericalTensorFields;
523  readFields(pMesh, objects, pointSphericalTensorFields, false);
524  PtrList<pointSymmTensorField> pointSymmTensorFields;
525  readFields(pMesh, objects, pointSymmTensorFields, false);
526  PtrList<pointTensorField> pointTensorFields;
527  readFields(pMesh, objects, pointTensorFields, false);
528 
529 
530  // Construct the Lagrangian fields
531  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
532 
533  fileNameList cloudDirs
534  (
535  readDir(runTime.timePath()/cloud::prefix, fileName::DIRECTORY)
536  );
537 
538  // Particles
539  PtrList<Cloud<indexedParticle> > lagrangianPositions
540  (
541  cloudDirs.size()
542  );
543  // Particles per cell
544  PtrList< List<SLList<indexedParticle*>*> > cellParticles
545  (
546  cloudDirs.size()
547  );
548 
549  PtrList<PtrList<labelIOField> > lagrangianLabelFields
550  (
551  cloudDirs.size()
552  );
553  PtrList<PtrList<labelFieldCompactIOField> >
554  lagrangianLabelFieldFields
555  (
556  cloudDirs.size()
557  );
558  PtrList<PtrList<scalarIOField> > lagrangianScalarFields
559  (
560  cloudDirs.size()
561  );
562  PtrList<PtrList<scalarFieldCompactIOField> >
563  lagrangianScalarFieldFields
564  (
565  cloudDirs.size()
566  );
567  PtrList<PtrList<vectorIOField> > lagrangianVectorFields
568  (
569  cloudDirs.size()
570  );
571  PtrList<PtrList<vectorFieldCompactIOField> >
572  lagrangianVectorFieldFields
573  (
574  cloudDirs.size()
575  );
576  PtrList<PtrList<sphericalTensorIOField> >
577  lagrangianSphericalTensorFields
578  (
579  cloudDirs.size()
580  );
581  PtrList<PtrList<sphericalTensorFieldCompactIOField> >
582  lagrangianSphericalTensorFieldFields(cloudDirs.size());
583  PtrList<PtrList<symmTensorIOField> > lagrangianSymmTensorFields
584  (
585  cloudDirs.size()
586  );
587  PtrList<PtrList<symmTensorFieldCompactIOField> >
588  lagrangianSymmTensorFieldFields
589  (
590  cloudDirs.size()
591  );
592  PtrList<PtrList<tensorIOField> > lagrangianTensorFields
593  (
594  cloudDirs.size()
595  );
596  PtrList<PtrList<tensorFieldCompactIOField> >
597  lagrangianTensorFieldFields
598  (
599  cloudDirs.size()
600  );
601 
602  label cloudI = 0;
603 
604  forAll(cloudDirs, i)
605  {
606  IOobjectList sprayObjs
607  (
608  mesh,
609  runTime.timeName(),
610  cloud::prefix/cloudDirs[i],
611  IOobject::MUST_READ,
612  IOobject::NO_WRITE,
613  false
614  );
615 
616  IOobject* positionsPtr = sprayObjs.lookup(word("positions"));
617 
618  if (positionsPtr)
619  {
620  // Read lagrangian particles
621  // ~~~~~~~~~~~~~~~~~~~~~~~~~
622 
623  Info<< "Identified lagrangian data set: " << cloudDirs[i]
624  << endl;
625 
626  lagrangianPositions.set
627  (
628  cloudI,
629  new Cloud<indexedParticle>
630  (
631  mesh,
632  cloudDirs[i],
633  false
634  )
635  );
636 
637 
638  // Sort particles per cell
639  // ~~~~~~~~~~~~~~~~~~~~~~~
640 
641  cellParticles.set
642  (
643  cloudI,
644  new List<SLList<indexedParticle*>*>
645  (
646  mesh.nCells(),
647  static_cast<SLList<indexedParticle*>*>(NULL)
648  )
649  );
650 
651  label i = 0;
652 
653  forAllIter
654  (
655  Cloud<indexedParticle>,
656  lagrangianPositions[cloudI],
657  iter
658  )
659  {
660  iter().index() = i++;
661 
662  label celli = iter().cell();
663 
664  // Check
665  if (celli < 0 || celli >= mesh.nCells())
666  {
668  << "Illegal cell number " << celli
669  << " for particle with index " << iter().index()
670  << " at position " << iter().position() << nl
671  << "Cell number should be between 0 and "
672  << mesh.nCells()-1 << nl
673  << "On this mesh the particle should"
674  << " be in cell "
675  << mesh.findCell(iter().position())
676  << exit(FatalError);
677  }
678 
679  if (!cellParticles[cloudI][celli])
680  {
681  cellParticles[cloudI][celli] =
682  new SLList<indexedParticle*>();
683  }
684 
685  cellParticles[cloudI][celli]->append(&iter());
686  }
687 
688  // Read fields
689  // ~~~~~~~~~~~
690 
691  IOobjectList lagrangianObjects
692  (
693  mesh,
694  runTime.timeName(),
695  cloud::prefix/cloudDirs[cloudI],
696  IOobject::MUST_READ,
697  IOobject::NO_WRITE,
698  false
699  );
700 
702  (
703  cloudI,
704  lagrangianObjects,
705  lagrangianLabelFields
706  );
707 
708  lagrangianFieldDecomposer::readFieldFields
709  (
710  cloudI,
711  lagrangianObjects,
712  lagrangianLabelFieldFields
713  );
714 
716  (
717  cloudI,
718  lagrangianObjects,
719  lagrangianScalarFields
720  );
721 
722  lagrangianFieldDecomposer::readFieldFields
723  (
724  cloudI,
725  lagrangianObjects,
726  lagrangianScalarFieldFields
727  );
728 
730  (
731  cloudI,
732  lagrangianObjects,
733  lagrangianVectorFields
734  );
735 
736  lagrangianFieldDecomposer::readFieldFields
737  (
738  cloudI,
739  lagrangianObjects,
740  lagrangianVectorFieldFields
741  );
742 
744  (
745  cloudI,
746  lagrangianObjects,
747  lagrangianSphericalTensorFields
748  );
749 
750  lagrangianFieldDecomposer::readFieldFields
751  (
752  cloudI,
753  lagrangianObjects,
754  lagrangianSphericalTensorFieldFields
755  );
756 
758  (
759  cloudI,
760  lagrangianObjects,
761  lagrangianSymmTensorFields
762  );
763 
764  lagrangianFieldDecomposer::readFieldFields
765  (
766  cloudI,
767  lagrangianObjects,
768  lagrangianSymmTensorFieldFields
769  );
770 
772  (
773  cloudI,
774  lagrangianObjects,
775  lagrangianTensorFields
776  );
777 
778  lagrangianFieldDecomposer::readFieldFields
779  (
780  cloudI,
781  lagrangianObjects,
782  lagrangianTensorFieldFields
783  );
784 
785  cloudI++;
786  }
787  }
788 
789  lagrangianPositions.setSize(cloudI);
790  cellParticles.setSize(cloudI);
791  lagrangianLabelFields.setSize(cloudI);
792  lagrangianLabelFieldFields.setSize(cloudI);
793  lagrangianScalarFields.setSize(cloudI);
794  lagrangianScalarFieldFields.setSize(cloudI);
795  lagrangianVectorFields.setSize(cloudI);
796  lagrangianVectorFieldFields.setSize(cloudI);
797  lagrangianSphericalTensorFields.setSize(cloudI);
798  lagrangianSphericalTensorFieldFields.setSize(cloudI);
799  lagrangianSymmTensorFields.setSize(cloudI);
800  lagrangianSymmTensorFieldFields.setSize(cloudI);
801  lagrangianTensorFields.setSize(cloudI);
802  lagrangianTensorFieldFields.setSize(cloudI);
803 
804 
805  // Any uniform data to copy/link?
806  fileName uniformDir("uniform");
807 
808  if (isDir(runTime.timePath()/uniformDir))
809  {
810  Info<< "Detected additional non-decomposed files in "
811  << runTime.timePath()/uniformDir
812  << endl;
813  }
814  else
815  {
816  uniformDir.clear();
817  }
818 
819  Info<< endl;
820 
821  // split the fields over processors
822  for (label procI = 0; procI < mesh.nProcs(); procI++)
823  {
824  Info<< "Processor " << procI << ": field transfer" << endl;
825 
826 
827  // open the database
828  if (!processorDbList.set(procI))
829  {
830  processorDbList.set
831  (
832  procI,
833  new Time
834  (
835  Time::controlDictName,
836  args.rootPath(),
837  args.caseName()
838  /fileName(word("processor") + name(procI))
839  )
840  );
841  }
842  Time& processorDb = processorDbList[procI];
843 
844 
845  processorDb.setTime(runTime);
846 
847  // read the mesh
848  if (!procMeshList.set(procI))
849  {
850  procMeshList.set
851  (
852  procI,
853  new fvMesh
854  (
855  IOobject
856  (
857  regionName,
858  processorDb.timeName(),
859  processorDb
860  )
861  )
862  );
863  }
864  const fvMesh& procMesh = procMeshList[procI];
865 
867  (
868  procMeshList,
869  procI,
870  "faceProcAddressing",
871  faceProcAddressingList
872  );
873 
874  const labelIOList& cellProcAddressing = procAddressing
875  (
876  procMeshList,
877  procI,
878  "cellProcAddressing",
879  cellProcAddressingList
880  );
881 
882  const labelIOList& boundaryProcAddressing = procAddressing
883  (
884  procMeshList,
885  procI,
886  "boundaryProcAddressing",
887  boundaryProcAddressingList
888  );
889 
890 
891  // FV fields
892  {
893  if (!fieldDecomposerList.set(procI))
894  {
895  fieldDecomposerList.set
896  (
897  procI,
898  new fvFieldDecomposer
899  (
900  mesh,
901  procMesh,
903  cellProcAddressing,
904  boundaryProcAddressing
905  )
906  );
907  }
908  const fvFieldDecomposer& fieldDecomposer =
909  fieldDecomposerList[procI];
910 
911  fieldDecomposer.decomposeFields(volScalarFields);
912  fieldDecomposer.decomposeFields(volVectorFields);
913  fieldDecomposer.decomposeFields(volSphericalTensorFields);
914  fieldDecomposer.decomposeFields(volSymmTensorFields);
915  fieldDecomposer.decomposeFields(volTensorFields);
916 
917  fieldDecomposer.decomposeFields(surfaceScalarFields);
918  fieldDecomposer.decomposeFields(surfaceVectorFields);
919  fieldDecomposer.decomposeFields
920  (
921  surfaceSphericalTensorFields
922  );
923  fieldDecomposer.decomposeFields(surfaceSymmTensorFields);
924  fieldDecomposer.decomposeFields(surfaceTensorFields);
925 
926  if (times.size() == 1)
927  {
928  // Clear cached decomposer
929  fieldDecomposerList.set(procI, NULL);
930  }
931  }
932 
933  // Dimensioned fields
934  {
935  if (!dimFieldDecomposerList.set(procI))
936  {
937  dimFieldDecomposerList.set
938  (
939  procI,
940  new dimFieldDecomposer
941  (
942  mesh,
943  procMesh,
945  cellProcAddressing
946  )
947  );
948  }
949  const dimFieldDecomposer& dimDecomposer =
950  dimFieldDecomposerList[procI];
951 
952  dimDecomposer.decomposeFields(dimScalarFields);
953  dimDecomposer.decomposeFields(dimVectorFields);
954  dimDecomposer.decomposeFields(dimSphericalTensorFields);
955  dimDecomposer.decomposeFields(dimSymmTensorFields);
956  dimDecomposer.decomposeFields(dimTensorFields);
957 
958  if (times.size() == 1)
959  {
960  dimFieldDecomposerList.set(procI, NULL);
961  }
962  }
963 
964 
965  // Point fields
966  if
967  (
968  pointScalarFields.size()
969  || pointVectorFields.size()
970  || pointSphericalTensorFields.size()
971  || pointSymmTensorFields.size()
972  || pointTensorFields.size()
973  )
974  {
975  const labelIOList& pointProcAddressing = procAddressing
976  (
977  procMeshList,
978  procI,
979  "pointProcAddressing",
980  pointProcAddressingList
981  );
982 
983  const pointMesh& procPMesh = pointMesh::New(procMesh);
984 
985  if (!pointFieldDecomposerList.set(procI))
986  {
987  pointFieldDecomposerList.set
988  (
989  procI,
990  new pointFieldDecomposer
991  (
992  pMesh,
993  procPMesh,
994  pointProcAddressing,
995  boundaryProcAddressing
996  )
997  );
998  }
999  const pointFieldDecomposer& pointDecomposer =
1000  pointFieldDecomposerList[procI];
1001 
1002  pointDecomposer.decomposeFields(pointScalarFields);
1003  pointDecomposer.decomposeFields(pointVectorFields);
1004  pointDecomposer.decomposeFields(pointSphericalTensorFields);
1005  pointDecomposer.decomposeFields(pointSymmTensorFields);
1006  pointDecomposer.decomposeFields(pointTensorFields);
1007 
1008 
1009  if (times.size() == 1)
1010  {
1011  pointProcAddressingList.set(procI, NULL);
1012  pointFieldDecomposerList.set(procI, NULL);
1013  }
1014  }
1015 
1016 
1017  // If there is lagrangian data write it out
1018  forAll(lagrangianPositions, cloudI)
1019  {
1020  if (lagrangianPositions[cloudI].size())
1021  {
1022  lagrangianFieldDecomposer fieldDecomposer
1023  (
1024  mesh,
1025  procMesh,
1027  cellProcAddressing,
1028  cloudDirs[cloudI],
1029  lagrangianPositions[cloudI],
1030  cellParticles[cloudI]
1031  );
1032 
1033  // Lagrangian fields
1034  {
1035  fieldDecomposer.decomposeFields
1036  (
1037  cloudDirs[cloudI],
1038  lagrangianLabelFields[cloudI]
1039  );
1040  fieldDecomposer.decomposeFieldFields
1041  (
1042  cloudDirs[cloudI],
1043  lagrangianLabelFieldFields[cloudI]
1044  );
1045  fieldDecomposer.decomposeFields
1046  (
1047  cloudDirs[cloudI],
1048  lagrangianScalarFields[cloudI]
1049  );
1050  fieldDecomposer.decomposeFieldFields
1051  (
1052  cloudDirs[cloudI],
1053  lagrangianScalarFieldFields[cloudI]
1054  );
1055  fieldDecomposer.decomposeFields
1056  (
1057  cloudDirs[cloudI],
1058  lagrangianVectorFields[cloudI]
1059  );
1060  fieldDecomposer.decomposeFieldFields
1061  (
1062  cloudDirs[cloudI],
1063  lagrangianVectorFieldFields[cloudI]
1064  );
1065  fieldDecomposer.decomposeFields
1066  (
1067  cloudDirs[cloudI],
1068  lagrangianSphericalTensorFields[cloudI]
1069  );
1070  fieldDecomposer.decomposeFieldFields
1071  (
1072  cloudDirs[cloudI],
1073  lagrangianSphericalTensorFieldFields[cloudI]
1074  );
1075  fieldDecomposer.decomposeFields
1076  (
1077  cloudDirs[cloudI],
1078  lagrangianSymmTensorFields[cloudI]
1079  );
1080  fieldDecomposer.decomposeFieldFields
1081  (
1082  cloudDirs[cloudI],
1083  lagrangianSymmTensorFieldFields[cloudI]
1084  );
1085  fieldDecomposer.decomposeFields
1086  (
1087  cloudDirs[cloudI],
1088  lagrangianTensorFields[cloudI]
1089  );
1090  fieldDecomposer.decomposeFieldFields
1091  (
1092  cloudDirs[cloudI],
1093  lagrangianTensorFieldFields[cloudI]
1094  );
1095  }
1096  }
1097  }
1098 
1099 
1100  // Any non-decomposed data to copy?
1101  if (uniformDir.size())
1102  {
1103  const fileName timePath = processorDb.timePath();
1104 
1105  if (copyUniform || mesh.distributed())
1106  {
1107  cp
1108  (
1109  runTime.timePath()/uniformDir,
1110  timePath/uniformDir
1111  );
1112  }
1113  else
1114  {
1115  // link with relative paths
1116  const string parentPath = string("..")/"..";
1117 
1118  fileName currentDir(cwd());
1119  chDir(timePath);
1120  ln
1121  (
1122  parentPath/runTime.timeName()/uniformDir,
1123  uniformDir
1124  );
1125  chDir(currentDir);
1126  }
1127  }
1128 
1129 
1130 
1131  // We have cached all the constant mesh data for the current
1132  // processor. This is only important if running with multiple
1133  // times, otherwise it is just extra storage.
1134  if (times.size() == 1)
1135  {
1136  boundaryProcAddressingList.set(procI, NULL);
1137  cellProcAddressingList.set(procI, NULL);
1138  faceProcAddressingList.set(procI, NULL);
1139  procMeshList.set(procI, NULL);
1140  processorDbList.set(procI, NULL);
1141  }
1142  }
1143  }
1144  }
1145 
1146  Info<< "\nEnd\n" << endl;
1147 
1148  return 0;
1149 }
1150 
1151 
1152 // ************************************************************************* //
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
Foam::compressible::New
autoPtr< BasicCompressibleTurbulenceModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const typename BasicCompressibleTurbulenceModel::transportModel &transport, const word &propertiesName)
Definition: turbulentFluidThermoModel.C:36
regionProperties.H
forAllIter
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:431
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
tensorIOField.H
IOobjectList.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
main
int main(int argc, char *argv[])
Definition: decomposePar.C:138
scalarIOField.H
Foam::labelIOList
IOList< label > labelIOList
Label container classes.
Definition: labelIOList.H:42
Foam::instantList
List< instant > instantList
List of instants.
Definition: instantList.H:42
Foam::argList::rootPath
const fileName & rootPath() const
Return root path.
Definition: argListI.H:36
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
tensorFieldIOField.H
scalarFieldIOField.H
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:54
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::label
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
vectorFieldIOField.H
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
addRegionOption.H
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:41
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:52
cp
const volScalarField & cp
Definition: setRegionSolidFields.H:8
labelFieldIOField.H
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::isDir
bool isDir(const fileName &)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:615
fvFieldDecomposer.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::fileNameList
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:50
vectorIOField.H
Foam::chDir
bool chDir(const fileName &dir)
Change the current directory to the one given and return true,.
Definition: POSIX.C:264
setRootCase.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
symmTensorFieldIOField.H
readFields
void readFields(const boolList &haveMesh, const fvMesh &mesh, const autoPtr< fvMeshSubset > &subsetterPtr, IOobjectList &allObjects, PtrList< GeoField > &fields)
Definition: redistributePar.C:589
createTime.H
Foam::readLabel
label readLabel(Istream &is)
Definition: label.H:64
Foam::argList::optionFound
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
faceProcAddressing
PtrList< labelIOList > & faceProcAddressing
Definition: checkFaceAddressingComp.H:9
symmTensorIOField.H
procAddressing
const labelIOList & procAddressing(const PtrList< fvMesh > &procMeshList, const label procI, const word &name, PtrList< labelIOList > &procAddressingList)
Definition: decomposePar.C:104
Foam::ln
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:854
Foam::cwd
fileName cwd()
Return current working directory path name.
Definition: POSIX.C:246
fvCFD.H
decompositionModel.H
List
Definition: Test.C:19
Foam::argList::caseName
const fileName & caseName() const
Return case name (parallel run) or global case (serial run)
Definition: argListI.H:42
sphericalTensorIOField.H
Foam::readDir
fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:660
args
Foam::argList args(argc, argv)
sphericalTensorFieldIOField.H
Foam::argList::optionReadIfPresent
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:198
Foam::rmDir
bool rmDir(const fileName &)
Remove a dirctory and its contents.
Definition: POSIX.C:974
pointFields.H
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
labelIOField.H