smoothAlignmentSolver.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) 2013-2016 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 \*---------------------------------------------------------------------------*/
25 
26 #include "smoothAlignmentSolver.H"
27 
28 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29 
30 template<class Triangulation, class Type>
31 Foam::tmp<Foam::Field<Type>> Foam::smoothAlignmentSolver::filterFarPoints
32 (
33  const Triangulation& mesh,
34  const Field<Type>& field
35 )
36 {
37  tmp<Field<Type>> tNewField(new Field<Type>(field.size()));
38  Field<Type>& newField = tNewField();
39 
40  label added = 0;
41  label count = 0;
42 
43  for
44  (
45  typename Triangulation::Finite_vertices_iterator vit =
46  mesh.finite_vertices_begin();
47  vit != mesh.finite_vertices_end();
48  ++vit
49  )
50  {
51  if (vit->real())
52  {
53  newField[added++] = field[count];
54  }
55 
56  count++;
57  }
58 
59  newField.resize(added);
60 
61  return tNewField;
62 }
63 
64 
65 template<class Triangulation>
66 Foam::autoPtr<Foam::mapDistribute> Foam::smoothAlignmentSolver::buildReferredMap
67 (
68  const Triangulation& mesh,
69  labelList& indices
70 )
71 {
72  globalIndex globalIndexing(mesh.vertexCount());
73 
74  DynamicList<label> dynIndices(mesh.vertexCount()/10);
75 
76  for
77  (
78  typename Triangulation::Finite_vertices_iterator vit =
79  mesh.finite_vertices_begin();
80  vit != mesh.finite_vertices_end();
81  ++vit
82  )
83  {
84  if (vit->referred())
85  {
86  dynIndices.append
87  (
88  globalIndexing.toGlobal(vit->procIndex(), vit->index())
89  );
90  }
91  }
92 
93  indices.transfer(dynIndices);
94 
95  List<Map<label>> compactMap;
96  return autoPtr<mapDistribute>
97  (
98  new mapDistribute
99  (
100  globalIndexing,
101  indices,
102  compactMap
103  )
104  );
105 }
106 
107 
108 template<class Triangulation>
109 Foam::autoPtr<Foam::mapDistribute> Foam::smoothAlignmentSolver::buildMap
110 (
111  const Triangulation& mesh,
112  labelListList& pointPoints
113 )
114 {
115  pointPoints.setSize(mesh.vertexCount());
116 
117  globalIndex globalIndexing(mesh.vertexCount());
118 
119  for
120  (
121  typename Triangulation::Finite_vertices_iterator vit =
122  mesh.finite_vertices_begin();
123  vit != mesh.finite_vertices_end();
124  ++vit
125  )
126  {
127  if (!vit->real())
128  {
129  continue;
130  }
131 
132  std::list<typename Triangulation::Vertex_handle> adjVerts;
133  mesh.finite_adjacent_vertices(vit, std::back_inserter(adjVerts));
134 
135  DynamicList<label> indices(adjVerts.size());
136 
137  for
138  (
139  typename std::list<typename Triangulation::Vertex_handle>::
140  const_iterator adjVertI = adjVerts.begin();
141  adjVertI != adjVerts.end();
142  ++adjVertI
143  )
144  {
145  typename Triangulation::Vertex_handle vh = *adjVertI;
146 
147  if (!vh->farPoint())
148  {
149  indices.append
150  (
151  globalIndexing.toGlobal(vh->procIndex(), vh->index())
152  );
153  }
154  }
155 
156  pointPoints[vit->index()].transfer(indices);
157  }
158 
159  List<Map<label>> compactMap;
160  return autoPtr<mapDistribute>
161  (
162  new mapDistribute
163  (
164  globalIndexing,
165  pointPoints,
166  compactMap
167  )
168  );
169 }
170 
171 
172 template<class Triangulation>
173 Foam::tmp<Foam::triadField> Foam::smoothAlignmentSolver::buildAlignmentField
174 (
175  const Triangulation& mesh
176 )
177 {
178  tmp<triadField> tAlignments
179  (
180  new triadField(mesh.vertexCount(), triad::unset)
181  );
182  triadField& alignments = tAlignments.ref();
183 
184  for
185  (
186  typename Triangulation::Finite_vertices_iterator vit =
187  mesh.finite_vertices_begin();
188  vit != mesh.finite_vertices_end();
189  ++vit
190  )
191  {
192  if (!vit->real())
193  {
194  continue;
195  }
196 
197  alignments[vit->index()] = vit->alignment();
198  }
199 
200  return tAlignments;
201 }
202 
203 
204 template<class Triangulation>
205 Foam::tmp<Foam::pointField> Foam::smoothAlignmentSolver::buildPointField
206 (
207  const Triangulation& mesh
208 )
209 {
210  tmp<pointField> tPoints
211  (
212  new pointField(mesh.vertexCount(), point(GREAT, GREAT, GREAT))
213  );
214  pointField& points = tPoints.ref();
215 
216  for
217  (
218  typename Triangulation::Finite_vertices_iterator vit =
219  mesh.finite_vertices_begin();
220  vit != mesh.finite_vertices_end();
221  ++vit
222  )
223  {
224  if (!vit->real())
225  {
226  continue;
227  }
228 
229  points[vit->index()] = topoint(vit->point());
230  }
231 
232  return tPoints;
233 }
234 
235 
236 void Foam::smoothAlignmentSolver::applyBoundaryConditions
237 (
238  const triad& fixedAlignment,
239  triad& t
240 ) const
241 {
242  label nFixed = 0;
243 
244  forAll(fixedAlignment, dirI)
245  {
246  if (fixedAlignment.set(dirI))
247  {
248  nFixed++;
249  }
250  }
251 
252  if (nFixed == 1)
253  {
254  forAll(fixedAlignment, dirI)
255  {
256  if (fixedAlignment.set(dirI))
257  {
258  t.align(fixedAlignment[dirI]);
259  }
260  }
261  }
262  else if (nFixed == 2)
263  {
264  forAll(fixedAlignment, dirI)
265  {
266  if (fixedAlignment.set(dirI))
267  {
268  t[dirI] = fixedAlignment[dirI];
269  }
270  else
271  {
272  t[dirI] = triad::unset[dirI];
273  }
274  }
275 
276  t.orthogonalize();
277  }
278  else if (nFixed == 3)
279  {
280  forAll(fixedAlignment, dirI)
281  {
282  if (fixedAlignment.set(dirI))
283  {
284  t[dirI] = fixedAlignment[dirI];
285  }
286  }
287  }
288 }
289 
290 
291 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
292 
293 Foam::smoothAlignmentSolver::smoothAlignmentSolver(cellShapeControlMesh& mesh)
294 :
295  mesh_(mesh)
296 {}
297 
298 
299 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
300 
302 {}
303 
304 
305 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
306 
308 (
309  const label maxSmoothingIterations
310 )
311 {
312  scalar minResidual = 0;
313 
314  labelListList pointPoints;
315  autoPtr<mapDistribute> meshDistributor = buildMap
316  (
317  mesh_,
318  pointPoints
319  );
320 
321  triadField alignments(buildAlignmentField(mesh_));
322  pointField points(buildPointField(mesh_));
323 
324  // Setup the sizes and alignments on each point
325  triadField fixedAlignments(mesh_.vertexCount(), triad::unset);
326 
327  for
328  (
329  CellSizeDelaunay::Finite_vertices_iterator vit =
330  mesh_.finite_vertices_begin();
331  vit != mesh_.finite_vertices_end();
332  ++vit
333  )
334  {
335  if (vit->real())
336  {
337  fixedAlignments[vit->index()] = vit->alignment();
338  }
339  }
340 
341  Info<< nl << "Smoothing alignments" << endl;
342 
343 
344  for (label iter = 0; iter < maxSmoothingIterations; iter++)
345  {
346  Info<< "Iteration " << iter;
347 
348  meshDistributor().distribute(points);
349  meshDistributor().distribute(fixedAlignments);
350  meshDistributor().distribute(alignments);
351 
352  scalar residual = 0;
353 
354  triadField triadAv(alignments.size(), triad::unset);
355 
356  forAll(pointPoints, pI)
357  {
358  const labelList& pPoints = pointPoints[pI];
359 
360  if (pPoints.empty())
361  {
362  continue;
363  }
364 
365  triad& newTriad = triadAv[pI];
366 
367  forAll(pPoints, adjPointi)
368  {
369  const label adjPointIndex = pPoints[adjPointi];
370 
371  scalar dist = mag(points[pI] - points[adjPointIndex]);
372 
373  triad tmpTriad = alignments[adjPointIndex];
374 
375  for (direction dir = 0; dir < 3; dir++)
376  {
377  if (tmpTriad.set(dir))
378  {
379  tmpTriad[dir] *= 1.0/(dist + SMALL);
380  }
381  }
382 
383  newTriad += tmpTriad;
384  }
385  }
386 
387  // Update the alignment field
388  forAll(alignments, pI)
389  {
390  const triad& oldTriad = alignments[pI];
391  triad& newTriad = triadAv[pI];
392 
393  newTriad.normalize();
394  newTriad.orthogonalize();
395 
396  // Enforce the boundary conditions
397  const triad& fixedAlignment = fixedAlignments[pI];
398 
399  applyBoundaryConditions
400  (
401  fixedAlignment,
402  newTriad
403  );
404 
405  newTriad = newTriad.sortxyz();
406 
407  // Residual Calculation
408  for (direction dir = 0; dir < 3; ++dir)
409  {
410  if
411  (
412  newTriad.set(dir)
413  && oldTriad.set(dir)
414  && !fixedAlignment.set(dir)
415  )
416  {
417  residual += diff(oldTriad, newTriad);
418  }
419  }
420 
421  alignments[pI] = newTriad;
422  }
423 
424  reduce(residual, sumOp<scalar>());
425 
426  Info<< ", Residual = "
427  << residual
428  /returnReduce(points.size(), sumOp<label>())
429  << endl;
430 
431  if (iter > 0 && residual <= minResidual)
432  {
433  break;
434  }
435  }
436 
437  meshDistributor().distribute(alignments);
438 
439  for
440  (
441  CellSizeDelaunay::Finite_vertices_iterator vit =
442  mesh_.finite_vertices_begin();
443  vit != mesh_.finite_vertices_end();
444  ++vit
445  )
446  {
447  if (vit->real())
448  {
449  vit->alignment() = alignments[vit->index()];
450  }
451  }
452 
453  labelList referredPoints;
454  autoPtr<mapDistribute> referredDistributor = buildReferredMap
455  (
456  mesh_,
457  referredPoints
458  );
459 
460  alignments.setSize(mesh_.vertexCount());
461  referredDistributor().distribute(alignments);
462 
463  label referredI = 0;
464  for
465  (
466  CellSizeDelaunay::Finite_vertices_iterator vit =
467  mesh_.finite_vertices_begin();
468  vit != mesh_.finite_vertices_end();
469  ++vit
470  )
471  {
472  if (vit->referred())
473  {
474  vit->alignment() = alignments[referredPoints[referredI++]];
475  }
476  }
477 }
478 
479 
480 // ************************************************************************* //
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition: triad.C:394
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
uint8_t direction
Definition: direction.H:46
pointFromPoint topoint(const Point &P)
void smoothAlignments(const label maxSmoothingIterations)
Smooth the alignments on the mesh.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
void orthogonalize()
Orthogonalize this triad so that it is ortho-normal.
Definition: triad.C:108
label vertexCount() const
Return the vertex count (the next unique vertex index)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
const pointField & points
static const triad unset
Definition: triad.H:99
List< label > labelList
A List of labels.
Definition: labelList.H:56
Field< triad > triadField
Specialisation of Field<T> for triad.
Definition: triadField.H:49
static const char nl
Definition: Ostream.H:262
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
vector point
Point is a vector.
Definition: point.H:41
messageStream Info
dimensioned< scalar > mag(const dimensioned< Type > &)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
A class for managing temporary objects.
Definition: PtrList.H:54
~smoothAlignmentSolver()
Destructor.