12#include <unordered_set>
26 NEW_TIMER_GROUP(tg_geometry,
"Geometry (solver #" + std::to_string(solverId_) +
")");
27 m_tg_geometry = tg_geometry;
28 NEW_TIMER(t_geometryAll,
"complete geometry", m_tg_geometry);
29 m_t_geometryAll = t_geometryAll;
30 g_tc_geometry.emplace_back(
"complete geometry", m_t_geometryAll);
31 RECORD_TIMER_START(m_t_geometryAll);
33 NEW_SUB_TIMER(t_initGeometry,
"init geometry", m_t_geometryAll);
35 RECORD_TIMER_START(t_initGeometry);
37 m_log <<
"#########################################################################################################"
40 m_log <<
"## Initializing Geometry in 3D "
43 m_log <<
"#########################################################################################################"
53 m_parGeomMemFactor = 1.0;
56 if(m_parallelGeometry) {
69 m_parallelGeomFileName = Context::getSolverProperty<MString>(
"parallelGeomFileName", solverId(), AT_);
71 stringstream errorMsg;
73 <<
"ERROR: parallel geometry is activated but no parallelGeomFileName is specified in the properties file"
75 m_log << errorMsg.str();
76 mTerm(1, AT_, errorMsg.str());
79 m_gridFileName = Context::getSolverProperty<MString>(
"gridInputFileName", solverId(), AT_);
81 stringstream errorMsg;
83 <<
"ERROR: parallel geometry is activated but no parallelGeomFileName is specified in the properties file"
85 m_log << errorMsg.str();
86 mTerm(1, AT_, errorMsg.str());
100 m_parGeomMemFactor = Context::getSolverProperty<MFloat>(
"parGeomMemFactor", solverId(), AT_, &m_parGeomMemFactor);
111 m_communicateSegmentsSerial =
true;
112 m_communicateSegmentsSerial =
113 Context::getSolverProperty<MBool>(
"communicateSegmentsSerial", solverId(), AT_, &m_communicateSegmentsSerial);
119 m_GFieldInitFromSTL =
false;
120 m_forceBoundingBox =
false;
121 m_levelSetIntfBndId = 0;
122 m_noLevelSetIntfBndIds = 0;
124 m_GFieldInitFromSTL = Context::getSolverProperty<MBool>(
"GFieldInitFromSTL", solverId(), AT_, &m_GFieldInitFromSTL);
126 if(m_GFieldInitFromSTL) {
127 m_levelSetIntfBndId = Context::getSolverProperty<MInt>(
"levelSetIntfBndId", solverId(), AT_, &m_levelSetIntfBndId);
129 m_forceBoundingBox = Context::getSolverProperty<MBool>(
"forcedBoundingBox", solverId(), AT_, &m_forceBoundingBox);
136 m_noLevelSetIntfBndIds = noBodyBndIds + noBndIds;
137 if(domainId() == 0) {
138 cerr <<
" noLevelSetIntfBndIds: " << m_noLevelSetIntfBndIds << endl;
140 m_levelSetIntfBndIds =
new MInt[m_noLevelSetIntfBndIds];
142 for(
MInt i = 0; i < noBodyBndIds; i++) {
143 m_levelSetIntfBndIds[i] = Context::getSolverProperty<MFloat>(
"bodyBndryCndIds", solverId(), AT_, i);
144 if(domainId() == 0) {
145 cerr <<
" levelSetIntfBndIds: " << m_levelSetIntfBndIds[i] << endl;
149 for(
MInt i = noBodyBndIds; i < m_noLevelSetIntfBndIds; i++) {
150 m_levelSetIntfBndIds[i] =
151 Context::getSolverProperty<MInt>(
"GFieldInitFromSTLBndCndIds", solverId(), AT_, i - noBodyBndIds);
152 if(domainId() == 0) {
153 cerr <<
" levelSetIntfBndIds: " << m_levelSetIntfBndIds[i] << endl;
158 m_levelSetIntfBndIds =
nullptr;
166 testcaseDir = Context::getSolverProperty<MString>(
"testcaseDir", solverId(), AT_, &testcaseDir);
180 inputDir = Context::getSolverProperty<MString>(
"inputDir", solverId(), AT_, &inputDir);
193 testcaseDir + inputDir + Context::getSolverProperty<MString>(
"geometryInputFileName", solverId(), AT_);
195 RECORD_TIMER_STOP(t_initGeometry);
197 NEW_SUB_TIMER(t_readGeomFile,
"read geometry property file", m_t_geometryAll);
201 m_log <<
" + Reading geometry property file " << endl;
202 if(tmpFileName.find(
".toml") == MString::npos) {
203 geometryContext().readPropertyFile(
NETCDF, tmpFileName.c_str());
205 geometryContext().readPropertyFile(
TOML, tmpFileName.c_str());
207 m_bodyMap = geometryContext().getBodies();
222 m_gridCutTest =
"SAT";
223 m_gridCutTest = Context::getSolverProperty<MString>(
"gridCutTest", solverId(), AT_, &m_gridCutTest);
225 m_bodyIt = m_bodyMap.begin();
227 m_noSegments = geometryContext().getNoSegments();
228 m_segmentOffsets.resize(m_noSegments + 1);
229 m_segmentOffsetsWithoutMB.resize(m_noSegments + 1);
234 NEW_SUB_TIMER(t_correctVertices,
"correct vertices", m_t_geometryAll);
235 g_tc_geometry.emplace_back(
"correct vertices", t_correctVertices);
236 RECORD_TIMER_START(t_correctVertices);
238 RECORD_TIMER_STOP(t_correctVertices);
241 NEW_SUB_TIMER(t_buildAdt,
"building adt", m_t_geometryAll);
243 RECORD_TIMER_START(t_buildAdt);
246 if(m_noElements > 0) m_adt->buildTree();
247 RECORD_TIMER_STOP(t_buildAdt);
250 if(m_GFieldInitFromSTL && m_noElements > 0) m_adt->buildTreeMB();
253 RECORD_TIMER_STOP(m_t_geometryAll);
256 DISPLAY_ALL_GROUP_TIMERS(m_tg_geometry);
273 m_log <<
"reading the auxiliary stl " << filename << endl;
331 m_log <<
" + Used memmory for collectors: "
338 m_log <<
" * adt tree: " << (
MFloat)
m_adt->memoryUsage() / 1024.0 / 1024.0 <<
" MB" << endl;
352 snd[2] = (
MFloat)
m_adt->memoryUsage() / 1024.0 / 1024.0;
356 "snd.getPointer()",
"mem.getPointer()");
360 ofl.open(
"memrep_geom.txt", std::ios_base::out | std::ios_base::trunc);
362 ofl <<
"###########################################################################################################"
366 ofl <<
"# domain no_triangles triangles[MB] tree[MB] tmb_triagles[MP]" << endl <<
"#" << endl;
369 for(
MInt i = 0; i < count; i++)
374 for(
MInt i = 0; i < count; i++) {
375 min[i] = 9999999999999999.9;
380 for(
MInt i = 0; i < count; i++) {
381 sums[i] += mem[d * count + i];
382 if(mem[d * count + i] > max[i]) max[i] = mem[d * count + i];
383 if(mem[d * count + i] < min[i]) min[i] = mem[d * count + i];
386 MString names[4] = {
"no_triangles",
"triangles",
"tree",
"mb_triangles"};
387 for(
MInt i = 0; i < count; i++) {
388 ofl <<
"# SUM " << names[i] <<
" = " << sums[i] << endl;
389 ofl <<
"# AVG " << names[i] <<
" = " << sums[i] /
noDomains() << endl;
390 ofl <<
"# MIN " << names[i] <<
" = " << min[i] << endl;
391 ofl <<
"# MAX " << names[i] <<
" = " << max[i] << endl << endl;
394 <<
"###########################################################################################################"
400 for(
MInt i = 0; i < count; i++)
401 ofl << mem[d * count + i] <<
"\t\t";
424 ifstream ifl(fileName);
427 stringstream errorMessage;
428 errorMessage <<
" ERROR in segment::readSegment, couldn't find file : " << fileName <<
"!";
429 mTerm(1, AT_, errorMessage.str());
435 while(text.find(
"endsolid") == std::string::npos) {
436 ifl.getline(tmp, 256);
438 if(text.find(
"facet") != std::string::npos && text.find(
"endface") == std::string::npos)
439 *noElements = *noElements + 1;
462 struct stat stat_buf {};
463 MInt rc = stat(fileName.c_str(), &stat_buf);
465 stringstream errorMessage;
466 errorMessage <<
" ERROR in segment::readSegment, couldn't determine file size of: " << fileName <<
"!";
467 mTerm(1, AT_, errorMessage.str());
470 *noElements = (stat_buf.st_size - (80 + 4)) / 50;
493 surface.readScalar(noElements,
"noTriangles");
514 ifstream ifl(fileName);
517 stringstream errorMessage;
518 errorMessage <<
" ERROR in segment::readSegment, couldn't find file : " << fileName <<
"!";
519 mTerm(1, AT_, errorMessage.str());
525 while(text.find(
"endsolid") == std::string::npos) {
526 ifl.getline(tmp, 1024);
528 if(text.find(
"normal") != std::string::npos) {
529 elemCollector->append();
531 std::vector<std::string> tokens;
535 for(
MInt i = 0; i < 3; i++) {
536 tokens[i + 2] = trim(tokens[i + 2]);
537 if(tokens[i + 2].find_first_not_of(
"0123456789.eE-+") != std::string::npos) {
538 cerr <<
"ERROR: normal component " << tokens[i + 2] <<
" is not a number " << endl;
542 allelements[*offset].
m_normal[i] = stod(tokens[i + 2]);
545 ifl.getline(tmp, 256);
549 for(
MInt j = 0; j < 3; j++) {
550 ifl.getline(tmp, 1024);
554 std::vector<std::string> vertex;
557 for(
MInt i = 0; i < 3; i++) {
558 vertex[i + 1] = trim(vertex[i + 1]);
559 if(vertex[i + 1].find_first_not_of(
"0123456789.eE-+") != std::string::npos) {
560 cerr <<
"ERROR: vertex component " << vertex[i + 1] <<
" is not a number " << endl;
565 allelements[*offset].
m_vertices[j][i] = stod(vertex[i + 1]);
578 *offset = *offset + 1;
593 char tmp_byte = buf[0];
612 } bint = {0x01020304};
614 return static_cast<MInt>(bint.c[0] == 1);
635 using facet_t =
struct {
float n[3], v1[3], v2[3], v3[3]; };
641 if((fp = fopen(fileName.c_str(),
"rb")) ==
nullptr) {
642 stringstream errorMessage;
643 errorMessage <<
" ERROR in segment::readSegment, couldn't find file : " << fileName <<
"!";
644 mTerm(1, AT_, errorMessage.str());
650 if(!fread(header, 1, 84, fp)) {
651 TERMM(-1,
"ERROR: Memory error!");
654 for(
MInt i = 0; fread(&facet, 48, 1, fp) > 0; i++) {
655 if(!fread(&ibuff2, 2, 1, fp)) {
656 TERMM(-1,
"ERROR: Memory error!");
659 elemCollector->append();
662 for(
float& k : facet.n) {
663 char* buf = (
char*)(&k);
666 for(
float& k : facet.v1) {
667 char* buf = (
char*)(&k);
670 for(
float& k : facet.v2) {
671 char* buf = (
char*)(&k);
674 for(
float& k : facet.v3) {
675 char* buf = (
char*)(&k);
681 allelements[*offset].
m_normal[j] = facet.n[j];
682 allelements[*offset].
m_vertices[0][j] = facet.v1[j];
683 allelements[*offset].
m_vertices[1][j] = facet.v2[j];
684 allelements[*offset].
m_vertices[2][j] = facet.v3[j];
696 *offset = *offset + 1;
721 using facet_t =
struct {
float n[3], v1[3], v2[3], v3[3]; };
727 if((fp = fopen(fileName.c_str(),
"rb")) ==
nullptr) {
728 stringstream errorMessage;
729 errorMessage <<
" ERROR in segment::readSegment, couldn't find file : " << fileName <<
"!";
730 mTerm(1, AT_, errorMessage.str());
737 if(fread(header, 1, 84, fp) == 0u) {
738 TERMM(-1,
"ERROR: Memory error!");
741 for(
MInt i = 0; fread(&facet, 48, 1, fp) > 0; i++) {
742 if(fread(&ibuff2, 2, 1, fp) == 0u) {
743 TERMM(-1,
"ERROR: Memory error!");
746 elemCollector->append();
749 allelements[*offset].
m_normal[j] = facet.n[j];
750 allelements[*offset].
m_vertices[0][j] = facet.v1[j];
751 allelements[*offset].
m_vertices[1][j] = facet.v2[j];
752 allelements[*offset].
m_vertices[2][j] = facet.v3[j];
764 *offset = *offset + 1;
784 MInt bndCndId,
MInt segmentId,
MInt* offset,
const MPI_Comm comm) {
789 MInt offsetstart = *offset;
790 MInt noTriangles = -1;
792 surface.readScalar(&noTriangles,
"noTriangles");
794 MInt noEntries = noTriangles;
799 for(
MInt i = 0; i < noTriangles; i++) {
800 elemCollector->append();
810 *offset = *offset + 1;
813 MString normalnames[3] = {
"normals0",
"normals1",
"normals2"};
814 MString vertexnames[3][3] = {{
"vertices00",
"vertices01",
"vertices02"},
815 {
"vertices10",
"vertices11",
"vertices12"},
816 {
"vertices20",
"vertices21",
"vertices22"}};
820 surface.setOffset(noEntries, 0);
821 surface.readArray(tmp_array.
begin(), normalnames[d]);
823 for(
MInt i = offsetstart, j = 0; i < offsetstart + noTriangles; i++, j++)
824 allelements[i].m_normal[d] = tmp_array[j];
828 for(
MInt vtx = 0; vtx <
nDim; vtx++) {
829 for(
MInt coord = 0; coord <
nDim; coord++) {
830 surface.setOffset(noEntries, 0);
831 surface.readArray(tmp_array.
begin(), vertexnames[vtx][coord]);
832 for(
MInt i = offsetstart, j = 0; i < offsetstart + noTriangles; i++, j++) {
833 allelements[i].
m_vertices[vtx][coord] = tmp_array[j];
838 for(
MInt i = offsetstart; i < offsetstart + noTriangles; i++) {
859 g_tc_geometry.emplace_back(
"count triangles", t_countTriangles);
860 RECORD_TIMER_START(t_countTriangles);
867 if(
m_bodyIt->second->name !=
"default") {
868 for(
MInt i = 0; i <
m_bodyIt->second->noSegments; i++) {
869 stringstream fileName;
874 fileName <<
"." << segmentId;
877 m_log <<
" - file: " << fileName.str() << endl;
894 m_log <<
" * no. triangles: " << noElements << endl;
907 RECORD_TIMER_STOP(t_countTriangles);
910 m_log <<
" + Reading segments ..." << endl;
913 g_tc_geometry.emplace_back(
"read triangles", t_readTriangles);
914 RECORD_TIMER_START(t_readTriangles);
926 if(
m_bodyIt->second->name !=
"default") {
927 for(
MInt index = 0; index <
m_bodyIt->second->noSegments; index++) {
928 stringstream fileName;
933 fileName <<
"." << segmentId;
936 allBCs.push_back(bndCndId);
938 m_log <<
" - file: " << fileName.str() << endl;
951 const MPI_Comm commSelf = MPI_COMM_SELF;
990 idsBuffer[i] = m_allelements->a[i].m_bndCndId;
991 idsBuffer[
m_noElements + i] = m_allelements->a[i].m_segmentId;
992 idsBuffer[(2 *
m_noElements) + i] = m_allelements->a[i].m_originalId;
994 normalsBuffer[(i *
nDim) + j] = m_allelements->a[i].m_normal[j];
996 verticesBuffer[(i * 9) + (j *
nDim) + k] = m_allelements->a[i].m_vertices[j][k];
1011 m_allelements->append();
1013 m_allelements->a[i].m_normal[j] = normalsBuffer[(i *
nDim) + j];
1015 m_allelements->a[i].m_vertices[j][k] = verticesBuffer[(i * 9) + (j *
nDim) + k];
1018 m_allelements->a[i].boundingBox();
1019 m_allelements->a[i].m_bndCndId = idsBuffer[i];
1020 m_allelements->a[i].m_segmentId = idsBuffer[
m_noElements + i];
1021 m_allelements->a[i].m_originalId = idsBuffer[(2 *
m_noElements) + i];
1028 "m_segmentOffsets");
1030 mpiComm(), AT_,
"m_segmentOffsetsWithoutMB");
1038 RECORD_TIMER_STOP(t_readTriangles);
1039 return m_allelements;
1079 g_tc_geometry.emplace_back(
"read triangles", t_readTriangles);
1080 RECORD_TIMER_START(t_readTriangles);
1082 m_log <<
" + Reading triangles ..." << endl;
1085 stringstream filename;
1087 m_log <<
" - reading workload from gridfile " << filename.str() << endl;
1089 MInt partitionCellsCnt = 0;
1090 MInt noLocalPartitionCells = 0;
1094 ParallelIo grid(filename.str(), PIO_READ, MPI_COMM_SELF);
1095 partitionCellsCnt = (
MInt)grid.getArraySize(
"partitionCellsGlobalId");
1097 MFloatScratchSpace partitionCellsWorkLoad(partitionCellsCnt, AT_,
"partitionCellsWorkLoad");
1098 grid.setOffset(partitionCellsCnt, 0);
1099 grid.readArray(partitionCellsWorkLoad.begin(),
"partitionCellsWorkload");
1102 m_log <<
" - partitioning workload" << endl;
1103 optimalPartitioningSerial(&partitionCellsWorkLoad[0], partitionCellsCnt,
noDomains(), &offset[0]);
1106 MPI_Bcast(&partitionCellsCnt, 1, MPI_INT, 0,
mpiComm(), AT_,
"partitionCellsCnt");
1111 MPI_Bcast(&partitionCellsCnt, 1, MPI_INT, 0,
mpiComm(), AT_,
"partitionCellsCnt");
1117 noLocalPartitionCells = partitionCellsCnt - offset[
domainId()];
1119 m_log <<
" - no. local partitionCells: " << noLocalPartitionCells << endl;
1122 m_log <<
" - reading basic geometry information" << endl;
1125 MInt noTriangles = 0;
1126 geomIO.readScalar(&noTriangles,
"noTriangles");
1127 geomIO.setOffset(noLocalPartitionCells, offset[
domainId()]);
1129 MIntScratchSpace noTrisPerPartitionCell(noLocalPartitionCells, AT_,
"noTrisPerPartitionCell");
1130 geomIO.readArray(noTrisPerPartitionCell.getPointer(),
"noTrisPerPartitionCell");
1135 for(
MInt i = 0; i < noLocalPartitionCells; i++) {
1136 noL += noTrisPerPartitionCell[i];
1139 MPI_Allgather(&noL, 1, MPI_INT, noAllLocalTris.getPointer(), 1, MPI_INT,
mpiComm(), AT_,
"noL",
1140 "noAllLocalTris.getPointer()");
1142 MInt originalTriIdOffset = 0;
1145 originalTriIdOffset += noAllLocalTris[d];
1185 geomIO.setOffset(noL, originalTriIdOffset);
1187 geomIO.readArray(dummyInt.getPointer(),
"originalTriId");
1189 geomIO.readArray(originalTriId.getPointer(),
"originalTriId");
1193 geomIO.readArray(dummyInt.getPointer(),
"segmentId");
1195 geomIO.readArray(segEntry.getPointer(),
"segmentId");
1197 vector<MInt> keepOffset;
1198 for(
MInt i = 0; i < noL; i++) {
1200 if(ret.second) keepOffset.push_back(i);
1214 m_allelements->append();
1217 m_log <<
" - actiually reading triangles" << endl;
1218 MString normalnames[3] = {
"normals0",
"normals1",
"normals2"};
1219 MString vertexnames[3][3] = {{
"vertices00",
"vertices01",
"vertices02"},
1220 {
"vertices10",
"vertices11",
"vertices12"},
1221 {
"vertices20",
"vertices21",
"vertices22"}};
1224 m_log <<
" * segmentOffsets" << endl;
1237 unordered_set<MInt> allBCs;
1240 m_log <<
" * segmentIds, bndCndIds, originalIds" << endl;
1242 MInt segmentId = segEntry[keepOffset[i]];
1256 allelements[segmentCnt[segmentId] + off].m_segmentId = segmentId;
1257 allelements[segmentCnt[segmentId] + off].m_bndCndId = bndCndId;
1258 allelements[segmentCnt[segmentId] + off].m_originalId = originalTriId[keepOffset[i]];
1259 allBCs.insert(bndCndId);
1260 segmentCnt[segmentId]++;
1266 for(
auto it = allBCs.begin(); it != allBCs.end(); ++it, iter++)
1270 m_log <<
" * normals" << endl;
1278 geomIO.readArray(dummyFloat.getPointer(), normalnames[d]);
1280 geomIO.readArray(normalEntry.getPointer(), normalnames[d]);
1283 MInt segmentId = segEntry[keepOffset[i]];
1285 allelements[segmentCnt[segmentId] + off].m_normal[d] = normalEntry[keepOffset[i]];
1286 segmentCnt[segmentId]++;
1291 m_log <<
" * vertices" << endl;
1299 geomIO.readArray(dummyFloat.getPointer(), vertexnames[v][d]);
1301 geomIO.readArray(vertexEntry.getPointer(), vertexnames[v][d]);
1304 MInt segmentId = segEntry[keepOffset[i]];
1306 allelements[segmentCnt[segmentId] + off].m_vertices[v][d] = vertexEntry[keepOffset[i]];
1307 segmentCnt[segmentId]++;
1312 m_log <<
" * calculating bounding box for the triangles" << endl;
1318 m_log <<
" - segment id " << i << endl;
1325 RECORD_TIMER_STOP(t_readTriangles);
1327 return m_allelements;
1344 RECORD_TIMER_START(t_readGeometry);
1368 m_log <<
" + Geometry configuration:" << endl;
1370 m_log <<
" - endianess: " << (
is_big_endian() ?
"big endian" :
"little endian") << endl;
1399 MInt mbelem_counter = 0, elem_counter = 0;
1400 MBool mbElem =
false;
1403 for(
MInt allelem_counter = 0; allelem_counter < m_allelements->size(); allelem_counter++) {
1416 for(
MInt j = 0; j < 3; j++) {
1418 for(
MInt i = 0; i < 3; i++) {
1435 for(
MInt j = 0; j < 3; j++) {
1436 elements[elem_counter].m_normal[j] = allelements[allelem_counter].
m_normal[j];
1437 for(
MInt i = 0; i < 3; i++) {
1438 elements[elem_counter].m_vertices[j][i] = allelements[allelem_counter].
m_vertices[j][i];
1441 elements[elem_counter].boundingBox();
1452 for(
MInt j = 0; j < 3; j++) {
1454 for(
MInt i = 0; i < 3; i++) {
1467 for(
MInt j = 0; j < 3; j++) {
1468 elements[elem_counter].m_normal[j] = allelements[allelem_counter].
m_normal[j];
1469 for(
MInt i = 0; i < 3; i++)
1470 elements[elem_counter].m_vertices[j][i] = allelements[allelem_counter].m_vertices[j][i];
1472 elements[elem_counter].boundingBox();
1482 delete m_allelements;
1484 RECORD_TIMER_STOP(t_readGeometry);
1486 NEW_SUB_TIMER(t_calcBndBox,
"calculating bounding box",
m_t_geometryAll);
1487 g_tc_geometry.emplace_back(
"calculating bounding box", t_calcBndBox);
1488 RECORD_TIMER_START(t_calcBndBox);
1491 RECORD_TIMER_STOP(t_calcBndBox);
1512 if(!allTimerRunning) {
1515 NEW_SUB_TIMER(t_wrtParGeom,
"writing parallel geometry",
m_t_geometryAll);
1516 g_tc_geometry.emplace_back(
"writing parallel geometry", t_wrtParGeom);
1517 RECORD_TIMER_START(t_wrtParGeom);
1520 name <<
"out/" <<
domainId() <<
"_" << filename <<
".vtk";
1522 st.open(name.str());
1523 st <<
"# vtk DataFile Version 3.0" << endl;
1524 st <<
"vtk output" << endl;
1525 st <<
"ASCII" << endl;
1526 st <<
"DATASET POLYDATA" << endl;
1530 for(
MInt v = 0; v < 3; v++) {
1531 for(
MInt d = 0; d < 3; d++)
1532 st <<
elements[i].m_vertices[v][d] <<
" ";
1540 for(
MInt v = 0; v < 3; v++, j++)
1547 st <<
"SCALARS domainId int 1" << endl;
1548 st <<
"LOOKUP_TABLE default" << endl;
1552 st <<
"SCALARS segmentId int 1" << endl;
1553 st <<
"LOOKUP_TABLE default" << endl;
1555 st <<
elements[i].m_segmentId << endl;
1557 st <<
"SCALARS originalCellId int 1" << endl;
1558 st <<
"LOOKUP_TABLE default" << endl;
1560 st <<
elements[i].m_originalId << endl;
1562 st <<
"SCALARS BC int 1" << endl;
1563 st <<
"LOOKUP_TABLE default" << endl;
1565 st <<
elements[i].m_bndCndId << endl;
1566 st <<
"SCALARS area double 1" << endl;
1567 st <<
"LOOKUP_TABLE default" << endl;
1576 cross[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
1577 cross[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
1578 cross[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
1580 MFloat area = sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]);
1584 RECORD_TIMER_STOP(t_wrtParGeom);
1585 if(!allTimerRunning) {
1601 m_log <<
" + Calculating bounding box ..." << endl;
1609 "noGlobalElem.getPointer()");
1612 if(noGlobalElem[d] > 0) {
1618 std::array<MFloat, 2 * nDim> triMinMax;
1619 triMinMax.fill(std::nanf(
""));
1622 for(
MInt j = 0; j < 2 *
nDim; j++) {
1623 triMinMax[j] =
elements[0].m_minMax[j];
1627 MPI_Bcast(triMinMax.data(), 2 *
nDim, MPI_DOUBLE, refDomain,
mpiComm(), AT_,
"triMinMax.getPointer()");
1645 m_log <<
" - local max: ";
1651 m_log <<
" - local min: ";
1661 "m_minMax[0]+nDim");
1665 m_log <<
" - max: ";
1671 m_log <<
" - min: ";
1675 m_log << endl << endl;
1681 m_log <<
" Bounding box for Moving Boundary segment:" << endl;
1716 MFloat epsilon = 0.0000001;
1717 MFloat maxCoordinate = F0;
1721 for(
MInt el = 0; el < noEl; el++)
1722 for(
MInt i = 0; i < 3; i++)
1723 for(
MInt j = 0; j < 3; j++)
1724 maxCoordinate =
mMax(
ABS(
elements[el].m_vertices[i][j]), maxCoordinate);
1727 epsilon *= maxCoordinate;
1730 for(
MInt el = 0; el < noEl; el++) {
1731 for(
MInt i = 0; i < 3; i++) {
1732 for(
MInt j = 0; j < 3; j++) {
1785 const MFloat*
const cell_coords) {
1790 m_adt->retrieveNodes(targetRegion, nodeList);
1791 const MInt noNodes = nodeList.size();
1792 MFloat vert_mov[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
1793 MFloat edge_mov[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
1794 MFloat edge_fabs[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
1801 MFloat normal[MAX_SPACE_DIMENSIONS];
1802 MFloat vmin[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1803 numeric_limits<MFloat>::max()};
1804 MFloat vmax[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1805 numeric_limits<MFloat>::max()};
1807 MInt combo[3][6] = {{0, 2, 0, 2, 1, 2}, {0, 2, 0, 2, 0, 1}, {0, 1, 0, 1, 1, 2}};
1809 MInt noReallyIntersectingNodes = 0;
1812 for(
MInt n = 0; n < noNodes; n++) {
1818 vert_mov[j][i] =
elements[nodeList[n]].m_vertices[j][i] - cell_coords[i];
1821 edge_mov[j][i] = vert_mov[(j + 1) %
nDim][i] - vert_mov[j][i];
1822 edge_fabs[j][i] = fabs(edge_mov[j][i]);
1831 for(
MInt l = 0, j = 2, k = 1; l <
nDim; l++) {
1832 p0 = mul * edge_mov[i][j] * vert_mov[combo[i][2 * l]][k] - mul * edge_mov[i][k] * vert_mov[combo[i][2 * l]][j];
1833 p1 = mul * edge_mov[i][j] * vert_mov[combo[i][2 * l + 1]][k]
1834 - mul * edge_mov[i][k] * vert_mov[combo[i][2 * l + 1]][j];
1836 (p0 < p1) ? (min = p0, max = p1) : (min = p1, max = p0);
1837 rad = cellHalfLength * (edge_fabs[i][j] + edge_fabs[i][k]);
1839 if(min > rad || max < -rad) {
1854 min = max = vert_mov[0][i];
1856 if(vert_mov[j][i] < min) min = vert_mov[j][i];
1857 if(vert_mov[j][i] > max) max = vert_mov[j][i];
1860 if(min > cellHalfLength || max < -cellHalfLength) {
1868 normal[0] = edge_mov[0][1] * edge_mov[1][2] - edge_mov[0][2] * edge_mov[1][1];
1869 normal[1] = edge_mov[0][2] * edge_mov[1][0] - edge_mov[0][0] * edge_mov[1][2];
1870 normal[2] = edge_mov[0][0] * edge_mov[1][1] - edge_mov[0][1] * edge_mov[1][0];
1874 d += normal[i] * vert_mov[0][i];
1878 if(normal[i] > 0.0f) {
1879 vmin[i] = -cellHalfLength;
1880 vmax[i] = cellHalfLength;
1882 vmin[i] = cellHalfLength;
1883 vmax[i] = -cellHalfLength;
1887 if((normal[0] * vmin[0] + normal[1] * vmin[1] + normal[2] * vmin[2]) + d > 0.0f)
continue;
1888 if((normal[0] * vmax[0] + normal[1] * vmax[1] + normal[2] * vmax[2]) + d >= 0.0f) {
1889 nodeList[noReallyIntersectingNodes] = nodeList[n];
1890 noReallyIntersectingNodes++;
1894 nodeList.resize(noReallyIntersectingNodes);
1898 return noReallyIntersectingNodes;
1915 MInt noReallyIntersectingNodes = 0;
1918 bitset<6> points[3];
1919 bitset<6> faceCodes[6];
1924 MInt edges[3][2] = {{0, 1}, {1, 2}, {0, 2}};
1928 MInt targetPoints[8][3] = {{0, 1, 2}, {3, 1, 2}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}, {3, 1, 5}, {0, 4, 5}, {3, 4, 5}};
1931 MInt targetEdges[12][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7},
1932 {0, 2}, {1, 3}, {4, 6}, {5, 7},
1933 {0, 4}, {1, 5}, {2, 6}, {3, 7}};
1937 MBool piercePointInside = 0;
1938 MBool triviallyAccepted = 0;
1946 MInt pointAInPlane[6][3] = {{0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}};
1948 MInt pointBInPlane[6][3] = {{0, 4, 2}, {3, 1, 5}, {3, 1, 2}, {0, 4, 5}, {3, 1, 2}, {3, 1, 5}};
1950 MInt pointCInPlane[6][3] = {{0, 1, 5}, {3, 4, 2}, {3, 1, 5}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}};
1951 MFloat a[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1952 numeric_limits<MFloat>::max()};
1953 MFloat b[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1954 numeric_limits<MFloat>::max()};
1955 MFloat c[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1956 numeric_limits<MFloat>::max()};
1957 MFloat d[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1958 numeric_limits<MFloat>::max()};
1959 MFloat e[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1960 numeric_limits<MFloat>::max()};
1965 MFloat epsilon = 0.00000000001;
1967 faceCodes[0] =
IPOW2(0);
1968 faceCodes[1] =
IPOW2(1);
1969 faceCodes[2] =
IPOW2(2);
1970 faceCodes[3] =
IPOW2(3);
1971 faceCodes[4] =
IPOW2(4);
1972 faceCodes[5] =
IPOW2(5);
1981 m_adt->retrieveNodes(targetRegion, nodeList);
1982 const MInt noNodes = nodeList.size();
1984 noReallyIntersectingNodes = 0;
1986 for(
MInt n = 0; n < noNodes; n++) {
1995 if(
elements[nodeList[n]].m_vertices[p][j] < targetRegion[j]) {
1996 points[p] |= faceCodes[2 * j];
1998 if(
elements[nodeList[n]].m_vertices[p][j] > targetRegion[j +
nDim]) {
1999 points[p] |= faceCodes[2 * j + 1];
2007 if((points[edges[i][0]] & points[edges[i][1]]) != 0) {
2011 triviallyAccepted =
false;
2013 if(points[k] == 0) {
2014 triviallyAccepted =
true;
2018 if(triviallyAccepted) {
2034 result = (points[edges[i][0]] | points[edges[i][1]]);
2035 piercePointInside =
false;
2036 for(
MInt j = 0; j < 2 *
nDim; j++) {
2037 if(result[j] == 1) {
2043 a[k] = targetRegion[pointAInPlane[j][k]];
2044 b[k] = targetRegion[pointBInPlane[j][k]];
2045 c[k] = targetRegion[pointCInPlane[j][k]];
2046 d[k] =
elements[nodeList[n]].m_vertices[edges[i][0]][k];
2047 e[k] =
elements[nodeList[n]].m_vertices[edges[i][1]][k];
2049 gamma = ((e[0] - d[0]) * ((
a[2] - c[2]) * (c[1] -
b[1]) - (
a[1] - c[1]) * (c[2] -
b[2]))
2050 - (e[1] - d[1]) * ((
a[2] - c[2]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[2] -
b[2]))
2051 + (e[2] - d[2]) * ((
a[1] - c[1]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[1] -
b[1])));
2053 s = ((c[0] - d[0]) * ((
a[2] - c[2]) * (c[1] -
b[1]) - (
a[1] - c[1]) * (c[2] -
b[2]))
2054 - (c[1] - d[1]) * ((
a[2] - c[2]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[2] -
b[2]))
2055 + (c[2] - d[2]) * ((
a[1] - c[1]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[1] -
b[1])))
2060 pP[k] = d[k] + s * (e[k] - d[k]);
2065 if(pP[k] < targetRegion[k]) {
2066 pCode |= faceCodes[2 * k];
2068 if(pP[k] > targetRegion[k +
nDim]) {
2069 pCode |= faceCodes[2 * k + 1];
2078 result = faceCodes[j];
2080 result = (result & pCode);
2082 piercePointInside =
true;
2086 if(!piercePointInside) {
2092 result = (points[0] | points[1] | points[2]);
2094 nodeList[noReallyIntersectingNodes] = nodeList[n];
2095 noReallyIntersectingNodes++;
2101 nodeList[noReallyIntersectingNodes] = nodeList[n];
2102 noReallyIntersectingNodes++;
2111 if(rejection >= 3) {
2112 for(
MInt t = 0; t < 12; t++) {
2114 e1[p] = targetRegion[targetPoints[targetEdges[t][0]][p]];
2115 e2[p] = targetRegion[targetPoints[targetEdges[t][1]][p]];
2123 if(t > 3 && t < 8) {
2135 a[k] =
elements[nodeList[n]].m_vertices[0][k];
2136 b[k] =
elements[nodeList[n]].m_vertices[1][k];
2137 c[k] =
elements[nodeList[n]].m_vertices[2][k];
2139 if(
approx(
a[spaceId1],
b[spaceId1], MFloatEps) && !
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
2141 q = (e1[spaceId1] -
a[spaceId1]) / (c[spaceId1] -
a[spaceId1]);
2142 p2 = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
2144 if(!
approx(
a[spaceId1],
b[spaceId1], MFloatEps) &&
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
2146 p2 = (e1[spaceId1] -
a[spaceId1]) / (
b[spaceId1] -
a[spaceId1]);
2147 q = (e1[spaceId] -
a[spaceId] - p2 * (
b[spaceId] -
a[spaceId])) / (c[spaceId] -
a[spaceId]);
2149 if(
approx(
a[spaceId],
b[spaceId], MFloatEps) && !
approx(
a[spaceId], c[spaceId], MFloatEps)) {
2151 q = (e1[spaceId] -
a[spaceId]) / (c[spaceId] -
a[spaceId]);
2152 p2 = (e1[spaceId1] -
a[spaceId1] - q * (c[spaceId1] -
a[spaceId1])) / (
b[spaceId1] -
a[spaceId1]);
2154 if(!
approx(
a[spaceId],
b[spaceId], MFloatEps) &&
approx(
a[spaceId], c[spaceId], MFloatEps)) {
2156 p2 = (e1[spaceId] -
a[spaceId]) / (
b[spaceId] -
a[spaceId]);
2157 q = (e1[spaceId1] -
a[spaceId1] - p2 * (
b[spaceId1] -
a[spaceId1])) / (c[spaceId1] -
a[spaceId1]);
2160 q = ((e1[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
2161 - (
b[spaceId1] -
a[spaceId1]) * (e1[spaceId] -
a[spaceId]))
2162 / ((c[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
2163 - (
b[spaceId1] -
a[spaceId1]) * (c[spaceId] -
a[spaceId]));
2164 p2 = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
2170 if(p2 * q >= 0 || p2 * q < 0) {
2172 gamma =
a[spaceId2] + p2 * (
b[spaceId2] -
a[spaceId2]) + q * (c[spaceId2] -
a[spaceId2]);
2173 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
2175 if(s < -epsilon || s > F1 + epsilon || p2 < -epsilon || q < -epsilon || (p2 + q) > F1 + epsilon) {
2181 nodeList[noReallyIntersectingNodes] = nodeList[n];
2182 noReallyIntersectingNodes++;
2192 if((noNodes != 0) && (noReallyIntersectingNodes == 0)) {
2196 nodeList.resize(noReallyIntersectingNodes);
2200 return noReallyIntersectingNodes;
2213 MInt noReallyIntersectingNodes = 0;
2216 bitset<6> points[3];
2217 bitset<6> faceCodes[6];
2219 MInt edges[3][2] = {{0, 1}, {1, 2}, {0, 2}};
2223 MInt targetPoints[8][3] = {{0, 1, 2}, {3, 1, 2}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}, {3, 1, 5}, {0, 4, 5}, {3, 4, 5}};
2226 MInt targetEdges[12][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7},
2227 {0, 2}, {1, 3}, {4, 6}, {5, 7},
2228 {0, 4}, {1, 5}, {2, 6}, {3, 7}};
2232 MBool piercePointInside = 0;
2233 MBool triviallyAccepted = 0;
2241 MInt pointAInPlane[6][3] = {{0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}};
2243 MInt pointBInPlane[6][3] = {{0, 4, 2}, {3, 1, 5}, {3, 1, 2}, {0, 4, 5}, {3, 1, 2}, {3, 1, 5}};
2245 MInt pointCInPlane[6][3] = {{0, 1, 5}, {3, 4, 2}, {3, 1, 5}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}};
2246 MFloat a[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2247 numeric_limits<MFloat>::max()};
2248 MFloat b[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2249 numeric_limits<MFloat>::max()};
2250 MFloat c[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2251 numeric_limits<MFloat>::max()};
2252 MFloat d[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2253 numeric_limits<MFloat>::max()};
2254 MFloat e[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2255 numeric_limits<MFloat>::max()};
2258 faceCodes[0] =
IPOW2(0);
2259 faceCodes[1] =
IPOW2(1);
2260 faceCodes[2] =
IPOW2(2);
2261 faceCodes[3] =
IPOW2(3);
2262 faceCodes[4] =
IPOW2(4);
2263 faceCodes[5] =
IPOW2(5);
2272 m_adt->retrieveNodes(targetRegion, nodeList);
2273 const MInt noNodes = nodeList.size();
2275 noReallyIntersectingNodes = 0;
2277 for(
MInt n = 0; n < noNodes; n++) {
2286 if(
elements[nodeList[n]].m_vertices[p][j] < targetRegion[j]) {
2287 points[p] |= faceCodes[2 * j];
2289 if(
elements[nodeList[n]].m_vertices[p][j] > targetRegion[j +
nDim]) {
2290 points[p] |= faceCodes[2 * j + 1];
2297 for(
auto& edge : edges) {
2298 if((points[edge[0]] & points[edge[1]]) != 0) {
2302 triviallyAccepted =
false;
2303 for(
auto& point : points) {
2305 triviallyAccepted =
true;
2309 if(triviallyAccepted) {
2325 result = (points[edge[0]] | points[edge[1]]);
2326 piercePointInside =
false;
2327 for(
MInt j = 0; j < 2 *
nDim; j++) {
2328 if(result[j] == 1) {
2334 a[k] = targetRegion[pointAInPlane[j][k]];
2335 b[k] = targetRegion[pointBInPlane[j][k]];
2336 c[k] = targetRegion[pointCInPlane[j][k]];
2337 d[k] =
elements[nodeList[n]].m_vertices[edge[0]][k];
2338 e[k] =
elements[nodeList[n]].m_vertices[edge[1]][k];
2340 gamma = ((e[0] - d[0]) * ((
a[2] - c[2]) * (c[1] -
b[1]) - (
a[1] - c[1]) * (c[2] -
b[2]))
2341 - (e[1] - d[1]) * ((
a[2] - c[2]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[2] -
b[2]))
2342 + (e[2] - d[2]) * ((
a[1] - c[1]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[1] -
b[1])));
2344 s = ((c[0] - d[0]) * ((
a[2] - c[2]) * (c[1] -
b[1]) - (
a[1] - c[1]) * (c[2] -
b[2]))
2345 - (c[1] - d[1]) * ((
a[2] - c[2]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[2] -
b[2]))
2346 + (c[2] - d[2]) * ((
a[1] - c[1]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[1] -
b[1])))
2351 pP[k] = d[k] + s * (e[k] - d[k]);
2356 if(pP[k] < targetRegion[k]) {
2357 pCode |= faceCodes[2 * k];
2359 if(pP[k] > targetRegion[k +
nDim]) {
2360 pCode |= faceCodes[2 * k + 1];
2369 result = faceCodes[j];
2371 result = (result & pCode);
2373 piercePointInside =
true;
2377 if(!piercePointInside) {
2383 result = (points[0] | points[1] | points[2]);
2385 nodeList[noReallyIntersectingNodes] = nodeList[n];
2386 noReallyIntersectingNodes++;
2392 nodeList[noReallyIntersectingNodes] = nodeList[n];
2393 noReallyIntersectingNodes++;
2402 if(rejection >= 3) {
2403 for(
auto& targetEdge : targetEdges) {
2405 e1[p] = targetRegion[targetPoints[targetEdge[0]][p]];
2406 e2[p] = targetRegion[targetPoints[targetEdge[1]][p]];
2410 elements[nodeList[n]].m_vertices[2], e1, e2)) {
2411 nodeList[noReallyIntersectingNodes] = nodeList[n];
2412 noReallyIntersectingNodes++;
2421 if(noNodes && !noReallyIntersectingNodes) {
2425 nodeList.resize(noReallyIntersectingNodes);
2427 return noReallyIntersectingNodes;
2443 MInt maxRfnLvl = (
sizeof(
MInt) * 8) - 6;
2445 MFloat a[3] = {trianglePoint1[0], trianglePoint1[1], trianglePoint1[2]};
2446 MFloat b[3] = {trianglePoint2[0], trianglePoint2[1], trianglePoint2[2]};
2447 MFloat c[3] = {trianglePoint3[0], trianglePoint3[1], trianglePoint3[2]};
2462 d[i] = edgePoint1[i];
2464 volume1 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2465 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2466 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2467 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2468 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2471 d[i] = edgePoint2[i];
2475 volume2 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2476 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2477 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2478 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2479 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2481 if(volume1 * volume2 >= eps) {
2487 a[i] = edgePoint1[i];
2488 b[i] = trianglePoint1[i];
2489 c[i] = trianglePoint2[i];
2490 d[i] = edgePoint2[i];
2492 volume1 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2493 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2494 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2495 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2496 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2499 a[i] = edgePoint1[i];
2500 b[i] = trianglePoint3[i];
2501 c[i] = trianglePoint1[i];
2502 d[i] = edgePoint2[i];
2504 volume2 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2505 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2506 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2507 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2508 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2511 a[i] = edgePoint1[i];
2512 b[i] = trianglePoint2[i];
2513 c[i] = trianglePoint3[i];
2514 d[i] = edgePoint2[i];
2516 volume3 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2517 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2518 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2519 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2520 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2527 if(((volume1 < eps) && (volume1 > -eps)) || ((volume2 < eps) && (volume2 > -eps))
2528 || ((volume3 < eps) && (volume3 > -eps))) {
2529 m_log <<
" ! SINGULARITY IN TRIANGLE INTERSECTION ! At: " <<
a[0] <<
", " <<
a[1] <<
", " <<
a[2] <<
"; " << d[0]
2530 <<
", " << d[1] <<
", " << d[2] << endl;
2537 if(volume1 >= 0.0 && volume2 >= 0.0 && volume3 >= 0.0) {
2540 if(volume1 <= 0.0 && volume2 <= 0.0 && volume3 <= 0.0) {
2561 MInt maxRfnLvl = (
sizeof(
MInt) * 8) - 6;
2563 MFloat a[3] = {trianglePoint1[0], trianglePoint1[1], trianglePoint1[2]};
2564 MFloat b[3] = {trianglePoint2[0], trianglePoint2[1], trianglePoint2[2]};
2565 MFloat c[3] = {trianglePoint3[0], trianglePoint3[1], trianglePoint3[2]};
2580 d[i] = edgePoint1[i];
2582 volume1 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2583 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2584 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2585 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2586 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2589 d[i] = edgePoint2[i];
2593 volume2 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2594 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2595 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2596 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2597 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2599 if(volume1 * volume2 >= eps) {
2605 a[i] = edgePoint1[i];
2606 b[i] = trianglePoint1[i];
2607 c[i] = trianglePoint2[i];
2608 d[i] = edgePoint2[i];
2610 volume1 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2611 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2612 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2613 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2614 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2617 a[i] = edgePoint1[i];
2618 b[i] = trianglePoint3[i];
2619 c[i] = trianglePoint1[i];
2620 d[i] = edgePoint2[i];
2622 volume2 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2623 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2624 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2625 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2626 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2629 a[i] = edgePoint1[i];
2630 b[i] = trianglePoint2[i];
2631 c[i] = trianglePoint3[i];
2632 d[i] = edgePoint2[i];
2634 volume3 = (
b[1] *
a[2] * d[0] - d[1] *
a[0] * c[2] + d[1] *
a[0] *
b[2] + c[1] *
a[0] * d[2] -
b[1] *
a[0] * d[2]
2635 -
a[1] * c[0] * d[2] +
a[1] * d[0] * c[2] -
a[1] * d[0] *
b[2] + d[1] *
a[2] * c[0] + d[1] * c[2] *
b[0]
2636 - d[1] *
a[2] *
b[0] - d[1] *
b[2] * c[0] - c[1] * d[2] *
b[0] - c[1] *
a[2] * d[0] + c[1] *
b[2] * d[0]
2637 -
b[1] * c[2] * d[0] +
b[1] * c[0] * d[2] +
a[1] *
b[0] * d[2] -
a[1] *
b[0] * c[2] -
b[1] *
a[2] * c[0]
2638 +
a[1] * c[0] *
b[2] + c[1] *
a[2] *
b[0] - c[1] *
a[0] *
b[2] +
b[1] *
a[0] * c[2]);
2645 if(((volume1 < eps) && (volume1 > -eps)) || ((volume2 < eps) && (volume2 > -eps))
2646 || ((volume3 < eps) && (volume3 > -eps))) {
2647 m_log <<
" ! SINGULARITY IN TRIANGLE INTERSECTION ! At: " <<
a[0] <<
", " <<
a[1] <<
", " <<
a[2] <<
"; " << d[0]
2648 <<
", " << d[1] <<
", " << d[2] << endl;
2655 if(volume1 >= 0.0 && volume2 >= 0.0 && volume3 >= 0.0)
return true;
2656 if(volume1 <= 0.0 && volume2 <= 0.0 && volume3 <= 0.0)
return true;
2682 MFloat intersection[3] = {0.0, 0.0, 0.0};
2683 MFloat normal[3] = {0.0, 0.0, 0.0};
2713 MFloat intersection[3] = {0.0, 0.0, 0.0};
2714 MFloat normal[3] = {0.0, 0.0, 0.0};
2770 std::array<MFloat, nDim> edge1{};
2771 std::array<MFloat, nDim> edge2{};
2772 std::array<MFloat, nDim> edge3{};
2773 std::array<MFloat, nDim> line{};
2774 std::array<MFloat, nDim> line_norm{};
2775 std::array<MFloat, nDim> normal_norm{};
2776 std::array<MFloat, nDim> trans_p1{};
2777 std::array<MFloat, nDim> trans_p2{};
2778 constexpr MFloat eps = 0.0000000000000001;
2779 constexpr MFloat eps2 = 0.00000001;
2783 edge1[d] = v2[d] - v1[d];
2784 edge2[d] = v3[d] - v1[d];
2785 edge3[d] = v3[d] - v2[d];
2786 line[d] = p2[d] - p1[d];
2788 trans_p1[d] = p1[d] - v1[d];
2789 trans_p2[d] = p2[d] - v1[d];
2793 MFloat line_n_length = 0.0;
2795 line_n_length += line[d] * line[d];
2798 line_n_length = sqrt(line_n_length);
2799 const MFloat F1BLine_n_length = 1.0 / line_n_length;
2803 line[d] = (line_n_length + radius) * line[d] * F1BLine_n_length;
2806 normal[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
2807 normal[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
2808 normal[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
2810 MFloat n_length_sq = 0.0;
2812 n_length_sq += normal[d] * normal[d];
2816 const MFloat n_length = sqrt(n_length_sq);
2817 const MFloat F1BN_length = 1.0 / n_length;
2819 normal_norm[d] = normal[d] * F1BN_length;
2820 line_norm[d] = line[d] * F1BLine_n_length;
2826 const MFloat denom = (normal_norm[0] * line_norm[0] + normal_norm[1] * line_norm[1] + normal_norm[2] * line_norm[2]);
2829 if(fabs(denom) < eps) {
2831 MFloat dot1 = trans_p1[0] * normal_norm[0] + trans_p1[1] * normal_norm[1] + trans_p1[2] * normal_norm[2];
2832 MFloat dot2 = trans_p2[0] * normal_norm[0] + trans_p2[1] * normal_norm[1] + trans_p2[2] * normal_norm[2];
2833 if(fabs(dot1) < eps && fabs(dot2) < eps) {
2838 if(normal_norm[d] > max) l_dim = d;
2841 const std::array<const MFloat*, 3> verts = {v1, v2, v3};
2843 MFloat line2d[2] = {0.0, 0.0};
2844 MFloat pl_1[2] = {0.0, 0.0};
2845 for(
MInt i = 0, j = 0; i <
nDim; i++) {
2847 line2d[j] = p2[i] - p1[i];
2854 MFloat shortest = 10000000000.0;
2859 MFloat tri_edge[2] = {0.0, 0.0};
2860 MFloat tri_v1[2] = {0.0, 0.0};
2862 for(
MInt i = 0, j = 0; i <
nDim; i++) {
2864 tri_edge[j] = verts[next][i] - verts[d][i];
2865 tri_v1[j] = verts[d][i];
2870 MFloat denom2 = tri_edge[1] * line2d[0];
2871 if(fabs(denom2) < eps)
continue;
2873 MFloat denom3 = 1.0 - (line2d[1] * tri_edge[0] / denom2);
2874 if(fabs(denom3) < eps)
continue;
2877 denom3 * (1.0 / line2d[0]) * (tri_v1[0] - pl_1[0] + (tri_edge[0] / tri_edge[1]) * (pl_1[1] - tri_v1[1]));
2880 if(alpha <= 1.0 && alpha >= 0.0) {
2881 MFloat beta = pl_1[1] / tri_edge[1] + alpha * line2d[1] / tri_edge[1] - tri_v1[1] / tri_edge[1];
2882 if(beta <= 1.0 && beta >= 0.0) {
2883 MFloat l = sqrt(alpha * alpha * line2d[0] * line2d[0] + alpha * alpha * line2d[1] * line2d[1]);
2884 if(l < shortest) shortest = l;
2910 (-normal_norm[0] * trans_p1[0] - normal_norm[1] * trans_p1[1] - normal_norm[2] * trans_p1[2]) / denom;
2913 std::array<MFloat, nDim> i_v1{};
2914 std::array<MFloat, nDim> i_v2{};
2915 std::array<MFloat, nDim> i_v3{};
2918 intersection[d] = p1[d] + r * line_norm[d];
2919 i_v1[d] = intersection[d] - v2[d];
2920 i_v2[d] = intersection[d] - v3[d];
2921 i_v3[d] = intersection[d] - v1[d];
2927 *lambda2 = r * F1BLine_n_length;
2932 if(fabs(*lambda2) > 1.0)
return false;
2934 std::array<MFloat, nDim> normal1;
2935 std::array<MFloat, nDim> normal2;
2936 std::array<MFloat, nDim> normal3;
2938 normal1[0] = edge3[1] * i_v1[2] - i_v1[1] * edge3[2];
2939 normal1[1] = edge3[2] * i_v1[0] - i_v1[2] * edge3[0];
2940 normal1[2] = edge3[0] * i_v1[1] - i_v1[0] * edge3[1];
2942 normal2[0] = -edge2[1] * i_v2[2] + i_v2[1] * edge2[2];
2943 normal2[1] = -edge2[2] * i_v2[0] + i_v2[2] * edge2[0];
2944 normal2[2] = -edge2[0] * i_v2[1] + i_v2[0] * edge2[1];
2946 normal3[0] = edge1[1] * i_v3[2] - i_v3[1] * edge1[2];
2947 normal3[1] = edge1[2] * i_v3[0] - i_v3[2] * edge1[0];
2948 normal3[2] = edge1[0] * i_v3[1] - i_v3[0] * edge1[1];
2953 alpha = beta = gamma = 0.0;
2956 alpha += normal[d] * normal1[d];
2957 beta += normal[d] * normal2[d];
2958 gamma += normal[d] * normal3[d];
2961 alpha /= n_length_sq;
2962 beta /= n_length_sq;
2963 gamma /= n_length_sq;
2966 if((alpha + beta + gamma <= 1.0 + eps2) && (alpha + beta + gamma >= 1.0 - eps2))
2967 if(alpha >= 0 && beta >= 0 && gamma >= 0)
2990 std::vector<MInt>& nodeList) {
2995 MBool singleIntersectionPoint = 0;
2996 MInt noReallyIntersectingNodes = 0;
2997 m_adt->retrieveNodes(targetRegion, nodeList);
2998 const MInt noNodes = nodeList.size();
2999 MInt maxNoNodes = 120;
3003 array<MFloat, nDim> e1{};
3004 array<MFloat, nDim> e2{};
3005 MFloat epsilon = 0.00000000001;
3006 array<MFloat, nDim>
a{};
3007 array<MFloat, nDim>
b{};
3008 array<MFloat, nDim> c{};
3013 array<MFloat, nDim> pP{};
3014 auto** temp =
new MFloat*[maxNoNodes];
3015 for(
MInt k = 0; k < maxNoNodes; k++) {
3020 e1[i] = targetRegion[i];
3021 e2[i] = targetRegion[i +
nDim];
3023 spaceId = spaceDirection[0];
3024 spaceId1 = spaceDirection[1];
3025 spaceId2 = spaceDirection[2];
3027 for(
MInt n = 0; n < noNodes; n++) {
3029 a[k] =
elements[nodeList[n]].m_vertices[0][k];
3030 b[k] =
elements[nodeList[n]].m_vertices[1][k];
3031 c[k] =
elements[nodeList[n]].m_vertices[2][k];
3033 if(
approx(
a[spaceId1],
b[spaceId1], MFloatEps) && !
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
3035 q = (e1[spaceId1] -
a[spaceId1]) / (c[spaceId1] -
a[spaceId1]);
3036 p = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
3038 if(!
approx(
a[spaceId1],
b[spaceId1], MFloatEps) &&
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
3040 p = (e1[spaceId1] -
a[spaceId1]) / (
b[spaceId1] -
a[spaceId1]);
3041 q = (e1[spaceId] -
a[spaceId] - p * (
b[spaceId] -
a[spaceId])) / (c[spaceId] -
a[spaceId]);
3043 if(
approx(
a[spaceId],
b[spaceId], MFloatEps) && !
approx(
a[spaceId], c[spaceId], MFloatEps)) {
3045 q = (e1[spaceId] -
a[spaceId]) / (c[spaceId] -
a[spaceId]);
3046 p = (e1[spaceId1] -
a[spaceId1] - q * (c[spaceId1] -
a[spaceId1])) / (
b[spaceId1] -
a[spaceId1]);
3048 if(!
approx(
a[spaceId],
b[spaceId], MFloatEps) &&
approx(
a[spaceId], c[spaceId], MFloatEps)) {
3050 p = (e1[spaceId] -
a[spaceId]) / (
b[spaceId] -
a[spaceId]);
3051 q = (e1[spaceId1] -
a[spaceId1] - p * (
b[spaceId1] -
a[spaceId1])) / (c[spaceId1] -
a[spaceId1]);
3054 q = ((e1[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
3055 - (
b[spaceId1] -
a[spaceId1]) * (e1[spaceId] -
a[spaceId]))
3056 / ((c[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
3057 - (
b[spaceId1] -
a[spaceId1]) * (c[spaceId] -
a[spaceId]));
3058 p = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
3064 if(p * q >= 0 || p * q < 0) {
3066 gamma =
a[spaceId2] + p * (
b[spaceId2] -
a[spaceId2]) + q * (c[spaceId2] -
a[spaceId2]);
3067 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
3069 if(s < -epsilon || s > F1 + epsilon || p < -epsilon || q < -epsilon || (p + q) > F1 + epsilon) {
3071 singleIntersectionPoint =
true;
3075 pP[g] = e1[g] + s * (e2[g] - e1[g]);
3076 temp[noReallyIntersectingNodes][g] = pP[g];
3079 if(noReallyIntersectingNodes == 0) {
3080 nodeList[noReallyIntersectingNodes] = nodeList[n];
3081 noReallyIntersectingNodes++;
3083 for(
MInt f = 0; f < noReallyIntersectingNodes; f++) {
3084 if((fabs(temp[f][0] - pP[0]) < epsilon) && (fabs(temp[f][1] - pP[1]) < epsilon)
3085 && (fabs(temp[f][2] - pP[2]) < epsilon)) {
3086 singleIntersectionPoint =
false;
3090 if(singleIntersectionPoint) {
3091 nodeList[noReallyIntersectingNodes] = nodeList[n];
3092 noReallyIntersectingNodes++;
3098 nodeList.resize(noReallyIntersectingNodes);
3101 for(
MInt k = 0; k < maxNoNodes; k++) {
3108 return noReallyIntersectingNodes;
3152 const MFloat eps = 0.00000000001;
3158 constexpr MInt maxNoNodes = 20;
3159 std::vector<MFloat> ips{};
3160 ips.reserve(
nDim * maxNoNodes);
3162 m_adt->retrieveNodes(targetRegion, nodeList);
3163 const MInt noNodes = nodeList.size();
3167 e1[i] = targetRegion[i];
3168 ray[i] = targetRegion[i +
nDim] - e1[i];
3171 MInt noReallyIntersectingNodes = 0;
3172 for(
MInt n = 0; n < noNodes; n++) {
3173 const MInt nodeId = nodeList[n];
3175 const MFloat*
const vert0 = verts[0];
3176 const MFloat*
const vert1 = verts[1];
3177 const MFloat*
const vert2 = verts[2];
3181 const MFloat v0 = vert0[i];
3182 u[i] = vert1[i] - v0;
3183 v[i] = vert2[i] - v0;
3188 const MFloat normal0 = u[1] * v[2] - u[2] * v[1];
3189 const MFloat normal1 = u[2] * v[0] - u[0] * v[2];
3190 const MFloat normal2 = u[0] * v[1] - u[1] * v[0];
3193 const MFloat a = -(normal0 * w[0] + normal1 * w[1] + normal2 * w[2]);
3194 const MFloat b = normal0 * ray[0] + normal1 * ray[1] + normal2 * ray[2];
3203 m_log <<
"Found ray in triangle plane" << endl;
3212 const MFloat F1eps = F1 + eps;
3214 if(r < -eps || r > F1eps)
continue;
3217 const MFloat uu = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
3218 const MFloat uv = u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
3219 const MFloat vv = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
3226 ip[i] = e1[i] + r * ray[i];
3227 const MFloat tmp = ip[i] - vert0[i];
3232 const MFloat D = uv * uv - uu * vv;
3234 const MFloat s = (uv * wv - vv * wu) / D;
3235 if(s < -eps || s > F1eps)
3239 const MFloat t = (uv * wu - uu * wv) / D;
3240 if(t < -eps || (s + t) > F1eps)
3246 if(noReallyIntersectingNodes == 0) {
3247 ASSERT(ips.empty(),
"ips not empty");
3249 ips.push_back(ip[i]);
3251 nodeList[noReallyIntersectingNodes] = nodeList[n];
3252 noReallyIntersectingNodes++;
3254 MBool singleIntersectionPoint =
true;
3255 for(
MInt f = 0; f < noReallyIntersectingNodes; f++) {
3256 if((fabs(ips[f *
nDim] - ip[0]) < eps) && (fabs(ips[f *
nDim + 1] - ip[1]) < eps)
3257 && (fabs(ips[f *
nDim + 2] - ip[2]) < eps)) {
3258 singleIntersectionPoint =
false;
3263 if(singleIntersectionPoint) {
3265 ips.push_back(ip[i]);
3267 nodeList[noReallyIntersectingNodes] = nodeList[n];
3268 noReallyIntersectingNodes++;
3269 ASSERT(ips.size() == (
MUlong)(noReallyIntersectingNodes *
nDim),
3270 "Error: wrong vector size of ips. " + std::to_string(ips.size())
3271 +
" != " + std::to_string(noReallyIntersectingNodes *
nDim));
3276 nodeList.resize(noReallyIntersectingNodes);
3280 return noReallyIntersectingNodes;
3286 TERMM(1,
"should not be used anymore");
3290 const MFloat eps = 0.00000000001;
3300 u[i] = v[i] = w[i] = numeric_limits<MFloat>::max();
3303 stack<MFloat*> allIPs;
3317 MInt noReallyIntersectingNodes = 0;
3319 std::vector<MInt> nodeList;
3321 MInt maxNoNodes = 30;
3322 auto** tmp =
new MFloat*[maxNoNodes];
3323 for(
MInt k = 0; k < maxNoNodes; k++) {
3326 MBool singleIntersectionPoint;
3328 m_adt->retrieveNodes(targetRegion, nodeList);
3329 const MInt noNodes = nodeList.size();
3334 e1[i] = targetRegion[i];
3335 e2[i] = targetRegion[i +
nDim];
3336 ray[i] = e2[i] - e1[i];
3339 for(
MInt n = 0; n < noNodes; n++) {
3341 a =
b = uu = uv = vv = wu = wv = 0.0;
3345 u[i] =
elements[nodeList[n]].m_vertices[1][i] -
elements[nodeList[n]].m_vertices[0][i];
3346 v[i] =
elements[nodeList[n]].m_vertices[2][i] -
elements[nodeList[n]].m_vertices[0][i];
3347 w[i] = e1[i] -
elements[nodeList[n]].m_vertices[0][i];
3351 normal[0] = u[1] * v[2] - u[2] * v[1];
3352 normal[1] = u[2] * v[0] - u[0] * v[2];
3353 normal[2] = u[0] * v[1] - u[1] * v[0];
3357 a += normal[i] * w[i];
3358 b += normal[i] * ray[i];
3365 nodeList[noReallyIntersectingNodes] = nodeList[n];
3367 m_log <<
"Found ray in triangle plane" << endl;
3376 if(r < -eps || r > F1 + eps)
continue;
3382 ip[i] = e1[i] + r * ray[i];
3386 w[i] = ip[i] -
elements[nodeList[n]].m_vertices[0][i];
3391 D = uv * uv - uu * vv;
3393 s = (uv * wv - vv * wu) / D;
3394 if(s < -eps || s > F1 + eps)
3397 t = (uv * wu - uu * wv) / D;
3398 if(t < -eps || (s + t) > F1 + eps)
3405 singleIntersectionPoint =
true;
3407 if(noReallyIntersectingNodes == 0) {
3409 tmp[noReallyIntersectingNodes][i] = ip[i];
3411 nodeList[noReallyIntersectingNodes] = nodeList[n];
3412 allIPs.push(tmp[noReallyIntersectingNodes]);
3414 noReallyIntersectingNodes++;
3416 for(
MInt f = 0; f < noReallyIntersectingNodes; f++) {
3417 if((fabs(tmp[f][0] - ip[0]) < eps) && (fabs(tmp[f][1] - ip[1]) < eps) && (fabs(tmp[f][2] - ip[2]) < eps)) {
3418 singleIntersectionPoint =
false;
3424 if(singleIntersectionPoint) {
3426 tmp[noReallyIntersectingNodes][i] = ip[i];
3428 nodeList[noReallyIntersectingNodes] = nodeList[n];
3429 noReallyIntersectingNodes++;
3437 nodeList.resize(noReallyIntersectingNodes);
3440 for(
MInt k = 0; k < maxNoNodes; k++) {
3449 return noReallyIntersectingNodes;
3462 *
dist = 100000000000.0;
3466 MFloat eps = 0.00000000001;
3476 ip[i] = w[i] = u[i] = v[i] = numeric_limits<MFloat>::max();
3480 MFloat D, uu, uv, vv, wu, wv;
3483 MInt noReallyIntersectingNodes = 0;
3486 MInt maxNoNodes = 30;
3488 for(
MInt k = 0; k < maxNoNodes; k++) {
3491 MBool singleIntersectionPoint;
3495 e1[i] = targetRegion[i];
3496 e2[i] = targetRegion[i +
nDim];
3497 ray[i] = e2[i] - e1[i];
3500 for(
MInt n = 0; n < (signed)nodeList.size(); n++) {
3501 if(
elements[nodeList[n]].m_bndCndId != bndCndId)
continue;
3506 a =
b = uu = uv = vv = wu = wv = 0.0;
3510 u[i] =
elements[nodeList[n]].m_vertices[1][i] -
elements[nodeList[n]].m_vertices[0][i];
3511 v[i] =
elements[nodeList[n]].m_vertices[2][i] -
elements[nodeList[n]].m_vertices[0][i];
3512 w[i] = e1[i] -
elements[nodeList[n]].m_vertices[0][i];
3516 normal[0] = u[1] * v[2] - u[2] * v[1];
3517 normal[1] = u[2] * v[0] - u[0] * v[2];
3518 normal[2] = u[0] * v[1] - u[1] * v[0];
3522 a += normal[i] * w[i];
3523 b += normal[i] * ray[i];
3531 noReallyIntersectingNodes++;
3541 if(r < -eps || r > F1 + eps)
continue;
3545 ip[i] = e1[i] + r * ray[i];
3549 w[i] = ip[i] -
elements[nodeList[n]].m_vertices[0][i];
3554 D = uv * uv - uu * vv;
3556 s = (uv * wv - vv * wu) / D;
3557 if(s < -eps || s > F1 + eps)
3560 t = (uv * wu - uu * wv) / D;
3561 if(t < -eps || (s + t) > F1 + eps)
3567 singleIntersectionPoint =
true;
3569 if(noReallyIntersectingNodes == 0) {
3571 tmp[noReallyIntersectingNodes][i] = ip[i];
3572 noReallyIntersectingNodes++;
3577 for(
MInt dim = 0; dim <
nDim; dim++)
3578 tmp_length += (r * ray[dim]) * (r * ray[dim]);
3580 tmp_length = sqrt(tmp_length);
3582 if(tmp_length < *
dist) *
dist = tmp_length;
3586 for(
MInt f = 0; f < noReallyIntersectingNodes; f++) {
3587 if((fabs(tmp[f][0] - ip[0]) < eps) && (fabs(tmp[f][1] - ip[1]) < eps) && (fabs(tmp[f][2] - ip[2]) < eps)) {
3588 singleIntersectionPoint =
false;
3592 if(singleIntersectionPoint) {
3594 tmp[noReallyIntersectingNodes][i] = ip[i];
3595 noReallyIntersectingNodes++;
3601 for(
MInt dim = 0; dim <
nDim; dim++)
3602 tmp_length += (r * ray[dim]) * (r * ray[dim]);
3604 tmp_length = sqrt(tmp_length);
3607 if(tmp_length < *
dist) *
dist = tmp_length;
3615 for(
MInt k = 0; k < maxNoNodes; k++) {
3632 MInt noReallyIntersectingNodes = 0;
3635 bitset<6> points[3];
3636 bitset<6> faceCodes[6];
3641 MInt edges[3][2] = {{0, 1}, {1, 2}, {0, 2}};
3645 MInt targetPoints[8][3] = {{0, 1, 2}, {3, 1, 2}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}, {3, 1, 5}, {0, 4, 5}, {3, 4, 5}};
3648 MInt targetEdges[12][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7},
3649 {0, 2}, {1, 3}, {4, 6}, {5, 7},
3650 {0, 4}, {1, 5}, {2, 6}, {3, 7}};
3654 MBool piercePointInside;
3655 MBool triviallyAccepted;
3663 MInt pointAInPlane[6][3] = {{0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}};
3665 MInt pointBInPlane[6][3] = {{0, 4, 2}, {3, 1, 5}, {3, 1, 2}, {0, 4, 5}, {3, 1, 2}, {3, 1, 5}};
3667 MInt pointCInPlane[6][3] = {{0, 1, 5}, {3, 4, 2}, {3, 1, 5}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}};
3671 MFloat d[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3672 numeric_limits<MFloat>::max()};
3673 MFloat e[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3674 numeric_limits<MFloat>::max()};
3679 MFloat epsilon = 0.00000000001;
3681 faceCodes[0] =
IPOW2(0);
3682 faceCodes[1] =
IPOW2(1);
3683 faceCodes[2] =
IPOW2(2);
3684 faceCodes[3] =
IPOW2(3);
3685 faceCodes[4] =
IPOW2(4);
3686 faceCodes[5] =
IPOW2(5);
3694 m_adt->retrieveNodesMBElements(targetRegion, nodeList);
3695 const MInt noNodes = nodeList.size();
3697 noReallyIntersectingNodes = 0;
3699 for(
MInt n = 0; n < noNodes; n++) {
3708 if(
mbelements[nodeList[n]].m_vertices[p][j] < targetRegion[j]) {
3709 points[p] |= faceCodes[2 * j];
3711 if(
mbelements[nodeList[n]].m_vertices[p][j] > targetRegion[j +
nDim]) {
3712 points[p] |= faceCodes[2 * j + 1];
3719 for(
auto& edge : edges) {
3720 if((points[edge[0]] & points[edge[1]]) != 0) {
3724 triviallyAccepted =
false;
3726 if(points[k] == 0) {
3727 triviallyAccepted =
true;
3731 if(triviallyAccepted) {
3747 result = (points[edge[0]] | points[edge[1]]);
3748 piercePointInside =
false;
3749 for(
MInt j = 0; j < 2 *
nDim; j++) {
3750 if(result[j] == 1) {
3756 a[k] = targetRegion[pointAInPlane[j][k]];
3757 b[k] = targetRegion[pointBInPlane[j][k]];
3758 c[k] = targetRegion[pointCInPlane[j][k]];
3759 d[k] =
mbelements[nodeList[n]].m_vertices[edge[0]][k];
3760 e[k] =
mbelements[nodeList[n]].m_vertices[edge[1]][k];
3762 gamma = ((e[0] - d[0]) * ((
a[2] - c[2]) * (c[1] -
b[1]) - (
a[1] - c[1]) * (c[2] -
b[2]))
3763 - (e[1] - d[1]) * ((
a[2] - c[2]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[2] -
b[2]))
3764 + (e[2] - d[2]) * ((
a[1] - c[1]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[1] -
b[1])));
3766 s = ((c[0] - d[0]) * ((
a[2] - c[2]) * (c[1] -
b[1]) - (
a[1] - c[1]) * (c[2] -
b[2]))
3767 - (c[1] - d[1]) * ((
a[2] - c[2]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[2] -
b[2]))
3768 + (c[2] - d[2]) * ((
a[1] - c[1]) * (c[0] -
b[0]) - (
a[0] - c[0]) * (c[1] -
b[1])))
3773 pP[k] = d[k] + s * (e[k] - d[k]);
3778 if(pP[k] < targetRegion[k]) {
3779 pCode |= faceCodes[2 * k];
3781 if(pP[k] > targetRegion[k +
nDim]) {
3782 pCode |= faceCodes[2 * k + 1];
3791 result = faceCodes[j];
3793 result = (result & pCode);
3795 piercePointInside =
true;
3799 if(!piercePointInside) {
3805 result = (points[0] | points[1] | points[2]);
3807 nodeList[noReallyIntersectingNodes] = nodeList[n];
3808 noReallyIntersectingNodes++;
3814 nodeList[noReallyIntersectingNodes] = nodeList[n];
3815 noReallyIntersectingNodes++;
3824 if(rejection >= 3) {
3825 for(
MInt t = 0; t < 12; t++) {
3827 e1[p] = targetRegion[targetPoints[targetEdges[t][0]][p]];
3828 e2[p] = targetRegion[targetPoints[targetEdges[t][1]][p]];
3836 if(t > 3 && t < 8) {
3850 c[k] =
mbelements[nodeList[n]].m_vertices[2][k];
3852 if(
approx(
a[spaceId1],
b[spaceId1], MFloatEps) && !
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
3854 q = (e1[spaceId1] -
a[spaceId1]) / (c[spaceId1] -
a[spaceId1]);
3855 p2 = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
3857 if(!
approx(
a[spaceId1],
b[spaceId1], MFloatEps) &&
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
3859 p2 = (e1[spaceId1] -
a[spaceId1]) / (
b[spaceId1] -
a[spaceId1]);
3860 q = (e1[spaceId] -
a[spaceId] - p2 * (
b[spaceId] -
a[spaceId])) / (c[spaceId] -
a[spaceId]);
3862 if(
approx(
a[spaceId],
b[spaceId], MFloatEps) && !
approx(
a[spaceId], c[spaceId], MFloatEps)) {
3864 q = (e1[spaceId] -
a[spaceId]) / (c[spaceId] -
a[spaceId]);
3865 p2 = (e1[spaceId1] -
a[spaceId1] - q * (c[spaceId1] -
a[spaceId1])) / (
b[spaceId1] -
a[spaceId1]);
3867 if(!
approx(
a[spaceId],
b[spaceId], MFloatEps) &&
approx(
a[spaceId], c[spaceId], MFloatEps)) {
3869 p2 = (e1[spaceId] -
a[spaceId]) / (
b[spaceId] -
a[spaceId]);
3870 q = (e1[spaceId1] -
a[spaceId1] - p2 * (
b[spaceId1] -
a[spaceId1])) / (c[spaceId1] -
a[spaceId1]);
3873 q = ((e1[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
3874 - (
b[spaceId1] -
a[spaceId1]) * (e1[spaceId] -
a[spaceId]))
3875 / ((c[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
3876 - (
b[spaceId1] -
a[spaceId1]) * (c[spaceId] -
a[spaceId]));
3877 p2 = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
3883 if(p2 * q >= 0 || p2 * q < 0) {
3885 gamma =
a[spaceId2] + p2 * (
b[spaceId2] -
a[spaceId2]) + q * (c[spaceId2] -
a[spaceId2]);
3886 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
3888 if(s < -epsilon || s > F1 + epsilon || p2 < -epsilon || q < -epsilon || (p2 + q) > F1 + epsilon) {
3894 nodeList[noReallyIntersectingNodes] = nodeList[n];
3895 noReallyIntersectingNodes++;
3905 if(noNodes && !noReallyIntersectingNodes) {
3908 nodeList.resize(noReallyIntersectingNodes);
3910 return noReallyIntersectingNodes;
3919 MInt noReallyIntersectingNodes = 0;
3922 MFloat target[6] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3923 numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3924 numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max()};
3925 MFloat enlargeFactor = 1.05;
3927 target[i] = P[i] - radius * enlargeFactor;
3928 target[i +
nDim] = P[i] + radius * enlargeFactor;
3932 m_adt->retrieveNodesMBElements(target, nodeList);
3933 const MInt noNodes = nodeList.size();
3935 MFloat A[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3936 numeric_limits<MFloat>::max()};
3937 MFloat B[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3938 numeric_limits<MFloat>::max()};
3939 MFloat C[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3940 numeric_limits<MFloat>::max()};
3941 MFloat AB[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3942 numeric_limits<MFloat>::max()};
3943 MFloat BC[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3944 numeric_limits<MFloat>::max()};
3945 MFloat CA[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3946 numeric_limits<MFloat>::max()};
3947 MFloat V[3], Q1[3], Q2[3], Q3[3], QC[3], QA[3], QB[3];
3950 for(
MInt n = 0; n < noNodes; n++) {
3953 A[i] =
mbelements[nodeList[n]].m_vertices[0][i];
3954 B[i] =
mbelements[nodeList[n]].m_vertices[1][i];
3955 C[i] =
mbelements[nodeList[n]].m_vertices[2][i];
3963 AB[i] = B[i] - A[i];
3964 BC[i] = C[i] - B[i];
3965 CA[i] = A[i] - C[i];
3967 V[0] = -AB[1] * CA[2] + AB[2] * CA[1];
3968 V[1] = -AB[2] * CA[0] + AB[0] * CA[2];
3969 V[2] = -AB[0] * CA[1] + AB[1] * CA[0];
3970 MFloat rr = radius * radius;
3991 e1 += AB[i] * AB[i];
3992 e2 += BC[i] * BC[i];
3993 e3 += CA[i] * CA[i];
3995 MBool sep1 = d * d > rr * e;
3996 MBool sep2 = (aa > rr) && (ab > aa) && (ac > aa);
3997 MBool sep3 = (bb > rr) && (ab > bb) && (bc > bb);
3998 MBool sep4 = (cc > rr) && (ac > cc) && (bc > cc);
4009 Q1[i] = A[i] * e1 - d1 * AB[i];
4010 Q2[i] = B[i] * e2 - d2 * BC[i];
4011 Q3[i] = C[i] * e3 - d3 * CA[i];
4012 QC[i] = C[i] * e1 - Q1[i];
4013 QA[i] = A[i] * e2 - Q2[i];
4014 QB[i] = B[i] * e3 - Q3[i];
4015 qq1 += Q1[i] * Q1[i];
4016 qq2 += Q2[i] * Q2[i];
4017 qq3 += Q3[i] * Q3[i];
4018 qq1c += Q1[i] * QC[i];
4019 qq2a += Q2[i] * QA[i];
4020 qq3b += Q3[i] * QB[i];
4022 MBool sep5 = (qq1 > rr * e1 * e1) && (qq1c > 0);
4023 MBool sep6 = (qq2 > rr * e2 * e2) && (qq2a > 0);
4024 MBool sep7 = (qq3 > rr * e3 * e3) && (qq3b > 0);
4026 MBool separated = sep1 || sep2 || sep3 || sep4 || sep5 || sep6 || sep7;
4029 nodeList[noReallyIntersectingNodes] = nodeList[n];
4030 noReallyIntersectingNodes++;
4033 nodeList.resize(noReallyIntersectingNodes);
4035 return noReallyIntersectingNodes;
4045 MInt noReallyIntersectingNodes = 0;
4046 m_adt->retrieveNodes(targetRegion, nodeList);
4047 const MInt noNodes = nodeList.size();
4050 e1[i] = targetRegion[i];
4051 e2[i] = targetRegion[i +
nDim];
4054 for(
MInt n = 0; n < noNodes; n++) {
4057 mbelements[nodeList[n]].m_vertices[2], e1, e2)) {
4058 nodeList[noReallyIntersectingNodes] = nodeList[n];
4059 noReallyIntersectingNodes++;
4062 nodeList.resize(noReallyIntersectingNodes);
4064 return noReallyIntersectingNodes;
4075 MBool singleIntersectionPoint;
4076 MInt noReallyIntersectingNodes = 0;
4077 m_adt->retrieveNodesMBElements(targetRegion, nodeList);
4078 const MInt noNodes = nodeList.size();
4080 MInt maxNoNodes = noNodes;
4081 MInt spaceId, spaceId1, spaceId2;
4084 MFloat epsilon = 0.00000000001;
4091 for(
MInt k = 0; k < maxNoNodes; k++) {
4096 e1[i] = targetRegion[i];
4097 e2[i] = targetRegion[i +
nDim];
4099 spaceId = spaceDirection[0];
4100 spaceId1 = spaceDirection[1];
4101 spaceId2 = spaceDirection[2];
4103 for(
MInt n = 0; n < noNodes; n++) {
4104 if(
mbelements[nodeList[n]].m_bndCndId != bcId)
continue;
4108 c[k] =
mbelements[nodeList[n]].m_vertices[2][k];
4110 if(
approx(
a[spaceId1],
b[spaceId1], MFloatEps) && !
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
4112 q = (e1[spaceId1] -
a[spaceId1]) / (c[spaceId1] -
a[spaceId1]);
4113 p = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
4115 if(!
approx(
a[spaceId1],
b[spaceId1], MFloatEps) &&
approx(
a[spaceId1], c[spaceId1], MFloatEps)) {
4117 p = (e1[spaceId1] -
a[spaceId1]) / (
b[spaceId1] -
a[spaceId1]);
4118 q = (e1[spaceId] -
a[spaceId] - p * (
b[spaceId] -
a[spaceId])) / (c[spaceId] -
a[spaceId]);
4120 if(
approx(
a[spaceId],
b[spaceId], MFloatEps) && !
approx(
a[spaceId], c[spaceId], MFloatEps)) {
4122 q = (e1[spaceId] -
a[spaceId]) / (c[spaceId] -
a[spaceId]);
4123 p = (e1[spaceId1] -
a[spaceId1] - q * (c[spaceId1] -
a[spaceId1])) / (
b[spaceId1] -
a[spaceId1]);
4125 if(!
approx(
a[spaceId],
b[spaceId], MFloatEps) &&
approx(
a[spaceId], c[spaceId], MFloatEps)) {
4127 p = (e1[spaceId] -
a[spaceId]) / (
b[spaceId] -
a[spaceId]);
4128 q = (e1[spaceId1] -
a[spaceId1] - p * (
b[spaceId1] -
a[spaceId1])) / (c[spaceId1] -
a[spaceId1]);
4131 q = ((e1[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
4132 - (
b[spaceId1] -
a[spaceId1]) * (e1[spaceId] -
a[spaceId]))
4133 / ((c[spaceId1] -
a[spaceId1]) * (
b[spaceId] -
a[spaceId])
4134 - (
b[spaceId1] -
a[spaceId1]) * (c[spaceId] -
a[spaceId]));
4135 p = (e1[spaceId] -
a[spaceId] - q * (c[spaceId] -
a[spaceId])) / (
b[spaceId] -
a[spaceId]);
4141 if(p * q >= 0 || p * q < 0) {
4143 gamma =
a[spaceId2] + p * (
b[spaceId2] -
a[spaceId2]) + q * (c[spaceId2] -
a[spaceId2]);
4144 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
4146 if(s < -epsilon || s > F1 + epsilon || p < -epsilon || q < -epsilon || (p + q) > F1 + epsilon) {
4148 singleIntersectionPoint =
true;
4152 pP[g] = e1[g] + s * (e2[g] - e1[g]);
4153 temp[noReallyIntersectingNodes][g] = pP[g];
4156 if(noReallyIntersectingNodes == 0) {
4157 nodeList[noReallyIntersectingNodes] = nodeList[n];
4158 noReallyIntersectingNodes++;
4160 for(
MInt f = 0; f < noReallyIntersectingNodes; f++) {
4161 if((fabs(temp[f][0] - pP[0]) < epsilon) && (fabs(temp[f][1] - pP[1]) < epsilon)
4162 && (fabs(temp[f][2] - pP[2]) < epsilon)) {
4163 singleIntersectionPoint =
false;
4167 if(singleIntersectionPoint) {
4168 nodeList[noReallyIntersectingNodes] = nodeList[n];
4169 noReallyIntersectingNodes++;
4175 nodeList.resize(noReallyIntersectingNodes);
4178 for(
MInt k = 0; k < maxNoNodes; k++) {
4199 return noReallyIntersectingNodes;
4245 MFloat v1[3], v2[3], n[3], norm_n = NAN;
4250 n[0] = v1[1] * v2[2] - v2[1] * v1[2];
4251 n[1] = v1[2] * v2[0] - v2[2] * v1[0];
4252 n[2] = v1[0] * v2[1] - v2[0] * v1[1];
4287 m_adt->buildTreeMB();
4299 ofl <<
"solid PRO2STL version 1.0 part " <<
domainId() << endl;
4302 ofl <<
" facet normal";
4303 for(
MInt j = 0; j < 3; j++) {
4304 ofl <<
" " <<
elements[i].m_normal[j];
4306 ofl << endl <<
" outer loop" << endl;
4308 for(
MInt k = 0; k < 3; k++) {
4310 for(
MInt l = 0; l < 3; l++) {
4311 ofl <<
" " <<
elements[i].m_vertices[k][l];
4316 ofl <<
" endloop" << endl <<
" endfacet" << endl;
4318 ofl <<
"endsolid PRO2STL version 1.0 part " <<
domainId() << endl;
4331 ofl <<
"solid PRO2STL version 1.0 part " <<
domainId() << endl;
4333 for(
MInt i = 0; i < noNodes; i++) {
4334 ofl <<
" facet normal";
4335 for(
MInt j = 0; j < 3; j++) {
4336 ofl <<
" " <<
mbelements[nodeList[i]].m_normal[j];
4338 ofl << endl <<
" outer loop" << endl;
4340 for(
MInt k = 0; k < 3; k++) {
4342 for(
MInt l = 0; l < 3; l++) {
4343 ofl <<
" " <<
mbelements[nodeList[i]].m_vertices[k][l];
4348 ofl <<
" endloop" << endl <<
" endfacet" << endl;
4350 ofl <<
"endsolid PRO2STL version 1.0 part " <<
domainId() << endl;
4358 ParallelIo::size_type count = 0;
4367 TERMM(1,
"untested I/O method, please see comment for how to proceed");
4375 ParallelIo::size_type tempDim[2];
4376 ParallelIo::size_type tempDim3D[3];
4383 tempDim3D[2] =
nDim;
4385 parallelIo.defineArray(PIO_FLOAT,
"minMax", 2 *
nDim);
4387 parallelIo.defineArray(PIO_FLOAT,
"vertexNormal", 2, tempDim);
4389 parallelIo.defineArray(PIO_FLOAT,
"vertexCoordinates", 3, tempDim3D);
4391 parallelIo.defineArray(PIO_INT,
"boundaryConditionId",
m_noElements);
4404 for(
MInt i = 0; i < 2 *
nDim; i++) {
4408 parallelIo.setOffset(count, 0);
4409 parallelIo.writeArray(&tmp[0],
"minMax");
4412 for(
MInt j = 0; j < 3; j++) {
4413 tmp[i * 3 + j] =
elements[i].m_normal[j];
4417 parallelIo.setOffset(count, 0, 2);
4418 parallelIo.writeArray(&tmp[0],
"vertexNormal");
4421 for(
MInt j = 0; j < 3; j++) {
4422 for(
MInt k = 0; k < 3; k++) {
4423 tmp[3 * (i * 3 + j) + k] =
elements[i].m_vertices[j][k];
4428 parallelIo.setOffset(count, 0, 3);
4429 parallelIo.writeArray(&tmp[0],
"vertexCoordinates");
4435 parallelIo.setOffset(count, 0);
4436 parallelIo.writeArray(&tmpI[0],
"boundaryConditionId");
4472 ParallelIo::size_type count = 0;
4481 TERMM(1,
"untested I/O method, please see comment for how to proceed");
4484 ParallelIo::size_type noVerticesVarSize = 0;
4485 noVerticesVarSize = parallelIo.getArraySize(
"noVertices");
4487 MInt domainStartRead;
4489 MInt elementsPerDomain = noVerticesVarSize /
noDomains() + 1;
4490 domainStartRead =
domainId() * elementsPerDomain;
4500 m_log <<
"no elements in file: " << noVerticesVarSize << endl;
4502 m_log <<
"domainStartRead = " << domainStartRead << endl;
4503 m_log <<
"domainEndRead = " << domainEndRead << endl;
4513 parallelIo.setOffset(count, 0, 2);
4514 parallelIo.readArray(tmp,
"vertexNormal");
4518 for(
MInt j = 0; j < 3; j++) {
4519 elements[i].m_normal[j] = tmp[i * 3 + j];
4524 parallelIo.setOffset(count, 0, 3);
4525 parallelIo.readArray(tmp,
"vertexCoordinates");
4528 for(
MInt j = 0; j < 3; j++) {
4529 for(
MInt k = 0; k < 3; k++) {
4530 elements[i].m_vertices[j][k] = tmp[3 * (i * 3 + j) + k];
4537 parallelIo.setOffset(count, 0);
4538 parallelIo.readArray(tmpI,
"boundaryConditionId");
4541 for(
MInt j = 0; j < 3; j++) {
4547 parallelIo.setOffset(count, 0);
4548 parallelIo.readArray(tmp,
"minMax");
4549 for(
MInt i = 0; i < 2 *
nDim; i++) {
4583 vector<pair<MFloat*, MFloat*>> edges;
4595 edges.emplace_back(p1, p2);
4597 auto it = edges.begin() + del;
4624 vector<pair<MFloat*, MFloat*>> edges;
4626 for(
MInt i = 0; i < size; i++) {
4627 MInt off = keepOffsets[i];
4638 edges.emplace_back(p1, p2);
4640 auto it = edges.begin() + del;
4665 for(
auto& edge : edges) {
4666 MBool pt1_in =
true;
4667 MBool pt2_in =
true;
4669 MFloat* pcol1 = edge.first;
4670 MFloat* pcol2 = edge.second;
4673 pt1_in = pt1_in &&
approx(p1[d], pcol1[d], MFloatEps);
4678 pt1_in = pt1_in &&
approx(p1[d], pcol2[d], MFloatEps);
4682 pt2_in = pt2_in &&
approx(p2[d], pcol1[d], MFloatEps);
4687 pt2_in = pt2_in &&
approx(p2[d], pcol2[d], MFloatEps);
4690 if(pt1_in && pt2_in) {
4720 vector<pair<MFloat*, MFloat*>> tmp_edges;
4728 if(tmp_edges.size() < 2) {
4729 stringstream errorMsg;
4730 errorMsg <<
"ERROR: No boundary edges found for segment " << segmentId << endl;
4731 m_log << errorMsg.str();
4732 mTerm(1, AT_, errorMsg.str());
4736 vector<MFloat*> tmp_points;
4738 for(
MInt i = 0; i < (signed)tmp_edges.size(); i++)
4742 tmp_points.push_back(tmp_edges[0].first);
4743 tmp_points.push_back(tmp_edges[0].second);
4746 MFloat* first = tmp_points[0];
4749 for(
MInt i = 1; i < (signed)tmp_edges.size(); i++) {
4750 for(
MInt j = 1; j < (signed)tmp_edges.size(); j++) {
4752 if(visited[j])
continue;
4754 pair<MFloat*, MFloat*> edge = tmp_edges[j];
4758 tmp_points.push_back(edge.second);
4761 }
else if(
vectorsEqual(edge.second, tmp_points[cmpPos])) {
4762 tmp_points.push_back(edge.first);
4769 if(!
vectorsEqual(tmp_points[tmp_points.size() - 1], first)) {
4770 stringstream errorMsg;
4771 errorMsg <<
"ERROR: Inconsistency in segment " << segmentId << endl;
4772 m_log << errorMsg.str();
4773 mTerm(1, AT_, errorMsg.str());
4777 MFloat** vertices =
new MFloat*[tmp_points.size() - 1];
4778 for(
MInt i = 0; i < (
MInt)tmp_points.size() - 1; i++) {
4781 vertices[i][j] = tmp_points[i][j];
4784 *num = tmp_points.size() - 1;
4801 MInt offsetStart = 0;
4812 mTerm(1, AT_,
"ERROR: You cannot choose a MB segment to calculate the characteristic Length");
4816 std::array<MFloat, nDim> cross;
4817 std::array<MFloat, nDim> edge1;
4818 std::array<MFloat, nDim> edge2;
4826 cross[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
4827 cross[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
4828 cross[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
4830 area += sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]) / 2;
4851 std::array<MFloat, nDim> cross;
4852 std::array<MFloat, nDim> edge1;
4853 std::array<MFloat, nDim> edge2;
4855 for(
MInt i = 0; i < size; i++) {
4858 if(keepOffset !=
nullptr) off = keepOffset[i];
4861 edge1[j] = vertices[off +
nDim + j] - vertices[off + j];
4862 edge2[j] = vertices[off + 2 *
nDim + j] - vertices[off + j];
4865 cross[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
4866 cross[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
4867 cross[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
4869 area += sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]) / 2;
4880 m_log <<
"******************** Geometry3D statistics ********************" << endl;
4888 m_log <<
"***************************************************************" << endl;
4918 if(*firstOwner < 0) *firstOwner = d;
4919 *sumowners += owners[d];
4953 MFloat cog_tmp[3][2] = {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}};
4954 MFloat cog[3] = {0.0, 0.0, 0.0};
4956 for(
MInt i = 0; i < num; i++) {
4957 MInt next = (i + 1) % num;
4958 MFloat xy = vertices[i][0] * vertices[next][1] - vertices[next][0] * vertices[i][1];
4959 MFloat xz = vertices[i][0] * vertices[next][2] - vertices[next][0] * vertices[i][2];
4960 MFloat yz = vertices[i][1] * vertices[next][2] - vertices[next][1] * vertices[i][2];
4966 cog_tmp[0][0] += (vertices[i][0] + vertices[next][0]) * xy;
4967 cog_tmp[0][1] += (vertices[i][0] + vertices[next][0]) * xz;
4968 cog_tmp[1][0] += (vertices[i][1] + vertices[next][1]) * xy;
4969 cog_tmp[1][1] += (vertices[i][1] + vertices[next][1]) * yz;
4970 cog_tmp[2][0] += (vertices[i][2] + vertices[next][2]) * xz;
4971 cog_tmp[2][1] += (vertices[i][2] + vertices[next][2]) * yz;
4974 areaXY = fabs(areaXY) * 0.5;
4975 areaXZ = fabs(areaXZ) * 0.5;
4976 areaYZ = fabs(areaYZ) * 0.5;
4981 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
4982 cog[1] = vertices[0][1];
4983 cog[2] = 1.0 / (6.0 * areaXZ) * cog_tmp[2][0];
4984 }
else if(areaXZ < eps) {
4985 cog[0] = vertices[0][0];
4986 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
4987 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
4989 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
4990 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
4991 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
4993 }
else if(areaXZ < eps) {
4995 cog[0] = 1.0 / (6.0 * areaXY) * cog_tmp[0][0];
4996 cog[1] = 1.0 / (6.0 * areaXY) * cog_tmp[1][0];
4997 cog[2] = vertices[0][2];
4999 cog[0] = 1.0 / (6.0 * areaXY) * cog_tmp[0][0];
5000 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
5001 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
5003 }
else if(areaYZ < eps) {
5004 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
5005 cog[1] = 1.0 / (6.0 * areaXY) * cog_tmp[1][0];
5006 cog[2] = 1.0 / (6.0 * areaXZ) * cog_tmp[2][0];
5008 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
5009 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
5010 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
5013 m_log <<
" * cog: " << cog[0] <<
" " << cog[1] <<
" " << cog[2] << endl;
5017 for(
MInt i = 0; i < num; i++) {
5018 MFloat tmp = (vertices[i][0] - cog[0]) * (vertices[i][0] - cog[0])
5019 + (vertices[i][1] - cog[1]) * (vertices[i][1] - cog[1])
5020 + (vertices[i][2] - cog[2]) * (vertices[i][2] - cog[2]);
5022 if(tmp > maxRadius) maxRadius = tmp;
5025 return sqrt(maxRadius);
5072 MInt segmentId = tri[1];
5091 tris[pos].m_normal[d] = tri[j++];
5094 tris[pos].m_vertices[d1][d2] = tri[j++];
5113 tris[to].m_normal[d] = tris[from].m_normal[d];
5117 tris[to].m_vertices[d1][d2] = tris[from].m_vertices[d1][d2];
5141 toPtr[to].m_normal[d] = fromPtr[from].m_normal[d];
5145 toPtr[to].m_vertices[d1][d2] = fromPtr[from].m_vertices[d1][d2];
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
static MInt propertyLength(const MString &name, MInt solverId=m_noSolvers)
Returns the number of elements of a property.
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
virtual Collector< element< 3 > > * readSegmentsParallel()
void writeSTLMB(const char *fileName, MInt &noNodes, MInt *&nodeList) override
MBool m_GFieldInitFromSTL
virtual void readSegmentTrianglesBINARY_BE(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
reads triangles from a BINARY file and swaps to big endian
virtual void readSegmentTrianglesBINARY_LE(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
reads triangles from a BINARY file and swaps to little endian
MBool edgeTriangleIntersectionLB(MFloat *trianglePoint1, MFloat *trianglePoint2, MFloat *trianglePoint3, MFloat *edgePoint1, MFloat *edgePoint2) override
Determine intersection between an edge and a triangle.
MInt getLineIntersectionElements(MFloat *targetRegion, std::vector< MInt > &nodeList) override
Returns the ids of all elements, cut by a ray by using the perp-dot operator.
MBool m_communicateSegmentsSerial
void rebuildAdtTree() override
Rebuilds the ADT tree.
virtual Collector< element< 3 > > * readSegmentsSerial()
reads the segments in serial
MFloat GetBoundarySize(MInt segmentId) override
Returns the area of a segment.
virtual void countSegmentTrianglesBINARY(MString fileName, MInt *noElements)
counts the number of triangles in a BINARY STL file
void MoveAllMBElementVertex(MFloat *dx) override
virtual std::vector< std::pair< MFloat *, MFloat * > > GetUniqueSegmentEdges(MInt segmentId)
Returns unique edges of a given set segment id.
static constexpr const MInt nDim
MFloat ** GetBoundaryVertices(MInt segmentId, MFloat *tri_vx, MInt *keepOffsets, MInt size, MInt *num) override
This function gets all boundary vertices of an element<3> in a circular order.
void UpdateMBNormalVector(MInt e) override
Geometry3D(const MInt solverId_, const MPI_Comm comm)
virtual MInt is_big_endian()
determines the CPU type big or little endian
void collectGlobalMemoryUsage() override
MBool edgeTriangleIntersection(MFloat *trianglePoint1, MFloat *trianglePoint2, MFloat *trianglePoint3, MFloat *edgePoint1, MFloat *edgePoint2) override
Determine intersection between an edge and a triangle.
void writeADTAndSTLToNetCDF(const char *fileName) override
virtual void correctVertexCoordinates()
MInt getLineIntersectionMBElements2(MFloat *targetRegion, MInt *spaceDirection, std::vector< MInt > &nodeList, MInt bcIc) override
MBool getLineTriangleIntersection(const MFloat *const p1, const MFloat *const p2, const MFloat radius, const MFloat *const v1, const MFloat *const v2, const MFloat *const v3, MFloat *intersection, MFloat *normal, MFloat *lambda2, MFloat *dist) override
This function determines if a line crosses a triangle.
void copyElement(MInt from, MInt to) override
Copies an element<3> from one poistion to another.
MBool getLineTriangleIntersectionSimple(MFloat *p1, MFloat *p2, MFloat *v1, MFloat *v2, MFloat *v3) override
This function determines if a line crosses a triangle.
void printMemoryUsage()
prints the current memory usage of this object
MInt getLineIntersectionElementsOld2(MFloat *targetRegion, MInt *spaceDirection, std::vector< MInt > &nodeList) override
Returns the ids of all elements, cut by a orthogonal line (or rectangular region)
MInt getIntersectionElements(MFloat *targetRegion, std::vector< MInt > &nodeList, MFloat cellHalfLength, const MFloat *const cell_coords) override
Determines all elements that are inside or intersect the target region with the separating axis theor...
virtual std::vector< std::pair< MFloat *, MFloat * > > GetUniqueSegmentEdgesParGeom(MFloat *tri_vx, MInt *keepOffsets, MInt size)
Returns unique edges of a given set segment id for parallel geometry.
MInt getSphereIntersectionMBElements(MFloat *P, MFloat radius, std::vector< MInt > &nodeList) override
MBool isEdgeAlreadyInCollection(std::vector< std::pair< MFloat *, MFloat * > > tmp_edges, MFloat *p1, MFloat *p2, MInt *pos) override
Checks if an edge given by two points is in a vector.
void addElement(MFloat *tri) override
Adds an element<3> to the collector.
void logStatistics() override
virtual void countSegmentTrianglesNETCDF(MString fileName, MInt *noElements, const MPI_Comm comm)
counts the number of triangles in a NETCDF STL file
virtual void countSegmentTrianglesASCII(MString fileName, MInt *noElements)
counts the number of triangles in an ASCII STL file
MInt m_getLIE2CallCounter
void resizeCollector(MInt new_size) override
deletes the current element<3> collector and reinitializes
virtual void readSegmentTrianglesNETCDF(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset, const MPI_Comm comm)
reads triangles from a BINARY file
void readSTLNetCDF(const char *fileName) override
void writeParallelGeometryVTK(MString filename) override
Write the current geometry to a VTK file for parallel computation.
virtual void readSegmentTrianglesASCII(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
reads triangles from an ASCII file
void calculateBoundingBox() override
Calculates the global bounding box of the geometry.
virtual MInt getIntersectionElementsTetraeder(MFloat *targetRegion, std::vector< MInt > &nodeList)
Determines all elements that are inside or intersect the target region.
void ReplaceMBElementVertex(MInt e, MInt v, MFloat *np) override
MInt m_noLevelSetIntfBndIds
void UpdateMBBoundingBox() override
MBool getClosestLineIntersectionLength(MInt bndCndId, const std::vector< MInt > &nodeList, MFloat *targetRegion, MFloat *dist) override
MInt getIntersectionMBElements(MFloat *targetRegion, std::vector< MInt > &nodeList) override
MInt * m_levelSetIntfBndIds
MFloat getBndMaxRadius(MFloat **vertices, MInt num) override
This function gets the maximal radius for a boundary segment.
void UpdateADT() override
MInt getLineIntersectionMBElements(MFloat *targetRegion, std::vector< MInt > &nodeList) override
void readSegments() override
reads the STL segments from file
MBool getLineTriangleIntersectionSimpleDistance(MFloat *p1, MFloat *p2, MFloat *v1, MFloat *v2, MFloat *v3, MFloat *dist) override
This function determines if a line crosses a triangle.
virtual void swap4BytesToBE(char *buf)
swaps 4 bytes from little to big endian
void MoveMBElementVertex(MInt e, MInt v, MFloat *dx) override
void determineSegmentOwnership(MInt segmentId, MInt *own, MInt *sumowners, MInt *firstOwner, MInt *owners) override
Determines the ownership of a segment.
void writeSTL(const char *fileName) override
MBool propertyExists(MString name, MInt solver)
GeometryProperty * getProperty(const MString &name, MInt segment)
const MFloat * boundingBox() const
MString m_parallelGeomFileName
std::array< MFloat, 2 *nDim > m_minMax
std::vector< MInt > m_segmentOffsets
Collector< element< nDim > > * m_elements
element< nDim > * elements
element< nDim > * mbelements
std::vector< MInt > m_segmentOffsetsWithoutMB
void setHaloElementOffset(MInt off)
MBool vectorsEqual(MFloat *a, MFloat *b)
Compares two vectors entry by entry.
GeometryContext & geometryContext()
std::set< MInt > m_uniqueOriginalTriId
Collector< element< nDim > > * m_mbelements
std::array< MFloat, 2 *nDim > m_mbminMax
GeometryAdt< nDim > * m_adt
MInt isRunning(const MInt timerId) const
This class is a ScratchSpace.
T * getPointer() const
Deprecated: use begin() instead!
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr Real POW2(const Real x)
MBool approx(const T &, const U &, const T)
constexpr T mMax(const T &x, const T &y)
void tokenize(const std::string &str, ContainerT &tokens, const std::string &delimiters=" ", MBool trimEmpty=false)
std::vector< std::pair< MString, MInt > > g_tc_geometry
constexpr MLong IPOW2(MInt x)
constexpr MFloat FPOW2(MInt x)
std::basic_string< char > MString
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gather
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
PARALLELIO_DEFAULT_BACKEND ParallelIo
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)