Nektar++
Public Member Functions | Private Member Functions | Private Attributes | List of all members
Nektar::NekMeshUtils::Octree Class Reference

class for octree More...

#include <Octree.h>

Public Member Functions

 Octree (MeshSharedPtr m)
 
void Process ()
 builds the octree based on curvature sampling and user defined spacing More...
 
NekDouble Query (Array< OneD, NekDouble > loc)
 once constructed queryies the octree based on x,y,z location to get a mesh spacing More...
 
NekDouble GetMinDelta ()
 returns the miminum spacing in the octree (for meshing purposes) More...
 
void SetParameters (NekDouble &min, NekDouble &max, NekDouble &ep)
 sets the parameters used for curvature sampling More...
 
void WriteOctree (std::string nm)
 populates the mesh m with a invalid hexahedral mesh based on the octree, used for visualisation More...
 
void Refinement (std::string nm)
 informs the octree there is a user defined spacing file More...
 

Private Member Functions

void SmoothAllOctants ()
 Smooths specification over all octants to a gradation criteria. More...
 
void CompileSourcePointList ()
 gets an optimum number of curvature sampling points and calculates the curavture at these points More...
 
void SubDivide ()
 Function which initiates and controls the subdivision process. More...
 
void SmoothSurfaceOctants ()
 Smooths specification over the surface encompasing octants to a gradation criteria. More...
 
void PropagateDomain ()
 takes the mesh specification from surface octants and progates that through the domain so all octants have a specification using gradiation crieteria More...
 
int CountElemt ()
 estimates the number of elements to be created in the mesh More...
 
NekDouble ddx (OctantSharedPtr i, OctantSharedPtr j)
 Calculates the difference in delta divided by the difference in location between two octants i and j. More...
 
bool VerifyNeigbours ()
 Looks over all leaf octants and checks that their neigbour assigments are valid. More...
 

Private Attributes

NekDouble m_minDelta
 minimum delta in the octree More...
 
NekDouble m_maxDelta
 maximum delta in the octree More...
 
NekDouble m_eps
 curavture sensivity paramter More...
 
Array< OneD, NekDoublem_centroid
 x,y,z location of the center of the octree More...
 
NekDouble m_dim
 physical size of the octree More...
 
std::vector< SPBaseSharedPtrm_SPList
 list of source points More...
 
std::vector< OctantSharedPtrm_octants
 list of leaf octants More...
 
OctantSharedPtr m_masteroct
 master octant for searching More...
 
int m_numoct
 number of octants made, used for id index More...
 
MeshSharedPtr m_mesh
 Mesh object. More...
 
std::string m_refinement
 
std::vector< linesourcem_lsources
 

Detailed Description

class for octree

This class contains the routines to generate and query a automatically generated set of mesh spacing parameters based on the CAD

Definition at line 106 of file Octree.h.

Constructor & Destructor Documentation

◆ Octree()

Nektar::NekMeshUtils::Octree::Octree ( MeshSharedPtr  m)
inline

Definition at line 110 of file Octree.h.

References CG_Iterations::loc.

110  : m_mesh(m)
111  {
112  }
MeshSharedPtr m_mesh
Mesh object.
Definition: Octree.h:235

Member Function Documentation

◆ CompileSourcePointList()

void Nektar::NekMeshUtils::Octree::CompileSourcePointList ( )
private

gets an optimum number of curvature sampling points and calculates the curavture at these points

TODO add extra source points from the line souce to the octree

Definition at line 836 of file Octree.cpp.

References CG_Iterations::loc, and Nektar::LibUtilities::PrintProgressbar().

