Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
NodeOpti.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: NodeOpti.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Calculate jacobians of elements.
33 //
34 ////////////////////////////////////////////////////////////////////////////////
35 
36 #include <boost/multi_array.hpp>
37 
38 #include <limits>
39 
40 #include "NodeOpti.h"
41 #include "Evaluator.hxx"
42 #include "Hessian.hxx"
43 
44 using namespace std;
45 using namespace Nektar::NekMeshUtils;
46 
47 namespace Nektar
48 {
49 namespace Utilities
50 {
51 
53 {
54  static NodeOptiFactory asd;
55  return asd;
56 }
57 
58 void NodeOpti::CalcMinJac()
59 {
60  m_minJac = numeric_limits<double>::max();
61  map<LibUtilities::ShapeType, vector<ElUtilSharedPtr> >::iterator typeIt;
62  for (typeIt = m_data.begin(); typeIt != m_data.end(); typeIt++)
63  {
64  for (int i = 0; i < typeIt->second.size(); i++)
65  {
66  m_minJac = min(m_minJac, typeIt->second[i]->GetMinJac());
67  }
68  }
69 }
70 
71 int NodeOpti2D2D::m_type = GetNodeOptiFactory().RegisterCreatorFunction(
72  22, NodeOpti2D2D::create, "2D2D");
73 
74 void NodeOpti2D2D::Optimise()
75 {
76  NekDouble minJacNew;
77  NekDouble currentW = GetFunctional<2>(minJacNew);
78  NekDouble newVal = currentW;
79 
80  // Gradient already zero
81  if (m_grad[0] * m_grad[0] + m_grad[1] * m_grad[1] > gradTol())
82  {
83  // needs to optimise
84  NekDouble xc = m_node->m_x;
85  NekDouble yc = m_node->m_y;
86 
88  NekDouble val;
89 
90  // Calculate minimum eigenvalue
91  MinEigen<2>(val);
92 
93  if (val < 1e-6)
94  {
95  // Add constant identity to Hessian matrix.
96  m_grad[2] += 1e-6 - val;
97  m_grad[4] += 1e-6 - val;
98  }
99 
100  sk[0] = -1.0 / (m_grad[2] * m_grad[4] - m_grad[3] * m_grad[3]) *
101  (m_grad[4] * m_grad[0] - m_grad[3] * m_grad[1]);
102  sk[1] = -1.0 / (m_grad[2] * m_grad[4] - m_grad[3] * m_grad[3]) *
103  (m_grad[2] * m_grad[1] - m_grad[3] * m_grad[0]);
104 
105  bool found = false;
106  NekDouble pg = (m_grad[0] * sk[0] + m_grad[1] * sk[1]);
107  // normal gradient line Search
108  NekDouble alpha = 1.0;
109 
110  while (alpha > alphaTol())
111  {
112  // Update node
113  m_node->m_x = xc + alpha * sk[0];
114  m_node->m_y = yc + alpha * sk[1];
115 
116  newVal = GetFunctional<2>(minJacNew, false);
117 
118  // Wolfe conditions
119  if (newVal <= currentW + c1() * (alpha * pg))
120  {
121  found = true;
122  break;
123  }
124 
125  alpha /= 2.0;
126  }
127 
128  if (!found)
129  {
130  // reset the node
131  m_node->m_x = xc;
132  m_node->m_y = yc;
133 
134  mtx.lock();
135  m_res->nReset[2]++;
136  mtx.unlock();
137  }
138  else
139  {
140  m_minJac = minJacNew;
141 
142  mtx.lock();
143  if (alpha < 1.0)
144  {
145  m_res->alphaI++;
146  }
147  mtx.unlock();
148  }
149 
150  mtx.lock();
151  m_res->val = max(sqrt((m_node->m_x - xc) * (m_node->m_x - xc) +
152  (m_node->m_y - yc) * (m_node->m_y - yc)),
153  m_res->val);
154  mtx.unlock();
155  }
156 
157  mtx.lock();
158  m_res->func += newVal;
159  mtx.unlock();
160 }
161 
162 int NodeOpti3D3D::m_type = GetNodeOptiFactory().RegisterCreatorFunction(
163  33, NodeOpti3D3D::create, "3D3D");
164 
165 void NodeOpti3D3D::Optimise()
166 {
167  NekDouble minJacNew;
168  NekDouble currentW = GetFunctional<3>(minJacNew);
169  NekDouble newVal = currentW;
170 
171  if (m_grad[0] * m_grad[0] + m_grad[1] * m_grad[1] + m_grad[2] * m_grad[2] >
172  gradTol())
173  {
174  // needs to optimise
175  NekDouble xc = m_node->m_x;
176  NekDouble yc = m_node->m_y;
177  NekDouble zc = m_node->m_z;
178 
180  NekDouble val;
181 
182  // Calculate minimum eigenvalue
183  MinEigen<3>(val);
184 
185  if (val < 1e-6)
186  {
187  // Add constant identity to Hessian matrix.
188  m_grad[3] += 1e-6 - val;
189  m_grad[6] += 1e-6 - val;
190  m_grad[8] += 1e-6 - val;
191  }
192 
193  // calculate sk
194  NekDouble det =
195  m_grad[3] * (m_grad[6] * m_grad[8] - m_grad[7] * m_grad[7]) -
196  m_grad[4] * (m_grad[4] * m_grad[8] - m_grad[5] * m_grad[7]) +
197  m_grad[5] * (m_grad[4] * m_grad[7] - m_grad[5] * m_grad[6]);
198 
199  sk[0] = m_grad[0] * (m_grad[6] * m_grad[8] - m_grad[7] * m_grad[7]) +
200  m_grad[1] * (m_grad[5] * m_grad[7] - m_grad[4] * m_grad[8]) +
201  m_grad[2] * (m_grad[4] * m_grad[7] - m_grad[3] * m_grad[7]);
202  sk[1] = m_grad[0] * (m_grad[7] * m_grad[5] - m_grad[4] * m_grad[5]) +
203  m_grad[1] * (m_grad[3] * m_grad[8] - m_grad[5] * m_grad[5]) +
204  m_grad[2] * (m_grad[4] * m_grad[5] - m_grad[3] * m_grad[7]);
205  sk[2] = m_grad[0] * (m_grad[4] * m_grad[7] - m_grad[6] * m_grad[5]) +
206  m_grad[1] * (m_grad[4] * m_grad[5] - m_grad[3] * m_grad[7]) +
207  m_grad[2] * (m_grad[3] * m_grad[6] - m_grad[4] * m_grad[4]);
208 
209  sk[0] /= det * -1.0;
210  sk[1] /= det * -1.0;
211  sk[2] /= det * -1.0;
212 
213  bool found = false;
214 
215  NekDouble pg =
216  (m_grad[0] * sk[0] + m_grad[1] * sk[1] + m_grad[2] * sk[2]);
217 
218  // normal gradient line Search
219  NekDouble alpha = 1.0;
220 
221  while (alpha > alphaTol())
222  {
223  // Update node
224  m_node->m_x = xc + alpha * sk[0];
225  m_node->m_y = yc + alpha * sk[1];
226  m_node->m_z = zc + alpha * sk[2];
227 
228  newVal = GetFunctional<3>(minJacNew, false);
229  // dont need the hessian again this function updates G to be the new
230  // location
231  //
232  // Wolfe conditions
233  if (newVal <= currentW + c1() * alpha * pg)
234  {
235  found = true;
236  break;
237  }
238 
239  alpha /= 2.0;
240  }
241 
242  if (!found)
243  {
244  m_node->m_x = xc;
245  m_node->m_y = yc;
246  m_node->m_z = zc;
247 
248  mtx.lock();
249  m_res->nReset[2]++;
250  mtx.unlock();
251  }
252  else
253  {
254  m_minJac = minJacNew;
255 
256  mtx.lock();
257  if (alpha < 1.0)
258  {
259  m_res->alphaI++;
260  }
261  mtx.unlock();
262  }
263 
264  mtx.lock();
265  m_res->val = max(sqrt((m_node->m_x - xc) * (m_node->m_x - xc) +
266  (m_node->m_y - yc) * (m_node->m_y - yc) +
267  (m_node->m_z - zc) * (m_node->m_z - zc)),
268  m_res->val);
269  mtx.unlock();
270  }
271  mtx.lock();
272  m_res->func += newVal;
273  mtx.unlock();
274 }
275 
276 NodeOptiJob *NodeOpti::GetJob()
277 {
278  return new NodeOptiJob(this);
279 }
280 }
281 }
NodeOptiFactory & GetNodeOptiFactory()
Definition: NodeOpti.cpp:52
STL namespace.
boost::mutex mtx
Definition: NodeOptiCAD.cpp:47
double NekDouble
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
Provides a generic Factory class.
Definition: NekFactory.hpp:116
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215