NURBS3DVolume.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2007-2019 PCOpt/NTUA
9  Copyright (C) 2013-2019 FOSS GP
10  Copyright (C) 2019 OpenCFD Ltd.
11 -------------------------------------------------------------------------------
12 License
13  This file is part of OpenFOAM.
14 
15  OpenFOAM is free software: you can redistribute it and/or modify it
16  under the terms of the GNU General Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27 
28 \*---------------------------------------------------------------------------*/
29 
31 #include "NURBS3DVolume.H"
32 
33 #include "OFstream.H"
34 #include "Time.H"
35 #include "deltaBoundary.H"
36 #include "coupledFvPatch.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(NURBS3DVolume, 0);
43  defineRunTimeSelectionTable(NURBS3DVolume, dictionary);
44 }
45 
46 
47 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
48 
50 (
51  const label i,
52  const label j,
53  const label k
54 ) const
55 {
56  const label nCPsU = basisU_.nCPs();
57  const label nCPsV = basisV_.nCPs();
58 
59  return k*nCPsU*nCPsV + j*nCPsU + i;
60 }
61 
62 
64 {
65  // It is considered an error to recompute points in the control boxes
66  if (mapPtr_.valid() || reverseMapPtr_.valid())
67  {
69  << "Attempting to recompute points residing within control boxes"
70  << exit(FatalError);
71  }
72 
73  mapPtr_.reset(new labelList(meshPoints.size(), -1));
74  reverseMapPtr_.reset(new labelList(meshPoints.size(), -1));
75  labelList& map = mapPtr_();
76  labelList& reverseMap = reverseMapPtr_();
77 
78  // Identify points inside morphing boxes
79  scalar lowerX = min(cps_.component(0));
80  scalar upperX = max(cps_.component(0));
81  scalar lowerY = min(cps_.component(1));
82  scalar upperY = max(cps_.component(1));
83  scalar lowerZ = min(cps_.component(2));
84  scalar upperZ = max(cps_.component(2));
85 
86  Info<< "Control Points bounds \n"
87  << "\tX1 : (" << lowerX << " " << upperX << ")\n"
88  << "\tX2 : (" << lowerY << " " << upperY << ")\n"
89  << "\tX3 : (" << lowerZ << " " << upperZ << ")\n" << endl;
90 
91  label count(0);
92  forAll(meshPoints, pI)
93  {
94  const vector& pointI = meshPoints[pI];
95  if
96  (
97  pointI.x() >= lowerX && pointI.x() <= upperX
98  && pointI.y() >= lowerY && pointI.y() <= upperY
99  && pointI.z() >= lowerZ && pointI.z() <= upperZ
100  )
101  {
102  map[count] = pI;
103  reverseMap[pI] = count;
104  ++count;
105  }
106  }
107 
108  // Resize lists
109  map.setSize(count);
110 
112  Info<< "Initially found " << count << " points inside control boxes"
113  << endl;
114 }
115 
116 
118 (
119  const vectorField& points
120 )
121 {
122  scalar timeBef = mesh_.time().elapsedCpuTime();
123 
124  if (parametricCoordinatesPtr_.valid())
125  {
127  << "Attempting to recompute parametric coordinates"
128  << exit(FatalError);
129  }
130 
131  labelList& map = mapPtr_();
132  labelList& reverseMap = reverseMapPtr_();
133 
134  parametricCoordinatesPtr_.reset
135  (
136  new pointVectorField
137  (
138  IOobject
139  (
140  "parametricCoordinates" + name_,
141  mesh_.time().timeName(),
142  mesh_,
145  ),
146  pointMesh::New(mesh_),
148  )
149  );
150  vectorField& paramCoors = parametricCoordinatesPtr_().primitiveFieldRef();
151 
152  // If already present, read from file
153  if
154  (
155  parametricCoordinatesPtr_().typeHeaderOk<pointVectorField>(true)
156  && readStoredData_
157  )
158  {
159  // These are the parametric coordinates that have been computed
160  // correctly (hopefully!) in a previous run.
161  // findPointsInBox has possibly found more points and lists need
162  // resizing
163  Info<< "Reading parametric coordinates from file" << endl;
164  IOobject& header = parametricCoordinatesPtr_().ref();
165  parametricCoordinatesPtr_() =
167  (
168  header,
169  pointMesh::New(mesh_)
170  );
171 
172  // Initialize intermidiate fields with sizes from findPointInBox
173  labelList actualMap(map.size());
174 
175  // Read and store
176  label curIndex(0);
177  forAll(map, pI)
178  {
179  const label globalPointIndex = map[pI];
180  if (paramCoors[globalPointIndex] != vector::zero)
181  {
182  actualMap[curIndex] = map[pI];
183  reverseMap[globalPointIndex] = curIndex;
184  ++curIndex;
185  }
186  else
187  {
188  reverseMap[globalPointIndex] = -1;
189  }
190  }
191 
192  // Resize intermidiate
193  actualMap.setSize(curIndex);
194 
195  reduce(curIndex, sumOp<label>());
196  Info<< "Read non-zero parametric coordinates for " << curIndex
197  << " points" << endl;
198 
199  // Update lists with the appropriate entries
200  map = actualMap;
201  }
202  // Else, compute parametric coordinates iteratively
203  else
204  {
205  // Initialize parametric coordinates based on min/max of control points
206  scalar minX1 = min(cps_.component(0));
207  scalar maxX1 = max(cps_.component(0));
208  scalar minX2 = min(cps_.component(1));
209  scalar maxX2 = max(cps_.component(1));
210  scalar minX3 = min(cps_.component(2));
211  scalar maxX3 = max(cps_.component(2));
212 
213  scalar oneOverDenomX(1./(maxX1 - minX1));
214  scalar oneOverDenomY(1./(maxX2 - minX2));
215  scalar oneOverDenomZ(1./(maxX3 - minX3));
216 
217  forAll(map, pI)
218  {
219  const label globalPI = map[pI];
220  paramCoors[globalPI].x() = (points[pI].x() - minX1)*oneOverDenomX;
221  paramCoors[globalPI].y() = (points[pI].y() - minX2)*oneOverDenomY;
222  paramCoors[globalPI].z() = (points[pI].z() - minX3)*oneOverDenomZ;
223  }
224 
225  // Indices of points that failed to converge
226  // (i.e. are bounded for nMaxBound iters)
227  boolList dropOffPoints(map.size(), false);
228  label nDropedPoints(0);
229 
230  // Initial cartesian coordinates
231  tmp<vectorField> tsplinesBasedCoors(coordinates(paramCoors));
232  vectorField& splinesBasedCoors = tsplinesBasedCoors.ref();
233 
234  // Newton-Raphson loop to compute parametric coordinates
235  // based on cartesian coordinates and the known control points
236  Info<< "Mapping of mesh points to parametric space for box " << name_
237  << " ..." << endl;
238  // Do loop on a point-basis and check residual of each point equation
239  label maxIterNeeded(0);
240  forAll(points, pI)
241  {
242  label iter(0);
243  label nBoundIters(0);
244  vector res(GREAT, GREAT, GREAT);
245  do
246  {
247  const label globalPI = map[pI];
248  vector& uVec = paramCoors[globalPI];
249  vector& coorPointI = splinesBasedCoors[pI];
250  uVec += ((inv(JacobianUVW(uVec))) & (points[pI] - coorPointI));
251  // Bounding might be needed for the first iterations
252  // If multiple bounds happen, point is outside of the control
253  // boxes and should be discarded
254  if (bound(uVec))
255  {
256  ++nBoundIters;
257  }
258  if (nBoundIters > nMaxBound_)
259  {
260  dropOffPoints[pI] = true;
261  ++nDropedPoints;
262  break;
263  }
264  // Update current cartesian coordinates based on parametric ones
265  coorPointI = coordinates(uVec);
266  // Compute residual
267  res = cmptMag(points[pI] - coorPointI);
268  }
269  while
270  (
271  (iter++ < maxIter_)
272  && (
273  res.component(0) > tolerance_
274  || res.component(1) > tolerance_
275  || res.component(2) > tolerance_
276  )
277  );
278  if (iter > maxIter_)
279  {
281  << "Mapping to parametric space for point " << pI
282  << " failed." << endl
283  << "Residual after " << maxIter_ + 1 << " iterations : "
284  << res << endl
285  << "parametric coordinates " << paramCoors[map[pI]]
286  << endl
287  << "Local system coordinates " << points[pI] << endl
288  << "Threshold residual per direction : " << tolerance_
289  << endl;
290  }
291  maxIterNeeded = max(maxIterNeeded, iter);
292  }
293  reduce(maxIterNeeded, maxOp<label>());
294 
295  label nParameterizedPoints = map.size() - nDropedPoints;
296 
297  // Resize mapping lists and parametric coordinates after dropping some
298  // points
299  labelList mapOld(map);
300 
301  map.setSize(nParameterizedPoints);
302 
303  label curIndex(0);
304  forAll(dropOffPoints, pI)
305  {
306  if (!dropOffPoints[pI])
307  {
308  map[curIndex] = mapOld[pI];
309  reverseMap[mapOld[pI]] = curIndex;
310  ++curIndex;
311  }
312  else
313  {
314  paramCoors[mapOld[pI]] = vector::zero;
315  reverseMap[mapOld[pI]] = -1;
316  }
317  }
318 
319  reduce(nDropedPoints, sumOp<label>());
320  reduce(nParameterizedPoints, sumOp<label>());
321  Info<< "Found " << nDropedPoints
322  << " to discard from morphing boxes" << endl;
323  Info<< "Keeping " << nParameterizedPoints
324  << " parameterized points in boxes" << endl;
325 
326  splinesBasedCoors = coordinates(paramCoors)();
327  scalar maxDiff(-GREAT);
328  forAll(splinesBasedCoors, pI)
329  {
330  scalar diff =
331  mag(splinesBasedCoors[pI] - localSystemCoordinates_[map[pI]]);
332  if (diff > maxDiff)
333  {
334  maxDiff = diff;
335  }
336  }
337  reduce(maxDiff, maxOp<scalar>());
338  scalar timeAft = mesh_.time().elapsedCpuTime();
339  Info<< "\tMapping completed in " << timeAft - timeBef << " seconds"
340  << endl;
341  Info<< "\tMax iterations per point needed to compute parametric "
342  << "coordinates : "
343  << maxIterNeeded << endl;
344  Info<< "\tMax difference between original mesh points and "
345  << "parameterized ones "
346  << maxDiff << endl;
347  }
348 }
349 
350 
352 (
353  tmp<vectorField> tPoints
354 )
355 {
356  const vectorField& points = tPoints();
357  computeParametricCoordinates(points);
358 }
359 
360 
362 (
363  vector& vec,
364  scalar minValue,
365  scalar maxValue
366 )
367 {
368  bool boundPoint(false);
369  // Lower value bounding
370  if (vec.x() < scalar(0))
371  {
372  vec.x() = minValue;
373  boundPoint = true;
374  }
375  if (vec.y() < scalar(0))
376  {
377  vec.y() = minValue;
378  boundPoint = true;
379  }
380  if (vec.z() < scalar(0))
381  {
382  vec.z() = minValue;
383  boundPoint = true;
384  }
385  // Upper value bounding
386  if (vec.x() > 1)
387  {
388  vec.x() = maxValue;
389  boundPoint = true;
390  }
391  if (vec.y() > 1)
392  {
393  vec.y() = maxValue;
394  boundPoint = true;
395  }
396  if (vec.z() > 1)
397  {
398  vec.z() = maxValue;
399  boundPoint = true;
400  }
401  return boundPoint;
402 }
403 
404 
406 {
407  if (Pstream::master())
408  {
409  mkDir(mesh_.time().globalPath()/"optimisation"/cpsFolder_);
410  }
411 }
412 
413 
415 {
416  label nCPs = cps_.size();
417  activeControlPoints_ = boolList(nCPs, true);
418  activeDesignVariables_ = boolList(3*nCPs, true);
419 
420  // Check whether all boundary control points should be confined
421  confineBoundaryControlPoints();
422 
423  // Apply confinement to maintain continuity
424  continuityRealatedConfinement();
425 
426  // Confine user-specified directions
427  confineControlPointsDirections();
428 
429  // Determine active control points. A control point is considered active
430  // if at least one of its components is free to move
431  forAll(activeControlPoints_, cpI)
432  {
433  if
434  (
435  !activeDesignVariables_[3*cpI]
436  && !activeDesignVariables_[3*cpI + 1]
437  && !activeDesignVariables_[3*cpI + 2]
438  )
439  {
440  activeControlPoints_[cpI] = false;
441  }
442  }
443 }
444 
445 
447 {
448  const label nCPsU = basisU_.nCPs();
449  const label nCPsV = basisV_.nCPs();
450  const label nCPsW = basisW_.nCPs();
451 
452  // Zero movement of the boundary control points. Active by default
453  if (confineBoundaryControlPoints_)
454  {
455  // Side patches
456  for (label iCPw = 0; iCPw < nCPsW; iCPw += nCPsW - 1)
457  {
458  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
459  {
460  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
461  {
462  confineControlPoint(getCPID(iCPu, iCPv, iCPw));
463  }
464  }
465  }
466  // Front-back patches
467  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
468  {
469  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
470  {
471  for (label iCPu = 0; iCPu < nCPsU; iCPu += nCPsU - 1)
472  {
473  confineControlPoint(getCPID(iCPu, iCPv, iCPw));
474  }
475  }
476  }
477  // Top-bottom patches
478  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
479  {
480  for (label iCPv = 0; iCPv < nCPsV; iCPv += nCPsV - 1)
481  {
482  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
483  {
484  confineControlPoint(getCPID(iCPu, iCPv, iCPw));
485  }
486  }
487  }
488  }
489 }
490 
491 
493 {
494  const label nCPsU = basisU_.nCPs();
495  const label nCPsV = basisV_.nCPs();
496  const label nCPsW = basisW_.nCPs();
497 
498  // Zero movement to a number of x-constant slices of cps in order to
499  // preserve continuity at the boundary of the parameterized space
500  forAll(boundUMinCPs_, iCPu)
501  {
502  const FixedList<bool, 3>& confineSlice = boundUMinCPs_[iCPu];
503  // Control points at the start of the parameterized space
504  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
505  {
506  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
507  {
508  confineControlPoint(getCPID(iCPu, iCPv, iCPw), confineSlice);
509  }
510  }
511  }
512 
513  forAll(boundUMaxCPs_, sliceI)
514  {
515  const FixedList<bool, 3>& confineSlice = boundUMaxCPs_[sliceI];
516  label iCPu = nCPsU - 1 - sliceI;
517  // Control points at the end of the parameterized space
518  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
519  {
520  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
521  {
522  confineControlPoint(getCPID(iCPu, iCPv, iCPw), confineSlice);
523  }
524  }
525  }
526 
527  // Zero movement to a number of y-constant slices of cps in order to
528  // preserve continuity at the boundary of the parameterized space
529  forAll(boundVMinCPs_, iCPv)
530  {
531  const FixedList<bool, 3>& confineSlice = boundVMinCPs_[iCPv];
532  // Control points at the start of the parameterized space
533  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
534  {
535  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
536  {
537  confineControlPoint(getCPID(iCPu, iCPv, iCPw), confineSlice);
538  }
539  }
540  }
541 
542  forAll(boundVMaxCPs_, sliceI)
543  {
544  const FixedList<bool, 3>& confineSlice = boundVMaxCPs_[sliceI];
545  label iCPv = nCPsV - 1 - sliceI;
546  // Control points at the end of the parameterized space
547  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
548  {
549  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
550  {
551  confineControlPoint(getCPID(iCPu, iCPv, iCPw), confineSlice);
552  }
553  }
554  }
555 
556  // Zero movement to a number of w-constant slices of cps in order to
557  // preserve continuity at the boundary of the parameterized space
558  forAll(boundWMinCPs_, iCPw)
559  {
560  const FixedList<bool, 3>& confineSlice = boundWMinCPs_[iCPw];
561  // Control points at the start of the parameterized space
562  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
563  {
564  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
565  {
566  confineControlPoint(getCPID(iCPu, iCPv, iCPw), confineSlice);
567  }
568  }
569  }
570 
571  forAll(boundWMaxCPs_, sliceI)
572  {
573  const FixedList<bool, 3>& confineSlice = boundWMaxCPs_[sliceI];
574  label iCPw = nCPsW - 1 - sliceI;
575  // Control points at the end of the parameterized space
576  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
577  {
578  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
579  {
580  confineControlPoint(getCPID(iCPu, iCPv, iCPw), confineSlice);
581  }
582  }
583  }
584 }
585 
586 
588 {
589  for (label cpI = 0; cpI < cps_.size(); ++cpI)
590  {
591  if (confineX1movement_) activeDesignVariables_[3*cpI] = false;
592  if (confineX2movement_) activeDesignVariables_[3*cpI + 1] = false;
593  if (confineX3movement_) activeDesignVariables_[3*cpI + 2] = false;
594  }
595 }
596 
597 
599 {
600  if (cpI < 0 || cpI > cps_.size() -1)
601  {
603  << "Attempted to confine contol point movement for a control point "
604  << " ID which is out of bounds"
605  << exit(FatalError);
606  }
607  else
608  {
609  activeDesignVariables_[3*cpI] = false;
610  activeDesignVariables_[3*cpI + 1] = false;
611  activeDesignVariables_[3*cpI + 2] = false;
612  }
613 }
614 
615 
617 (
618  const label cpI,
619  const FixedList<bool, 3>& confineDirections
620 )
621 {
622  if (cpI < 0 || cpI > cps_.size() -1)
623  {
625  << "Attempted to confine contol point movement for a control point "
626  << " ID which is out of bounds"
627  << exit(FatalError);
628  }
629  else
630  {
631  if (confineDirections[0]) activeDesignVariables_[3*cpI] = false;
632  if (confineDirections[1]) activeDesignVariables_[3*cpI + 1] = false;
633  if (confineDirections[2]) activeDesignVariables_[3*cpI + 2] = false;
634  }
635 }
636 
637 
638 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
639 
641 (
642  const dictionary& dict,
643  const fvMesh& mesh,
644  bool computeParamCoors
645 )
646 :
647  mesh_(mesh),
648  name_(dict.dictName()),
649  basisU_(dict.get<label>("nCPsU"), dict.get<label>("degreeU")),
650  basisV_(dict.get<label>("nCPsV"), dict.get<label>("degreeV")),
651  basisW_(dict.get<label>("nCPsW"), dict.get<label>("degreeW")),
652  maxIter_(dict.lookupOrDefault<label>("maxIterations", 10)),
653  tolerance_(dict.lookupOrDefault<scalar>("tolerance", 1.e-10)),
654  nMaxBound_(dict.lookupOrDefault<scalar>("nMaxBoundIterations", 4)),
655  cps_(0),
656  mapPtr_(nullptr),
657  reverseMapPtr_(nullptr),
658  parametricCoordinatesPtr_(nullptr),
659  localSystemCoordinates_(mesh_.nPoints(), Zero),
660  confineX1movement_(dict.lookupOrDefault<bool>("confineX1movement", false)),
661  confineX2movement_(dict.lookupOrDefault<bool>("confineX2movement", false)),
662  confineX3movement_(dict.lookupOrDefault<bool>("confineX3movement", false)),
663  confineBoundaryControlPoints_
664  (
665  dict.lookupOrDefault<bool>("confineBoundaryControlPoints", true)
666  ),
667  boundUMinCPs_
668  (
669  dict.lookupOrDefault<boolListList3>("boundUMinCPs", boolListList3(0))
670  ),
671  boundUMaxCPs_
672  (
673  dict.lookupOrDefault<boolListList3>("boundUMaxCPs", boolListList3(0))
674  ),
675  boundVMinCPs_
676  (
677  dict.lookupOrDefault<boolListList3>("boundVMinCPs", boolListList3(0))
678  ),
679  boundVMaxCPs_
680  (
681  dict.lookupOrDefault<boolListList3>("boundVMaxCPs", boolListList3(0))
682  ),
683  boundWMinCPs_
684  (
685  dict.lookupOrDefault<boolListList3>("boundWMinCPs", boolListList3(0))
686  ),
687  boundWMaxCPs_
688  (
689  dict.lookupOrDefault<boolListList3>("boundWMaxCPs", boolListList3(0))
690  ),
691  activeControlPoints_(0), //zero here, execute sanity checks first
692  activeDesignVariables_(0), //zero here, execute sanity checks first
693  cpsFolder_("controlPoints"),
694  readStoredData_(dict.lookupOrDefault<bool>("readStoredData", true))
695 {
696  // Create folders
697  makeFolders();
698 
699  // Sanity checks
700  if
701  (
702  (boundUMinCPs_.size() + boundUMaxCPs_.size() >= basisU_.nCPs())
703  || (boundVMinCPs_.size() + boundVMaxCPs_.size() >= basisV_.nCPs())
704  || (boundWMinCPs_.size() + boundWMaxCPs_.size() >= basisW_.nCPs())
705  )
706  {
708  << "Number of control point slices to be kept frozen at "
709  << "the boundaries is invalid \n"
710  << "Number of control points in u " << basisU_.nCPs() << "\n"
711  << "Number of control points in v " << basisV_.nCPs() << "\n"
712  << "Number of control points in w " << basisW_.nCPs() << "\n"
713  << exit(FatalError);
714  }
715 
716  word controlPointsDefinition(dict.get<word>("controlPointsDefinition"));
717 
718  // Read specific control points if given
719  if (controlPointsDefinition == "fromFile")
720  {
721  Info<< "Reading control points from file " << endl;
722  IOdictionary cpsDict
723  (
724  IOobject
725  (
726  name_ + "cpsBsplines" + mesh_.time().timeName(),
727  mesh_.time().caseConstant(),
728  cpsFolder_,
729  mesh_,
732  false
733  )
734  );
735 
736  cpsDict.readEntry("controlPoints", cps_);
737  if (cps_.size() != (basisU_.nCPs()*basisV_.nCPs()*basisW_.nCPs()))
738  {
740  << "Number of control points does not agree with "
741  << "nCPsU*nCPv*nCPsW"
742  << exit(FatalError);
743  }
744  }
745  // Else, construct control points based on their min, max coordinates and
746  // their number
747  else if (controlPointsDefinition == "axisAligned")
748  {
749  const label nCPsU = basisU_.nCPs();
750  const label nCPsV = basisV_.nCPs();
751  const label nCPsW = basisW_.nCPs();
752 
753  cps_.setSize(nCPsU * nCPsV * nCPsW);
754 
755  vector lowerBounds(dict.get<vector>("lowerCpBounds"));
756  vector upperBounds(dict.get<vector>("upperCpBounds"));
757 
758  // Equidistribute cps in th u,v,w directions
759  for (label iCPw = 0; iCPw < nCPsW; ++iCPw)
760  {
761  for (label iCPv = 0; iCPv < nCPsV; ++iCPv)
762  {
763  for (label iCPu = 0; iCPu < nCPsU; ++iCPu)
764  {
765  cps_[getCPID(iCPu, iCPv, iCPw)] =
766  (
767  lowerBounds.x()
768  +scalar(iCPu)/scalar(nCPsU - 1)
769  *(upperBounds.x()-lowerBounds.x())
770  )*vector(1, 0, 0)
771  + (
772  lowerBounds.y()
773  +scalar(iCPv)/scalar(nCPsV - 1)
774  *(upperBounds.y()-lowerBounds.y())
775  )*vector(0, 1, 0)
776  + (
777  lowerBounds.z()
778  +scalar(iCPw)/scalar(nCPsW - 1)
779  *(upperBounds.z()-lowerBounds.z())
780  )*vector(0, 0, 1);
781  }
782  }
783  }
784  }
785  else
786  {
788  << "Unknown controlPointsDefinition type "
789  << controlPointsDefinition
790  << endl << endl
791  << "Valid types are : axisAligned, fromFile" << endl
792  << exit(FatalError);
793  }
794  determineActiveDesignVariablesAndPoints();
795  writeCpsInDict();
796 }
797 
798 
799 // * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
800 
802 (
803  const dictionary& dict,
804  const fvMesh& mesh,
805  bool computeParamCoors
806 )
807 {
808  const word modelType(dict.get<word>("type"));
809 
810  Info<< "NURBS3DVolume type : " << modelType << endl;
811 
812  auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
813 
814  if (!cstrIter.found())
815  {
817  (
818  dict,
819  "type",
820  modelType,
821  *dictionaryConstructorTablePtr_
822  ) << exit(FatalIOError);
823  }
824 
825  return autoPtr<NURBS3DVolume>(cstrIter()(dict, mesh, computeParamCoors));
826 }
827 
828 
829 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
830 
832 (
833  const scalar u,
834  const scalar v,
835  const scalar w
836 ) const
837 {
838  const label degreeU = basisU_.degree();
839  const label degreeV = basisV_.degree();
840  const label degreeW = basisW_.degree();
841 
842  const label nCPsU = basisU_.nCPs();
843  const label nCPsV = basisV_.nCPs();
844  const label nCPsW = basisW_.nCPs();
845 
846  vector derivative(Zero);
847 
848  for (label iCPw = 0; iCPw < nCPsW; ++iCPw)
849  {
850  for (label iCPv = 0; iCPv < nCPsV; ++iCPv)
851  {
852  for (label iCPu = 0; iCPu < nCPsU; ++iCPu)
853  {
854  derivative +=
855  cps_[getCPID(iCPu, iCPv, iCPw)]
856  *basisU_.basisDerivativeU(iCPu, degreeU, u)
857  *basisV_.basisValue(iCPv, degreeV, v)
858  *basisW_.basisValue(iCPw, degreeW, w);
859  }
860  }
861  }
862 
863  return derivative;
864 }
865 
866 
868 (
869  const scalar u,
870  const scalar v,
871  const scalar w
872 ) const
873 {
874  const label degreeU = basisU_.degree();
875  const label degreeV = basisV_.degree();
876  const label degreeW = basisW_.degree();
877 
878  const label nCPsU = basisU_.nCPs();
879  const label nCPsV = basisV_.nCPs();
880  const label nCPsW = basisW_.nCPs();
881 
882  vector derivative(Zero);
883 
884  for (label iCPw = 0; iCPw < nCPsW; ++iCPw)
885  {
886  for (label iCPv = 0; iCPv < nCPsV; ++iCPv)
887  {
888  for (label iCPu = 0; iCPu < nCPsU; ++iCPu)
889  {
890  derivative +=
891  cps_[getCPID(iCPu, iCPv, iCPw)]
892  *basisU_.basisValue(iCPu, degreeU, u)
893  *basisV_.basisDerivativeU(iCPv, degreeV, v)
894  *basisW_.basisValue(iCPw, degreeW, w);
895  }
896  }
897  }
898 
899  return derivative;
900 }
901 
902 
904 (
905  const scalar u,
906  const scalar v,
907  const scalar w
908 ) const
909 {
910  const label degreeU = basisU_.degree();
911  const label degreeV = basisV_.degree();
912  const label degreeW = basisW_.degree();
913 
914  const label nCPsU = basisU_.nCPs();
915  const label nCPsV = basisV_.nCPs();
916  const label nCPsW = basisW_.nCPs();
917 
918  vector derivative(Zero);
919 
920  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
921  {
922  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
923  {
924  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
925  {
926  derivative +=
927  cps_[getCPID(iCPu, iCPv, iCPw)]
928  *basisU_.basisValue(iCPu, degreeU, u)
929  *basisV_.basisValue(iCPv, degreeV, v)
930  *basisW_.basisDerivativeU(iCPw, degreeW, w);
931  }
932  }
933  }
934 
935  return derivative;
936 }
937 
938 
940 (
941  const vector& uVector
942 ) const
943 {
944  const scalar u = uVector.x();
945  const scalar v = uVector.y();
946  const scalar w = uVector.z();
947 
948  vector uDeriv = volumeDerivativeU(u, v, w);
949  vector vDeriv = volumeDerivativeV(u, v, w);
950  vector wDeriv = volumeDerivativeW(u, v, w);
951 
952  tensor Jacobian(Zero);
953 
954  Jacobian[0] = uDeriv.component(0);
955  Jacobian[1] = vDeriv.component(0);
956  Jacobian[2] = wDeriv.component(0);
957  Jacobian[3] = uDeriv.component(1);
958  Jacobian[4] = vDeriv.component(1);
959  Jacobian[5] = wDeriv.component(1);
960  Jacobian[6] = uDeriv.component(2);
961  Jacobian[7] = vDeriv.component(2);
962  Jacobian[8] = wDeriv.component(2);
963 
964  return Jacobian;
965 }
966 
967 
969 (
970  const vector& uVector,
971  const label cpI
972 ) const
973 {
974  const scalar u = uVector.x();
975  const scalar v = uVector.y();
976  const scalar w = uVector.z();
977 
978  const label nCPsU = basisU_.nCPs();
979  const label nCPsV = basisV_.nCPs();
980 
981  const label degreeU = basisU_.degree();
982  const label degreeV = basisV_.degree();
983  const label degreeW = basisW_.degree();
984 
985  label iCPw = cpI/label(nCPsU*nCPsV);
986  label iCPv = (cpI - iCPw*nCPsU*nCPsV)/nCPsU;
987  label iCPu = (cpI - iCPw*nCPsU*nCPsV - iCPv*nCPsU);
988 
989  // Normally, this should be a tensor, however the parameterization is
990  // isotropic. Hence the tensor degenerates to a diagonal tensor with all
991  // diagonal elements being equal. This returns the (unique) diag element
992  scalar derivative =
993  basisU_.basisValue(iCPu, degreeU, u)
994  *basisV_.basisValue(iCPv, degreeV, v)
995  *basisW_.basisValue(iCPw, degreeW, w);
996 
997  return derivative;
998 }
999 
1000 
1003  const pointVectorField& pointSens,
1004  const labelList& sensitivityPatchIDs
1005 )
1006 {
1007  vectorField controlPointDerivs(cps_.size(), Zero);
1008 
1009  // Get parametric coordinates
1010  const vectorField& parametricCoordinates = getParametricCoordinates();
1011 
1012  forAll(controlPointDerivs, cpI)
1013  {
1014  forAll(sensitivityPatchIDs, pI)
1015  {
1016  const label patchI = sensitivityPatchIDs[pI];
1017  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1018  const labelList& meshPoints = patch.meshPoints();
1019 
1020  forAll(meshPoints, mpI)
1021  {
1022  const label globalIndex = meshPoints[mpI];
1023  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1024 
1025  // If point resides within control points box,
1026  // add contribution to cp derivative
1027  if (whichPointInBox != -1)
1028  {
1029  controlPointDerivs[cpI] +=
1030  (
1031  pointSens[globalIndex]
1032  & transformationTensorDxDb(globalIndex)
1033  )
1034  *volumeDerivativeCP
1035  (
1036  parametricCoordinates[globalIndex],
1037  cpI
1038  );
1039  }
1040  }
1041  }
1042  }
1043 
1044  // Sum contributions from all processors
1045  Pstream::listCombineGather(controlPointDerivs, plusEqOp<vector>());
1046  Pstream::listCombineScatter(controlPointDerivs);
1047 
1048  return controlPointDerivs;
1049 }
1050 
1051 
1054  const volVectorField& faceSens,
1055  const labelList& sensitivityPatchIDs
1056 )
1057 {
1058  return
1059  computeControlPointSensitivities
1060  (
1061  faceSens.boundaryField(),
1062  sensitivityPatchIDs
1063  );
1064 }
1065 
1066 
1069  const boundaryVectorField& faceSens,
1070  const labelList& sensitivityPatchIDs
1071 )
1072 {
1073  // Return field
1074  vectorField controlPointDerivs(cps_.size(), Zero);
1075 
1076  // Get parametric coordinates
1077  const vectorField& parametricCoordinates = getParametricCoordinates();
1078 
1079  // Auxilary quantities
1081  const labelList& reverseMap = reverseMapPtr_();
1082 
1083  forAll(controlPointDerivs, cpI)
1084  {
1085  forAll(sensitivityPatchIDs, pI)
1086  {
1087  const label patchI = sensitivityPatchIDs[pI];
1088  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1089  const label patchStart = patch.start();
1090  const fvPatchVectorField& patchSens = faceSens[patchI];
1091 
1092  // loop over patch faces
1093  forAll(patch, fI)
1094  {
1095  const face& fGlobal = mesh_.faces()[fI + patchStart];
1096  const pointField facePoints = fGlobal.points(mesh_.points());
1097  // loop over face points
1098  tensorField facePointDerivs(facePoints.size(), Zero);
1099  forAll(fGlobal, pI)
1100  {
1101  const label globalIndex = fGlobal[pI]; //global point index
1102  const label whichPointInBox = reverseMap[globalIndex];
1103  // if point resides within control points box,
1104  // add contribution to d( facePoints )/db
1105  if (whichPointInBox != -1)
1106  {
1107  // TENSOR-BASED
1108  //~~~~~~~~~~~~~
1109  facePointDerivs[pI] =
1110  transformationTensorDxDb(globalIndex)
1111  * volumeDerivativeCP
1112  (
1113  parametricCoordinates[globalIndex],
1114  cpI
1115  );
1116 
1117  }
1118  }
1119 
1120  tensor fCtrs_d =
1122  (
1123  facePoints,
1124  facePointDerivs
1125  )[0];
1126  controlPointDerivs[cpI] += patchSens[fI] & fCtrs_d;
1127  }
1128  }
1129  }
1130  // Sum contributions from all processors
1131  Pstream::listCombineGather(controlPointDerivs, plusEqOp<vector>());
1132  Pstream::listCombineScatter(controlPointDerivs);
1133 
1134  return controlPointDerivs;
1135 }
1136 
1137 
1140  const vectorField& faceSens,
1141  const label patchI,
1142  const label cpI
1143 )
1144 {
1145  // Return vector
1146  vector cpSens(Zero);
1147  // Get parametric coordinates
1148  const vectorField& parametricCoordinates = getParametricCoordinates();
1149 
1150  // Auxilary quantities
1152  const labelList& reverseMap = reverseMapPtr_();
1153 
1154  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1155  const label patchStart = patch.start();
1156  // Loop over patch faces
1157  forAll(patch, fI)
1158  {
1159  const face& fGlobal = mesh_.faces()[fI + patchStart];
1160  const pointField facePoints = fGlobal.points(mesh_.points());
1161  // Loop over face points
1162  tensorField facePointDerivs(facePoints.size(), Zero);
1163  forAll(fGlobal, pI)
1164  {
1165  const label globalIndex = fGlobal[pI]; //global point index
1166  const label whichPointInBox = reverseMap[globalIndex];
1167  // If point resides within control points box,
1168  // add contribution to d( facePoints )/db
1169  if (whichPointInBox != -1)
1170  {
1171  // TENSOR-BASED
1172  //~~~~~~~~~~~~~
1173  facePointDerivs[pI] =
1174  transformationTensorDxDb(globalIndex)
1175  *volumeDerivativeCP
1176  (
1177  parametricCoordinates[globalIndex],
1178  cpI
1179  );
1180  }
1181  }
1182 
1183  tensor fCtrs_d =
1185  (
1186  facePoints,
1187  facePointDerivs
1188  )[0];
1189  cpSens += faceSens[fI] & fCtrs_d;
1190  }
1191  // Sum contributions from all processors
1192  reduce(cpSens, sumOp<vector>());
1193 
1194  return cpSens;
1195 }
1196 
1197 
1200  const label patchI,
1201  const label cpI,
1202  bool DimensionedNormalSens
1203 )
1204 {
1205  const fvPatch& patch = mesh_.boundary()[patchI];
1206  const polyPatch& ppatch = patch.patch();
1207  // Return field
1208  tmp<tensorField> tdndbSens(new tensorField(patch.size(), Zero));
1209  tensorField& dndbSens = tdndbSens.ref();
1210  // Auxilary quantities
1212  const label patchStart = ppatch.start();
1213  const labelList& reverseMap = reverseMapPtr_();
1214 
1215  // Get parametric coordinates
1216  const vectorField& parametricCoordinates = getParametricCoordinates();
1217 
1218  // Loop over patch faces
1219  forAll(patch, fI)
1220  {
1221  const face& fGlobal = mesh_.faces()[fI + patchStart];
1222  const pointField facePoints = fGlobal.points(mesh_.points());
1223  // Loop over face points
1224  tensorField facePointDerivs(facePoints.size(), Zero);
1225  forAll(fGlobal, pI)
1226  {
1227  const label globalIndex = fGlobal[pI]; //global point index
1228  const label whichPointInBox = reverseMap[globalIndex];
1229  // If point resides within control points box,
1230  // add contribution to d( facePoints )/db
1231  if (whichPointInBox != -1)
1232  {
1233  // TENSOR-BASED
1234  //~~~~~~~~~~~~~
1235  facePointDerivs[pI] =
1236  transformationTensorDxDb(globalIndex)
1237  *volumeDerivativeCP
1238  (
1239  parametricCoordinates[globalIndex],
1240  cpI
1241  );
1242  }
1243  }
1244 
1245  // Determine whether to return variance of dimensioned or unit normal
1246  tensorField dNdbSens =
1248  (
1249  facePoints,
1250  facePointDerivs
1251  );
1252 
1253  if (DimensionedNormalSens)
1254  {
1255  dndbSens[fI] = dNdbSens[1];
1256  }
1257  else
1258  {
1259  dndbSens[fI] = dNdbSens[2];
1260  }
1261  }
1262 
1263  return tdndbSens;
1264 }
1265 
1266 
1269  const label patchI,
1270  const label cpI
1271 )
1272 {
1273  // Get parametric coordinates
1274  const vectorField& parametricCoordinates = getParametricCoordinates();
1275 
1276  // Patch data
1277  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1278  const labelList& meshPoints = patch.meshPoints();
1279 
1280  // Return field
1281  auto tdxdb = tmp<tensorField>::New(patch.nPoints(), Zero);
1282  auto& dxdb = tdxdb.ref();
1283 
1284  forAll(meshPoints, pI)
1285  {
1286  const label globalIndex = meshPoints[pI]; //global point index
1287  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1288 
1289  // If point resides within control points box, find dxdb
1290  if (whichPointInBox != -1)
1291  {
1292  dxdb[pI] =
1293  transformationTensorDxDb(globalIndex)
1294  *volumeDerivativeCP
1295  (
1296  parametricCoordinates[globalIndex],
1297  cpI
1298  );
1299  }
1300  }
1301 
1302  return tdxdb;
1303 }
1304 
1305 
1308  const label patchI,
1309  const label cpI
1310 )
1311 {
1312  // get parametric coordinates
1313  const vectorField& parametricCoordinates = getParametricCoordinates();
1314 
1315  // Patch data
1316  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1317  const label patchStart = patch.start();
1318 
1319  // Return field
1320  auto tdxdb = tmp<tensorField>::New(patch.size(), Zero);
1321  auto& dxdb = tdxdb.ref();
1322 
1323  // Mesh differentiation engine
1324  deltaBoundary deltaBound(mesh_);
1325 
1326  forAll(patch, fI)
1327  {
1328  const face& fGlobal = mesh_.faces()[fI + patchStart];
1329  const pointField facePoints = fGlobal.points(mesh_.points());
1330  // Loop over face points
1331  tensorField facePointDerivs(facePoints.size(), Zero);
1332  forAll(fGlobal, pI)
1333  {
1334  const label globalIndex = fGlobal[pI]; //global point index
1335  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1336  // If point resides within control points box,
1337  // add contribution to d( facePoints )/db
1338  if (whichPointInBox != -1)
1339  {
1340  // TENSOR-BASED
1341  //~~~~~~~~~~~~~
1342  facePointDerivs[pI] =
1343  transformationTensorDxDb(globalIndex)
1344  *volumeDerivativeCP
1345  (
1346  parametricCoordinates[globalIndex],
1347  cpI
1348  );
1349 
1350  }
1351  }
1352  dxdb[fI] =
1353  deltaBound.makeFaceCentresAndAreas_d
1354  (
1355  facePoints,
1356  facePointDerivs
1357  )[0];
1358  }
1359 
1360  return tdxdb;
1361 }
1362 
1363 
1366  const vectorField& uVector
1367 ) const
1368 {
1369  const label degreeU = basisU_.degree();
1370  const label degreeV = basisV_.degree();
1371  const label degreeW = basisW_.degree();
1372 
1373  const label nCPsU = basisU_.nCPs();
1374  const label nCPsV = basisV_.nCPs();
1375  const label nCPsW = basisW_.nCPs();
1376 
1377  const label nPoints = mapPtr_().size();
1378  auto tpoints = tmp<vectorField>::New(nPoints, Zero);
1379  auto& points = tpoints.ref();
1380 
1381  forAll(points, pI)
1382  {
1383  const label globalPI = mapPtr_()[pI];
1384  const scalar u = uVector[globalPI].x();
1385  const scalar v = uVector[globalPI].y();
1386  const scalar w = uVector[globalPI].z();
1387  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
1388  {
1389  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
1390  {
1391  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
1392  {
1393  points[pI] +=
1394  cps_[getCPID(iCPu, iCPv, iCPw)]
1395  *basisU_.basisValue(iCPu, degreeU, u)
1396  *basisV_.basisValue(iCPv, degreeV, v)
1397  *basisW_.basisValue(iCPw, degreeW, w);
1398  }
1399  }
1400  }
1401  }
1402 
1403  return tpoints;
1404 }
1405 
1406 
1409  const vector& uVector
1410 ) const
1411 {
1412  const label degreeU = basisU_.degree();
1413  const label degreeV = basisV_.degree();
1414  const label degreeW = basisW_.degree();
1415 
1416  const label nCPsU = basisU_.nCPs();
1417  const label nCPsV = basisV_.nCPs();
1418  const label nCPsW = basisW_.nCPs();
1419 
1420  const scalar u = uVector.x();
1421  const scalar v = uVector.y();
1422  const scalar w = uVector.z();
1423 
1424  vector point(Zero);
1425  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
1426  {
1427  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
1428  {
1429  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
1430  {
1431  point +=
1432  cps_[getCPID(iCPu, iCPv, iCPw)]
1433  *basisU_.basisValue(iCPu, degreeU, u)
1434  *basisV_.basisValue(iCPv, degreeV, v)
1435  *basisW_.basisValue(iCPw, degreeW, w);
1436  }
1437  }
1438  }
1439 
1440  return point;
1441 }
1442 
1443 
1446  const vectorField& controlPointsMovement
1447 )
1448 {
1449  // Get parametric coordinates and map
1450  const vectorField& paramCoors = getParametricCoordinates();
1451  const labelList& map = mapPtr_();
1452 
1453  // Update control points position
1454  cps_ += controlPointsMovement;
1455  writeCps("cpsBsplines"+mesh_.time().timeName());
1456  writeCpsInDict();
1457 
1458  // Compute new mesh points based on updated control points
1459  tmp<vectorField> tparameterizedPoints = coordinates(paramCoors);
1460  const vectorField& parameterizedPoints = tparameterizedPoints();
1461 
1462  // Return field. Initialized with current mesh points
1463  tmp<vectorField> tnewPoints(new vectorField(mesh_.points()));
1464  vectorField& newPoints = tnewPoints.ref();
1465 
1466  // Update position of parameterized points
1467  forAll(parameterizedPoints, pI)
1468  {
1469  newPoints[map[pI]] = transformPointToCartesian(parameterizedPoints[pI]);
1470  }
1471 
1472  // Update coordinates in the local system based on the cartesian points
1473  updateLocalCoordinateSystem(newPoints);
1474  DebugInfo
1475  << "Max mesh movement equal to "
1476  << gMax(mag(newPoints - mesh_.points())) << endl;
1477 
1478  return tnewPoints;
1479 }
1480 
1481 
1484  const vectorField& controlPointsMovement,
1485  const labelList& patchesToBeMoved
1486 )
1487 {
1488  // Get parametric coordinates
1489  const vectorField& paramCoors = getParametricCoordinates();
1490 
1491  // Update control points position
1492  cps_ += controlPointsMovement;
1493 
1494  writeCps("cpsBsplines"+mesh_.time().timeName());
1495  writeCpsInDict();
1496 
1497  // Return field. Initialized with current mesh points
1498  tmp<vectorField> tnewPoints(new vectorField(mesh_.points()));
1499  vectorField& newPoints = tnewPoints.ref();
1500 
1501  // Update position of parameterized boundary points
1502  for (const label patchI : patchesToBeMoved)
1503  {
1504  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1505  const labelList& meshPoints = patch.meshPoints();
1506 
1507  for (const label globalIndex : meshPoints)
1508  {
1509  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1510  // If point resides within control points box,
1511  // compute new cartesian coordinates
1512  if (whichPointInBox != -1)
1513  {
1514  newPoints[globalIndex] =
1515  transformPointToCartesian
1516  (
1517  coordinates
1518  (
1519  paramCoors[globalIndex]
1520  )
1521  );
1522  }
1523  }
1524  }
1525 
1526  // Update coordinates in the local system based on the cartesian points
1527  updateLocalCoordinateSystem(newPoints);
1528  DebugInfo
1529  << "Max mesh movement equal to "
1530  << gMax(mag(newPoints - mesh_.points())) << endl;
1531 
1532  return tnewPoints;
1533 }
1534 
1535 
1537 {
1538  if (cps_.size() != newCps.size())
1539  {
1541  << "Attempting to replace control points with a set of "
1542  << "different size"
1543  << exit(FatalError);
1544  }
1545  cps_ = newCps;
1546 }
1547 
1548 
1551  vectorField& controlPointsMovement
1552 )
1553 {
1554  forAll(controlPointsMovement, cpI)
1555  {
1556  if (!activeDesignVariables_[3*cpI])
1557  {
1558  controlPointsMovement[cpI].x() = Zero;
1559  }
1560  if (!activeDesignVariables_[3*cpI + 1])
1561  {
1562  controlPointsMovement[cpI].y() = Zero;
1563  }
1564  if (!activeDesignVariables_[3*cpI + 2])
1565  {
1566  controlPointsMovement[cpI].z() = Zero;
1567  }
1568  }
1569 }
1570 
1571 
1574  const vectorField& controlPointsMovement,
1575  const labelList& patchesToBeMoved
1576 )
1577 {
1578  // Backup old cps
1579  vectorField oldCPs = cps_;
1580  // Get parametric coordinates
1581  const vectorField& paramCoors = getParametricCoordinates();
1582  // Update control points position
1583  cps_ += controlPointsMovement;
1584  // Update position of parameterized boundary points
1585  scalar maxDisplacement(Zero);
1586  for (const label patchI : patchesToBeMoved)
1587  {
1588  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1589  const labelList& meshPoints = patch.meshPoints();
1590 
1591  for (const label globalIndex : meshPoints)
1592  {
1593  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1594  // If point resides within control points box,
1595  // compute new cartesian coordinates
1596  if (whichPointInBox != -1)
1597  {
1598  vector newPoint =
1599  transformPointToCartesian
1600  (
1601  coordinates
1602  (
1603  paramCoors[globalIndex]
1604  )
1605  );
1606  maxDisplacement =
1607  max
1608  (
1609  maxDisplacement,
1610  mag(newPoint - mesh_.points()[globalIndex])
1611  );
1612  }
1613  }
1614  }
1615  reduce(maxDisplacement, maxOp<scalar>());
1616  cps_ = oldCPs;
1617 
1618  return maxDisplacement;
1619 }
1620 
1621 
1623 {
1624  if (mapPtr_.empty())
1625  {
1626  findPointsInBox(localSystemCoordinates_);
1627  }
1628  tmp<vectorField> pointsInBox
1629  (
1630  new vectorField(localSystemCoordinates_, mapPtr_())
1631  );
1632 
1633  return pointsInBox;
1634 }
1635 
1636 
1638 {
1639  if (mapPtr_.empty())
1640  {
1641  findPointsInBox(localSystemCoordinates_);
1642  }
1643 
1644  return mapPtr_();
1645 }
1646 
1647 
1649 {
1650  if (reverseMapPtr_.empty())
1651  {
1652  findPointsInBox(localSystemCoordinates_);
1653  }
1654 
1655  return reverseMapPtr_();
1656 }
1657 
1658 
1660 {
1661  // If not computed yet, compute parametric coordinates
1662  if (parametricCoordinatesPtr_.empty())
1663  {
1664  // Find mesh points inside control points box
1665  // if they have been identified yet
1666  if (mapPtr_.empty())
1667  {
1668  findPointsInBox(localSystemCoordinates_);
1669  }
1670  computeParametricCoordinates(getPointsInBox()());
1671  }
1672 
1673  return parametricCoordinatesPtr_();
1674 }
1675 
1676 
1678 {
1679  // Get parametric coordinates
1680  const vectorField& parametricCoordinates = getParametricCoordinates();
1681 
1682  // Set return field to zero
1683  tmp<pointTensorField> tDxDb
1684  (
1685  new pointTensorField
1686  (
1687  IOobject
1688  (
1689  "DxDb",
1690  mesh_.time().timeName(),
1691  mesh_,
1694  ),
1695  pointMesh::New(mesh_),
1697  )
1698  );
1699 
1700  pointTensorField& DxDb = tDxDb.ref();
1701 
1702  // All points outside the control box remain unmoved.
1703  // Loop over only points within the control box
1704  const labelList& map = mapPtr_();
1705  for (const label globalIndex : map)
1706  {
1707  DxDb[globalIndex] =
1708  transformationTensorDxDb(globalIndex)
1709  *volumeDerivativeCP
1710  (
1711  parametricCoordinates[globalIndex],
1712  cpI
1713  );
1714  }
1715 
1716  return tDxDb;
1717 }
1718 
1719 
1722  const label cpI
1723 )
1724 {
1725  // Get parametric coordinates
1726  const vectorField& parametricCoordinates = getParametricCoordinates();
1727 
1728  // Set return field to zero
1729  tmp<volTensorField> tDxDb
1730  (
1731  new volTensorField
1732  (
1733  IOobject
1734  (
1735  "DxDb",
1736  mesh_.time().timeName(),
1737  mesh_,
1740  ),
1741  mesh_,
1743  )
1744  );
1745 
1746  volTensorField& DxDb = tDxDb.ref();
1747  deltaBoundary deltaBound(mesh_);
1748  const labelListList& pointCells = mesh_.pointCells();
1749 
1750  // All points outside the control box remain unmoved.
1751  // Loop over only points within the control box
1752  const labelList& map = mapPtr_();
1753  for (const label globalIndex : map)
1754  {
1755  tensor pointDxDb =
1756  transformationTensorDxDb(globalIndex)
1757  *volumeDerivativeCP
1758  (
1759  parametricCoordinates[globalIndex],
1760  cpI
1761  );
1762  const labelList& pointCellsI = pointCells[globalIndex];
1763  tmp<tensorField> tC_d = deltaBound.cellCenters_d(globalIndex);
1764  const tensorField& C_d = tC_d();
1765  forAll(pointCellsI, cI)
1766  {
1767  const label cellI = pointCellsI[cI];
1768  DxDb[cellI] += C_d[cI] & pointDxDb;
1769  }
1770  }
1771 
1772  // Assign boundary values since the grad of this field is often needed
1773  forAll(mesh_.boundary(), pI)
1774  {
1775  const fvPatch& patch = mesh_.boundary()[pI];
1776  if (!isA<coupledFvPatch>(patch))
1777  {
1778  DxDb.boundaryFieldRef()[pI] = patchDxDbFace(pI, cpI);
1779  }
1780  }
1781 
1782  // Correct coupled boundaries
1784 
1785  return tDxDb;
1786 }
1787 
1788 
1790 {
1791  label nU(basisU_.nCPs());
1792  if (nU % 2 == 0)
1793  {
1794  nU /=2;
1795  }
1796  else
1797  {
1798  nU = (nU - 1)/2 + 1;
1799  }
1800  return nU;
1801 }
1802 
1803 
1805 {
1806  label nV(basisV_.nCPs());
1807  if (nV % 2 == 0)
1808  {
1809  nV /=2;
1810  }
1811  else
1812  {
1813  nV = (nV - 1)/2 + 1;
1814  }
1815  return nV;
1816 }
1817 
1818 
1820 {
1821  label nW(basisW_.nCPs());
1822  if (nW % 2 == 0)
1823  {
1824  nW /=2;
1825  }
1826  else
1827  {
1828  nW = (nW - 1)/2 + 1;
1829  }
1830  return nW;
1831 }
1832 
1833 
1834 void Foam::NURBS3DVolume::writeCps(const string fileName) const
1835 {
1836  const label nCPsU = basisU_.nCPs();
1837  const label nCPsV = basisV_.nCPs();
1838 
1839  vectorField cpsInCartesian(cps_.size(), Zero);
1840  forAll(cpsInCartesian, cpI)
1841  {
1842  cpsInCartesian[cpI] = transformPointToCartesian(cps_[cpI]);
1843  }
1844 
1845  Info<< "Writing control point positions to file" << endl;
1846 
1847  if (Pstream::master())
1848  {
1849  OFstream cpsFile(("optimisation"/cpsFolder_/name_ + fileName + ".csv").c_str());
1850  // Write header
1851  cpsFile
1852  << "\"Points : 0\", \"Points : 1\", \"Points : 2\","
1853  << "\"u\", \"v\", \"w\","
1854  << "\"active : 0\", \"active : 1\", \"active : 2\"" << endl;
1855  forAll(cpsInCartesian, cpI)
1856  {
1857  const label iCPw = cpI/label(nCPsU*nCPsV);
1858  const label iCPv = (cpI - iCPw*nCPsU*nCPsV)/nCPsU;
1859  const label iCPu = (cpI - iCPw*nCPsU*nCPsV - iCPv*nCPsU);
1860 
1861  cpsFile
1862  << cpsInCartesian[cpI].x() << ", "
1863  << cpsInCartesian[cpI].y() << ", "
1864  << cpsInCartesian[cpI].z() << ", "
1865  << iCPu << ", "
1866  << iCPv << ", "
1867  << iCPw << ", "
1868  << activeDesignVariables_[3*cpI] << ", "
1869  << activeDesignVariables_[3*cpI + 1] << ", "
1870  << activeDesignVariables_[3*cpI + 2] << endl;
1871  }
1872  }
1873 }
1874 
1875 
1877 {
1878  if (Pstream::master())
1879  {
1880  IOdictionary cpsDict
1881  (
1882  IOobject
1883  (
1884  name_ + "cpsBsplines" + mesh_.time().timeName(),
1885  mesh_.time().caseConstant(),
1886  cpsFolder_,
1887  mesh_,
1890  false
1891  )
1892  );
1893 
1894  cpsDict.add("controlPoints", cps_);
1895  // Always write in ASCII format.
1896  // Even when choosing to write in binary through controlDict,
1897  // the content is written in ASCII format but with a binary header.
1898  // This creates problems when the content is read back in
1899  // (e.g. continuation)
1900  cpsDict.regIOobject::writeObject
1901  (
1904  mesh_.time().writeCompression(),
1905  true
1906  );
1907  }
1908 }
1909 
1910 
1912 {
1913  parametricCoordinatesPtr_().write();
1914 }
1915 
1916 
1917 // ************************************************************************* //
Foam::fvPatchField< vector >
Foam::NURBS3DVolume::computeParametricCoordinates
void computeParametricCoordinates(const vectorField &points)
Definition: NURBS3DVolume.C:118
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:54
Foam::Tensor< scalar >
Foam::maxOp
Definition: ops.H:223
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::Vector::x
const Cmpt & x() const
Access to the vector x component.
Definition: VectorI.H:78
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:129
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::deltaBoundary
Differentiation of the mesh data structure.
Definition: deltaBoundary.H:58
Foam::face::points
pointField points(const UList< point > &points) const
Return the points corresponding to this face.
Definition: faceI.H:91
Foam::NURBS3DVolume::nWSymmetry
label nWSymmetry() const
Get number of variables if CPs are moved symmetrically in W.
Definition: NURBS3DVolume.C:1819
Foam::VectorSpace::component
const Cmpt & component(const direction) const
Definition: VectorSpaceI.H:100
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::NURBS3DVolume::nUSymmetry
label nUSymmetry() const
Get number of variables if CPs are moved symmetrically in U.
Definition: NURBS3DVolume.C:1789
Foam::NURBS3DVolume::getMap
const labelList & getMap()
Get map of points in box to mesh points.
Definition: NURBS3DVolume.C:1637
Foam::NURBS3DVolume::volumeDerivativeU
vector volumeDerivativeU(const scalar u, const scalar v, const scalar w) const
Volume point derivative wrt u at point u,v,w.
Definition: NURBS3DVolume.C:832
Foam::NURBS3DVolume::write
void write() const
Write parametric coordinates.
Definition: NURBS3DVolume.C:1911
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::defineRunTimeSelectionTable
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
Foam::bound
volScalarField & bound(volScalarField &, const dimensionedScalar &lowerBound)
Bound the given scalar field if it has gone unbounded.
Definition: bound.C:35
Foam::NURBS3DVolume::volumeDerivativeW
vector volumeDerivativeW(const scalar u, const scalar v, const scalar w) const
Volume point derivative wrt w at point u,v,w.
Definition: NURBS3DVolume.C:904
Foam::MeshObject< polyMesh, UpdateableMeshObject, pointMesh >::New
static const pointMesh & New(const polyMesh &mesh, Args &&... args)
Get existing or create a new MeshObject.
Definition: MeshObject.C:48
Foam::IOstreamOption::currentVersion
static const versionNumber currentVersion
The current version number.
Definition: IOstreamOption.H:193
Foam::tensorField
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
Definition: primitiveFieldsFwd.H:57
Foam::NURBS3DVolume::computeNewBoundaryPoints
tmp< vectorField > computeNewBoundaryPoints(const vectorField &controlPointsMovement, const labelList &patchesToBeMoved)
Boundary mesh movement based on given control point movement.
Definition: NURBS3DVolume.C:1483
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
Foam::FatalIOError
IOerror FatalIOError
Foam::NURBS3DVolume::makeFolders
void makeFolders()
Create folders to store cps and derivatives.
Definition: NURBS3DVolume.C:405
Foam::NURBS3DVolume::bound
bool bound(vector &vec, scalar minValue=1e-7, scalar maxValue=0.999999)
Bound components to certain limits.
Definition: NURBS3DVolume.C:362
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::NURBS3DVolume::confineControlPoint
void confineControlPoint(const label cpI)
Confine all three movements for a prescribed control point.
Definition: NURBS3DVolume.C:598
Foam::NURBS3DVolume::cps_
vectorField cps_
The volumetric B-Splines control points.
Definition: NURBS3DVolume.H:97
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::dictionary::lookupOrDefault
T lookupOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.H:1241
Foam::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:90
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::NURBS3DVolume::confineControlPointsDirections
void confineControlPointsDirections()
Confine movement in all control points for user-defined directions.
Definition: NURBS3DVolume.C:587
Foam::NURBS3DVolume::continuityRealatedConfinement
void continuityRealatedConfinement()
Confine control point movement to maintain user-defined continuity.
Definition: NURBS3DVolume.C:492
Foam::NURBS3DVolume::computeControlPointSensitivities
vectorField computeControlPointSensitivities(const pointVectorField &pointSens, const labelList &sensitivityPatchIDs)
Definition: NURBS3DVolume.C:1002
Foam::sumOp
Definition: ops.H:213
Foam::NURBS3DVolume::reverseMapPtr_
autoPtr< labelList > reverseMapPtr_
Map of mesh points to points-in-box.
Definition: NURBS3DVolume.H:104
Foam::NURBS3DVolume::getCPID
label getCPID(const label i, const label j, const label k) const
Get control point ID from its I-J-K coordinates.
Definition: NURBS3DVolume.C:50
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
coupledFvPatch.H
OFstream.H
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::dimensionedVector
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Definition: dimensionedVector.H:50
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::NURBS3DVolume::getParametricCoordinates
const pointVectorField & getParametricCoordinates()
Get parametric coordinates.
Definition: NURBS3DVolume.C:1659
Foam::diff
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition: triad.C:378
Foam::NURBS3DVolume::confineBoundaryControlPoints
void confineBoundaryControlPoints()
Confine movement in boundary control points if necessary.
Definition: NURBS3DVolume.C:446
Foam::cmptMag
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:400
Foam::pointVectorField
GeometricField< vector, pointPatchField, pointMesh > pointVectorField
Definition: pointFields.H:52
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:258
FatalIOErrorInLookup
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:380
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:62
Foam::Field< vector >
Foam::NURBS3DVolume::findPointsInBox
void findPointsInBox(const vectorField &meshPoints)
Find points within control points box.
Definition: NURBS3DVolume.C:63
Foam::inv
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:73
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::deltaBoundary::cellCenters_d
tmp< tensorField > cellCenters_d(const label pointI)
Definition: deltaBoundary.C:285
coordinates
PtrList< coordinateSystem > coordinates(solidRegions.size())
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:63
Foam::NURBS3DVolume::determineActiveDesignVariablesAndPoints
void determineActiveDesignVariablesAndPoints()
Create lists with active design variables and control points.
Definition: NURBS3DVolume.C:414
Foam::NURBS3DVolume::mapPtr_
autoPtr< labelList > mapPtr_
Map of points-in-box to mesh points.
Definition: NURBS3DVolume.H:100
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:314
Foam::NURBS3DVolume::writeCps
void writeCps(const string="cpsFile") const
Definition: NURBS3DVolume.C:1834
Foam::NURBS3DVolume::volumeDerivativeCP
scalar volumeDerivativeCP(const vector &u, const label cpI) const
Volume point derivative wrt to control point cpI at point u,v,w.
Definition: NURBS3DVolume.C:969
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::dictionary::dictName
word dictName() const
The local dictionary name (final part of scoped name)
Definition: dictionary.H:458
Foam::NURBS3DVolume::nVSymmetry
label nVSymmetry() const
Get number of variables if CPs are moved symmetrically in V.
Definition: NURBS3DVolume.C:1804
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::deltaBoundary::makeFaceCentresAndAreas_d
vectorField makeFaceCentresAndAreas_d(const pointField &p, const pointField &p_d)
Definition: deltaBoundary.C:72
Foam::NURBS3DVolume::writeCpsInDict
void writeCpsInDict() const
Write control points on the local coordinate system.
Definition: NURBS3DVolume.C:1876
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
Foam::Field::component
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:562
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:311
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:99
Foam::NURBS3DVolume::getPointsInBox
tmp< vectorField > getPointsInBox()
Definition: NURBS3DVolume.C:1622
Foam::GeometricField::correctBoundaryConditions
void correctBoundaryConditions()
Correct boundary field.
Definition: GeometricField.C:909
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
deltaBoundary.H
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
Time.H
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::NURBS3DVolume::volumeDerivativeV
vector volumeDerivativeV(const scalar u, const scalar v, const scalar w) const
Volume point derivative wrt v at point u,v,w.
Definition: NURBS3DVolume.C:868
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:84
Foam::IOstreamOption::ASCII
"ascii"
Definition: IOstreamOption.H:66
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::NURBS3DVolume::setControlPoints
void setControlPoints(const vectorField &newCps)
Set new control points.
Definition: NURBS3DVolume.C:1536
Foam::NURBS3DVolume::dndbBasedSensitivities
tmp< tensorField > dndbBasedSensitivities(const label patchI, const label cpI, bool DimensionedNormalSens=true)
Definition: NURBS3DVolume.C:1199
Foam::GeometricField::Boundary
Definition: GeometricField.H:114
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:350
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
Definition: BitOps.H:74
Foam::GeometricField::boundaryFieldRef
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Definition: GeometricField.C:752
Foam::Vector< scalar >
Foam::NURBS3DVolume::getReverseMap
const labelList & getReverseMap()
Definition: NURBS3DVolume.C:1648
Foam::NURBS3DVolume::boundControlPointMovement
void boundControlPointMovement(vectorField &controlPointsMovement)
Definition: NURBS3DVolume.C:1550
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::NURBS3DVolume::JacobianUVW
tensor JacobianUVW(const vector &u) const
Jacobian matrix wrt to the volume parametric coordinates.
Definition: NURBS3DVolume.C:940
Foam::FixedList
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:104
points
const pointField & points
Definition: gmvOutputHeader.H:1
k
label k
Boltzmann constant.
Definition: LISASMDCalcMethod2.H:41
Foam::NURBS3DVolume::coordinates
tmp< vectorField > coordinates(const vectorField &uVector) const
Definition: NURBS3DVolume.C:1365
Foam::tmp::New
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
NURBS3DVolume.H
Foam::NURBS3DVolume::NURBS3DVolume
NURBS3DVolume(const dictionary &dict, const fvMesh &mesh, bool computeParamCoors=true)
Construct from dictionary.
Definition: NURBS3DVolume.C:641
Foam::NURBS3DVolume::computeMaxBoundaryDisplacement
scalar computeMaxBoundaryDisplacement(const vectorField &controlPointsMovement, const labelList &patchesToBeMoved)
Compute max. displacement at the boundary.
Definition: NURBS3DVolume.C:1573
Foam::NURBS3DVolume::patchDxDbFace
tmp< tensorField > patchDxDbFace(const label patchI, const label cpI)
Get patch dx/db.
Definition: NURBS3DVolume.C:1307
minValue
scalar minValue
Definition: LISASMDCalcMethod2.H:12
Foam::NURBS3DVolume::New
static autoPtr< NURBS3DVolume > New(const dictionary &dict, const fvMesh &mesh, bool computeParamCoors=true)
Return a reference to the selected NURBS model.
Definition: NURBS3DVolume.C:802
Foam::NURBS3DVolume::getDxDb
tmp< pointTensorField > getDxDb(const label cpI)
Get dxCartesiandb for a certain control point.
Definition: NURBS3DVolume.C:1677
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:703
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
Foam::pointCells
Smooth ATC in cells having a point to a set of patches supplied by type.
Definition: pointCells.H:56
Foam::plusEqOp
Definition: ops.H:72
Foam::NURBS3DVolume::getDxCellsDb
tmp< volTensorField > getDxCellsDb(const label cpI)
Get dxCartesiandb for a certain control point on cells.
Definition: NURBS3DVolume.C:1721
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::GeometricField< vector, pointPatchField, pointMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:123
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::NURBS3DVolume::patchDxDb
tmp< tensorField > patchDxDb(const label patchI, const label cpI)
Get patch dx/db.
Definition: NURBS3DVolume.C:1268
Foam::NURBS3DVolume::computeNewPoints
tmp< vectorField > computeNewPoints(const vectorField &controlPointsMovement)
Mesh movement based on given control point movement.
Definition: NURBS3DVolume.C:1445
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:294
Foam::dimensionedTensor
dimensioned< tensor > dimensionedTensor
Dimensioned tensor obtained from generic dimensioned type.
Definition: dimensionedTensor.H:51
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62
maxValue
scalar maxValue
Definition: LISASMDCalcMethod1.H:5
Foam::IOobject::MUST_READ
Definition: IOobject.H:120