DAFunctionMeshQualityKS.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2 
3  DAFoam : Discrete Adjoint with OpenFOAM
4  Version : v4
5 
6 \*---------------------------------------------------------------------------*/
7 
9 
10 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
11 
12 namespace Foam
13 {
14 
15 defineTypeNameAndDebug(DAFunctionMeshQualityKS, 0);
16 addToRunTimeSelectionTable(DAFunction, DAFunctionMeshQualityKS, dictionary);
17 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
18 
20  const fvMesh& mesh,
21  const DAOption& daOption,
22  const DAModel& daModel,
23  const DAIndex& daIndex,
24  const word functionName)
25  : DAFunction(
26  mesh,
27  daOption,
28  daModel,
29  daIndex,
30  functionName)
31 {
32 
33  functionDict_.readEntry<scalar>("coeffKS", coeffKS_);
34 
35  functionDict_.readEntry<word>("metric", metric_);
36 
37  // the polyMeshTools funcs are not fully AD in parallel, so the mesh quality
38  // computed at the processor faces will not be properly back-propagate in AD
39  // we can ignore the mesh quality at proc patches if includeProcPatches = False (default)
40  includeProcPatches_ = functionDict_.lookupOrDefault<label>("includeProcPatches", 0);
41  includeFaceList_.setSize(mesh_.nFaces(), 1);
43  {
44  label nInterF = mesh_.nInternalFaces();
45  label faceCounter = 0;
46  forAll(mesh.boundaryMesh(), patchI)
47  {
48  if (mesh.boundaryMesh()[patchI].type() == "processor")
49  {
50  forAll(mesh.boundaryMesh()[patchI], faceI)
51  {
52  includeFaceList_[nInterF + faceCounter] = 0;
53  faceCounter += 1;
54  }
55  }
56  else
57  {
58  faceCounter += mesh.boundaryMesh()[patchI].size();
59  }
60  }
61  }
62 
63  if (daOption.getOption<label>("debug"))
64  {
65  Info << "includeFaceList " << includeFaceList_ << endl;
66  }
67 }
68 
71 {
72  /*
73  Description:
74  Calculate the mesh quality and aggregate with the KS function
75  e.g., if metric is the faceSkewness, the function value will be the
76  approximated max skewness
77  */
78 
79  // initialize objFunValue
80  scalar functionValue = 0.0;
81 
82  if (metric_ == "faceOrthogonality")
83  {
84  // faceOrthogonality ranges from 0 to 1 and the nonOrthoAngle is acos(faceOrthogonality)
85  const scalarField faceOrthogonality(
86  polyMeshTools::faceOrthogonality(
87  mesh_,
88  mesh_.faceAreas(),
89  mesh_.cellCentres()));
90 
91  // calculate the KS mesh quality
92  forAll(faceOrthogonality, faceI)
93  {
94  if (includeFaceList_[faceI] == 1)
95  {
96  functionValue += exp(coeffKS_ * faceOrthogonality[faceI]);
97  }
98 
99  if (functionValue > 1e200)
100  {
101  FatalErrorIn(" ") << "KS function summation term too large! "
102  << "Reduce coeffKS! " << abort(FatalError);
103  }
104  }
105  }
106  else if (metric_ == "nonOrthoAngle")
107  {
108  const scalarField faceOrthogonality(
109  polyMeshTools::faceOrthogonality(
110  mesh_,
111  mesh_.faceAreas(),
112  mesh_.cellCentres()));
113 
114  // Face based non ortho angle
115  scalarField nonOrthoAngle = faceOrthogonality;
116  forAll(faceOrthogonality, faceI)
117  {
118  scalar val = faceOrthogonality[faceI];
119  // bound it to less than 1.0 - 1e-6. We can't let val = 1
120  // because its derivative will be divided by zero
121  scalar boundV = 1.0 - 1e-6;
122  if (val > boundV)
123  {
124  val = boundV;
125  }
126  if (val < -boundV)
127  {
128  val = -boundV;
129  }
130  // compute non ortho angle
131  scalar angleRad = acos(val);
132  // convert rad to degree
133  scalar pi = constant::mathematical::pi;
134  scalar angleDeg = angleRad * 180.0 / pi;
135  nonOrthoAngle[faceI] = angleDeg;
136  }
137 
138  // calculate the KS mesh quality
139  forAll(nonOrthoAngle, faceI)
140  {
141  if (includeFaceList_[faceI] == 1)
142  {
143  functionValue += exp(coeffKS_ * nonOrthoAngle[faceI]);
144  }
145 
146  if (functionValue > 1e200)
147  {
148  FatalErrorIn(" ") << "KS function summation term too large! "
149  << "Reduce coeffKS! " << abort(FatalError);
150  }
151  }
152  }
153  else if (metric_ == "faceSkewness")
154  {
155  const scalarField faceSkewness(
156  polyMeshTools::faceSkewness(
157  mesh_,
158  mesh_.points(),
159  mesh_.faceCentres(),
160  mesh_.faceAreas(),
161  mesh_.cellCentres()));
162 
163  // calculate the KS mesh quality
164  forAll(faceSkewness, faceI)
165  {
166  if (includeFaceList_[faceI] == 1)
167  {
168  functionValue += exp(coeffKS_ * faceSkewness[faceI]);
169  }
170 
171  if (functionValue > 1e200)
172  {
173  FatalErrorIn(" ") << "KS function summation term too large! "
174  << "Reduce coeffKS! " << abort(FatalError);
175  }
176  }
177  }
178  else
179  {
180  FatalErrorIn(" ") << "metric not valid! "
181  << "Options: faceOrthogonality, nonOrthoAngle, or faceSkewness "
182  << abort(FatalError);
183  }
184 
185  // need to reduce the sum of force across all processors
186  reduce(functionValue, sumOp<scalar>());
187 
188  functionValue = log(functionValue) / coeffKS_;
189 
190  // check if we need to calculate refDiff.
191  this->calcRefVar(functionValue);
192 
193  return functionValue;
194 }
195 
196 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
197 
198 } // End namespace Foam
199 
200 // ************************************************************************* //
Foam::DAFunctionMeshQualityKS::includeProcPatches_
label includeProcPatches_
whether to include the processor patches for mesh quality calculation
Definition: DAFunctionMeshQualityKS.H:39
Foam::DAFunctionMeshQualityKS::metric_
word metric_
which mesh quality metric to use
Definition: DAFunctionMeshQualityKS.H:36
Foam::DAOption
Definition: DAOption.H:29
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(DAFunction, DAFunctionForce, dictionary)
Foam::DAFunctionMeshQualityKS::calcFunction
virtual scalar calcFunction()
calculate the value of objective function
Definition: DAFunctionMeshQualityKS.C:70
Foam::DAFunctionMeshQualityKS::coeffKS_
scalar coeffKS_
coefficient for the KS function
Definition: DAFunctionMeshQualityKS.H:33
Foam::DAOption::getOption
classType getOption(const word key) const
get an option from subDict and key
Definition: DAOption.H:92
Foam::DAFunction::calcRefVar
void calcRefVar(scalar &functionValue)
calculate (var-ref)^2
Definition: DAFunction.C:216
DAFunctionMeshQualityKS.H
mesh
fvMesh & mesh
Definition: createRefsHeatTransfer.H:4
Foam::DAIndex
Definition: DAIndex.H:32
Foam::DAModel
Definition: DAModel.H:57
Foam::DAFunction
Definition: DAFunction.H:31
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(DAFunction, 0)
Foam
Definition: checkGeometry.C:32
Foam::DAFunctionMeshQualityKS::includeFaceList_
labelList includeFaceList_
a list of included faces for the mesh quality calculation
Definition: DAFunctionMeshQualityKS.H:42
forAll
forAll(nuTilda1, cellI)
Definition: nuTilda1EqnIrkPimple.H:19
Foam::DAFunctionMeshQualityKS::DAFunctionMeshQualityKS
DAFunctionMeshQualityKS(const fvMesh &mesh, const DAOption &daOption, const DAModel &daModel, const DAIndex &daIndex, const word functionName)
Definition: DAFunctionMeshQualityKS.C:19
Foam::DAFunction::functionDict_
dictionary functionDict_
dictionary containing the information for the objective function
Definition: DAFunction.H:64
Foam::DAFunction::mesh_
const fvMesh & mesh_
fvMesh
Definition: DAFunction.H:43