FreeFOAM The Cross-Platform CFD Toolkit
fvMeshAdderTemplates.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) 1991-2010 OpenCFD Ltd.
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 
26 
27 #include <finiteVolume/volFields.H>
30 
31 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
32 
33 template<class Type>
34 void Foam::fvMeshAdder::map
35 (
36  const Field<Type>& oldFld,
37  const labelList& oldToNew,
38  Field<Type>& fld
39 )
40 {
41  forAll(oldFld, cellI)
42  {
43  label newCellI = oldToNew[cellI];
44 
45  if (newCellI >= 0 && newCellI < fld.size())
46  {
47  fld[newCellI] = oldFld[cellI];
48  }
49  }
50 }
51 
52 
53 template<class Type>
54 void Foam::fvMeshAdder::MapVolField
55 (
56  const mapAddedPolyMesh& meshMap,
57 
58  GeometricField<Type, fvPatchField, volMesh>& fld,
59  const GeometricField<Type, fvPatchField, volMesh>& fldToAdd
60 )
61 {
62  const fvMesh& mesh = fld.mesh();
63 
64  // Internal field
65  // ~~~~~~~~~~~~~~
66 
67  {
68  // Store old internal field
69  Field<Type> oldInternalField(fld.internalField());
70 
71  // Modify internal field
72  Field<Type>& intFld = fld.internalField();
73 
74  intFld.setSize(mesh.nCells());
75 
76  map(oldInternalField, meshMap.oldCellMap(), intFld);
77  map(fldToAdd.internalField(), meshMap.addedCellMap(), intFld);
78  }
79 
80 
81  // Patch fields from old mesh
82  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
83 
84  {
85  const labelList& oldPatchMap = meshMap.oldPatchMap();
86  const labelList& oldPatchStarts = meshMap.oldPatchStarts();
87  const labelList& oldPatchSizes = meshMap.oldPatchSizes();
88 
89  // Reorder old patches in order of new ones. Put removed patches at end.
90 
91  label unusedPatchI = 0;
92 
93  forAll(oldPatchMap, patchI)
94  {
95  label newPatchI = oldPatchMap[patchI];
96 
97  if (newPatchI != -1)
98  {
99  unusedPatchI++;
100  }
101  }
102 
103  label nUsedPatches = unusedPatchI;
104 
105  // Reorder list for patchFields
106  labelList oldToNew(oldPatchMap.size());
107 
108  forAll(oldPatchMap, patchI)
109  {
110  label newPatchI = oldPatchMap[patchI];
111 
112  if (newPatchI != -1)
113  {
114  oldToNew[patchI] = newPatchI;
115  }
116  else
117  {
118  oldToNew[patchI] = unusedPatchI++;
119  }
120  }
121 
122 
123  // Sort deleted ones last so is now in newPatch ordering
124  fld.boundaryField().reorder(oldToNew);
125  // Extend to covers all patches
126  fld.boundaryField().setSize(mesh.boundaryMesh().size());
127  // Delete unused patches
128  for
129  (
130  label newPatchI = nUsedPatches;
131  newPatchI < fld.boundaryField().size();
132  newPatchI++
133  )
134  {
135  fld.boundaryField().set(newPatchI, NULL);
136  }
137 
138 
139  // Map old values
140  // ~~~~~~~~~~~~~~
141 
142  forAll(oldPatchMap, patchI)
143  {
144  label newPatchI = oldPatchMap[patchI];
145 
146  if (newPatchI != -1)
147  {
148  labelList newToOld
149  (
150  calcPatchMap
151  (
152  oldPatchStarts[patchI],
153  oldPatchSizes[patchI],
154  meshMap.oldFaceMap(),
155  mesh.boundaryMesh()[newPatchI],
156  0 // unmapped value
157  )
158  );
159 
160  directFvPatchFieldMapper patchMapper(newToOld);
161 
162 
163  // Create new patchField with same type as existing one.
164  // Note:
165  // - boundaryField already in new order so access with newPatchI
166  // - fld.boundaryField()[newPatchI] both used for type and old
167  // value
168  // - hope that field mapping allows aliasing since old and new
169  // are same memory!
170  fld.boundaryField().set
171  (
172  newPatchI,
173  fvPatchField<Type>::New
174  (
175  fld.boundaryField()[newPatchI], // old field
176  mesh.boundary()[newPatchI], // new fvPatch
177  fld.dimensionedInternalField(), // new internal field
178  patchMapper // mapper (new to old)
179  )
180  );
181  }
182  }
183  }
184 
185 
186 
187  // Patch fields from added mesh
188  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189 
190  {
191  const labelList& addedPatchMap = meshMap.addedPatchMap();
192 
193  // Add addedMesh patches
194  forAll(addedPatchMap, patchI)
195  {
196  label newPatchI = addedPatchMap[patchI];
197 
198  if (newPatchI != -1)
199  {
200  const polyPatch& newPatch = mesh.boundaryMesh()[newPatchI];
201  const polyPatch& oldPatch =
202  fldToAdd.mesh().boundaryMesh()[patchI];
203 
204  if (!fld.boundaryField()(newPatchI))
205  {
206  // First occurrence of newPatchI. Map from existing
207  // patchField
208 
209  // From new patch faces to patch faces on added mesh.
210  labelList newToAdded
211  (
212  calcPatchMap
213  (
214  oldPatch.start(),
215  oldPatch.size(),
216  meshMap.addedFaceMap(),
217  newPatch,
218  0 // unmapped values
219  )
220  );
221 
222  directFvPatchFieldMapper patchMapper(newToAdded);
223 
224  fld.boundaryField().set
225  (
226  newPatchI,
227  fvPatchField<Type>::New
228  (
229  fldToAdd.boundaryField()[patchI], // added field
230  mesh.boundary()[newPatchI], // new fvPatch
231  fld.dimensionedInternalField(), // new int. field
232  patchMapper // mapper
233  )
234  );
235  }
236  else
237  {
238  // PatchField will have correct size already. Just slot in
239  // my elements.
240 
241  // From new patch faces to patch faces on added mesh. This
242  // time keep unmapped elements -1.
243  labelList newToAdded
244  (
245  calcPatchMap
246  (
247  oldPatch.start(),
248  oldPatch.size(),
249  meshMap.addedFaceMap(),
250  newPatch,
251  -1 // unmapped values
252  )
253  );
254 
255  const fvPatchField<Type>& addedFld =
256  fldToAdd.boundaryField()[patchI];
257 
258  fvPatchField<Type>& newFld = fld.boundaryField()[newPatchI];
259 
260  forAll(newFld, i)
261  {
262  label oldFaceI = newToAdded[i];
263 
264  if (oldFaceI >= 0 && oldFaceI < addedFld.size())
265  {
266  newFld[i] = addedFld[oldFaceI];
267  }
268  }
269  }
270  }
271  }
272  }
273 }
274 
275 
276 template<class Type>
278 (
279  const mapAddedPolyMesh& meshMap,
280  const fvMesh& mesh,
281  const fvMesh& meshToAdd
282 )
283 {
285  (
286  mesh.objectRegistry::lookupClass
288  ()
289  );
290 
292  (
293  meshToAdd.objectRegistry::lookupClass
295  ()
296  );
297 
298  // It is necessary to enforce that all old-time fields are stored
299  // before the mapping is performed. Otherwise, if the
300  // old-time-level field is mapped before the field itself, sizes
301  // will not match.
302 
303  for
304  (
306  iterator fieldIter = fields.begin();
307  fieldIter != fields.end();
308  ++fieldIter
309  )
310  {
311  const_cast<GeometricField<Type, fvPatchField, volMesh>*>(fieldIter())
312  ->storeOldTimes();
313  }
314 
315 
316  for
317  (
319  iterator fieldIter = fields.begin();
320  fieldIter != fields.end();
321  ++fieldIter
322  )
323  {
326  (
327  *fieldIter()
328  );
329 
330  if (fieldsToAdd.found(fld.name()))
331  {
332  Pout<< "Mapping field " << fld.name() << endl;
333 
335  *fieldsToAdd[fld.name()];
336 
337  MapVolField<Type>(meshMap, fld, fldToAdd);
338  }
339  else
340  {
341  WarningIn("fvMeshAdder::MapVolFields")
342  << "Not mapping field " << fld.name()
343  << " since not present on mesh to add"
344  << endl;
345  }
346  }
347 }
348 
349 
350 template<class Type>
351 void Foam::fvMeshAdder::MapSurfaceField
352 (
353  const mapAddedPolyMesh& meshMap,
354 
357 )
358 {
359  const fvMesh& mesh = fld.mesh();
360  const labelList& oldPatchStarts = meshMap.oldPatchStarts();
361 
362  // Internal field
363  // ~~~~~~~~~~~~~~
364 
365  // Store old internal field
366  {
367  Field<Type> oldField(fld);
368 
369  // Modify internal field
370  Field<Type>& intFld = fld.internalField();
371 
372  intFld.setSize(mesh.nInternalFaces());
373 
374  map(oldField, meshMap.oldFaceMap(), intFld);
375  map(fldToAdd, meshMap.addedFaceMap(), intFld);
376 
377  // Faces that were boundary faces but are not anymore.
378  // Use owner value (so lowest numbered cell, i.e. from 'old' not 'added'
379  // mesh)
380  forAll(fld.boundaryField(), patchI)
381  {
382  const fvsPatchField<Type>& pf = fld.boundaryField()[patchI];
383 
384  label start = oldPatchStarts[patchI];
385 
386  forAll(pf, i)
387  {
388  label newFaceI = meshMap.oldFaceMap()[start + i];
389 
390  if (newFaceI >= 0 && newFaceI < mesh.nInternalFaces())
391  {
392  intFld[newFaceI] = pf[i];
393  }
394  }
395  }
396  }
397 
398 
399  // Patch fields from old mesh
400  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
401 
402  {
403  const labelList& oldPatchMap = meshMap.oldPatchMap();
404  const labelList& oldPatchSizes = meshMap.oldPatchSizes();
405 
406  // Reorder old patches in order of new ones. Put removed patches at end.
407 
408  label unusedPatchI = 0;
409 
410  forAll(oldPatchMap, patchI)
411  {
412  label newPatchI = oldPatchMap[patchI];
413 
414  if (newPatchI != -1)
415  {
416  unusedPatchI++;
417  }
418  }
419 
420  label nUsedPatches = unusedPatchI;
421 
422  // Reorder list for patchFields
423  labelList oldToNew(oldPatchMap.size());
424 
425  forAll(oldPatchMap, patchI)
426  {
427  label newPatchI = oldPatchMap[patchI];
428 
429  if (newPatchI != -1)
430  {
431  oldToNew[patchI] = newPatchI;
432  }
433  else
434  {
435  oldToNew[patchI] = unusedPatchI++;
436  }
437  }
438 
439 
440  // Sort deleted ones last so is now in newPatch ordering
441  fld.boundaryField().reorder(oldToNew);
442  // Extend to covers all patches
443  fld.boundaryField().setSize(mesh.boundaryMesh().size());
444  // Delete unused patches
445  for
446  (
447  label newPatchI = nUsedPatches;
448  newPatchI < fld.boundaryField().size();
449  newPatchI++
450  )
451  {
452  fld.boundaryField().set(newPatchI, NULL);
453  }
454 
455 
456  // Map old values
457  // ~~~~~~~~~~~~~~
458 
459  forAll(oldPatchMap, patchI)
460  {
461  label newPatchI = oldPatchMap[patchI];
462 
463  if (newPatchI != -1)
464  {
465  labelList newToOld
466  (
467  calcPatchMap
468  (
469  oldPatchStarts[patchI],
470  oldPatchSizes[patchI],
471  meshMap.oldFaceMap(),
472  mesh.boundaryMesh()[newPatchI],
473  0 // unmapped value
474  )
475  );
476 
477  directFvPatchFieldMapper patchMapper(newToOld);
478 
479 
480  // Create new patchField with same type as existing one.
481  // Note:
482  // - boundaryField already in new order so access with newPatchI
483  // - fld.boundaryField()[newPatchI] both used for type and old
484  // value
485  // - hope that field mapping allows aliasing since old and new
486  // are same memory!
487  fld.boundaryField().set
488  (
489  newPatchI,
490  fvsPatchField<Type>::New
491  (
492  fld.boundaryField()[newPatchI], // old field
493  mesh.boundary()[newPatchI], // new fvPatch
494  fld.dimensionedInternalField(), // new internal field
495  patchMapper // mapper (new to old)
496  )
497  );
498  }
499  }
500  }
501 
502 
503 
504  // Patch fields from added mesh
505  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
506 
507  {
508  const labelList& addedPatchMap = meshMap.addedPatchMap();
509 
510  // Add addedMesh patches
511  forAll(addedPatchMap, patchI)
512  {
513  label newPatchI = addedPatchMap[patchI];
514 
515  if (newPatchI != -1)
516  {
517  const polyPatch& newPatch = mesh.boundaryMesh()[newPatchI];
518  const polyPatch& oldPatch =
519  fldToAdd.mesh().boundaryMesh()[patchI];
520 
521  if (!fld.boundaryField()(newPatchI))
522  {
523  // First occurrence of newPatchI. Map from existing
524  // patchField
525 
526  // From new patch faces to patch faces on added mesh.
527  labelList newToAdded
528  (
529  calcPatchMap
530  (
531  oldPatch.start(),
532  oldPatch.size(),
533  meshMap.addedFaceMap(),
534  newPatch,
535  0 // unmapped values
536  )
537  );
538 
539  directFvPatchFieldMapper patchMapper(newToAdded);
540 
541  fld.boundaryField().set
542  (
543  newPatchI,
544  fvsPatchField<Type>::New
545  (
546  fldToAdd.boundaryField()[patchI],// added field
547  mesh.boundary()[newPatchI], // new fvPatch
548  fld.dimensionedInternalField(), // new int. field
549  patchMapper // mapper
550  )
551  );
552  }
553  else
554  {
555  // PatchField will have correct size already. Just slot in
556  // my elements.
557 
558  // From new patch faces to patch faces on added mesh. This
559  // time keep unmapped elements -1.
560  labelList newToAdded
561  (
562  calcPatchMap
563  (
564  oldPatch.start(),
565  oldPatch.size(),
566  meshMap.addedFaceMap(),
567  newPatch,
568  -1 // unmapped values
569  )
570  );
571 
572  const fvsPatchField<Type>& addedFld =
573  fldToAdd.boundaryField()[patchI];
574 
575  fvsPatchField<Type>& newFld =
576  fld.boundaryField()[newPatchI];
577 
578  forAll(newFld, i)
579  {
580  label oldFaceI = newToAdded[i];
581 
582  if (oldFaceI >= 0 && oldFaceI < addedFld.size())
583  {
584  newFld[i] = addedFld[oldFaceI];
585  }
586  }
587  }
588  }
589  }
590  }
591 }
592 
593 
594 template<class Type>
596 (
597  const mapAddedPolyMesh& meshMap,
598  const fvMesh& mesh,
599  const fvMesh& meshToAdd
600 )
601 {
603 
605  (
606  mesh.objectRegistry::lookupClass<fldType>()
607  );
608 
609  HashTable<const fldType*> fieldsToAdd
610  (
611  meshToAdd.objectRegistry::lookupClass<fldType>()
612  );
613 
614  // It is necessary to enforce that all old-time fields are stored
615  // before the mapping is performed. Otherwise, if the
616  // old-time-level field is mapped before the field itself, sizes
617  // will not match.
618 
619  for
620  (
621  typename HashTable<const fldType*>::
622  iterator fieldIter = fields.begin();
623  fieldIter != fields.end();
624  ++fieldIter
625  )
626  {
627  const_cast<fldType*>(fieldIter())
628  ->storeOldTimes();
629  }
630 
631 
632  for
633  (
634  typename HashTable<const fldType*>::
635  iterator fieldIter = fields.begin();
636  fieldIter != fields.end();
637  ++fieldIter
638  )
639  {
640  fldType& fld = const_cast<fldType&>(*fieldIter());
641 
642  if (fieldsToAdd.found(fld.name()))
643  {
644  Pout<< "Mapping field " << fld.name() << endl;
645 
646  const fldType& fldToAdd = *fieldsToAdd[fld.name()];
647 
648  MapSurfaceField<Type>(meshMap, fld, fldToAdd);
649  }
650  else
651  {
652  WarningIn("fvMeshAdder::MapSurfaceFields")
653  << "Not mapping field " << fld.name()
654  << " since not present on mesh to add"
655  << endl;
656  }
657  }
658 }
659 
660 
661 // ************************ vim: set sw=4 sts=4 et: ************************ //