motionSmootherAlgo.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 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 "motionSmootherAlgo.H"
30 #include "twoDPointCorrector.H"
31 #include "faceSet.H"
32 #include "pointSet.H"
34 #include "pointConstraints.H"
35 #include "syncTools.H"
36 #include "meshTools.H"
37 #include "OFstream.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(motionSmootherAlgo, 0);
44 }
45 
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
49 void Foam::motionSmootherAlgo::testSyncPositions
50 (
51  const pointField& fld,
52  const scalar maxMag
53 ) const
54 {
55  pointField syncedFld(fld);
56 
58  (
59  mesh_,
60  syncedFld,
61  minEqOp<point>(), // combine op
62  point(GREAT,GREAT,GREAT) // null
63  );
64 
65  forAll(syncedFld, i)
66  {
67  if (mag(syncedFld[i] - fld[i]) > maxMag)
68  {
70  << "On point " << i << " point:" << fld[i]
71  << " synchronised point:" << syncedFld[i]
72  << abort(FatalError);
73  }
74  }
75 }
76 
77 
78 void Foam::motionSmootherAlgo::checkFld(const pointScalarField& fld)
79 {
80  forAll(fld, pointi)
81  {
82  const scalar val = fld[pointi];
83 
84  if ((val > -GREAT) && (val < GREAT))
85  {}
86  else
87  {
89  << "Problem : point:" << pointi << " value:" << val
90  << abort(FatalError);
91  }
92  }
93 }
94 
95 
96 Foam::labelHashSet Foam::motionSmootherAlgo::getPoints
97 (
98  const labelHashSet& faceLabels
99 ) const
100 {
101  labelHashSet usedPoints(mesh_.nPoints()/100);
102 
103  for (const label faceId : faceLabels)
104  {
105  usedPoints.insert(mesh_.faces()[faceId]);
106  }
107 
108  return usedPoints;
109 }
110 
111 
112 Foam::tmp<Foam::scalarField> Foam::motionSmootherAlgo::calcEdgeWeights
113 (
114  const pointField& points
115 ) const
116 {
117  const edgeList& edges = mesh_.edges();
118 
119  auto twght = tmp<scalarField>::New(edges.size());
120  auto& wght = twght.ref();
121 
122  forAll(edges, edgei)
123  {
124  wght[edgei] = 1.0/(edges[edgei].mag(points)+SMALL);
125  }
126  return twght;
127 }
128 
129 
130 // Smooth on selected points (usually patch points)
131 void Foam::motionSmootherAlgo::minSmooth
132 (
133  const scalarField& edgeWeights,
134  const bitSet& isAffectedPoint,
135  const labelList& meshPoints,
136  const pointScalarField& fld,
137  pointScalarField& newFld
138 ) const
139 {
140  tmp<pointScalarField> tavgFld = avg
141  (
142  fld,
143  edgeWeights //scalarField(mesh_.nEdges(), 1.0) // uniform weighting
144  );
145  const pointScalarField& avgFld = tavgFld();
146 
147  for (const label pointi : meshPoints)
148  {
149  if (isAffectedPoint.test(pointi))
150  {
151  newFld[pointi] = min
152  (
153  fld[pointi],
154  0.5*fld[pointi] + 0.5*avgFld[pointi]
155  );
156  }
157  }
158 
159  // Single and multi-patch constraints
160  pointConstraints::New(pMesh()).constrain(newFld, false);
161 }
162 
163 
164 // Smooth on all internal points
165 void Foam::motionSmootherAlgo::minSmooth
166 (
167  const scalarField& edgeWeights,
168  const bitSet& isAffectedPoint,
169  const pointScalarField& fld,
170  pointScalarField& newFld
171 ) const
172 {
173  tmp<pointScalarField> tavgFld = avg
174  (
175  fld,
176  edgeWeights //scalarField(mesh_.nEdges(), 1.0) // uniform weighting
177  );
178  const pointScalarField& avgFld = tavgFld();
179 
180  forAll(fld, pointi)
181  {
182  if (isAffectedPoint.test(pointi) && isInternalPoint_.test(pointi))
183  {
184  newFld[pointi] = min
185  (
186  fld[pointi],
187  0.5*fld[pointi] + 0.5*avgFld[pointi]
188  );
189  }
190  }
191 
192  // Single and multi-patch constraints
193  pointConstraints::New(pMesh()).constrain(newFld, false);
194 
195 }
196 
197 
198 // Scale on all internal points
199 void Foam::motionSmootherAlgo::scaleField
200 (
201  const labelHashSet& pointLabels,
202  const scalar scale,
204 ) const
205 {
206  for (const label pointi : pointLabels)
207  {
208  if (isInternalPoint_.test(pointi))
209  {
210  fld[pointi] *= scale;
211  }
212  }
213 
214  // Single and multi-patch constraints
215  pointConstraints::New(pMesh()).constrain(fld, false);
216 }
217 
218 
219 // Scale on selected points (usually patch points)
220 void Foam::motionSmootherAlgo::scaleField
221 (
222  const labelList& meshPoints,
223  const labelHashSet& pointLabels,
224  const scalar scale,
226 ) const
227 {
228  for (const label pointi : meshPoints)
229  {
230  if (pointLabels.found(pointi))
231  {
232  fld[pointi] *= scale;
233  }
234  }
235 }
236 
237 
238 // Lower on internal points
239 void Foam::motionSmootherAlgo::subtractField
240 (
241  const labelHashSet& pointLabels,
242  const scalar f,
244 ) const
245 {
246  for (const label pointi : pointLabels)
247  {
248  if (isInternalPoint_.test(pointi))
249  {
250  fld[pointi] = max(0.0, fld[pointi]-f);
251  }
252  }
253 
254  // Single and multi-patch constraints
256 }
257 
258 
259 // Scale on selected points (usually patch points)
260 void Foam::motionSmootherAlgo::subtractField
261 (
262  const labelList& meshPoints,
263  const labelHashSet& pointLabels,
264  const scalar f,
266 ) const
267 {
268  for (const label pointi : meshPoints)
269  {
270  if (pointLabels.found(pointi))
271  {
272  fld[pointi] = max(0.0, fld[pointi]-f);
273  }
274  }
275 }
276 
277 
278 void Foam::motionSmootherAlgo::getAffectedFacesAndPoints
279 (
280  const label nPointIter,
281  const faceSet& wrongFaces,
282 
283  labelList& affectedFaces,
284  bitSet& isAffectedPoint
285 ) const
286 {
287  isAffectedPoint.reset();
288  isAffectedPoint.resize(mesh_.nPoints());
289 
290  faceSet nbrFaces(mesh_, "checkFaces", wrongFaces);
291 
292  // Find possible points influenced by nPointIter iterations of
293  // scaling and smoothing by doing pointCellpoint walk.
294  // Also update faces-to-be-checked to extend one layer beyond the points
295  // that will get updated.
296 
297  for (label i = 0; i < nPointIter; i++)
298  {
299  pointSet nbrPoints(mesh_, "grownPoints", getPoints(nbrFaces));
300 
301  for (const label pointi : nbrPoints)
302  {
303  for (const label celli : mesh_.pointCells(pointi))
304  {
305  nbrFaces.set(mesh_.cells()[celli]); // set multiple
306  }
307  }
308  nbrFaces.sync(mesh_);
309 
310  if (i == nPointIter - 2)
311  {
312  for (const label facei : nbrFaces)
313  {
314  isAffectedPoint.set(mesh_.faces()[facei]); // set multiple
315  }
316  }
317  }
318 
319  affectedFaces = nbrFaces.toc();
320 }
321 
322 
323 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
324 
325 Foam::motionSmootherAlgo::motionSmootherAlgo
326 (
327  polyMesh& mesh,
328  pointMesh& pMesh,
330  pointVectorField& displacement,
331  pointScalarField& scale,
332  pointField& oldPoints,
333  const labelList& adaptPatchIDs,
334  const dictionary& paramDict,
335  const bool dryRun
336 )
337 :
338  mesh_(mesh),
339  pMesh_(pMesh),
340  pp_(pp),
341  displacement_(displacement),
342  scale_(scale),
343  oldPoints_(oldPoints),
344  adaptPatchIDs_(adaptPatchIDs),
345  paramDict_(paramDict),
346  dryRun_(dryRun),
347  isInternalPoint_(mesh_.nPoints(), true)
348 {
349  updateMesh();
350 }
351 
352 
353 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
354 
356 {}
357 
358 
359 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
360 
362 {
363  return mesh_;
364 }
365 
366 
368 {
369  return pMesh_;
370 }
371 
372 
374 {
375  return pp_;
376 }
377 
378 
380 {
381  return adaptPatchIDs_;
382 }
383 
384 
386 {
387  return paramDict_;
388 }
389 
390 
392 {
393  oldPoints_ = mesh_.points();
394 
395  scale_ = 1.0;
396 
397  // No need to update twoDmotion corrector since only holds edge labels
398  // which will remain the same as before. So unless the mesh was distorted
399  // severely outside of motionSmootherAlgo there will be no need.
400 }
401 
402 
404 (
405  const labelList& patchIDs,
406  pointVectorField& displacement
407 )
408 {
409  pointVectorField::Boundary& displacementBf =
410  displacement.boundaryFieldRef();
411 
412  // Adapt the fixedValue bc's (i.e. copy internal point data to
413  // boundaryField for all affected patches)
414  for (const label patchi : patchIDs)
415  {
416  displacementBf[patchi] ==
417  displacementBf[patchi].patchInternalField();
418  }
419 
420  // Make consistent with non-adapted bc's by evaluating those now and
421  // resetting the displacement from the values.
422  // Note that we're just doing a correctBoundaryConditions with
423  // fixedValue bc's first.
424  labelHashSet adaptPatchSet(patchIDs);
425 
426  const lduSchedule& patchSchedule = displacement.mesh().globalData().
427  patchSchedule();
428 
429  forAll(patchSchedule, patchEvalI)
430  {
431  const label patchi = patchSchedule[patchEvalI].patch;
432 
433  if (!adaptPatchSet.found(patchi))
434  {
435  if (patchSchedule[patchEvalI].init)
436  {
437  displacementBf[patchi]
438  .initEvaluate(Pstream::commsTypes::scheduled);
439  }
440  else
441  {
442  displacementBf[patchi]
444  }
445  }
446  }
447 
448  // Multi-patch constraints
449  pointConstraints::New(displacement.mesh()).constrainCorners(displacement);
450 
451  // Adapt the fixedValue bc's (i.e. copy internal point data to
452  // boundaryField for all affected patches) to take the changes caused
453  // by multi-corner constraints into account.
454  for (const label patchi : patchIDs)
455  {
456  displacementBf[patchi] == displacementBf[patchi].patchInternalField();
457  }
458 }
459 
460 
462 {
463  setDisplacementPatchFields(adaptPatchIDs_, displacement_);
464 }
465 
466 
468 (
469  const labelList& patchIDs,
470  const indirectPrimitivePatch& pp,
471  pointField& patchDisp,
472  pointVectorField& displacement
473 )
474 {
475  const polyMesh& mesh = displacement.mesh()();
476 
477  // See comment in .H file about shared points.
478  // We want to disallow effect of loose coupled points - we only
479  // want to see effect of proper fixedValue boundary conditions
480 
481  const labelList& cppMeshPoints =
483 
484  const labelList& ppMeshPoints = pp.meshPoints();
485 
486  // Knock out displacement on points which are not on pp but are coupled
487  // to them since we want 'proper' values from displacement to take
488  // precedence.
489  {
490  bitSet isPatchPoint(mesh.nPoints(), ppMeshPoints);
492  (
493  mesh,
494  isPatchPoint,
496  0u
497  );
498 
499  for (const label pointi : cppMeshPoints)
500  {
501  if (isPatchPoint.test(pointi))
502  {
503  displacement[pointi] = Zero;
504  }
505  }
506  }
507 
508 
509  // Set internal point data from displacement on combined patch points.
510  forAll(ppMeshPoints, patchPointi)
511  {
512  displacement[ppMeshPoints[patchPointi]] = patchDisp[patchPointi];
513  }
514 
515 
516  // Combine any coupled points
518  (
519  mesh,
520  displacement,
521  maxMagEqOp(), // combine op
522  vector::zero // null value
523  );
524 
525 
526  // Adapt the fixedValue bc's (i.e. copy internal point data to
527  // boundaryField for all affected patches)
528  setDisplacementPatchFields(patchIDs, displacement);
529 
530 
531  if (debug)
532  {
533  OFstream str(mesh.db().path()/"changedPoints.obj");
534  label nVerts = 0;
535  forAll(ppMeshPoints, patchPointi)
536  {
537  const vector& newDisp = displacement[ppMeshPoints[patchPointi]];
538 
539  if (mag(newDisp-patchDisp[patchPointi]) > SMALL)
540  {
541  const point& pt = mesh.points()[ppMeshPoints[patchPointi]];
542 
543  meshTools::writeOBJ(str, pt);
544  nVerts++;
545  //Pout<< "Point:" << pt
546  // << " oldDisp:" << patchDisp[patchPointi]
547  // << " newDisp:" << newDisp << endl;
548  }
549  }
550  Pout<< "Written " << nVerts << " points that are changed to file "
551  << str.name() << endl;
552  }
553 
554  // Now reset input displacement
555  forAll(ppMeshPoints, patchPointi)
556  {
557  patchDisp[patchPointi] = displacement[ppMeshPoints[patchPointi]];
558  }
559 }
560 
561 
563 {
564  setDisplacement(adaptPatchIDs_, pp_, patchDisp, displacement_);
565 }
566 
567 
568 // correctBoundaryConditions with fixedValue bc's first.
570 (
571  pointVectorField& displacement
572 ) const
573 {
574  labelHashSet adaptPatchSet(adaptPatchIDs_);
575 
576  const lduSchedule& patchSchedule = mesh_.globalData().patchSchedule();
577 
578  pointVectorField::Boundary& displacementBf =
579  displacement.boundaryFieldRef();
580 
581  // 1. evaluate on adaptPatches
582  forAll(patchSchedule, patchEvalI)
583  {
584  const label patchi = patchSchedule[patchEvalI].patch;
585 
586  if (adaptPatchSet.found(patchi))
587  {
588  if (patchSchedule[patchEvalI].init)
589  {
590  displacementBf[patchi]
591  .initEvaluate(Pstream::commsTypes::blocking);
592  }
593  else
594  {
595  displacementBf[patchi]
597  }
598  }
599  }
600 
601 
602  // 2. evaluate on non-AdaptPatches
603  forAll(patchSchedule, patchEvalI)
604  {
605  const label patchi = patchSchedule[patchEvalI].patch;
606 
607  if (!adaptPatchSet.found(patchi))
608  {
609  if (patchSchedule[patchEvalI].init)
610  {
611  displacementBf[patchi]
612  .initEvaluate(Pstream::commsTypes::blocking);
613  }
614  else
615  {
616  displacementBf[patchi]
618  }
619  }
620  }
621 
622  // Multi-patch constraints
623  pointConstraints::New(displacement.mesh()).constrainCorners(displacement);
624 
625  // Correct for problems introduced by corner constraints
627  (
628  mesh_,
629  displacement,
630  maxMagEqOp(), // combine op
631  vector::zero // null value
632  );
633 }
634 
635 
636 
638 {
639  // Correct for 2-D motion
640  const twoDPointCorrector& twoDCorrector = twoDPointCorrector::New(mesh_);
641 
642  if (twoDCorrector.required())
643  {
644  Info<< "Correcting 2-D mesh motion";
645 
646  if (mesh_.globalData().parallel())
647  {
649  << "2D mesh-motion probably not correct in parallel" << endl;
650  }
651 
652  // We do not want to move 3D planes so project all points onto those
653  const pointField& oldPoints = mesh_.points();
654  const edgeList& edges = mesh_.edges();
655 
656  const labelList& neIndices = twoDCorrector.normalEdgeIndices();
657  const vector& pn = twoDCorrector.planeNormal();
658 
659  for (const label edgei : neIndices)
660  forAll(neIndices, i)
661  {
662  const edge& e = edges[edgei];
663 
664  point& pStart = newPoints[e.start()];
665 
666  pStart += pn*(pn & (oldPoints[e.start()] - pStart));
667 
668  point& pEnd = newPoints[e.end()];
669 
670  pEnd += pn*(pn & (oldPoints[e.end()] - pEnd));
671  }
672 
673  // Correct tangentially
674  twoDCorrector.correctPoints(newPoints);
675  Info<< " ...done" << endl;
676  }
677 
678  if (debug)
679  {
680  Pout<< "motionSmootherAlgo::modifyMotionPoints :"
681  << " testing sync of newPoints."
682  << endl;
683  testSyncPositions(newPoints, 1e-6*mesh_.bounds().mag());
684  }
685 }
686 
687 
689 {
690  // Make sure to clear out tetPtIs since used in checks (sometimes, should
691  // really check)
692  mesh_.clearTetBasePtIs();
693  pp_.movePoints(mesh_.points());
694 }
695 
696 
698 (
699  const scalar errorReduction
700 )
701 {
702  scalar old = paramDict_.get<scalar>("errorReduction");
703 
704  paramDict_.remove("errorReduction");
705  paramDict_.add("errorReduction", errorReduction);
706 
707  return old;
708 }
709 
710 
712 (
713  labelList& checkFaces,
714  const bool smoothMesh,
715  const label nAllowableErrors
716 )
717 {
718  List<labelPair> emptyBaffles;
719  return scaleMesh
720  (
721  checkFaces,
722  emptyBaffles,
723  smoothMesh,
724  nAllowableErrors
725  );
726 }
727 
728 
730 (
731  labelList& checkFaces,
732  const List<labelPair>& baffles,
733  const bool smoothMesh,
734  const label nAllowableErrors
735 )
736 {
737  return scaleMesh
738  (
739  checkFaces,
740  baffles,
741  paramDict_,
742  paramDict_,
743  smoothMesh,
744  nAllowableErrors
745  );
746 }
747 
748 
750 {
751  // Set newPoints as old + scale*displacement
752 
753  // Create overall displacement with same b.c.s as displacement_
754  wordList actualPatchTypes;
755  {
756  const pointBoundaryMesh& pbm = displacement_.mesh().boundary();
757  actualPatchTypes.setSize(pbm.size());
758  forAll(pbm, patchi)
759  {
760  actualPatchTypes[patchi] = pbm[patchi].type();
761  }
762  }
763 
764  wordList actualPatchFieldTypes;
765  {
766  const pointVectorField::Boundary& pfld =
767  displacement_.boundaryField();
768  actualPatchFieldTypes.setSize(pfld.size());
769  forAll(pfld, patchi)
770  {
771  if (isA<fixedValuePointPatchField<vector>>(pfld[patchi]))
772  {
773  // Get rid of funny
774  actualPatchFieldTypes[patchi] =
776  }
777  else
778  {
779  actualPatchFieldTypes[patchi] = pfld[patchi].type();
780  }
781  }
782  }
783 
784  pointVectorField totalDisplacement
785  (
786  IOobject
787  (
788  "totalDisplacement",
789  mesh_.time().timeName(),
790  mesh_,
793  false
794  ),
795  scale_*displacement_,
796  actualPatchFieldTypes,
797  actualPatchTypes
798  );
799  correctBoundaryConditions(totalDisplacement);
800 
801  if (debug)
802  {
803  Pout<< "scaleMesh : testing sync of totalDisplacement" << endl;
804  testSyncField
805  (
806  totalDisplacement,
807  maxMagEqOp(),
808  vector::zero, // null value
809  1e-6*mesh_.bounds().mag()
810  );
811  }
812 
813  tmp<pointField> tnewPoints(oldPoints_ + totalDisplacement.primitiveField());
814 
815  // Correct for 2-D motion
816  modifyMotionPoints(tnewPoints.ref());
817 
818  return tnewPoints;
819 }
820 
821 
823 (
824  labelList& checkFaces,
825  const List<labelPair>& baffles,
826  const dictionary& paramDict,
827  const dictionary& meshQualityDict,
828  const bool smoothMesh,
829  const label nAllowableErrors
830 )
831 {
832  if (!smoothMesh && adaptPatchIDs_.empty())
833  {
835  << "You specified both no movement on the internal mesh points"
836  << " (smoothMesh = false)" << nl
837  << "and no movement on the patch (adaptPatchIDs is empty)" << nl
838  << "Hence nothing to adapt."
839  << exit(FatalError);
840  }
841 
842  if (debug)
843  {
844  // Had a problem with patches moved non-synced. Check transformations.
845  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
846 
847  Pout<< "Entering scaleMesh : coupled patches:" << endl;
848  forAll(patches, patchi)
849  {
850  if (patches[patchi].coupled())
851  {
852  const coupledPolyPatch& pp =
853  refCast<const coupledPolyPatch>(patches[patchi]);
854 
855  Pout<< '\t' << patchi << '\t' << pp.name()
856  << " parallel:" << pp.parallel()
857  << " separated:" << pp.separated()
858  << " forwardT:" << pp.forwardT().size()
859  << endl;
860  }
861  }
862  }
863 
864  const scalar errorReduction = get<scalar>
865  (
866  paramDict, "errorReduction", dryRun_, keyType::REGEX_RECURSIVE
867  );
868  const label nSmoothScale = get<label>
869  (
870  paramDict, "nSmoothScale", dryRun_, keyType::REGEX_RECURSIVE
871  );
872 
873  // Note: displacement_ should already be synced already from setDisplacement
874  // but just to make sure.
876  (
877  mesh_,
878  displacement_,
879  maxMagEqOp(),
880  vector::zero // null value
881  );
882 
883  Info<< "Moving mesh using displacement scaling :"
884  << " min:" << gMin(scale_.primitiveField())
885  << " max:" << gMax(scale_.primitiveField())
886  << endl;
887 
888  // Get points using current displacement and scale. Optionally 2D corrected.
889  pointField newPoints(curPoints());
890 
891  // Move. No need to do 2D correction since curPoints already done that.
892  mesh_.movePoints(newPoints);
893  movePoints();
894 
895 
896  // Check. Returns parallel number of incorrect faces.
897  faceSet wrongFaces(mesh_, "wrongFaces", mesh_.nFaces()/100+100);
898  checkMesh
899  (
900  false,
901  mesh_,
902  meshQualityDict,
903  checkFaces,
904  baffles,
905  wrongFaces,
906  dryRun_
907  );
908 
909  if (returnReduce(wrongFaces.size(), sumOp<label>()) <= nAllowableErrors)
910  {
911  return true;
912  }
913  else
914  {
915  // Sync across coupled faces by extending the set.
916  wrongFaces.sync(mesh_);
917 
918  // Special case:
919  // if errorReduction is set to zero, extend wrongFaces
920  // to face-Cell-faces to ensure quick return to previously valid mesh
921 
922  if (mag(errorReduction) < SMALL)
923  {
924  labelHashSet newWrongFaces(wrongFaces);
925  for (const label facei : wrongFaces)
926  {
927  const label own = mesh_.faceOwner()[facei];
928  const cell& ownFaces = mesh_.cells()[own];
929 
930  newWrongFaces.insert(ownFaces);
931 
932  if (facei < mesh_.nInternalFaces())
933  {
934  const label nei = mesh_.faceNeighbour()[facei];
935  const cell& neiFaces = mesh_.cells()[nei];
936 
937  newWrongFaces.insert(neiFaces);
938  }
939  }
940  wrongFaces.transfer(newWrongFaces);
941  wrongFaces.sync(mesh_);
942  }
943 
944 
945  // Find out points used by wrong faces and scale displacement.
946  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
947 
948  pointSet usedPoints(mesh_, "usedPoints", getPoints(wrongFaces));
949  usedPoints.sync(mesh_);
950 
951 
952  // Grow a few layers to determine
953  // - points to be smoothed
954  // - faces to be checked in next iteration
955  bitSet isAffectedPoint(mesh_.nPoints());
956  getAffectedFacesAndPoints
957  (
958  nSmoothScale, // smoothing iterations
959  wrongFaces, // error faces
960  checkFaces,
961  isAffectedPoint
962  );
963 
964  if (debug)
965  {
966  Pout<< "Faces in error:" << wrongFaces.size()
967  << " with points:" << usedPoints.size()
968  << endl;
969  }
970 
971  if (adaptPatchIDs_.size())
972  {
973  // Scale conflicting patch points
974  scaleField(pp_.meshPoints(), usedPoints, errorReduction, scale_);
975  //subtractField(pp_.meshPoints(), usedPoints, 0.1, scale_);
976  }
977  if (smoothMesh)
978  {
979  // Scale conflicting internal points
980  scaleField(usedPoints, errorReduction, scale_);
981  //subtractField(usedPoints, 0.1, scale_);
982  }
983 
984  scalarField eWeights(calcEdgeWeights(oldPoints_));
985 
986  for (label i = 0; i < nSmoothScale; ++i)
987  {
988  if (adaptPatchIDs_.size())
989  {
990  // Smooth patch values
991  pointScalarField oldScale(scale_);
992  minSmooth
993  (
994  eWeights,
995  isAffectedPoint,
996  pp_.meshPoints(),
997  oldScale,
998  scale_
999  );
1000  checkFld(scale_);
1001  }
1002  if (smoothMesh)
1003  {
1004  // Smooth internal values
1005  pointScalarField oldScale(scale_);
1006  minSmooth(eWeights, isAffectedPoint, oldScale, scale_);
1007  checkFld(scale_);
1008  }
1009  }
1010 
1012  (
1013  mesh_,
1014  scale_,
1015  maxEqOp<scalar>(),
1016  -GREAT // null value
1017  );
1018 
1019 
1020  if (debug)
1021  {
1022  Pout<< "scale_ after smoothing :"
1023  << " min:" << Foam::gMin(scale_)
1024  << " max:" << Foam::gMax(scale_)
1025  << endl;
1026  }
1027 
1028  return false;
1029  }
1030 }
1031 
1032 
1034 {
1035  const pointBoundaryMesh& patches = pMesh_.boundary();
1036 
1037  // Check whether displacement has fixed value b.c. on adaptPatchID
1038  for (const label patchi : adaptPatchIDs_)
1039  {
1040  if
1041  (
1042  !isA<fixedValuePointPatchVectorField>
1043  (
1044  displacement_.boundaryField()[patchi]
1045  )
1046  )
1047  {
1049  << "Patch " << patches[patchi].name()
1050  << " has wrong boundary condition "
1051  << displacement_.boundaryField()[patchi].type()
1052  << " on field " << displacement_.name() << nl
1053  << "Only type allowed is "
1054  << fixedValuePointPatchVectorField::typeName
1055  << exit(FatalError);
1056  }
1057  }
1058 
1059 
1060  // Determine internal points. Note that for twoD there are no internal
1061  // points so we use the points of adaptPatchIDs instead
1062 
1063  isInternalPoint_.unset(pp_.meshPoints()); // unset multiple
1064 
1065  // Calculate master edge addressing
1066  isMasterEdge_ = syncTools::getMasterEdges(mesh_);
1067 }
1068 
1069 
1070 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
meshTools.H
Foam::motionSmootherAlgo::setErrorReduction
scalar setErrorReduction(const scalar)
Set the errorReduction (by how much to scale the displacement.
Definition: motionSmootherAlgo.C:698
Foam::pointMesh::boundary
const pointBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: pointMesh.H:109
Foam::edgeList
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
Foam::motionSmootherAlgo::modifyMotionPoints
void modifyMotionPoints(pointField &newPoints) const
Apply optional point constraint (2d correction)
Definition: motionSmootherAlgo.C:637
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::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::motionSmootherAlgo::correctBoundaryConditions
void correctBoundaryConditions(pointVectorField &) const
Special correctBoundaryConditions which evaluates fixedValue.
Definition: motionSmootherAlgo.C:570
Foam::twoDPointCorrector::planeNormal
const vector & planeNormal() const
Return plane normal.
Definition: twoDPointCorrector.C:249
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of a point.
Definition: meshTools.C:203
Foam::motionSmootherAlgo::correct
void correct()
Take over existing mesh position.
Definition: motionSmootherAlgo.C:391
Foam::motionSmootherAlgo::updateMesh
void updateMesh()
Update for new mesh topology.
Definition: motionSmootherAlgo.C:1033
Foam::motionSmootherAlgo::patch
const indirectPrimitivePatch & patch() const
Reference to patch.
Definition: motionSmootherAlgo.C:373
Foam::motionSmootherAlgo::adaptPatchIDs
const labelList & adaptPatchIDs() const
Patch labels that are being adapted.
Definition: motionSmootherAlgo.C:379
Foam::coupledPolyPatch::forwardT
virtual const tensorField & forwardT() const
Return face transformation tensor.
Definition: coupledPolyPatch.H:301
Foam::GeometricField::primitiveField
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
Definition: GeometricFieldI.H:53
Foam::motionSmootherAlgo::curPoints
tmp< pointField > curPoints() const
Get the current points (oldPoints+scale*displacement)
Definition: motionSmootherAlgo.C:749
Foam::MeshObject< pointMesh, UpdateableMeshObject, pointConstraints >::New
static const pointConstraints & New(const pointMesh &mesh, Args &&... args)
Get existing or create a new MeshObject.
Definition: MeshObject.C:48
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::motionSmootherAlgo::scaleMesh
bool scaleMesh(labelList &checkFaces, const bool smoothMesh=true, const label nAllow=0)
Move mesh with given scale. Return true if mesh ok or has.
Definition: motionSmootherAlgo.C:712
Foam::faceSet
A list of face labels.
Definition: faceSet.H:51
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::coupledPolyPatch
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
Definition: coupledPolyPatch.H:54
Foam::motionSmootherAlgo::setDisplacementPatchFields
void setDisplacementPatchFields()
Set patch fields on displacement to be consistent with.
Definition: motionSmootherAlgo.C:461
Foam::syncTools::syncPointPositions
static void syncPointPositions(const polyMesh &mesh, List< point > &positions, const CombineOp &cop, const point &nullValue)
Synchronize locations on all mesh points.
Definition: syncTools.H:201
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::HashSet< label, Hash< label > >
syncTools.H
Foam::pointBoundaryMesh::mesh
const pointMesh & mesh() const noexcept
Return the mesh reference.
Definition: pointBoundaryMesh.H:97
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::syncTools::syncPointList
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
Definition: syncToolsTemplates.C:721
Foam::sumOp
Definition: ops.H:213
Foam::primitiveMesh::nPoints
label nPoints() const noexcept
Number of mesh points.
Definition: primitiveMeshI.H:37
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
OFstream.H
Foam::coupledPolyPatch::parallel
virtual bool parallel() const
Are the cyclic planes parallel.
Definition: coupledPolyPatch.H:295
correctBoundaryConditions
cellMask correctBoundaryConditions()
Foam::twoDPointCorrector
Class applies a two-dimensional correction to mesh motion point field.
Definition: twoDPointCorrector.H:63
Foam::coupledPolyPatch::separated
virtual bool separated() const
Are the planes separated.
Definition: coupledPolyPatch.H:283
Foam::fixedValuePointPatchField< vector >
Foam::motionSmootherAlgo::~motionSmootherAlgo
~motionSmootherAlgo()
Destructor.
Definition: motionSmootherAlgo.C:355
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
pointConstraints.H
faceId
label faceId(-1)
Foam::OSstream::name
virtual const fileName & name() const
Get the name of the stream.
Definition: OSstream.H:107
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
faceSet.H
init
mesh init(true)
Foam::pointSet::sync
virtual void sync(const polyMesh &mesh)
Sync set across coupled patches. Adds coupled points to set.
Definition: pointSet.C:130
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::pointMesh
Mesh representing a set of points created from polyMesh.
Definition: pointMesh.H:51
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::maxEqOp
Definition: ops.H:80
Foam::motionSmootherAlgo::paramDict
const dictionary & paramDict() const
Definition: motionSmootherAlgo.C:385
fixedValuePointPatchFields.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::syncTools::getMasterEdges
static bitSet getMasterEdges(const polyMesh &mesh)
Definition: syncTools.C:97
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::pointBoundaryMesh
Foam::pointBoundaryMesh.
Definition: pointBoundaryMesh.H:56
Foam::IOobject::name
const word & name() const noexcept
Return name.
Definition: IOobjectI.H:65
Foam::isA
const TargetType * isA(const Type &t)
Check if dynamic_cast to TargetType is possible.
Definition: typeInfo.H:197
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::pointSet
A set of point labels.
Definition: pointSet.H:51
Foam::UPstream::commsTypes::scheduled
f
labelList f(nPoints)
Foam::GeometricField::boundaryFieldRef
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Definition: GeometricField.C:783
Foam::Vector< scalar >
Foam::List< label >
Foam::globalMeshData::coupledPatch
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
Definition: globalMeshData.C:2046
Foam::motionSmootherAlgo::mesh
const polyMesh & mesh() const
Reference to mesh.
Definition: motionSmootherAlgo.C:361
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
motionSmootherAlgo.H
Foam::motionSmootherAlgo::setDisplacement
static void setDisplacement(const labelList &patchIDs, const indirectPrimitivePatch &pp, pointField &patchDisp, pointVectorField &displacement)
Set displacement field from displacement on patch points.
Definition: motionSmootherAlgo.C:468
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::tmp::New
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::twoDPointCorrector::required
bool required() const
Is 2D correction required, i.e. is the mesh a wedge or slab.
Definition: twoDPointCorrector.H:132
Foam::motionSmootherAlgo::movePoints
void movePoints()
Update for new mesh geometry.
Definition: motionSmootherAlgo.C:688
Foam::motionSmootherAlgo::pMesh
const pointMesh & pMesh() const
Reference to pointMesh.
Definition: motionSmootherAlgo.C:367
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
twoDPointCorrector.H
Foam::patchIdentifier::name
const word & name() const noexcept
The patch name.
Definition: patchIdentifier.H:135
Foam::pointConstraints::constrain
void constrain(GeometricField< Type, pointPatchField, pointMesh > &pf, const bool overrideValue=false) const
Apply boundary conditions (single-patch constraints) and.
Definition: pointConstraintsTemplates.C:131
Foam::twoDPointCorrector::normalEdgeIndices
const labelList & normalEdgeIndices() const
Return indices of normal edges.
Definition: twoDPointCorrector.C:260
coupled
bool coupled(solutionDict.getOrDefault("coupledEnergyField", false))
Foam::twoDPointCorrector::correctPoints
void correctPoints(pointField &p) const
Correct motion points.
Definition: twoDPointCorrector.C:271
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1295
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::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatch.C:330
Foam::GeometricField< vector, pointPatchField, pointMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::IOobject::path
fileName path() const
The complete path.
Definition: IOobject.C:511
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
pointLabels
labelList pointLabels(nPoints, -1)
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatch.H:79
Foam::UPstream::commsTypes::blocking
Foam::pointScalarField
GeometricField< scalar, pointPatchField, pointMesh > pointScalarField
Definition: pointFieldsFwd.H:56
Foam::keyType::REGEX_RECURSIVE
Definition: keyType.H:87
Foam::IOobject::db
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:487
pointSet.H