837 {
838  int totalEnt = 0;
839  if(m_mesh->m_cad->Is2D())
840  {
841  totalEnt += m_mesh->m_cad->GetNumCurve();
842  for (int i = 1; i <= m_mesh->m_cad->GetNumCurve(); i++)
843  {
844  if (m_mesh->m_verbose)
845  {
846  LibUtilities::PrintProgressbar(i, totalEnt,
847  "\tCompiling source points");
848  }
849 
850  CADCurveSharedPtr curve = m_mesh->m_cad->GetCurve(i);
851  Array<OneD, NekDouble> bds = curve->GetBounds();
852  //this works assuming the curves are not distorted
853  int samples = ceil(curve->Length(bds[0],bds[1]) / m_minDelta) * 2;
854  samples = max(40, samples);
855  NekDouble dt = (bds[1] - bds[0]) / (samples + 1);
856  for (int j = 1; j < samples - 1; j++) // dont want first and last point
857  {
858  NekDouble t = bds[0] + dt * j;
859  NekDouble C = curve->Curvature(t);
860 
861  Array<OneD, NekDouble> loc = curve->P(t);
862 
863  vector<pair<CADSurfSharedPtr, CADOrientation::Orientation> > ss =
864  curve->GetAdjSurf();
865  Array<OneD, NekDouble> uv = ss[0].first->locuv(loc);
866 
867  if (C != 0.0)
868  {
869  NekDouble del = 2.0 * (1.0 / C) * sqrt(m_eps * (2.0 - m_eps));
870 
871  if (del > m_maxDelta)
872  {
873  del = m_maxDelta;
874  }
875  if (del < m_minDelta)
876  {
877  del = m_minDelta;
878  }
879 
880  CPointSharedPtr newCPoint =
882  ss[0].first->GetId(), uv, loc, del);
883 
884  m_SPList.push_back(newCPoint);
885  }
886  else
887  {
888  BPointSharedPtr newBPoint =
890  ss[0].first->GetId(), uv, loc);
891 
892  m_SPList.push_back(newBPoint);
893  }
894  }
895  }
896  }
897  else
898  {
899  totalEnt = m_mesh->m_cad->GetNumSurf();
900  for (int i = 1; i <= totalEnt; i++)
901  {
902  if (m_mesh->m_verbose)
903  {
904  LibUtilities::PrintProgressbar(i, totalEnt,
905  "\tCompiling source points");
906  }
907 
908  CADSurfSharedPtr surf = m_mesh->m_cad->GetSurf(i);
909  Array<OneD, NekDouble> bounds = surf->GetBounds();
910 
911  // to figure out the amount of curvature sampling to be conducted on
912  // each parameter plane the surface is first sampled with a 40x40
913  // grid the real space lengths of this grid are analyzed to find the
914  // largest stretching in the u and v directions
915  // this stretching is then considered with the mindelta user input
916  // to find a number of sampling points in each direction which
917  // ensures that in the final octree each surface octant will have at
918  // least one sample point within its volume.
919  // the 40x40 grid is used to ensure each surface has a minimum of
920  // 40x40 samples.
921  NekDouble du = (bounds[1] - bounds[0]) / (40 - 1);
922  NekDouble dv = (bounds[3] - bounds[2]) / (40 - 1);
923 
924  NekDouble DeltaU = 0.0;
925  NekDouble DeltaV = 0.0;
926 
927  Array<TwoD, Array<OneD, NekDouble> > samplepoints(40, 40);
928 
929  for (int j = 0; j < 40; j++)
930  {
931  for (int k = 0; k < 40; k++)
932  {
933  Array<OneD, NekDouble> uv(2);
934  uv[0] = k * du + bounds[0];
935  uv[1] = j * dv + bounds[2];
936  if (j == 40 - 1)
937  uv[1] = bounds[3];
938  if (k == 40 - 1)
939  uv[0] = bounds[1];
940  samplepoints[k][j] = surf->P(uv);
941  }
942  }
943 
944  for (int j = 0; j < 40 - 1; j++)
945  {
946  for (int k = 0; k < 40 - 1; k++)
947  {
948  NekDouble deltau = sqrt(
949  (samplepoints[k][j][0] - samplepoints[k + 1][j][0]) *
950  (samplepoints[k][j][0] - samplepoints[k + 1][j][0]) +
951  (samplepoints[k][j][1] - samplepoints[k + 1][j][1]) *
952  (samplepoints[k][j][1] - samplepoints[k + 1][j][1]) +
953  (samplepoints[k][j][2] - samplepoints[k + 1][j][2]) *
954  (samplepoints[k][j][2] - samplepoints[k + 1][j][2]));
955  NekDouble deltav = sqrt(
956  (samplepoints[k][j][0] - samplepoints[k][j + 1][0]) *
957  (samplepoints[k][j][0] - samplepoints[k][j + 1][0]) +
958  (samplepoints[k][j][1] - samplepoints[k][j + 1][1]) *
959  (samplepoints[k][j][1] - samplepoints[k][j + 1][1]) +
960  (samplepoints[k][j][2] - samplepoints[k][j + 1][2]) *
961  (samplepoints[k][j][2] - samplepoints[k][j + 1][2]));
962 
963  if (deltau > DeltaU)
964  DeltaU = deltau;
965  if (deltav > DeltaV)
966  DeltaV = deltav;
967  }
968  }
969 
970  // these are the acutal number of sample points in each parametric
971  // direction
972  int nu = ceil(DeltaU * 40 / m_minDelta) * 2;
973  int nv = ceil(DeltaV * 40 / m_minDelta) * 2;
974  nu = max(40, nu);
975  nv = max(40, nv);
976 
977  for (int j = 0; j < nu; j++)
978  {
979  for (int k = 0; k < nv; k++)
980  {
981  Array<OneD, NekDouble> uv(2);
982  uv[0] = (bounds[1] - bounds[0]) / (nu - 1) * j + bounds[0];
983  uv[1] = (bounds[3] - bounds[2]) / (nv - 1) * k + bounds[2];
984 
985  // this prevents round off error at the end of the surface
986  // may not be neseercary but works
987  if (j == nu - 1)
988  uv[0] = bounds[1];
989  if (k == nv - 1)
990  uv[1] = bounds[3];
991 
992  NekDouble C = surf->Curvature(uv);
993 
994  // create new point based on smallest R, flat surfaces have
995  // k=0 but still need a point for element estimation
996  if (C != 0.0)
997  {
998  NekDouble del =
999  2.0 * (1.0 / C) * sqrt(m_eps * (2.0 - m_eps));
1000 
1001  if (del > m_maxDelta)
1002  {
1003  del = m_maxDelta;
1004  }
1005  if (del < m_minDelta)
1006  {
1007  del = m_minDelta;
1008  }
1009 
1010  CPointSharedPtr newCPoint =
1012  surf->GetId(), uv, surf->P(uv), del);
1013 
1014  m_SPList.push_back(newCPoint);
1015  }
1016  else
1017  {
1018  BPointSharedPtr newBPoint =
1020  surf->GetId(), uv, surf->P(uv));
1021 
1022  m_SPList.push_back(newBPoint);
1023  }
1024  }
1025  }
1026  }
1027  }
1028  if (m_mesh->m_verbose)
1029  {
1030  cout << endl;
1031  }
1032 
1033  if (m_refinement.size() > 0)
1034  {
1035  if (m_mesh->m_verbose)
1036  {
1037  cout << "\t\tModifying based on refinement lines" << endl;
1038  }
1039  // now deal with the user defined spacing
1040  vector<string> lines;
1041 
1042  boost::split(lines, m_refinement, boost::is_any_of(":"));
1043 
1044  for (int i = 0; i < lines.size(); i++)
1045  {
1046  vector<NekDouble> data;
1047  ParseUtils::GenerateVector(lines[i], data);
1048 
1049  Array<OneD, NekDouble> x1(3), x2(3);
1050 
1051  x1[0] = data[0];
1052  x1[1] = data[1];
1053  x1[2] = data[2];
1054  x2[0] = data[3];
1055  x2[1] = data[4];
1056  x2[2] = data[5];
1057 
1058  m_lsources.push_back(linesource(x1, x2, data[6], data[7]));
1059  }
1060 
1061  // this takes any existing sourcepoints within the influence range
1062  // and modifies them
1063  /*for (int i = 0; i < m_SPList.size(); i++)
1064  {
1065  for (int j = 0; j < m_lsources.size(); j++)
1066  {
1067  if (m_lsources[j].withinRange(m_SPList[i]->GetLoc()))
1068  {
1069  if(m_SPList[i]->GetType() == ePBoundary)
1070  {
1071  BPointSharedPtr bp =
1072  std::dynamic_pointer_cast<BPoint>
1073  (m_SPList[i]);
1074 
1075  m_SPList[i] = bp->ChangeType();
1076 
1077  }
1078  m_SPList[i]->SetDelta(m_lsources[j].delta);
1079  }
1080  }
1081  }*/
1082  /// TODO add extra source points from the line souce to the octree
1083  }
1084 }
std::shared_ptr< CADSurf > CADSurfSharedPtr
Definition: CADCurve.h:51
std::vector< SPBaseSharedPtr > m_SPList
list of source points
Definition: Octree.h:227
std::shared_ptr< BPoint > BPointSharedPtr
int PrintProgressbar(const int position, const int goal, const std::string message, int lastprogress=-1)
Prints a progressbar.
Definition: Progressbar.hpp:67
NekDouble m_minDelta
minimum delta in the octree
Definition: Octree.h:217
std::string m_refinement
Definition: Octree.h:237
std::shared_ptr< CADCurve > CADCurveSharedPtr
Definition: CADCurve.h:219
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< CPoint > CPointSharedPtr
double NekDouble
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
Definition: ParseUtils.cpp:135
std::vector< linesource > m_lsources
Definition: Octree.h:238
NekDouble m_eps
curavture sensivity paramter
Definition: Octree.h:221
MeshSharedPtr m_mesh
Mesh object.
Definition: Octree.h:235
NekDouble m_maxDelta
maximum delta in the octree
Definition: Octree.h:219

