63 std::string fallback_name =
"ClassNONE";
64 std::string input = rootXML.get(
"ClassName", fallback_name);
65 input = bitpit::utils::string::trim(input);
66 if(input ==
"mimmo.OBBox"){
94 std::swap(m_origin, x.m_origin);
95 std::swap(m_span, x.m_span);
96 std::swap(m_axes, x.m_axes);
97 std::swap(m_listgeo, x.m_listgeo);
98 std::swap(m_strategy, x.m_strategy);
99 std::swap(m_writeInfo, x.m_writeInfo);
167 std::vector<MimmoSharedPointer<MimmoObject> >
169 std::vector<MimmoSharedPointer<MimmoObject> > result;
172 result.push_back(pp.first);
201 for(
auto val : listgeo){
214 if (geo ==
nullptr) {
215 (*m_log)<<
"warning: "<<
m_name<<
" not valid Geometry pointer. Doing nothing"<<std::endl;
219 if (geo->getType() == 2 ) {
220 (*m_log)<<
"warning: "<<
m_name<<
" does not support volumetric tessellation. Geometry not set"<<std::endl;
224 m_listgeo.insert(std::make_pair(geo, geo->getType()));
252 strategyflag = std::min(2, std::max(strategyflag, 0));
273 OBBox::plot(std::string directory, std::string filename,
int counter,
bool binary){
281 activeP[0] = - 0.5 *
m_span;
282 activeP[6] = 0.5 *
m_span;
284 activeP[1] = activeP[0]; activeP[1][0] +=
m_span[0];
285 activeP[3] = activeP[0]; activeP[3][1] +=
m_span[1];
286 activeP[2] = activeP[6]; activeP[2][2] += -1.0*
m_span[2];
288 activeP[7] = activeP[6]; activeP[7][0] += -1.0*
m_span[0];
289 activeP[5] = activeP[6]; activeP[5][1] += -1.0*
m_span[1];
290 activeP[4] = activeP[0]; activeP[4][2] +=
m_span[2];
294 for(
auto &val : activeP){
295 for(
int i=0; i<3; ++i){
296 temp[i] = dotProduct(val, inv[i]);
302 for(
int i=0; i<8; ++i) activeConn[0].push_back(i);
304 bitpit::VTKFormat codex = bitpit::VTKFormat::ASCII;
305 if(binary){codex=bitpit::VTKFormat::APPENDED;}
306 bitpit::VTKElementType elDM = bitpit::VTKElementType::HEXAHEDRON;
307 bitpit::VTKUnstructuredGrid vtk(directory, filename, elDM);
308 vtk.setGeomData( bitpit::VTKUnstructuredField::POINTS, activeP) ;
309 vtk.setGeomData( bitpit::VTKUnstructuredField::CONNECTIVITY, activeConn) ;
310 vtk.setDimensions(1, 8);
312 if(counter>=0){vtk.setCounter(counter);}
318 MPI_Barrier(m_communicator);
339 *
m_log<<
"Warning in "<<
m_name<<
" : no external geometry provided"<<std::endl;
344 std::vector<MimmoSharedPointer<MimmoObject>> vector_listgeo =
getGeometries();
346 darray3E originOBB, spanOBB, originAABB, spanAABB;
350 computeOBB(vector_listgeo, originOBB, spanOBB, axesOBB);
352 std::swap(
m_span, spanOBB);
353 std::swap(
m_axes, axesOBB);
356 computeAABB(vector_listgeo, originAABB, spanAABB, axesAABB);
358 std::swap(
m_span, spanAABB);
359 std::swap(
m_axes, axesAABB);
362 computeOBB(vector_listgeo, originOBB, spanOBB, axesOBB);
363 computeAABB(vector_listgeo, originAABB, spanAABB, axesAABB);
365 if(spanOBB[0]*spanOBB[1]*spanOBB[2] < spanAABB[0]*spanAABB[1]*spanAABB[2] ){
367 std::swap(
m_span, spanOBB);
368 std::swap(
m_axes, axesOBB);
371 std::swap(
m_span, spanAABB);
372 std::swap(
m_axes, axesAABB);
389 out<<
"OBBox "<<std::to_string(
getId())<<
" info:"<<std::endl;
392 out<<
"Origin: "<<std::scientific<<
m_origin<<std::endl;
394 out<<
"Axis 0: "<<std::scientific<<
m_axes[0]<<std::endl;
395 out<<
"Axis 1: "<<std::scientific<<
m_axes[1]<<std::endl;
396 out<<
"Axis 2: "<<std::scientific<<
m_axes[2]<<std::endl;
398 out<<
"Span: "<<std::scientific<<
m_span<<std::endl;
403 MPI_Barrier(m_communicator);
421 bool allCloud =
false;
423 allCloud = allCloud || (ptr->getType() == 3 || ptr->getType() == 4);
430 covariance = evaluatePointsCovarianceMatrix(vector_listgeo);
432 covariance = evaluateElementsCovarianceMatrix(vector_listgeo);
435 axes = eigenVectors(covariance, spectrum);
436 adjustBasis(axes, spectrum);
440 pmin.fill(std::numeric_limits<double>::max());
441 pmax.fill(-1.0*std::numeric_limits<double>::max());
444 livector1D vertIds = ptr->getVerticesIds(
true);
445 for(
long id: vertIds){
446 darray3E coord =ptr->getVertexCoords(
id);
447 for(
int i=0;i<3; ++i){
448 val = dotProduct(coord, axes[i]);
449 pmin[i] = std::fmin(pmin[i], val);
450 pmax[i] = std::fmax(pmax[i], val);
457 MPI_Allreduce(MPI_IN_PLACE, pmin.data(), 3, MPI_DOUBLE, MPI_MIN, m_communicator);
458 MPI_Allreduce(MPI_IN_PLACE, pmax.data(), 3, MPI_DOUBLE, MPI_MAX, m_communicator);
465 double avg_span = 0.0;
466 for(
double & val: span) avg_span+=val;
469 for(
double &val : span) {
470 val = std::fmax(val, 1.E-04*avg_span);
473 darray3E originLoc = 0.5*(pmin+pmax);
474 for(
int i=0; i<3; ++i){
475 origin[i] = dotProduct(originLoc, inv[i]);
491 axes[0] = {{1.,0.,0.}};
492 axes[1] = {{0.,1.,0.}};
493 axes[2] = {{0.,0.,1.}};
496 pmin.fill(std::numeric_limits<double>::max());
497 pmax.fill(-1.0*std::numeric_limits<double>::max());
500 livector1D vertIds = ptr->getVerticesIds(
true);
501 for(
long id: vertIds){
502 darray3E coord =ptr->getVertexCoords(
id);
503 for(
int i=0;i<3; ++i){
504 pmin[i] = std::fmin(pmin[i], coord[i]);
505 pmax[i] = std::fmax(pmax[i], coord[i]);
512 MPI_Allreduce(MPI_IN_PLACE, pmin.data(), 3, MPI_DOUBLE, MPI_MIN, m_communicator);
513 MPI_Allreduce(MPI_IN_PLACE, pmax.data(), 3, MPI_DOUBLE, MPI_MAX, m_communicator);
519 double avg_span = 0.0;
520 for(
double & val: span) avg_span+=val;
523 for(
double &val : span) {
524 val = std::fmax(val, 1.E-04*avg_span);
527 origin = 0.5*(pmin+pmax);
539 std::string nameGrid =
m_name;
556 if(slotXML.hasOption(
"ForceAABB")){
557 std::string input = slotXML.get(
"ForceAABB");
558 input = bitpit::utils::string::trim(input);
561 std::stringstream ss(input);
569 if(slotXML.hasOption(
"OBBStrategy")){
570 std::string input = slotXML.get(
"OBBStrategy");
571 input = bitpit::utils::string::trim(input);
574 std::stringstream ss(input);
580 if(slotXML.hasOption(
"WriteInfo")){
581 std::string input = slotXML.get(
"WriteInfo");
582 input = bitpit::utils::string::trim(input);
585 std::stringstream ss(input);
604 slotXML.set(
"OBBStrategy", std::to_string(
static_cast<int>(
m_strategy)));
605 slotXML.set(
"WriteInfo", std::to_string((
int)
m_writeInfo));
619 std::unordered_map<MimmoSharedPointer<MimmoObject>, std::vector<long>> vertIds;
622 darray3E masscenter = {{0.0,0.0,0.0}};
624 for(MimmoSharedPointer<MimmoObject>& geo: list){
625 vertIds[geo] = geo->getVerticesIds(
true);
626 for(
long id : vertIds[geo]){
627 masscenter += geo->getVertexCoords(
id);
629 countvert += long(vertIds[geo].size());
634 MPI_Allreduce(MPI_IN_PLACE, &countvert, 1, MPI_LONG, MPI_SUM, m_communicator);
635 MPI_Allreduce(MPI_IN_PLACE, masscenter.data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
638 masscenter /= double(countvert);
644 for(
auto & val:covariance) val.fill(0.0);
647 for(MimmoSharedPointer<MimmoObject>& geo: list){
649 for(
long id : vertIds[geo]){
650 temp = geo->getVertexCoords(
id) - masscenter;
651 for(
int j=0; j<3; ++j){
652 for(
int k=j; k<3; ++k){
653 loc[j][k] += temp[j]*temp[k];
659 for(
auto & val: covariance){
667 MPI_Allreduce(MPI_IN_PLACE, covariance[0].data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
668 MPI_Allreduce(MPI_IN_PLACE, covariance[1].data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
669 MPI_Allreduce(MPI_IN_PLACE, covariance[2].data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
673 for(
auto & val: covariance){
674 val /= double(countvert);
679 covariance[1][0] = covariance[0][1];
680 covariance[2][0] = covariance[0][2];
681 covariance[2][1] = covariance[1][2];
696 OBBox::evaluateElementsCovarianceMatrix(std::vector<MimmoSharedPointer<MimmoObject> > list){
704 darray3E masscenter = {{0.0,0.0,0.0}};
707 for(
auto & val:moments) val.fill(0.0);
710 double areatri, areatot(0.0);
713 for(MimmoSharedPointer<MimmoObject>& geo: list){
717 for(
long id : cellIds){
719 std::array<long,3> vids = get3RepPoints(
id, geo);
723 p = geo->getVertexCoords(vids[0]);
724 q = geo->getVertexCoords(vids[1]);
725 r = geo->getVertexCoords(vids[2]);
727 areatri = 0.5*norm2(crossProduct(q-p, r-p));
728 centroid = (p+q+r)/3.0;
729 masscenter += areatri*centroid;
734 moments[0][0] += areatri*(9.0*centroid[0]*centroid[0] + p[0]*p[0] + q[0]*q[0] + r[0]*r[0])/12.0;
735 moments[1][1] += areatri*(9.0*centroid[1]*centroid[1] + p[1]*p[1] + q[1]*q[1] + r[1]*r[1])/12.0;
736 moments[2][2] += areatri*(9.0*centroid[2]*centroid[2] + p[2]*p[2] + q[2]*q[2] + r[2]*r[2])/12.0;
739 moments[0][1] += areatri*(9.0*centroid[0]*centroid[1] + p[0]*p[1] + q[0]*q[1] + r[0]*r[1])/12.0;
740 moments[0][2] += areatri*(9.0*centroid[0]*centroid[2] + p[0]*p[2] + q[0]*q[2] + r[0]*r[2])/12.0;
741 moments[1][2] += areatri*(9.0*centroid[1]*centroid[2] + p[1]*p[2] + q[1]*q[2] + r[1]*r[2])/12.0;
746 moments[1][0] = moments[0][1];
747 moments[2][0] = moments[0][2];
748 moments[2][1] = moments[1][2];
753 MPI_Allreduce(MPI_IN_PLACE, &areatot, 1, MPI_DOUBLE, MPI_SUM, m_communicator);
754 MPI_Allreduce(MPI_IN_PLACE, masscenter.data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
755 MPI_Allreduce(MPI_IN_PLACE, moments[0].data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
756 MPI_Allreduce(MPI_IN_PLACE, moments[1].data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
757 MPI_Allreduce(MPI_IN_PLACE, moments[2].data(), 3, MPI_DOUBLE, MPI_SUM, m_communicator);
761 masscenter /= areatot;
765 for(
int i=0; i<3; ++i ){
766 for(
int j=0; j<3; ++j ){
767 covariance[i][j] = moments[i][j]/areatot - masscenter[i]*masscenter[j];
784 double * a =
new double [9];
785 double * s =
new double[3];
788 for(
int i=0; i<3; i++){
789 for(
int j=0; j<3; j++){
796 LAPACKE_dsyev( LAPACK_COL_MAJOR,
'V',
'U', 3, a, 3, s);
800 for (
int i=0; i<9; i++){
801 result[i/3][i%3] = a[i];
803 for(
int i=0; i<3; ++i) {
804 result[i] /= norm2(result[i]);
805 eigenvalues[i] = s[i];
809 std::swap(result[0], result[2]);
810 std::swap(eigenvalues[0], eigenvalues[2]);
813 delete [] a; a =
nullptr;
814 delete [] s; s =
nullptr;
832 double tol = std::numeric_limits<double>::min();
834 diff[0] = std::abs(eigVal[1]-eigVal[0]);
835 diff[1] = std::abs(eigVal[2]-eigVal[1]);
836 diff[2] = std::abs(eigVal[0]-eigVal[2]);
839 if(diff[0]<=tol && diff[1]<=tol && diff[2]<= tol){
841 for(
auto & val : eigVec){
850 if(diff[0]>tol && diff[1]>tol && diff[2]>tol){
852 if(dotProduct(eigVec[2], crossProduct(eigVec[0], eigVec[1])) < 0.0){
858 int guess = 0, third =1, stable=2;
866 eigVec[third] = crossProduct(eigVec[stable],eigVec[guess]);
867 double normv = norm2(eigVec[third]);
868 if(normv > std::numeric_limits<double>::min()){
869 eigVec[third] /= normv;
873 if(dotProduct(eigVec[2], crossProduct(eigVec[0], eigVec[1])) < 0.0){
888 for(std::size_t i=0; i<3; ++i){
889 for(std::size_t j=0; j<3; ++j){
890 out[j][i] = mat[i][j];
904 double det = mat[0][0] * (mat[1][1]*mat[2][2] - mat[2][1]*mat[1][2]) -
905 mat[0][1] * (mat[1][0]*mat[2][2] - mat[2][0]*mat[1][2]) +
906 mat[0][2] * (mat[1][0]*mat[2][1] - mat[2][0]*mat[1][1]);
908 out[0][0] = (mat[1][1]*mat[2][2] - mat[2][1]*mat[1][2])/det;
909 out[0][1] = (mat[0][2]*mat[2][1] - mat[2][2]*mat[0][1])/det;
910 out[0][2] = (mat[0][1]*mat[1][2] - mat[1][1]*mat[0][2])/det;
911 out[1][0] = (mat[1][2]*mat[2][0] - mat[2][2]*mat[1][0])/det;
912 out[1][1] = (mat[0][0]*mat[2][2] - mat[2][0]*mat[0][2])/det;
913 out[1][2] = (mat[0][2]*mat[1][0] - mat[1][2]*mat[0][0])/det;
914 out[2][0] = (mat[1][0]*mat[2][1] - mat[2][0]*mat[1][1])/det;
915 out[2][1] = (mat[0][1]*mat[2][0] - mat[2][1]*mat[0][0])/det;
916 out[2][2] = (mat[0][0]*mat[1][1] - mat[1][0]*mat[0][1])/det;
931 if(!geo)
return{{-1,-1,-1}};
932 bitpit::Cell & cell = geo->getCells().at(cellID);
933 std::array<long,3> result;
935 switch(cell.getType()){
936 case bitpit::ElementType::TRIANGLE:
938 long * conn = cell.getConnect();
944 case bitpit::ElementType::QUAD:
945 case bitpit::ElementType::POLYGON:
947 bitpit::ConstProxyVector<long> vertids = cell.getVertexIds();
948 std::size_t ssz= vertids.size();
952 result[0] = vertids[0];
953 p0 = geo->getVertexCoords(result[0]);
955 std::size_t cand = 2;
958 while(cand < ssz && !found){
959 result[1] = vertids[cand-1];
960 result[2] = vertids[cand];
961 s1 = geo->getVertexCoords(result[1]) - p0;
962 s2 = geo->getVertexCoords(result[2]) - p0;
963 found = (norm2(crossProduct(s1,s2)) > 0.0);