knuppMetric.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | cfMesh: A library for mesh generation
4  \\ / O peration |
5  \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6  \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of cfMesh.
10 
11  cfMesh is free software; you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by the
13  Free Software Foundation; either version 3 of the License, or (at your
14  option) any later version.
15 
16  cfMesh 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 cfMesh. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "demandDrivenData.H"
29 #include "knuppMetric.H"
30 #include "partTetMeshSimplex.H"
31 
32 //#define DEBUGSmooth
33 
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 // Private member functions
41 
43 {
44  scalar val(0.0);
45 
46  forAll(normals_, nI)
47  {
48  const scalar fx = (normals_[nI] & (p_ - centres_[nI])) - beta_;
49  val += Foam::sqr(mag(fx) - fx);
50  }
51 
52  return val;
53 }
54 
56 {
57  scalar val(0.0);
58 
59  forAll(normals_, nI)
60  {
61  const scalar fx = (normals_[nI] & (p_ - centres_[nI]));
62  val += Foam::sqr(mag(fx) - fx);
63  }
64 
65  return val;
66 }
67 
69 {
71  gradGrad = tensor::zero;
72 
73  forAll(normals_, nI)
74  {
75  const scalar fx = (normals_[nI] & (p_ - centres_[nI])) - beta_;
76  const vector gfx = (Foam::sign(fx) - 1) * normals_[nI];
77 
78  grad += (Foam::mag(fx) - fx) * gfx;
79  gradGrad += gfx * gfx;
80  }
81 }
82 
83 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
84 
86 :
87  simplexSmoother(simplex),
88  p_(simplex.pts()[simplex.tets()[0][3]]),
89  normals_(),
90  centres_(),
91  beta_()
92 {
93  forAll(tets_, tetI)
94  {
95  const partTet& pt = tets_[tetI];
96  const triangle<point, point> tri
97  (
98  points_[pt.a()],
99  points_[pt.b()],
100  points_[pt.c()]
101  );
102 
103  const vector n = tri.normal();
104  const scalar d = mag(n);
105 
106  if( d > VSMALL )
107  {
108  centres_.append(tri.centre());
109  normals_.append(n/d);
110  }
111  }
112 
113  beta_ = 0.01 * bb_.mag();
114 }
115 
116 
118 {
119 }
120 
121 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
122 
123 // Implementation of knupp metric untangling
124 void knuppMetric::optimizeNodePosition(const scalar /*tolObsolete*/)
125 {
126  if( !bb_.contains(p_) )
127  p_ = 0.5 * (bb_.min() + bb_.max());
128 
129  const scalar tol = Foam::sqr(2.0 * SMALL) * magSqr(bb_.min() - bb_.max());
130 
131  label iterI, outerIter(0);
132 
133  vector gradF, disp;
134  tensor gradGradF;
135 
136  scalar func, lastFunc;
137 
138  # ifdef DEBUGSmooth
139  forAll(normals_, nI)
140  {
141  const scalar fx = normals_[nI] & (p_ - centres_[nI]);
142  Info << "Tet " << nI << " has distance " << fx << " func "
143  << Foam::sqr(mag(fx) - fx) << endl;
144  }
145  Info << "BoundBox size " << (bb_.max() - bb_.min()) << endl;
146  Info << "Tolerance " << tol << endl;
147  # endif
148 
149  bool finished;
150  do
151  {
152  finished = true;
153 
154  lastFunc = evaluateMetric();
155 
156  iterI = 0;
157  do
158  {
159  # ifdef DEBUGSmooth
160  Info << "Iteration " << iterI << endl;
161  Info << "Initial metric value " << lastFunc << endl;
162  # endif
163 
164  //- store previous value
165  const point pOrig = p_;
166 
167  //- evaluate gradients
168  evaluateGradients(gradF, gradGradF);
169 
170  //- calculate displacement
171  const scalar determinant = det(gradGradF);
172  if( determinant > SMALL )
173  {
174  disp = (inv(gradGradF, determinant) & gradF);
175 
176  for(direction i=0;i<vector::nComponents;++i)
177  {
178  const scalar& val = disp[i];
179  if( (val != val) || ((val - val) != (val - val)) )
180  {
181  disp = vector::zero;
182  break;
183  }
184  }
185 
186  p_ -= disp;
187 
188  func = evaluateMetric();
189 
190  # ifdef DEBUGSmooth
191  Info << "Second grad " << gradGradF << endl;
192  Info << "inv(gradGradF, determinant) " << inv(gradGradF, determinant) << endl;
193  Info << "Gradient " << gradF << endl;
194  Info << "Determinant " << determinant << endl;
195  Info << "Displacement " << disp << endl;
196  Info << "New metric value " << func << endl;
197  # endif
198 
199 
200  scalar relax(0.8);
201  label nLoops(0);
202  while( func > lastFunc )
203  {
204  p_ = pOrig - relax * disp;
205  relax *= 0.5;
206  func = evaluateMetric();
207 
208  if( func < lastFunc )
209  continue;
210 
211  //- it seems that this direction is wrong
212  if( ++nLoops == 5 )
213  {
214  p_ = pOrig;
215  disp = vector::zero;
216  func = 0.0;
217  }
218  }
219 
220  lastFunc = func;
221  }
222  else
223  {
224  disp = vector::zero;
225  }
226  } while( (magSqr(disp) > tol) && (++iterI < 10) );
227 
228  if( (lastFunc < VSMALL) && (evaluateMetricNoBeta() > VSMALL) )
229  {
230  beta_ /= 2.0;
231  finished = false;
232  }
233 
234  } while( !finished && (++outerIter < 5) );
235 
236  # ifdef DEBUGSmooth
237  Info << "Last value " << lastFunc << endl;
238  Info << "Beta " << beta_ << endl;
239  Info << "Metric with no beta " << evaluateMetricNoBeta() << endl;
240  forAll(normals_, nI)
241  {
242  const scalar fx = normals_[nI] & (p_ - centres_[nI]);
243  Info << "Tet " << nI << " has distance " << fx << " func "
244  << Foam::sqr(mag(fx) - fx) << endl;
245  }
246  //::exit(1);
247  # endif
248 }
249 
250 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
251 
252 } // End namespace Foam
253 
254 // ************************************************************************* //
Foam::Tensor
Templated 3D tensor derived from VectorSpace adding construction from 9 components,...
Definition: complexI.H:224
Foam::boundBox::mag
scalar mag() const
The magnitude of the bounding box span.
Definition: boundBoxI.H:90
Foam::fvc::grad
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:52
relax
p relax()
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
Foam::partTetMeshSimplex
Definition: partTetMeshSimplex.H:52
Foam::knuppMetric::evaluateMetric
scalar evaluateMetric() const
evaluate the value of the metric
Definition: knuppMetric.C:42
Foam::boundBox::max
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:60
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::partTet::b
label b() const
Definition: partTetI.H:68
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::knuppMetric::p_
point & p_
free vertex
Definition: knuppMetric.H:59
Foam::partTet
Definition: partTet.H:53
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
@ nComponents
Number of components in this vector space.
Definition: VectorSpace.H:88
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::knuppMetric::~knuppMetric
~knuppMetric()
Definition: knuppMetric.C:117
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::sign
dimensionedScalar sign(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:179
Foam::knuppMetric::beta_
scalar beta_
control parameter. It helps the point get inside the feasible region
Definition: knuppMetric.H:68
Foam::knuppMetric::knuppMetric
knuppMetric(partTetMeshSimplex &simplex)
Definition: knuppMetric.C:85
Foam::triangle::centre
Point centre() const
Return centre (centroid)
Definition: triangleI.H:102
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:59
n
label n
Definition: TABSMDCalcMethod2.H:31
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
Foam::simplexSmoother
class for volume optimizer
Definition: simplexSmoother.H:56
Foam::triangle::normal
vector normal() const
Return vector normal.
Definition: triangleI.H:116
Foam::inv
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:71
Foam::Info
messageStream Info
partTetMeshSimplex.H
Foam::simplexSmoother::points_
DynList< point, 128 > & points_
mesh points
Definition: simplexSmoother.H:62
Foam::knuppMetric::evaluateMetricNoBeta
scalar evaluateMetricNoBeta() const
Definition: knuppMetric.C:55
Foam::func
void func(FieldField< Field, Type > &f, const FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
Foam::boundBox::min
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:54
Foam::knuppMetric::normals_
DynList< vector, 64 > normals_
normals of triangles forming the outer hull
Definition: knuppMetric.H:62
Foam::simplexSmoother::tets_
const DynList< partTet, 128 > & tets_
list tets around the given vertex
Definition: simplexSmoother.H:65
Foam::partTet::c
label c() const
Definition: partTetI.H:73
Foam::Tensor::zero
static const Tensor zero
Definition: Tensor.H:80
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::knuppMetric::optimizeNodePosition
void optimizeNodePosition(const scalar tol=0.001)
Definition: knuppMetric.C:124
Foam::simplexSmoother::bb_
boundBox bb_
bound box
Definition: simplexSmoother.H:71
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::Vector< scalar >
Foam::boundBox::contains
bool contains(const point &) const
Contains point? (inside or on edge)
Definition: boundBoxI.H:170
Foam::knuppMetric::evaluateGradients
void evaluateGradients(vector &grad, tensor &gradGrad) const
evaluate metric gradients
Definition: knuppMetric.C:68
Foam::direction
unsigned char direction
Definition: direction.H:43
knuppMetric.H
Foam::det
dimensionedScalar det(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:60
Foam::partTet::a
label a() const
Return vertices.
Definition: partTetI.H:63
Foam::knuppMetric::centres_
DynList< point, 64 > centres_
centres of triangles forming the outer hull
Definition: knuppMetric.H:65
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)