◆ CountElemt()

int Nektar::NekMeshUtils::Octree::CountElemt ( )
private

estimates the number of elements to be created in the mesh

Definition at line 724 of file Octree.cpp.

References Nektar::NekMeshUtils::eBack, Nektar::NekMeshUtils::eDown, Nektar::NekMeshUtils::eForward, Nektar::NekMeshUtils::eInside, Nektar::NekMeshUtils::eLeft, Nektar::NekMeshUtils::eOnBoundary, Nektar::NekMeshUtils::eRight, and Nektar::NekMeshUtils::eUp.

725 {
726  // by considering the volume of a tet evaluate the number of elements in the
727  // mesh
728 
729  NekDouble total = 0.0;
730 
731  Array<OneD, NekDouble> boundingBox = m_mesh->m_cad->GetBoundingBox();
732 
733  for (int i = 0; i < m_octants.size(); i++)
734  {
735  OctantSharedPtr oct = m_octants[i];
736  if (oct->GetLocation() == eInside)
737  {
738  total += 8.0 * oct->DX() * oct->DX() * oct->DX() /
739  (oct->GetDelta() * oct->GetDelta() * oct->GetDelta() /
740  6.0 / sqrt(2));
741  }
742  else if (oct->GetLocation() == eOnBoundary)
743  {
744  NekDouble vol = 1.0;
745  if (oct->FX(eBack) < boundingBox[1] &&
746  oct->FX(eForward) > boundingBox[0])
747  {
748  // then there is some over lap in x
749  NekDouble min, max;
750  if (oct->FX(eBack) > boundingBox[0])
751  {
752  min = oct->FX(eBack);
753  }
754  else
755  {
756  min = boundingBox[0];
757  }
758  if (boundingBox[1] < oct->FX(eForward))
759  {
760  max = boundingBox[1];
761  }
762  else
763  {
764  max = oct->FX(eForward);
765  }
766  vol *= (max - min);
767  }
768  else
769  {
770  vol *= 0.0;
771  }
772 
773  if (oct->FX(eDown) < boundingBox[3] &&
774  oct->FX(eUp) > boundingBox[2])
775  {
776  // then there is some over lap in x
777  NekDouble min, max;
778  if (oct->FX(eDown) > boundingBox[2])
779  {
780  min = oct->FX(eDown);
781  }
782  else
783  {
784  min = boundingBox[2];
785  }
786  if (boundingBox[3] < oct->FX(eUp))
787  {
788  max = boundingBox[3];
789  }
790  else
791  {
792  max = oct->FX(eUp);
793  }
794  vol *= (max - min);
795  }
796  else
797  {
798  vol *= 0.0;
799  }
800 
801  if (oct->FX(eRight) < boundingBox[5] &&
802  oct->FX(eLeft) > boundingBox[4])
803  {
804  // then there is some over lap in x
805  NekDouble min, max;
806  if (oct->FX(eRight) > boundingBox[4])
807  {
808  min = oct->FX(eRight);
809  }
810  else
811  {
812  min = boundingBox[4];
813  }
814  if (boundingBox[5] < oct->FX(eLeft))
815  {
816  max = boundingBox[5];
817  }
818  else
819  {
820  max = oct->FX(eLeft);
821  }
822  vol *= (max - min);
823  }
824  else
825  {
826  vol *= 0.0;
827  }
828  total += vol / 2.0 / (oct->GetDelta() * oct->GetDelta() *
829  oct->GetDelta() / 6.0 / sqrt(2));
830  }
831  }
832 
833  return int(total);
834 }
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
double NekDouble
std::shared_ptr< Octant > OctantSharedPtr
Definition: Octant.h:73
MeshSharedPtr m_mesh
Mesh object.
Definition: Octree.h:235

◆ ddx()

NekDouble Nektar::NekMeshUtils::Octree::ddx ( OctantSharedPtr  i,
OctantSharedPtr  j 
)
private

Calculates the difference in delta divided by the difference in location between two octants i and j.

Definition at line 1086 of file Octree.cpp.

1087 {
1088  return fabs(i->GetDelta() - j->GetDelta()) / i->Distance(j);
1089 }

◆ GetMinDelta()

NekDouble Nektar::NekMeshUtils::Octree::GetMinDelta ( )

