Nektar++
OptimiseFunctions.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: OptimseFunctions.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 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: functions and gradients for optimisation
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
37 
38 using namespace std;
39 namespace Nektar
40 {
41 namespace NekMeshUtils
42 {
43 
45 {
46  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
47 }
49 {
51  ret[0] = a[0] - b[0];
52  ret[1] = a[1] - b[1];
53  ret[2] = a[2] - b[2];
54  return ret;
55 }
57 {
59  ret[0] = a[0] * t;
60  ret[1] = a[1] * t;
61  ret[2] = a[2] * t;
62  return ret;
63 }
65 {
67  ret[0] = a[0] + b[0];
68  ret[1] = a[1] + b[1];
69  ret[2] = a[2] + b[2];
70  return ret;
71 }
72 
73 Array<OneD, NekDouble> OptiEdge::Getxi()
74 {
76 
77  switch (o->GetType())
78  {
79  case CADType::eCurve:
80  xi = Array<OneD, NekDouble>(all.num_elements() - 2);
81  for (int i = 1; i < all.num_elements() - 1; i++)
82  {
83  xi[i - 1] = all[i];
84  }
85  break;
86 
87  case CADType::eSurf:
88  xi = Array<OneD, NekDouble>(all.num_elements() - 4);
89  for (int i = 2; i < all.num_elements() - 2; i++)
90  {
91  xi[i - 2] = all[i];
92  }
93  break;
94 
95  case CADType::eVert:
96  ASSERTL0(false, "Should not be able to pass vert");
97  }
98  return xi;
99 }
100 
101 Array<OneD, NekDouble> OptiEdge::Getli()
102 {
105  switch (o->GetType())
106  {
107  case CADType::eCurve:
108  li = Array<OneD, NekDouble>(all.num_elements() - 2);
109  bnds = std::dynamic_pointer_cast<CADCurve>(o)->GetBounds();
110  for (int i = 1; i < all.num_elements() - 1; i++)
111  {
112  li[i - 1] = bnds[0];
113  }
114  break;
115 
116  case CADType::eSurf:
117  li = Array<OneD, NekDouble>(all.num_elements() - 4);
118  bnds = std::dynamic_pointer_cast<CADSurf>(o)->GetBounds();
119  for (int i = 2; i < all.num_elements() - 2; i++)
120  {
121  if (i % 2 == 0)
122  {
123  li[i - 2] = bnds[0];
124  }
125  else
126  {
127  li[i - 2] = bnds[2];
128  }
129  }
130  break;
131 
132  case CADType::eVert:
133  ASSERTL0(false, "Should not be able to pass vert");
134  }
135  return li;
136 }
137 
138 Array<OneD, NekDouble> OptiEdge::Getui()
139 {
142  switch (o->GetType())
143  {
144  case CADType::eCurve:
145  ui = Array<OneD, NekDouble>(all.num_elements() - 2);
146  bnds = std::dynamic_pointer_cast<CADCurve>(o)->GetBounds();
147  for (int i = 1; i < all.num_elements() - 1; i++)
148  {
149  ui[i - 1] = bnds[1];
150  }
151  break;
152 
153  case CADType::eSurf:
154  ui = Array<OneD, NekDouble>(all.num_elements() - 4);
155  bnds = std::dynamic_pointer_cast<CADSurf>(o)->GetBounds();
156  for (int i = 2; i < all.num_elements() - 2; i++)
157  {
158  if (i % 2 == 0)
159  {
160  ui[i - 2] = bnds[1];
161  }
162  else
163  {
164  ui[i - 2] = bnds[3];
165  }
166  }
167  break;
168 
169  case CADType::eVert:
170  ASSERTL0(false, "Should not be able to pass vert");
171  }
172  return ui;
173 }
174 
176 {
177  Array<OneD, NekDouble> val(all.num_elements());
178 
179  if (o->GetType() == CADType::eCurve)
180  {
181  val[0] = all[0];
182  for (int i = 0; i < xitst.num_elements(); i++)
183  {
184  val[i + 1] = xitst[i];
185  }
186  val[all.num_elements() - 1] = all[all.num_elements() - 1];
187  }
188  else if (o->GetType() == CADType::eSurf)
189  {
190  val[0] = all[0];
191  val[1] = all[1];
192  for (int i = 0; i < xitst.num_elements(); i++)
193  {
194  val[i + 2] = xitst[i];
195  }
196  val[all.num_elements() - 2] = all[all.num_elements() - 2];
197  val[all.num_elements() - 1] = all[all.num_elements() - 1];
198  }
199 
200  NekDouble ret = 0.0;
201  if (o->GetType() == CADType::eCurve)
202  {
203  CADCurveSharedPtr c = std::dynamic_pointer_cast<CADCurve>(o);
204 
205  for (int i = 0; i < all.num_elements() - 1; i++)
206  {
207  Array<OneD, NekDouble> dis = Take(c->P(val[i + 1]), c->P(val[i]));
208  NekDouble norm =
209  dis[0] * dis[0] + dis[1] * dis[1] + dis[2] * dis[2];
210  ret += norm / (z[i + 1] - z[i]);
211  }
212  }
213  else if (o->GetType() == CADType::eSurf)
214  {
215  CADSurfSharedPtr s = std::dynamic_pointer_cast<CADSurf>(o);
216  // need to organise the val array
217  Array<OneD, Array<OneD, NekDouble> > uv(val.num_elements() / 2);
218  for (int i = 0; i < val.num_elements() / 2; i++)
219  {
220  uv[i] = Array<OneD, NekDouble>(2);
221  uv[i][0] = val[i * 2 + 0];
222  uv[i][1] = val[i * 2 + 1];
223  }
224  for (int i = 0; i < uv.num_elements() - 1; i++)
225  {
226  Array<OneD, NekDouble> dis = Take(s->P(uv[i + 1]), s->P(uv[i]));
227  NekDouble norm =
228  dis[0] * dis[0] + dis[1] * dis[1] + dis[2] * dis[2];
229  ret += norm / (z[i + 1] - z[i]);
230  }
231  }
232  return ret;
233 }
234 
235 DNekMat OptiEdge::dF(Array<OneD, NekDouble> xitst)
236 {
237  Array<OneD, NekDouble> val(all.num_elements());
238 
239  if (o->GetType() == CADType::eCurve)
240  {
241  val[0] = all[0];
242  for (int i = 0; i < xitst.num_elements(); i++)
243  {
244  val[i + 1] = xitst[i];
245  }
246  val[all.num_elements() - 1] = all[all.num_elements() - 1];
247  }
248  else if (o->GetType() == CADType::eSurf)
249  {
250  val[0] = all[0];
251  val[1] = all[1];
252  for (int i = 0; i < xitst.num_elements(); i++)
253  {
254  val[i + 2] = xitst[i];
255  }
256  val[all.num_elements() - 2] = all[all.num_elements() - 2];
257  val[all.num_elements() - 1] = all[all.num_elements() - 1];
258  }
259 
260  DNekMat ret;
261 
262  if (o->GetType() == CADType::eCurve)
263  {
264  CADCurveSharedPtr c = std::dynamic_pointer_cast<CADCurve>(o);
265  vector<Array<OneD, NekDouble> > r;
266  vector<Array<OneD, NekDouble> > dr;
267 
268  for (int i = 0; i < all.num_elements(); i++)
269  {
270  Array<OneD, NekDouble> ri(3), dri(3);
271  Array<OneD, NekDouble> d2 = c->D2(val[i]);
272  for (int j = 0; j < 3; j++)
273  {
274  ri[j] = d2[j];
275  dri[j] = d2[j + 3];
276  }
277  r.push_back(ri);
278  dr.push_back(dri);
279  }
280 
281  DNekMat J(all.num_elements() - 2, 1, 0.0);
282  for (int i = 0; i < all.num_elements() - 2; i++)
283  {
284  J(i, 0) =
285  2.0 / (z[i + 1] - z[i]) * Dot(dr[i + 1], Take(r[i + 1], r[i])) -
286  2.0 / (z[i + 2] - z[i + 1]) *
287  Dot(dr[i + 1], Take(r[i + 2], r[i + 1]));
288  }
289 
290  ret = J;
291  }
292  else if (o->GetType() == CADType::eSurf)
293  {
294  CADSurfSharedPtr s = std::dynamic_pointer_cast<CADSurf>(o);
295  // need to organise the all array
296  Array<OneD, Array<OneD, NekDouble> > uv(val.num_elements() / 2);
297  for (int i = 0; i < val.num_elements() / 2; i++)
298  {
299  uv[i] = Array<OneD, NekDouble>(2);
300  uv[i][0] = val[i * 2 + 0];
301  uv[i][1] = val[i * 2 + 1];
302  }
303 
304  vector<Array<OneD, NekDouble> > r;
305  vector<Array<OneD, NekDouble> > dru, drv;
306  for (int i = 0; i < uv.num_elements(); i++)
307  {
308  Array<OneD, NekDouble> ri(3), drui(3), drvi(3);
309  Array<OneD, NekDouble> d2 = s->D1(uv[i]);
310  for (int j = 0; j < 3; j++)
311  {
312  ri[j] = d2[j];
313  drui[j] = d2[j + 3];
314  drvi[j] = d2[j + 6];
315  }
316  r.push_back(ri);
317  dru.push_back(drui);
318  drv.push_back(drvi);
319  }
320 
321  DNekMat J(2 * (uv.num_elements() - 2), 1, 0.0);
322  for (int i = 0; i < uv.num_elements() - 2; i++)
323  {
324  J(2 * i + 0, 0) = 2.0 / (z[i + 1] - z[i]) *
325  Dot(dru[i + 1], Take(r[i + 1], r[i])) +
326  2.0 / (z[i + 2] - z[i + 1]) *
327  Dot(dru[i + 1], Take(r[i + 1], r[i + 2]));
328 
329  J(2 * i + 1, 0) = 2.0 / (z[i + 1] - z[i]) *
330  Dot(drv[i + 1], Take(r[i + 1], r[i])) +
331  2.0 / (z[i + 2] - z[i + 1]) *
332  Dot(drv[i + 1], Take(r[i + 1], r[i + 2]));
333  }
334 
335  ret = J;
336  }
337 
338  return ret;
339 }
340 
341 void OptiEdge::Update(Array<OneD, NekDouble> xinew)
342 {
343  if (o->GetType() == CADType::eCurve)
344  {
345  for (int i = 0; i < xinew.num_elements(); i++)
346  {
347  all[i + 1] = xinew[i];
348  }
349  }
350  else if (o->GetType() == CADType::eSurf)
351  {
352  for (int i = 0; i < xinew.num_elements(); i++)
353  {
354  all[i + 2] = xinew[i];
355  }
356  }
357 }
358 }
359 }
std::shared_ptr< CADSurf > CADSurfSharedPtr
Definition: CADCurve.h:51
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
base class for CAD curves.
Definition: CADCurve.h:58
Array< OneD, NekDouble > Take(Array< OneD, NekDouble > a, Array< OneD, NekDouble > b)
STL namespace.
Array< OneD, NekDouble > Times(NekDouble t, Array< OneD, NekDouble > a)
NekDouble Dot(Array< OneD, NekDouble > a, Array< OneD, NekDouble > b)
std::shared_ptr< CADCurve > CADCurveSharedPtr
Definition: CADCurve.h:219
base class for a cad surface
Definition: CADSurf.h:71
double NekDouble
Array< OneD, NekDouble > Add(Array< OneD, NekDouble > a, Array< OneD, NekDouble > b)