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-2020 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 intermediate 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 intermediate
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(confineUMinCPs_, iCPu)
501  {
502  const FixedList<bool, 3>& confineSlice = confineUMinCPs_[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(confineUMaxCPs_, sliceI)
514  {
515  const FixedList<bool, 3>& confineSlice = confineUMaxCPs_[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(confineVMinCPs_, iCPv)
530  {
531  const FixedList<bool, 3>& confineSlice = confineVMinCPs_[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(confineVMaxCPs_, sliceI)
543  {
544  const FixedList<bool, 3>& confineSlice = confineVMaxCPs_[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(confineWMinCPs_, iCPw)
559  {
560  const FixedList<bool, 3>& confineSlice = confineWMinCPs_[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(confineWMaxCPs_, sliceI)
572  {
573  const FixedList<bool, 3>& confineSlice = confineWMaxCPs_[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 (confineUMovement_) activeDesignVariables_[3*cpI] = false;
592  if (confineVMovement_) activeDesignVariables_[3*cpI + 1] = false;
593  if (confineWMovement_) activeDesignVariables_[3*cpI + 2] = false;
594  }
595 }
596 
597 
599 {
600  if (cpI < 0 || cpI > cps_.size() -1)
601  {
603  << "Attempted to confine control 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 control 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.getOrDefault<label>("maxIterations", 10)),
653  tolerance_(dict.getOrDefault<scalar>("tolerance", 1.e-10)),
654  nMaxBound_(dict.getOrDefault<scalar>("nMaxBoundIterations", 4)),
655  cps_(0),
656  mapPtr_(nullptr),
657  reverseMapPtr_(nullptr),
658  parametricCoordinatesPtr_(nullptr),
659  localSystemCoordinates_(mesh_.nPoints(), Zero),
660  confineUMovement_
661  (
663  (
664  "confineUMovement", {{"confineX1movement", 1912}}, false
665  )
666  ),
667  confineVMovement_
668  (
670  (
671  "confineVMovement", {{"confineX2movement", 1912}}, false
672  )
673  ),
674  confineWMovement_
675  (
677  (
678  "confineWMovement", {{"confineX3movement", 1912}}, false
679  )
680  ),
681  confineBoundaryControlPoints_
682  (
683  dict.getOrDefault<bool>("confineBoundaryControlPoints", true)
684  ),
685  confineUMinCPs_
686  (
687  dict.getOrDefaultCompat<boolListList3>
688  (
689  "confineUMinCPs", {{"boundUMinCPs", 1912}}, boolListList3(0)
690  )
691  ),
692  confineUMaxCPs_
693  (
694  dict.getOrDefaultCompat<boolListList3>
695  (
696  "confineUMaxCPs", {{"boundUMaxCPs", 1912}}, boolListList3(0)
697  )
698  ),
699  confineVMinCPs_
700  (
701  dict.getOrDefaultCompat<boolListList3>
702  (
703  "confineVMinCPs", {{"boundVMinCPs", 1912}}, boolListList3(0)
704  )
705  ),
706  confineVMaxCPs_
707  (
708  dict.getOrDefaultCompat<boolListList3>
709  (
710  "confineVMaxCPs", {{"boundVMaxCPs", 1912}}, boolListList3(0)
711  )
712  ),
713  confineWMinCPs_
714  (
715  dict.getOrDefaultCompat<boolListList3>
716  (
717  "confineWMinCPs", {{"boundWMinCPs", 1912}}, boolListList3(0)
718  )
719  ),
720  confineWMaxCPs_
721  (
722  dict.getOrDefaultCompat<boolListList3>
723  (
724  "confineWMaxCPs", {{"boundWMaxCPs", 1912}}, boolListList3(0)
725  )
726  ),
727  activeControlPoints_(0), //zero here, execute sanity checks first
728  activeDesignVariables_(0), //zero here, execute sanity checks first
729  cpsFolder_("controlPoints"),
730  readStoredData_(dict.getOrDefault<bool>("readStoredData", true))
731 {
732  // Create folders
733  makeFolders();
734 
735  // Sanity checks
736  if
737  (
738  (confineUMinCPs_.size() + confineUMaxCPs_.size() >= basisU_.nCPs())
739  || (confineVMinCPs_.size() + confineVMaxCPs_.size() >= basisV_.nCPs())
740  || (confineWMinCPs_.size() + confineWMaxCPs_.size() >= basisW_.nCPs())
741  )
742  {
744  << "Number of control point slices to be kept frozen at "
745  << "the boundaries is invalid \n"
746  << "Number of control points in u " << basisU_.nCPs() << "\n"
747  << "Number of control points in v " << basisV_.nCPs() << "\n"
748  << "Number of control points in w " << basisW_.nCPs() << "\n"
749  << exit(FatalError);
750  }
751 
752  word controlPointsDefinition(dict.get<word>("controlPointsDefinition"));
753 
754  // Read specific control points if given
755  if (controlPointsDefinition == "fromFile")
756  {
757  Info<< "Reading control points from file " << endl;
758  IOdictionary cpsDict
759  (
760  IOobject
761  (
762  name_ + "cpsBsplines" + mesh_.time().timeName(),
763  mesh_.time().caseConstant(),
764  cpsFolder_,
765  mesh_,
768  false
769  )
770  );
771 
772  cpsDict.readEntry("controlPoints", cps_);
773  if (cps_.size() != (basisU_.nCPs()*basisV_.nCPs()*basisW_.nCPs()))
774  {
776  << "Number of control points does not agree with "
777  << "nCPsU*nCPv*nCPsW"
778  << exit(FatalError);
779  }
780  }
781  // Else, construct control points based on their min, max coordinates and
782  // their number
783  else if (controlPointsDefinition == "axisAligned")
784  {
785  const label nCPsU = basisU_.nCPs();
786  const label nCPsV = basisV_.nCPs();
787  const label nCPsW = basisW_.nCPs();
788 
789  cps_.setSize(nCPsU * nCPsV * nCPsW);
790 
791  vector lowerBounds(dict.get<vector>("lowerCpBounds"));
792  vector upperBounds(dict.get<vector>("upperCpBounds"));
793 
794  // Equidistribute cps in th u,v,w directions
795  for (label iCPw = 0; iCPw < nCPsW; ++iCPw)
796  {
797  for (label iCPv = 0; iCPv < nCPsV; ++iCPv)
798  {
799  for (label iCPu = 0; iCPu < nCPsU; ++iCPu)
800  {
801  cps_[getCPID(iCPu, iCPv, iCPw)] =
802  (
803  lowerBounds.x()
804  +scalar(iCPu)/scalar(nCPsU - 1)
805  *(upperBounds.x()-lowerBounds.x())
806  )*vector(1, 0, 0)
807  + (
808  lowerBounds.y()
809  +scalar(iCPv)/scalar(nCPsV - 1)
810  *(upperBounds.y()-lowerBounds.y())
811  )*vector(0, 1, 0)
812  + (
813  lowerBounds.z()
814  +scalar(iCPw)/scalar(nCPsW - 1)
815  *(upperBounds.z()-lowerBounds.z())
816  )*vector(0, 0, 1);
817  }
818  }
819  }
820  }
821  else
822  {
824  << "Unknown controlPointsDefinition type "
825  << controlPointsDefinition
826  << endl << endl
827  << "Valid types are : axisAligned, fromFile" << endl
828  << exit(FatalError);
829  }
830  determineActiveDesignVariablesAndPoints();
831  writeCpsInDict();
832 }
833 
834 
835 // * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
836 
838 (
839  const dictionary& dict,
840  const fvMesh& mesh,
841  bool computeParamCoors
842 )
843 {
844  const word modelType(dict.get<word>("type"));
845 
846  Info<< "NURBS3DVolume type : " << modelType << endl;
847 
848  auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
849 
850  if (!cstrIter.found())
851  {
853  (
854  dict,
855  "type",
856  modelType,
857  *dictionaryConstructorTablePtr_
858  ) << exit(FatalIOError);
859  }
860 
861  return autoPtr<NURBS3DVolume>(cstrIter()(dict, mesh, computeParamCoors));
862 }
863 
864 
865 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
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_.basisDerivativeU(iCPu, degreeU, u)
893  *basisV_.basisValue(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_.basisDerivativeU(iCPv, degreeV, v)
930  *basisW_.basisValue(iCPw, degreeW, w);
931  }
932  }
933  }
934 
935  return derivative;
936 }
937 
938 
940 (
941  const scalar u,
942  const scalar v,
943  const scalar w
944 ) const
945 {
946  const label degreeU = basisU_.degree();
947  const label degreeV = basisV_.degree();
948  const label degreeW = basisW_.degree();
949 
950  const label nCPsU = basisU_.nCPs();
951  const label nCPsV = basisV_.nCPs();
952  const label nCPsW = basisW_.nCPs();
953 
954  vector derivative(Zero);
955 
956  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
957  {
958  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
959  {
960  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
961  {
962  derivative +=
963  cps_[getCPID(iCPu, iCPv, iCPw)]
964  *basisU_.basisValue(iCPu, degreeU, u)
965  *basisV_.basisValue(iCPv, degreeV, v)
966  *basisW_.basisDerivativeU(iCPw, degreeW, w);
967  }
968  }
969  }
970 
971  return derivative;
972 }
973 
974 
976 (
977  const vector& uVector
978 ) const
979 {
980  const scalar u = uVector.x();
981  const scalar v = uVector.y();
982  const scalar w = uVector.z();
983 
984  vector uDeriv = volumeDerivativeU(u, v, w);
985  vector vDeriv = volumeDerivativeV(u, v, w);
986  vector wDeriv = volumeDerivativeW(u, v, w);
987 
988  tensor Jacobian(Zero);
989 
990  Jacobian[0] = uDeriv.component(0);
991  Jacobian[1] = vDeriv.component(0);
992  Jacobian[2] = wDeriv.component(0);
993  Jacobian[3] = uDeriv.component(1);
994  Jacobian[4] = vDeriv.component(1);
995  Jacobian[5] = wDeriv.component(1);
996  Jacobian[6] = uDeriv.component(2);
997  Jacobian[7] = vDeriv.component(2);
998  Jacobian[8] = wDeriv.component(2);
999 
1000  return Jacobian;
1001 }
1002 
1003 
1006  const vector& uVector,
1007  const label cpI
1008 ) const
1009 {
1010  const scalar u = uVector.x();
1011  const scalar v = uVector.y();
1012  const scalar w = uVector.z();
1013 
1014  const label nCPsU = basisU_.nCPs();
1015  const label nCPsV = basisV_.nCPs();
1016 
1017  const label degreeU = basisU_.degree();
1018  const label degreeV = basisV_.degree();
1019  const label degreeW = basisW_.degree();
1020 
1021  label iCPw = cpI/label(nCPsU*nCPsV);
1022  label iCPv = (cpI - iCPw*nCPsU*nCPsV)/nCPsU;
1023  label iCPu = (cpI - iCPw*nCPsU*nCPsV - iCPv*nCPsU);
1024 
1025  // Normally, this should be a tensor, however the parameterization is
1026  // isotropic. Hence the tensor degenerates to a diagonal tensor with all
1027  // diagonal elements being equal. This returns the (unique) diag element
1028  scalar derivative =
1029  basisU_.basisValue(iCPu, degreeU, u)
1030  *basisV_.basisValue(iCPv, degreeV, v)
1031  *basisW_.basisValue(iCPw, degreeW, w);
1032 
1033  return derivative;
1034 }
1035 
1036 
1039  const pointVectorField& pointSens,
1040  const labelList& sensitivityPatchIDs
1041 )
1042 {
1043  vectorField controlPointDerivs(cps_.size(), Zero);
1044 
1045  // Get parametric coordinates
1046  const vectorField& parametricCoordinates = getParametricCoordinates();
1047 
1048  forAll(controlPointDerivs, cpI)
1049  {
1050  forAll(sensitivityPatchIDs, pI)
1051  {
1052  const label patchI = sensitivityPatchIDs[pI];
1053  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1054  const labelList& meshPoints = patch.meshPoints();
1055 
1056  forAll(meshPoints, mpI)
1057  {
1058  const label globalIndex = meshPoints[mpI];
1059  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1060 
1061  // If point resides within control points box,
1062  // add contribution to cp derivative
1063  if (whichPointInBox != -1)
1064  {
1065  controlPointDerivs[cpI] +=
1066  (
1067  pointSens[globalIndex]
1068  & transformationTensorDxDb(globalIndex)
1069  )
1070  *volumeDerivativeCP
1071  (
1072  parametricCoordinates[globalIndex],
1073  cpI
1074  );
1075  }
1076  }
1077  }
1078  }
1079 
1080  // Sum contributions from all processors
1081  Pstream::listCombineGather(controlPointDerivs, plusEqOp<vector>());
1082  Pstream::listCombineScatter(controlPointDerivs);
1083 
1084  return controlPointDerivs;
1085 }
1086 
1087 
1090  const volVectorField& faceSens,
1091  const labelList& sensitivityPatchIDs
1092 )
1093 {
1094  return
1095  computeControlPointSensitivities
1096  (
1097  faceSens.boundaryField(),
1098  sensitivityPatchIDs
1099  );
1100 }
1101 
1102 
1105  const boundaryVectorField& faceSens,
1106  const labelList& sensitivityPatchIDs
1107 )
1108 {
1109  // Return field
1110  vectorField controlPointDerivs(cps_.size(), Zero);
1111 
1112  // Get parametric coordinates
1113  const vectorField& parametricCoordinates = getParametricCoordinates();
1114 
1115  // Auxiliary quantities
1117  const labelList& reverseMap = reverseMapPtr_();
1118 
1119  forAll(controlPointDerivs, cpI)
1120  {
1121  forAll(sensitivityPatchIDs, pI)
1122  {
1123  const label patchI = sensitivityPatchIDs[pI];
1124  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1125  const label patchStart = patch.start();
1126  const fvPatchVectorField& patchSens = faceSens[patchI];
1127 
1128  // loop over patch faces
1129  forAll(patch, fI)
1130  {
1131  const face& fGlobal = mesh_.faces()[fI + patchStart];
1132  const pointField facePoints = fGlobal.points(mesh_.points());
1133  // loop over face points
1134  tensorField facePointDerivs(facePoints.size(), Zero);
1135  forAll(fGlobal, pI)
1136  {
1137  const label globalIndex = fGlobal[pI]; //global point index
1138  const label whichPointInBox = reverseMap[globalIndex];
1139  // if point resides within control points box,
1140  // add contribution to d( facePoints )/db
1141  if (whichPointInBox != -1)
1142  {
1143  // TENSOR-BASED
1144  //~~~~~~~~~~~~~
1145  facePointDerivs[pI] =
1146  transformationTensorDxDb(globalIndex)
1147  * volumeDerivativeCP
1148  (
1149  parametricCoordinates[globalIndex],
1150  cpI
1151  );
1152 
1153  }
1154  }
1155 
1156  tensor fCtrs_d =
1158  (
1159  facePoints,
1160  facePointDerivs
1161  )[0];
1162  controlPointDerivs[cpI] += patchSens[fI] & fCtrs_d;
1163  }
1164  }
1165  }
1166  // Sum contributions from all processors
1167  Pstream::listCombineGather(controlPointDerivs, plusEqOp<vector>());
1168  Pstream::listCombineScatter(controlPointDerivs);
1169 
1170  return controlPointDerivs;
1171 }
1172 
1173 
1176  const vectorField& faceSens,
1177  const label patchI,
1178  const label cpI
1179 )
1180 {
1181  // Return vector
1182  vector cpSens(Zero);
1183  // Get parametric coordinates
1184  const vectorField& parametricCoordinates = getParametricCoordinates();
1185 
1186  // Auxiliary quantities
1188  const labelList& reverseMap = reverseMapPtr_();
1189 
1190  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1191  const label patchStart = patch.start();
1192  // Loop over patch faces
1193  forAll(patch, fI)
1194  {
1195  const face& fGlobal = mesh_.faces()[fI + patchStart];
1196  const pointField facePoints = fGlobal.points(mesh_.points());
1197  // Loop over face points
1198  tensorField facePointDerivs(facePoints.size(), Zero);
1199  forAll(fGlobal, pI)
1200  {
1201  const label globalIndex = fGlobal[pI]; //global point index
1202  const label whichPointInBox = reverseMap[globalIndex];
1203  // If point resides within control points box,
1204  // add contribution to d( facePoints )/db
1205  if (whichPointInBox != -1)
1206  {
1207  // TENSOR-BASED
1208  //~~~~~~~~~~~~~
1209  facePointDerivs[pI] =
1210  transformationTensorDxDb(globalIndex)
1211  *volumeDerivativeCP
1212  (
1213  parametricCoordinates[globalIndex],
1214  cpI
1215  );
1216  }
1217  }
1218 
1219  tensor fCtrs_d =
1221  (
1222  facePoints,
1223  facePointDerivs
1224  )[0];
1225  cpSens += faceSens[fI] & fCtrs_d;
1226  }
1227  // Sum contributions from all processors
1228  reduce(cpSens, sumOp<vector>());
1229 
1230  return cpSens;
1231 }
1232 
1233 
1236  const label patchI,
1237  const label cpI,
1238  bool DimensionedNormalSens
1239 )
1240 {
1241  const fvPatch& patch = mesh_.boundary()[patchI];
1242  const polyPatch& ppatch = patch.patch();
1243  // Return field
1244  tmp<tensorField> tdndbSens(new tensorField(patch.size(), Zero));
1245  tensorField& dndbSens = tdndbSens.ref();
1246  // Auxiliary quantities
1248  const label patchStart = ppatch.start();
1249  const labelList& reverseMap = reverseMapPtr_();
1250 
1251  // Get parametric coordinates
1252  const vectorField& parametricCoordinates = getParametricCoordinates();
1253 
1254  // Loop over patch faces
1255  forAll(patch, fI)
1256  {
1257  const face& fGlobal = mesh_.faces()[fI + patchStart];
1258  const pointField facePoints = fGlobal.points(mesh_.points());
1259  // Loop over face points
1260  tensorField facePointDerivs(facePoints.size(), Zero);
1261  forAll(fGlobal, pI)
1262  {
1263  const label globalIndex = fGlobal[pI]; //global point index
1264  const label whichPointInBox = reverseMap[globalIndex];
1265  // If point resides within control points box,
1266  // add contribution to d( facePoints )/db
1267  if (whichPointInBox != -1)
1268  {
1269  // TENSOR-BASED
1270  //~~~~~~~~~~~~~
1271  facePointDerivs[pI] =
1272  transformationTensorDxDb(globalIndex)
1273  *volumeDerivativeCP
1274  (
1275  parametricCoordinates[globalIndex],
1276  cpI
1277  );
1278  }
1279  }
1280 
1281  // Determine whether to return variance of dimensioned or unit normal
1282  tensorField dNdbSens =
1284  (
1285  facePoints,
1286  facePointDerivs
1287  );
1288 
1289  if (DimensionedNormalSens)
1290  {
1291  dndbSens[fI] = dNdbSens[1];
1292  }
1293  else
1294  {
1295  dndbSens[fI] = dNdbSens[2];
1296  }
1297  }
1298 
1299  return tdndbSens;
1300 }
1301 
1302 
1305  const label patchI,
1306  const label cpI
1307 )
1308 {
1309  // Get parametric coordinates
1310  const vectorField& parametricCoordinates = getParametricCoordinates();
1311 
1312  // Patch data
1313  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1314  const labelList& meshPoints = patch.meshPoints();
1315 
1316  // Return field
1317  auto tdxdb = tmp<tensorField>::New(patch.nPoints(), Zero);
1318  auto& dxdb = tdxdb.ref();
1319 
1320  forAll(meshPoints, pI)
1321  {
1322  const label globalIndex = meshPoints[pI]; //global point index
1323  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1324 
1325  // If point resides within control points box, find dxdb
1326  if (whichPointInBox != -1)
1327  {
1328  dxdb[pI] =
1329  transformationTensorDxDb(globalIndex)
1330  *volumeDerivativeCP
1331  (
1332  parametricCoordinates[globalIndex],
1333  cpI
1334  );
1335  }
1336  }
1337 
1338  return tdxdb;
1339 }
1340 
1341 
1344  const label patchI,
1345  const label cpI
1346 )
1347 {
1348  // get parametric coordinates
1349  const vectorField& parametricCoordinates = getParametricCoordinates();
1350 
1351  // Patch data
1352  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1353  const label patchStart = patch.start();
1354 
1355  // Return field
1356  auto tdxdb = tmp<tensorField>::New(patch.size(), Zero);
1357  auto& dxdb = tdxdb.ref();
1358 
1359  // Mesh differentiation engine
1360  deltaBoundary deltaBound(mesh_);
1361 
1362  forAll(patch, fI)
1363  {
1364  const face& fGlobal = mesh_.faces()[fI + patchStart];
1365  const pointField facePoints = fGlobal.points(mesh_.points());
1366  // Loop over face points
1367  tensorField facePointDerivs(facePoints.size(), Zero);
1368  forAll(fGlobal, pI)
1369  {
1370  const label globalIndex = fGlobal[pI]; //global point index
1371  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1372  // If point resides within control points box,
1373  // add contribution to d( facePoints )/db
1374  if (whichPointInBox != -1)
1375  {
1376  // TENSOR-BASED
1377  //~~~~~~~~~~~~~
1378  facePointDerivs[pI] =
1379  transformationTensorDxDb(globalIndex)
1380  *volumeDerivativeCP
1381  (
1382  parametricCoordinates[globalIndex],
1383  cpI
1384  );
1385 
1386  }
1387  }
1388  dxdb[fI] =
1389  deltaBound.makeFaceCentresAndAreas_d
1390  (
1391  facePoints,
1392  facePointDerivs
1393  )[0];
1394  }
1395 
1396  return tdxdb;
1397 }
1398 
1399 
1402  const vectorField& uVector
1403 ) const
1404 {
1405  const label degreeU = basisU_.degree();
1406  const label degreeV = basisV_.degree();
1407  const label degreeW = basisW_.degree();
1408 
1409  const label nCPsU = basisU_.nCPs();
1410  const label nCPsV = basisV_.nCPs();
1411  const label nCPsW = basisW_.nCPs();
1412 
1413  const label nPoints = mapPtr_().size();
1414  auto tpoints = tmp<vectorField>::New(nPoints, Zero);
1415  auto& points = tpoints.ref();
1416 
1417  forAll(points, pI)
1418  {
1419  const label globalPI = mapPtr_()[pI];
1420  const scalar u = uVector[globalPI].x();
1421  const scalar v = uVector[globalPI].y();
1422  const scalar w = uVector[globalPI].z();
1423  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
1424  {
1425  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
1426  {
1427  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
1428  {
1429  points[pI] +=
1430  cps_[getCPID(iCPu, iCPv, iCPw)]
1431  *basisU_.basisValue(iCPu, degreeU, u)
1432  *basisV_.basisValue(iCPv, degreeV, v)
1433  *basisW_.basisValue(iCPw, degreeW, w);
1434  }
1435  }
1436  }
1437  }
1438 
1439  return tpoints;
1440 }
1441 
1442 
1445  const vector& uVector
1446 ) const
1447 {
1448  const label degreeU = basisU_.degree();
1449  const label degreeV = basisV_.degree();
1450  const label degreeW = basisW_.degree();
1451 
1452  const label nCPsU = basisU_.nCPs();
1453  const label nCPsV = basisV_.nCPs();
1454  const label nCPsW = basisW_.nCPs();
1455 
1456  const scalar u = uVector.x();
1457  const scalar v = uVector.y();
1458  const scalar w = uVector.z();
1459 
1460  vector point(Zero);
1461  for (label iCPw = 0; iCPw < nCPsW; iCPw++)
1462  {
1463  for (label iCPv = 0; iCPv < nCPsV; iCPv++)
1464  {
1465  for (label iCPu = 0; iCPu < nCPsU; iCPu++)
1466  {
1467  point +=
1468  cps_[getCPID(iCPu, iCPv, iCPw)]
1469  *basisU_.basisValue(iCPu, degreeU, u)
1470  *basisV_.basisValue(iCPv, degreeV, v)
1471  *basisW_.basisValue(iCPw, degreeW, w);
1472  }
1473  }
1474  }
1475 
1476  return point;
1477 }
1478 
1479 
1482  const vectorField& controlPointsMovement
1483 )
1484 {
1485  // Get parametric coordinates and map
1486  const vectorField& paramCoors = getParametricCoordinates();
1487  const labelList& map = mapPtr_();
1488 
1489  // Update control points position
1490  cps_ += controlPointsMovement;
1491  writeCps("cpsBsplines"+mesh_.time().timeName());
1492  writeCpsInDict();
1493 
1494  // Compute new mesh points based on updated control points
1495  tmp<vectorField> tparameterizedPoints = coordinates(paramCoors);
1496  const vectorField& parameterizedPoints = tparameterizedPoints();
1497 
1498  // Return field. Initialized with current mesh points
1499  tmp<vectorField> tnewPoints(new vectorField(mesh_.points()));
1500  vectorField& newPoints = tnewPoints.ref();
1501 
1502  // Update position of parameterized points
1503  forAll(parameterizedPoints, pI)
1504  {
1505  newPoints[map[pI]] = transformPointToCartesian(parameterizedPoints[pI]);
1506  }
1507 
1508  // Update coordinates in the local system based on the cartesian points
1509  updateLocalCoordinateSystem(newPoints);
1510  DebugInfo
1511  << "Max mesh movement equal to "
1512  << gMax(mag(newPoints - mesh_.points())) << endl;
1513 
1514  return tnewPoints;
1515 }
1516 
1517 
1520  const vectorField& controlPointsMovement,
1521  const labelList& patchesToBeMoved
1522 )
1523 {
1524  // Get parametric coordinates
1525  const vectorField& paramCoors = getParametricCoordinates();
1526 
1527  // Update control points position
1528  cps_ += controlPointsMovement;
1529 
1530  writeCps("cpsBsplines"+mesh_.time().timeName());
1531  writeCpsInDict();
1532 
1533  // Return field. Initialized with current mesh points
1534  tmp<vectorField> tnewPoints(new vectorField(mesh_.points()));
1535  vectorField& newPoints = tnewPoints.ref();
1536 
1537  // Update position of parameterized boundary points
1538  for (const label patchI : patchesToBeMoved)
1539  {
1540  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1541  const labelList& meshPoints = patch.meshPoints();
1542 
1543  for (const label globalIndex : meshPoints)
1544  {
1545  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1546  // If point resides within control points box,
1547  // compute new cartesian coordinates
1548  if (whichPointInBox != -1)
1549  {
1550  newPoints[globalIndex] =
1551  transformPointToCartesian
1552  (
1553  coordinates
1554  (
1555  paramCoors[globalIndex]
1556  )
1557  );
1558  }
1559  }
1560  }
1561 
1562  // Update coordinates in the local system based on the cartesian points
1563  updateLocalCoordinateSystem(newPoints);
1564  DebugInfo
1565  << "Max mesh movement equal to "
1566  << gMax(mag(newPoints - mesh_.points())) << endl;
1567 
1568  return tnewPoints;
1569 }
1570 
1571 
1573 {
1574  if (cps_.size() != newCps.size())
1575  {
1577  << "Attempting to replace control points with a set of "
1578  << "different size"
1579  << exit(FatalError);
1580  }
1581  cps_ = newCps;
1582 }
1583 
1584 
1587  vectorField& controlPointsMovement
1588 )
1589 {
1590  forAll(controlPointsMovement, cpI)
1591  {
1592  if (!activeDesignVariables_[3*cpI])
1593  {
1594  controlPointsMovement[cpI].x() = Zero;
1595  }
1596  if (!activeDesignVariables_[3*cpI + 1])
1597  {
1598  controlPointsMovement[cpI].y() = Zero;
1599  }
1600  if (!activeDesignVariables_[3*cpI + 2])
1601  {
1602  controlPointsMovement[cpI].z() = Zero;
1603  }
1604  }
1605 }
1606 
1607 
1610  const vectorField& controlPointsMovement,
1611  const labelList& patchesToBeMoved
1612 )
1613 {
1614  // Backup old cps
1615  vectorField oldCPs = cps_;
1616  // Get parametric coordinates
1617  const vectorField& paramCoors = getParametricCoordinates();
1618  // Update control points position
1619  cps_ += controlPointsMovement;
1620  // Update position of parameterized boundary points
1621  scalar maxDisplacement(Zero);
1622  for (const label patchI : patchesToBeMoved)
1623  {
1624  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
1625  const labelList& meshPoints = patch.meshPoints();
1626 
1627  for (const label globalIndex : meshPoints)
1628  {
1629  const label whichPointInBox = reverseMapPtr_()[globalIndex];
1630  // If point resides within control points box,
1631  // compute new cartesian coordinates
1632  if (whichPointInBox != -1)
1633  {
1634  vector newPoint =
1635  transformPointToCartesian
1636  (
1637  coordinates
1638  (
1639  paramCoors[globalIndex]
1640  )
1641  );
1642  maxDisplacement =
1643  max
1644  (
1645  maxDisplacement,
1646  mag(newPoint - mesh_.points()[globalIndex])
1647  );
1648  }
1649  }
1650  }
1651  reduce(maxDisplacement, maxOp<scalar>());
1652  cps_ = oldCPs;
1653 
1654  return maxDisplacement;
1655 }
1656 
1657 
1659 {
1660  if (mapPtr_.empty())
1661  {
1662  findPointsInBox(localSystemCoordinates_);
1663  }
1664  tmp<vectorField> pointsInBox
1665  (
1666  new vectorField(localSystemCoordinates_, mapPtr_())
1667  );
1668 
1669  return pointsInBox;
1670 }
1671 
1672 
1674 {
1675  if (mapPtr_.empty())
1676  {
1677  findPointsInBox(localSystemCoordinates_);
1678  }
1679 
1680  return mapPtr_();
1681 }
1682 
1683 
1685 {
1686  if (reverseMapPtr_.empty())
1687  {
1688  findPointsInBox(localSystemCoordinates_);
1689  }
1690 
1691  return reverseMapPtr_();
1692 }
1693 
1694 
1696 {
1697  // If not computed yet, compute parametric coordinates
1698  if (parametricCoordinatesPtr_.empty())
1699  {
1700  // Find mesh points inside control points box
1701  // if they have been identified yet
1702  if (mapPtr_.empty())
1703  {
1704  findPointsInBox(localSystemCoordinates_);
1705  }
1706  computeParametricCoordinates(getPointsInBox()());
1707  }
1708 
1709  return parametricCoordinatesPtr_();
1710 }
1711 
1712 
1714 {
1715  // Get parametric coordinates
1716  const vectorField& parametricCoordinates = getParametricCoordinates();
1717 
1718  // Set return field to zero
1719  tmp<pointTensorField> tDxDb
1720  (
1721  new pointTensorField
1722  (
1723  IOobject
1724  (
1725  "DxDb",
1726  mesh_.time().timeName(),
1727  mesh_,
1730  ),
1731  pointMesh::New(mesh_),
1733  )
1734  );
1735 
1736  pointTensorField& DxDb = tDxDb.ref();
1737 
1738  // All points outside the control box remain unmoved.
1739  // Loop over only points within the control box
1740  const labelList& map = mapPtr_();
1741  for (const label globalIndex : map)
1742  {
1743  DxDb[globalIndex] =
1744  transformationTensorDxDb(globalIndex)
1745  *volumeDerivativeCP
1746  (
1747  parametricCoordinates[globalIndex],
1748  cpI
1749  );
1750  }
1751 
1752  return tDxDb;
1753 }
1754 
1755 
1758  const label cpI
1759 )
1760 {
1761  // Get parametric coordinates
1762  const vectorField& parametricCoordinates = getParametricCoordinates();
1763 
1764  // Set return field to zero
1765  tmp<volTensorField> tDxDb
1766  (
1767  new volTensorField
1768  (
1769  IOobject
1770  (
1771  "DxDb",
1772  mesh_.time().timeName(),
1773  mesh_,
1776  ),
1777  mesh_,
1779  )
1780  );
1781 
1782  volTensorField& DxDb = tDxDb.ref();
1783  deltaBoundary deltaBound(mesh_);
1784  const labelListList& pointCells = mesh_.pointCells();
1785 
1786  // All points outside the control box remain unmoved.
1787  // Loop over only points within the control box
1788  const labelList& map = mapPtr_();
1789  for (const label globalIndex : map)
1790  {
1791  tensor pointDxDb =
1792  transformationTensorDxDb(globalIndex)
1793  *volumeDerivativeCP
1794  (
1795  parametricCoordinates[globalIndex],
1796  cpI
1797  );
1798  const labelList& pointCellsI = pointCells[globalIndex];
1799  tmp<tensorField> tC_d = deltaBound.cellCenters_d(globalIndex);
1800  const tensorField& C_d = tC_d();
1801  forAll(pointCellsI, cI)
1802  {
1803  const label cellI = pointCellsI[cI];
1804  DxDb[cellI] += C_d[cI] & pointDxDb;
1805  }
1806  }
1807 
1808  // Assign boundary values since the grad of this field is often needed
1809  forAll(mesh_.boundary(), pI)
1810  {
1811  const fvPatch& patch = mesh_.boundary()[pI];
1812  if (!isA<coupledFvPatch>(patch))
1813  {
1814  DxDb.boundaryFieldRef()[pI] = patchDxDbFace(pI, cpI);
1815  }
1816  }
1817 
1818  // Correct coupled boundaries
1820 
1821  return tDxDb;
1822 }
1823 
1824 
1826 {
1827  label nU(basisU_.nCPs());
1828  if (nU % 2 == 0)
1829  {
1830  nU /=2;
1831  }
1832  else
1833  {
1834  nU = (nU - 1)/2 + 1;
1835  }
1836  return nU;
1837 }
1838 
1839 
1841 {
1842  label nV(basisV_.nCPs());
1843  if (nV % 2 == 0)
1844  {
1845  nV /=2;
1846  }
1847  else
1848  {
1849  nV = (nV - 1)/2 + 1;
1850  }
1851  return nV;
1852 }
1853 
1854 
1856 {
1857  label nW(basisW_.nCPs());
1858  if (nW % 2 == 0)
1859  {
1860  nW /=2;
1861  }
1862  else
1863  {
1864  nW = (nW - 1)/2 + 1;
1865  }
1866  return nW;
1867 }
1868 
1869 
1870 void Foam::NURBS3DVolume::writeCps(const fileName& baseName) const
1871 {
1872  const label nCPsU = basisU_.nCPs();
1873  const label nCPsV = basisV_.nCPs();
1874 
1875  vectorField cpsInCartesian(cps_.size(), Zero);
1876  forAll(cpsInCartesian, cpI)
1877  {
1878  cpsInCartesian[cpI] = transformPointToCartesian(cps_[cpI]);
1879  }
1880 
1881  Info<< "Writing control point positions to file" << endl;
1882 
1883  if (Pstream::master())
1884  {
1885  OFstream cpsFile("optimisation"/cpsFolder_/name_ + baseName + ".csv");
1886  // Write header
1887  cpsFile
1888  << "\"Points : 0\", \"Points : 1\", \"Points : 2\","
1889  << "\"i\", \"j\", \"k\","
1890  << "\"active : 0\", \"active : 1\", \"active : 2\"" << endl;
1891 
1892  forAll(cpsInCartesian, cpI)
1893  {
1894  const label iCPw = cpI/label(nCPsU*nCPsV);
1895  const label iCPv = (cpI - iCPw*nCPsU*nCPsV)/nCPsU;
1896  const label iCPu = (cpI - iCPw*nCPsU*nCPsV - iCPv*nCPsU);
1897 
1898  cpsFile
1899  << cpsInCartesian[cpI].x() << ", "
1900  << cpsInCartesian[cpI].y() << ", "
1901  << cpsInCartesian[cpI].z() << ", "
1902  << iCPu << ", "
1903  << iCPv << ", "
1904  << iCPw << ", "
1905  << activeDesignVariables_[3*cpI] << ", "
1906  << activeDesignVariables_[3*cpI + 1] << ", "
1907  << activeDesignVariables_[3*cpI + 2] << endl;
1908  }
1909  }
1910 }
1911 
1912 
1914 {
1915  if (Pstream::master())
1916  {
1917  IOdictionary cpsDict
1918  (
1919  IOobject
1920  (
1921  name_ + "cpsBsplines" + mesh_.time().timeName(),
1922  mesh_.time().caseConstant(),
1923  cpsFolder_,
1924  mesh_,
1927  false
1928  )
1929  );
1930 
1931  cpsDict.add("controlPoints", cps_);
1932 
1933  // Always write in ASCII, but allow compression
1934  cpsDict.regIOobject::writeObject
1935  (
1936  IOstreamOption(IOstream::ASCII, mesh_.time().writeCompression()),
1937  true
1938  );
1939  }
1940 }
1941 
1942 
1944 {
1945  parametricCoordinatesPtr_().write();
1946 }
1947 
1948 
1949 // ************************************************************************* //
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:71
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:73
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:85
Foam::NURBS3DVolume::nWSymmetry
label nWSymmetry() const
Get number of variables if CPs are moved symmetrically in W.
Definition: NURBS3DVolume.C:1855
Foam::VectorSpace::component
const Cmpt & component(const direction) const
Definition: VectorSpaceI.H:87
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:1825
Foam::NURBS3DVolume::getMap
const labelList & getMap()
Get map of points in box to mesh points.
Definition: NURBS3DVolume.C:1673
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:868
Foam::NURBS3DVolume::write
void write() const
Write parametric coordinates.
Definition: NURBS3DVolume.C:1943
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
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:940
Foam::dictionary::getOrDefaultCompat
T getOrDefaultCompat(const word &keyword, std::initializer_list< std::pair< const char *, int >> compat, const T &deflt, enum keyType::option=keyType::REGEX) const
Definition: dictionaryTemplates.C:444
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::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:1519
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:69
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:350
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::Vector::z
const Cmpt & z() const
Access to the vector z component.
Definition: VectorI.H:85
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:1038
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:296
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:1695
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:397
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:67
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:65
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.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::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:1005
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:1840
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:1913
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:551
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:312
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:87
Foam::NURBS3DVolume::getPointsInBox
tmp< vectorField > getPointsInBox()
Get mesh points that reside within the control points box.
Definition: NURBS3DVolume.C:1658
Foam::GeometricField::correctBoundaryConditions
void correctBoundaryConditions()
Correct boundary field.
Definition: GeometricField.C:940
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:439
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:904
Foam::Vector::y
const Cmpt & y() const
Access to the vector y component.
Definition: VectorI.H:79
Foam::IOstreamOption::ASCII
"ascii" (normal default)
Definition: IOstreamOption.H:72
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::NURBS3DVolume::setControlPoints
void setControlPoints(const vectorField &newCps)
Set new control points.
Definition: NURBS3DVolume.C:1572
Foam::NURBS3DVolume::dndbBasedSensitivities
tmp< tensorField > dndbBasedSensitivities(const label patchI, const label cpI, bool DimensionedNormalSens=true)
Definition: NURBS3DVolume.C:1235
Foam::GeometricField::Boundary
Definition: GeometricField.H:114
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:354
Foam::NURBS3DVolume::writeCps
void writeCps(const fileName &baseName="cpsFile") const
Definition: NURBS3DVolume.C:1870
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:783
Foam::Vector< scalar >
Foam::NURBS3DVolume::getReverseMap
const labelList & getReverseMap()
Definition: NURBS3DVolume.C:1684
Foam::NURBS3DVolume::boundControlPointMovement
void boundControlPointMovement(vectorField &controlPointsMovement)
Definition: NURBS3DVolume.C:1586
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:976
Foam::FixedList< bool, 3 >
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:1401
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:1609
Foam::NURBS3DVolume::patchDxDbFace
tmp< tensorField > patchDxDbFace(const label patchI, const label cpI)
Get patch dx/db.
Definition: NURBS3DVolume.C:1343
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:838
Foam::NURBS3DVolume::getDxDb
tmp< pointTensorField > getDxDb(const label cpI)
Get dxCartesiandb for a certain control point.
Definition: NURBS3DVolume.C:1713
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:708
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
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:1757
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::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
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:1304
Foam::NURBS3DVolume::computeNewPoints
tmp< vectorField > computeNewPoints(const vectorField &controlPointsMovement)
Mesh movement based on given control point movement.
Definition: NURBS3DVolume.C:1481
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::dimensionedTensor
dimensioned< tensor > dimensionedTensor
Dimensioned tensor obtained from generic dimensioned type.
Definition: dimensionedTensor.H:52
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