returns the miminum spacing in the octree (for meshing purposes)

Returns
miminum delta in octree

Definition at line 190 of file Octree.cpp.

191 {
192  NekDouble tmp = numeric_limits<double>::max();
193 
194  for (int i = 0; i < m_lsources.size(); i++)
195  {
196  tmp = min(m_lsources[i].delta, tmp);
197  }
198  return min(m_minDelta, tmp);
199 }
NekDouble m_minDelta
minimum delta in the octree
Definition: Octree.h:217
double NekDouble
std::vector< linesource > m_lsources
Definition: Octree.h:238

◆ Process()

void Nektar::NekMeshUtils::Octree::Process ( )

builds the octree based on curvature sampling and user defined spacing

Definition at line 51 of file Octree.cpp.

52 {
53  Array<OneD, NekDouble> boundingBox = m_mesh->m_cad->GetBoundingBox();
54 
55  // build curvature samples
57 
58  if (m_mesh->m_verbose)
59  {
60  cout << "\tCurvature samples: " << m_SPList.size() << endl;
61  }
62 
63  // make master octant based on the bounding box of the domain
64  m_dim = max((boundingBox[1] - boundingBox[0]) / 2.0,
65  (boundingBox[3] - boundingBox[2]) / 2.0);
66 
67  m_dim = max(m_dim, (boundingBox[5] - boundingBox[4]) / 2.0);
68 
69  m_centroid = Array<OneD, NekDouble>(3);
70  m_centroid[0] = (boundingBox[1] + boundingBox[0]) / 2.0;
71  m_centroid[1] = (boundingBox[3] + boundingBox[2]) / 2.0;
72  m_centroid[2] = (boundingBox[5] + boundingBox[4]) / 2.0;
73 
75  0, m_centroid[0], m_centroid[1], m_centroid[2], m_dim, m_SPList);
76 
77  // begin recersive subdivision
78  SubDivide();
79 
80  m_octants.clear();
81  m_masteroct->CompileLeaves(m_octants);
82 
83  if (m_mesh->m_verbose)
84  {
85  cout << "\tOctants: " << m_octants.size() << endl;
86  }
87 
89 
91 
93 
94  if (m_mesh->m_verbose)
95  {
96  int elem = CountElemt();
97  cout << "\tPredicted mesh: " << elem << endl;
98  }
99 }
std::vector< SPBaseSharedPtr > m_SPList
list of source points
Definition: Octree.h:227
void SubDivide()
Function which initiates and controls the subdivision process.
Definition: Octree.cpp:268
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
OctantSharedPtr m_masteroct
master octant for searching
Definition: Octree.h:231
void PropagateDomain()
takes the mesh specification from surface octants and progates that through the domain so all octants...
Definition: Octree.cpp:515
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
int CountElemt()
estimates the number of elements to be created in the mesh
Definition: Octree.cpp:724
void CompileSourcePointList()
gets an optimum number of curvature sampling points and calculates the curavture at these points ...
Definition: Octree.cpp:836
NekDouble m_dim
physical size of the octree
Definition: Octree.h:225
Array< OneD, NekDouble > m_centroid
x,y,z location of the center of the octree
Definition: Octree.h:223
MeshSharedPtr m_mesh
Mesh object.
Definition: Octree.h:235
void SmoothSurfaceOctants()
Smooths specification over the surface encompasing octants to a gradation criteria.
Definition: Octree.cpp:458
void SmoothAllOctants()
Smooths specification over all octants to a gradation criteria.
Definition: Octree.cpp:675

◆ PropagateDomain()

void Nektar::NekMeshUtils::Octree::PropagateDomain ( )
private

takes the mesh specification from surface octants and progates that through the domain so all octants have a specification using gradiation crieteria

Definition at line 515 of file Octree.cpp.

References ASSERTL0, Nektar::NekMeshUtils::eInside, Nektar::NekMeshUtils::eOnBoundary, Nektar::NekMeshUtils::eOutside, and Nektar::SpatialDomains::eUnknown.

516 {
517  // until all m_octants know their delta specifcation and orientaion
518  // look over all m_octants and if their neighours know either their
519  // orientation
520  // or specifcation calculate one for this octant
521  int ct = 0;
522 
523  do
524  {
525  ct = 0;
526  for (int i = 0; i < m_octants.size(); i++)
527  {
528  OctantSharedPtr oct = m_octants[i];
529 
530  if (!oct->IsDeltaKnown())
531  { // if delta has not been asigned
532  vector<OctantSharedPtr> known;
533  map<OctantFace, vector<OctantSharedPtr> > nList =
534  oct->GetNeigbours();
535  map<OctantFace, vector<OctantSharedPtr> >::iterator it;
536 
537  for (it = nList.begin(); it != nList.end(); it++)
538  {
539  for (int j = 0; j < it->second.size(); j++)
540  {
541  if (it->second[j]->IsDeltaKnown())
542  {
543  known.push_back(it->second[j]);
544  }
545  }
546  }
547 
548  if (known.size() > 0)
549  {
550  vector<NekDouble> deltaPrime;
551  for (int j = 0; j < known.size(); j++)
552  {
553  NekDouble r = oct->Distance(known[j]);
554 
555  if (0.199 * r + known[j]->GetDelta() < m_maxDelta)
556  {
557  deltaPrime.push_back(0.199 * r +
558  known[j]->GetDelta());
559  }
560  else
561  {
562  deltaPrime.push_back(m_maxDelta);
563  }
564  }
565  NekDouble min = numeric_limits<double>::max();
566  for (int j = 0; j < deltaPrime.size(); j++)
567  {
568  if (deltaPrime[j] < min)
569  {
570  min = deltaPrime[j];
571  }
572  }
573  oct->SetDelta(min);
574  ct += 1;
575  deltaPrime.clear();
576  }
577  known.clear();
578  }
579 
580  if (oct->GetLocation() == eUnknown)
581  { // if the node does not know its location
582  vector<OctantSharedPtr> known;
583  map<OctantFace, vector<OctantSharedPtr> > nList =
584  oct->GetNeigbours();
585  map<OctantFace, vector<OctantSharedPtr> >::iterator it;
586 
587  for (it = nList.begin(); it != nList.end(); it++)
588  {
589  for (int j = 0; j < it->second.size(); j++)
590  {
591  if (it->second[j]->GetLocation() != eUnknown)
592  {
593  known.push_back(it->second[j]);
594  }
595  }
596  }
597 
598  if (known.size() > 0)
599  {
600  vector<OctantSharedPtr> isNotOnBound;
601  for (int j = 0; j < known.size(); j++)
602  {
603  if (known[j]->GetLocation() != eOnBoundary)
604  {
605  isNotOnBound.push_back(known[j]);
606  }
607  }
608 
609  if (isNotOnBound.size() > 0)
610  {
611  oct->SetLocation(isNotOnBound[0]->GetLocation());
612  }
613  else
614  {
615  NekDouble dist = numeric_limits<double>::max();
616 
617  OctantSharedPtr closest;
618 
619  bool f = false;
620  for (int j = 0; j < known.size(); j++)
621  {
622  if (oct->Distance(known[j]) < dist)
623  {
624  closest = known[j];
625  dist = oct->Distance(known[j]);
626  f = true;
627  }
628  }
629  ASSERTL0(f, "closest never set");
630 
631  SPBaseSharedPtr sp = closest->GetABoundPoint();
632 
633  Array<OneD, NekDouble> octloc, sploc, vec(3), uv, N;
634  int surf;
635  sp->GetCAD(surf, uv);
636  N = m_mesh->m_cad->GetSurf(surf)->N(uv);
637 
638  octloc = oct->GetLoc();
639  sploc = sp->GetLoc();
640 
641  vec[0] = octloc[0] - sploc[0];
642  vec[1] = octloc[1] - sploc[1];
643  vec[2] = octloc[2] - sploc[2];
644 
645  NekDouble dot =
646  vec[0] * N[0] + vec[1] * N[1] + vec[2] * N[2];
647 
648  if (dot <= 0.0)
649  {
650  oct->SetLocation(eOutside);
651  ct += 1;
652  }
653  else
654  {
655  oct->SetLocation(eInside);
656  ct += 1;
657  }
658  }
659  }
660  known.clear();
661  }
662  }
663 
664  } while (ct > 0);
665 
666  for (int i = 0; i < m_octants.size(); i++)
667  {
668  if (!m_octants[i]->IsDeltaKnown())
669  {
670  m_octants[i]->SetDelta(m_maxDelta);
671  }
672  }
673 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
double NekDouble
std::shared_ptr< Octant > OctantSharedPtr
Definition: Octant.h:73
MeshSharedPtr m_mesh
Mesh object.
Definition: Octree.h:235
std::shared_ptr< SPBase > SPBaseSharedPtr
NekDouble m_maxDelta
maximum delta in the octree
Definition: Octree.h:219

◆ Query()

NekDouble Nektar::NekMeshUtils::Octree::Query ( Array< OneD, NekDouble loc)

once constructed queryies the octree based on x,y,z location to get a mesh spacing

Parameters
locarray of x,y,z
Returns
mesh spacing parameter

Definition at line 101 of file Octree.cpp.

References ASSERTL0.

102 {
103  // starting at master octant 0 move through succsesive m_octants which
104  // contain the point loc until a leaf is found
105  // first search through sourcepoints
106 
107  NekDouble tmp = numeric_limits<double>::max();
108 
109  for (int i = 0; i < m_lsources.size(); i++)
110  {
111  if (m_lsources[i].withinRange(loc))
112  {
113  tmp = min(m_lsources[i].delta, tmp);
114  }
115  }
116 
118  int quad = 0;
119 
120  bool found = false;
121 
122  while (!found)
123  {
124  Array<OneD, NekDouble> octloc = n->GetLoc();
125 
126  if (!(loc[0] < octloc[0]) && // forward
127  !(loc[1] < octloc[1]) && // forward
128  !(loc[2] < octloc[2])) // forward
129  {
130  quad = 0;
131  }
132  else if (!(loc[0] < octloc[0]) && // forward
133  !(loc[1] < octloc[1]) && // forward
134  !(loc[2] > octloc[2])) // back
135  {
136  quad = 1;
137  }
138  else if (!(loc[0] < octloc[0]) && // forward
139  !(loc[1] > octloc[1]) && // back
140  !(loc[2] < octloc[2])) // forward
141  {
142  quad = 2;
143  }
144  else if (!(loc[0] < octloc[0]) && // forward
145  !(loc[1] > octloc[1]) && // back
146  !(loc[2] > octloc[2])) // back
147  {
148  quad = 3;
149  }
150  else if (!(loc[0] > octloc[0]) && // back
151  !(loc[1] < octloc[1]) && // forward
152  !(loc[2] < octloc[2])) // forward
153  {
154  quad = 4;
155  }
156  else if (!(loc[0] > octloc[0]) && // back
157  !(loc[1] < octloc[1]) && // forward
158  !(loc[2] > octloc[2])) // back
159  {
160  quad = 5;
161  }
162  else if (!(loc[0] > octloc[0]) && // back
163  !(loc[1] > octloc[1]) && // back
164  !(loc[2] < octloc[2])) // forward
165  {
166  quad = 6;
167  }
168  else if (!(loc[0] > octloc[0]) && // back
169  !(loc[1] > octloc[1]) && // back
170  !(loc[2] > octloc[2])) // back
171  {
172  quad = 7;
173  }
174  else
175  {
176  ASSERTL0(false, "Cannot locate quadrant");
177  }
178 
179  n = n->GetChild(quad);
180 
181  if (n->IsLeaf())
182  {
183  found = true;
184  }
185  }
186 
187  return min(n->GetDelta(), tmp);
188 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
OctantSharedPtr m_masteroct
master octant for searching
Definition: Octree.h:231
double NekDouble
std::vector< linesource > m_lsources
Definition: Octree.h:238
std::shared_ptr< Octant > OctantSharedPtr
Definition: Octant.h:73

◆ Refinement()

void Nektar::NekMeshUtils::Octree::Refinement ( std::string  nm)
inline

informs the octree there is a user defined spacing file

Parameters
nmname of the user defined spacing file

Definition at line 162 of file Octree.h.

163  {
164  m_refinement = nm;
165  }
std::string m_refinement
Definition: Octree.h:237

◆ SetParameters()

void Nektar::NekMeshUtils::Octree::SetParameters ( NekDouble min,
NekDouble max,
NekDouble ep 
)
inline

sets the parameters used for curvature sampling

Parameters
minminimum spacing to be found in the mesh
maxmaximum spacing to be found in the mesh
epscurvature sensivity relating radius of curvature to spacing

Definition at line 143 of file Octree.h.

144  {
145  m_minDelta = min;
146  m_maxDelta = max;
147  m_eps = ep;
148  }
NekDouble m_minDelta
minimum delta in the octree
Definition: Octree.h:217
NekDouble m_eps
curavture sensivity paramter
Definition: Octree.h:221
NekDouble m_maxDelta
maximum delta in the octree
Definition: Octree.h:219

◆ SmoothAllOctants()

void Nektar::NekMeshUtils::Octree::SmoothAllOctants ( )
private

Smooths specification over all octants to a gradation criteria.

Definition at line 675 of file Octree.cpp.

676 {
677  // until no more changes occur smooth the mesh specification between all
678  // m_octants not particualrly strictly
679  int ct = 0;
680 
681  do
682  {
683  ct = 0;
684  for (int i = 0; i < m_octants.size(); i++)
685  {
686  OctantSharedPtr oct = m_octants[i];
687 
688  vector<OctantSharedPtr> check;
689  map<OctantFace, vector<OctantSharedPtr> > nList =
690  oct->GetNeigbours();
691  map<OctantFace, vector<OctantSharedPtr> >::iterator it;
692  for (it = nList.begin(); it != nList.end(); it++)
693  {
694  for (int j = 0; j < it->second.size(); j++)
695  {
696  if (it->second[j]->GetDelta() < oct->GetDelta() &&
697  ddx(oct, it->second[j]) > 0.2)
698  {
699  check.push_back(it->second[j]);
700  }
701  }
702  }
703 
704  if (check.size() > 0)
705  {
706  NekDouble deltaSM = numeric_limits<double>::max();
707  for (int j = 0; j < check.size(); j++)
708  {
709  NekDouble r = oct->Distance(check[j]);
710 
711  if (0.199 * r + check[j]->GetDelta() < deltaSM)
712  {
713  deltaSM = 0.199 * r + check[j]->GetDelta();
714  }
715  }
716  oct->SetDelta(deltaSM);
717  ct += 1;
718  }
719  }
720 
721  } while (ct > 0);
722 }
NekDouble ddx(OctantSharedPtr i, OctantSharedPtr j)
Calculates the difference in delta divided by the difference in location between two octants i and j...
Definition: Octree.cpp:1086
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
double NekDouble
std::shared_ptr< Octant > OctantSharedPtr
Definition: Octant.h:73

◆ SmoothSurfaceOctants()

void Nektar::NekMeshUtils::Octree::SmoothSurfaceOctants ( )
private

Smooths specification over the surface encompasing octants to a gradation criteria.

Definition at line 458 of file Octree.cpp.

459 {
460  // for all the m_octants which are surface containing and know their delta
461  // specification, look over all neighbours and ensure the specification
462  // between them is smooth
463  int ct = 0;
464 
465  do
466  {
467  ct = 0;
468  for (int i = 0; i < m_octants.size(); i++)
469  {
470  OctantSharedPtr oct = m_octants[i];
471 
472  if (oct->IsDeltaKnown())
473  {
474  vector<OctantSharedPtr> check;
475  map<OctantFace, vector<OctantSharedPtr> > nList =
476  oct->GetNeigbours();
477  map<OctantFace, vector<OctantSharedPtr> >::iterator it;
478 
479  for (it = nList.begin(); it != nList.end(); it++)
480  {
481  for (int j = 0; j < it->second.size(); j++)
482  {
483  if (it->second[j]->IsDeltaKnown() &&
484  it->second[j]->GetDelta() < oct->GetDelta() &&
485  ddx(oct, it->second[j]) > 0.2)
486  {
487  check.push_back(it->second[j]);
488  }
489  }
490  }
491 
492  // for each neighbour listed in check_id, figure out the
493  // smoothed
494  // delta, and asign the miminum of these to nodes[i].GetDelta()
495  if (check.size() > 0)
496  {
497  NekDouble deltaSM = numeric_limits<double>::max();
498  for (int j = 0; j < check.size(); j++)
499  {
500  NekDouble r = oct->Distance(check[j]);
501 
502  if (0.199 * r + check[j]->GetDelta() < deltaSM)
503  {
504  deltaSM = 0.199 * r + check[j]->GetDelta();
505  }
506  }
507  oct->SetDelta(deltaSM);
508  ct += 1;
509  }
510  }
511  }
512  } while (ct > 0);
513 }
NekDouble ddx(OctantSharedPtr i, OctantSharedPtr j)
Calculates the difference in delta divided by the difference in location between two octants i and j...
Definition: Octree.cpp:1086
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
double NekDouble
std::shared_ptr< Octant > OctantSharedPtr
Definition: Octant.h:73

◆ SubDivide()

void Nektar::NekMeshUtils::Octree::SubDivide ( )
private

Function which initiates and controls the subdivision process.

Definition at line 268 of file Octree.cpp.

269 {
270  bool repeat;
271  int ct = 1;
272 
273  m_numoct = 1;
274  m_masteroct->Subdivide(m_masteroct, m_numoct);
275 
276  if (m_mesh->m_verbose)
277  {
278  cout << "\tSubdivide iteration: ";
279  }
280 
281  do
282  {
283  if (m_mesh->m_verbose)
284  {
285  cout << "\r ";
286  cout << "\r";
287  cout << "\tSubdivide iteration: " << ct;
288  cout.flush();
289  }
290  ct++;
291  repeat = false;
292  m_octants.clear();
293  // grab a list of the leaves curently in the octree
294  m_masteroct->CompileLeaves(m_octants);
295 
296  VerifyNeigbours();
297 
298  // neeed to create a divide list, in the first list will be m_octants
299  // which need to
300  // subdivide based on curvature,
301  // in the next list will be ocants which need to subdivide to make sure
302  // level criteria is statisified for the previous list and so on
303  // the list will keep building till no more lists are required.
304  // the list will then be iterated through backwards to subdivide all the
305  // sublists in turn.
306  vector<vector<OctantSharedPtr> > dividelist;
307  set<int> inlist;
308  // build initial list
309  {
310  vector<OctantSharedPtr> sublist;
311  for (int i = 0; i < m_octants.size(); i++)
312  {
313  if (m_octants[i]->NeedDivide() &&
314  m_octants[i]->DX() / 4.0 > m_minDelta)
315  {
316  sublist.push_back(m_octants[i]);
317  inlist.insert(m_octants[i]->GetId());
318  repeat = true; // if there is a subdivision this whole
319  // process needs to be repeated
320  }
321  }
322  dividelist.push_back(sublist);
323  }
324  // then loop over building sublists until no more are required
325  int ct2 = 0;
326  while (true)
327  {
328  ct2++;
329  vector<OctantSharedPtr> newsublist,
330  previouslist = dividelist.back();
331  for (int i = 0; i < previouslist.size(); i++)
332  {
333  map<OctantFace, vector<OctantSharedPtr> > nlist =
334  previouslist[i]->GetNeigbours();
335  map<OctantFace, vector<OctantSharedPtr> >::iterator it;
336  for (it = nlist.begin(); it != nlist.end(); it++)
337  {
338  for (int j = 0; j < it->second.size(); j++)
339  {
340  if (previouslist[i]->DX() < it->second[j]->DX())
341  {
342  set<int>::iterator s =
343  inlist.find(it->second[j]->GetId());
344  if (s == inlist.end())
345  {
346  inlist.insert(it->second[j]->GetId());
347  newsublist.push_back(it->second[j]);
348  }
349  }
350  }
351  }
352  }
353  if (newsublist.size() == 0)
354  {
355  break;
356  }
357  else
358  {
359  dividelist.push_back(newsublist);
360  }
361  }
362 
363  vector<vector<OctantSharedPtr> >::reverse_iterator rit;
364  for (rit = dividelist.rbegin(); rit != dividelist.rend(); rit++)
365  {
366  vector<OctantSharedPtr> currentlist = *rit;
367  for (int i = 0; i < currentlist.size(); i++)
368  {
369  currentlist[i]->Subdivide(currentlist[i], m_numoct);
370  }
371  }
372  } while (repeat);
373 
374  if (m_mesh->m_verbose)
375  {
376  cout << endl;
377  }
378 }
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
NekDouble m_minDelta
minimum delta in the octree
Definition: Octree.h:217
bool VerifyNeigbours()
Looks over all leaf octants and checks that their neigbour assigments are valid.
Definition: Octree.cpp:380
OctantSharedPtr m_masteroct
master octant for searching
Definition: Octree.h:231
int m_numoct
number of octants made, used for id index
Definition: Octree.h:233
MeshSharedPtr m_mesh
Mesh object.
Definition: Octree.h:235

◆ VerifyNeigbours()

bool Nektar::NekMeshUtils::Octree::VerifyNeigbours ( )
private

Looks over all leaf octants and checks that their neigbour assigments are valid.

Definition at line 380 of file Octree.cpp.

References Nektar::NekMeshUtils::eBack, Nektar::NekMeshUtils::eDown, Nektar::NekMeshUtils::eForward, Nektar::NekMeshUtils::eLeft, Nektar::NekMeshUtils::eRight, and Nektar::NekMeshUtils::eUp.

381 {
382  // check all octant links to their neighbours
383  // at all times in the subdivision the set of neigbours must
384  // conform to a set of criteria such as smoothness in size
385  // this checks that
386  bool error = false;
387  for (int i = 0; i < m_octants.size(); i++)
388  {
389  bool valid = true;
390  map<OctantFace, vector<OctantSharedPtr> > nlist =
391  m_octants[i]->GetNeigbours();
392  map<OctantFace, vector<OctantSharedPtr> >::iterator it;
393  for (it = nlist.begin(); it != nlist.end(); it++)
394  {
395  if (it->second.size() == 0)
396  {
397  NekDouble expectedfx = 0.0;
398  switch (it->first)
399  {
400  case eUp:
401  expectedfx = m_centroid[1] + m_dim;
402  break;
403  case eDown:
404  expectedfx = m_centroid[1] - m_dim;
405  break;
406  case eLeft:
407  expectedfx = m_centroid[2] + m_dim;
408  break;
409  case eRight:
410  expectedfx = m_centroid[2] - m_dim;
411  break;
412  case eForward:
413  expectedfx = m_centroid[0] + m_dim;
414  break;
415  case eBack:
416  expectedfx = m_centroid[0] - m_dim;
417  break;
418  }
419  if (fabs(m_octants[i]->FX(it->first) - expectedfx) > 1E-6)
420  {
421  valid = false;
422  cout << "wall neigbour error" << endl;
423  cout << expectedfx << " " << m_octants[i]->FX(it->first)
424  << " " << it->first << endl;
425  }
426  }
427  else if (it->second.size() == 1)
428  {
429  if (!(m_octants[i]->DX() == it->second[0]->DX() ||
430  it->second[0]->DX() == 2.0 * m_octants[i]->DX()))
431  {
432  valid = false;
433  cout << " 1 neigbour error" << endl;
434  cout << m_octants[i]->DX() << " " << it->second[0]->DX()
435  << endl;
436  }
437  }
438  else if (it->second.size() == 4)
439  {
440  if (!(m_octants[i]->DX() / 2.0 == it->second[0]->DX()))
441  {
442  valid = false;
443  cout << "4 neibour error" << endl;
444  cout << m_octants[i]->DX() << " " << it->second[0]->DX()
445  << endl;
446  }
447  }
448  }
449  if (!valid)
450  {
451  error = true;
452  cout << "invalid neigbour config" << endl;
453  }
454  }
455  return !error;
456 }
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
double NekDouble
NekDouble m_dim
physical size of the octree
Definition: Octree.h:225
Array< OneD, NekDouble > m_centroid
x,y,z location of the center of the octree
Definition: Octree.h:223

◆ WriteOctree()

void Nektar::NekMeshUtils::Octree::WriteOctree ( std::string  nm)

populates the mesh m with a invalid hexahedral mesh based on the octree, used for visualisation

Parameters
nmname of the mesh file to be made

Definition at line 201 of file Octree.cpp.

References Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::NekMeshUtils::eBack, Nektar::NekMeshUtils::eDown, Nektar::NekMeshUtils::eForward, Nektar::LibUtilities::eHexahedron, Nektar::NekMeshUtils::eLeft, Nektar::FieldUtils::eOutputModule, Nektar::NekMeshUtils::eRight, Nektar::NekMeshUtils::eUp, Nektar::NekMeshUtils::GetElementFactory(), Nektar::FieldUtils::GetModuleFactory(), CG_Iterations::Mesh, and class_topology::Node.

202 {
203  MeshSharedPtr oct = std::shared_ptr<Mesh>(new Mesh());
204  oct->m_expDim = 3;
205  oct->m_spaceDim = 3;
206  oct->m_nummode = 2;
207 
208  for (int i = 0; i < m_octants.size(); i++)
209  {
210  /*if(m_octants[i]->GetLocation() != eOnBoundary)
211  {
212  continue;
213  }*/
214 
215  vector<NodeSharedPtr> ns(8);
216 
217  ns[0] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eBack),
218  m_octants[i]->FX(eDown),
219  m_octants[i]->FX(eRight)));
220 
221  ns[1] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eForward),
222  m_octants[i]->FX(eDown),
223  m_octants[i]->FX(eRight)));
224 
225  ns[2] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eForward),
226  m_octants[i]->FX(eUp),
227  m_octants[i]->FX(eRight)));
228 
229  ns[3] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eBack),
230  m_octants[i]->FX(eUp),
231  m_octants[i]->FX(eRight)));
232 
233  ns[4] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eBack),
234  m_octants[i]->FX(eDown),
235  m_octants[i]->FX(eLeft)));
236 
237  ns[5] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eForward),
238  m_octants[i]->FX(eDown),
239  m_octants[i]->FX(eLeft)));
240 
241  ns[6] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eForward),
242  m_octants[i]->FX(eUp),
243  m_octants[i]->FX(eLeft)));
244 
245  ns[7] = std::shared_ptr<Node>(new Node(0, m_octants[i]->FX(eBack),
246  m_octants[i]->FX(eUp),
247  m_octants[i]->FX(eLeft)));
248 
249  vector<int> tags;
250  tags.push_back(0);
251  ElmtConfig conf(LibUtilities::eHexahedron, 1, false, false);
253  LibUtilities::eHexahedron, conf, ns, tags);
254  oct->m_element[3].push_back(E);
255  }
256 
257  ModuleSharedPtr mod =
259  mod->RegisterConfig("outfile", nm);
260  mod->ProcessVertices();
261  mod->ProcessEdges();
262  mod->ProcessFaces();
263  mod->ProcessElements();
264  mod->ProcessComposites();
265  mod->Process();
266 }
std::vector< OctantSharedPtr > m_octants
list of leaf octants
Definition: Octree.h:229
std::shared_ptr< Module > ModuleSharedPtr
std::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Definition: Mesh.h:156
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
std::pair< ModuleType, std::string > ModuleKey

Member Data Documentation

◆ m_centroid

Array<OneD, NekDouble> Nektar::NekMeshUtils::Octree::m_centroid
private

x,y,z location of the center of the octree

Definition at line 223 of file Octree.h.

◆ m_dim

NekDouble Nektar::NekMeshUtils::Octree::m_dim
private

physical size of the octree

Definition at line 225 of file Octree.h.

◆ m_eps

NekDouble Nektar::NekMeshUtils::Octree::m_eps
private

curavture sensivity paramter

Definition at line 221 of file Octree.h.

◆ m_lsources

std::vector<linesource> Nektar::NekMeshUtils::Octree::m_lsources
private

Definition at line 238 of file Octree.h.

◆ m_masteroct

OctantSharedPtr Nektar::NekMeshUtils::Octree::m_masteroct
private

master octant for searching

Definition at line 231 of file Octree.h.

◆ m_maxDelta

NekDouble Nektar::NekMeshUtils::Octree::m_maxDelta
private

maximum delta in the octree

Definition at line 219 of file Octree.h.

◆ m_mesh

MeshSharedPtr Nektar::NekMeshUtils::Octree::m_mesh
private

Mesh object.

Definition at line 235 of file Octree.h.

◆ m_minDelta

NekDouble Nektar::NekMeshUtils::Octree::m_minDelta
private

minimum delta in the octree

Definition at line 217 of file Octree.h.

◆ m_numoct

int Nektar::NekMeshUtils::Octree::m_numoct
private

number of octants made, used for id index

Definition at line 233 of file Octree.h.

◆ m_octants

std::vector<OctantSharedPtr> Nektar::NekMeshUtils::Octree::m_octants
private

list of leaf octants

Definition at line 229 of file Octree.h.

◆ m_refinement

std::string Nektar::NekMeshUtils::Octree::m_refinement
private

Definition at line 237 of file Octree.h.

◆ m_SPList

std::vector<SPBaseSharedPtr> Nektar::NekMeshUtils::Octree::m_SPList
private

list of source points

Definition at line 227 of file Octree.h.