Computes shortest distance to wall/fluid-porous interface, which is described by the grid as the sum of linear line elements and stores the information required to exchange interpolated data from the nearest neighbors to a cell.
1371 {
1372
1373 MFloat maxWallDistance = numeric_limits<MFloat>::max();
1374 maxWallDistance = Context::getSolverProperty<MFloat>(
"maxWallDistance",
m_solverId, AT_, &maxWallDistance);
1376 r_cells_fq_distance[
id] = maxWallDistance;
1377 }
1378
1379
1380 const MInt noWallDistInfo = wallDistInfo.size();
1381 std::vector<MInt> wallNormalIndex(noWallDistInfo);
1382 std::vector<MInt> normalDir(noWallDistInfo);
1383 std::vector<std::array<MInt, 2 * nDim>> startEndTangential(noWallDistInfo);
1384
1385 MInt cellmemSize = 0;
1386 for(
MInt nn = 0; nn < noWallDistInfo; ++nn) {
1387
1388 const MInt*
const start = wallDistInfo[nn]->start1;
1389 const MInt*
const end = wallDistInfo[nn]->end1;
1390 const MInt face = wallDistInfo[nn]->face;
1391 normalDir[nn] = face / 2;
1392 wallNormalIndex[nn] = start[normalDir[nn]];
1393
1395 for(
MInt dim = 0; dim <
nDim - 1; ++dim) {
1396 const MInt tangentialDir = (normalDir[nn] + (dim + 1)) %
nDim;
1397 startEndTangential[nn][dim * 2 + 0] = start[tangentialDir];
1398 startEndTangential[nn][dim * 2 + 1] =
1399 end[tangentialDir] + 1;
1400 size *= startEndTangential[nn][dim * 2 + 1] - startEndTangential[nn][dim * 2 + 0];
1401 }
1402 cellmemSize += size;
1403#ifndef NDEBUG
1404 cout << "Debug output: wallDistInfo=" << nn << ": face=" << face << "; normalDir=" << normalDir[nn]
1405 << "; wallNormalIndex=" << wallNormalIndex[nn] << "; startEndTangential=" << startEndTangential[nn][0] << "|"
1406 << startEndTangential[nn][1] << "normal start/end=" << start[normalDir[nn]] << "|" << end[normalDir[nn]]
1407 << endl;
1408#endif
1409 }
1410
1411
1412
1415 for(
MInt dim = 0; dim <
nDim; ++dim)
1416 wallDistSurfCoords[dim] = &coordGridMem[dim * cellmemSize];
1417
1418 MIntScratchSpace isStartEndPoint(std::max(1, cellmemSize), AT_,
"isStartEndPoint");
1419
1420
1422 for(
MInt nn = 0; nn < noWallDistInfo; ++nn) {
1424 MInt& i = (normalDir[nn] == 0) ? wallNormalIndex[nn] : tIdx;
1425 MInt& j = (normalDir[nn] == 0) ? tIdx : wallNormalIndex[nn];
1426 for(tIdx = startEndTangential[nn][0]; tIdx < startEndTangential[nn][1]; ++tIdx) {
1428 wallDistSurfCoords[0][cnt] =
m_grid->m_coordinates[0][
p];
1429 wallDistSurfCoords[1][cnt] =
m_grid->m_coordinates[1][
p];
1430
1431 if(tIdx == startEndTangential[nn][0] && tIdx == startEndTangential[nn][1] - 1)
1432 isStartEndPoint[cnt] = 3;
1433 else if(tIdx == startEndTangential[nn][0])
1434 isStartEndPoint[cnt] = 1;
1435 else if(tIdx == startEndTangential[nn][1] - 1)
1436 isStartEndPoint[cnt] = -1;
1437 else
1438 isStartEndPoint[cnt] =
1439 0;
1440 ++cnt;
1441 }
1442 }
1443
1444
1447
1448 std::vector<MInt> recvcounts(noRanks);
1450 "recvcounts");
1451 r_displs.resize(noRanks);
1452 for(
MInt r = 0; r < noRanks - 1; ++r) {
1453 r_displs[r + 1] = r_displs[r] + recvcounts[r];
1454 }
1455 const MInt noTotalWallPoints = r_displs[noRanks - 1] + recvcounts[noRanks - 1];
1456
1457 std::vector<std::vector<MFloat>> wallDistSurfCoordsAll(
nDim);
1458 for(
MInt dim = 0; dim <
nDim; ++dim) {
1459 wallDistSurfCoordsAll[dim].resize(noTotalWallPoints);
1460 MPI_Allgatherv(&wallDistSurfCoords[dim][0], cellmemSize, MPI_DOUBLE, wallDistSurfCoordsAll[dim].data(),
1462 "wallDistSurfCoords", "wallDistSurfCoordsAll");
1463 }
1464 std::vector<MInt> isStartEndPointAll(noTotalWallPoints);
1465 MPI_Allgatherv(&isStartEndPoint[0], cellmemSize, MPI_INT, isStartEndPointAll.data(), recvcounts.data(),
1467
1468 std::vector<MInt> blockIds(noRanks, -1);
1471 "blockId");
1472
1473
1474
1475
1476
1477
1478 r_cellId2globalWallId.assign(
m_noCells, std::make_pair(-1, -1));
1479
1480
1482
1483
1484
1485 if(noTotalWallPoints == 0) return;
1486
1487
1488
1489 vector<Point<3>> pts;
1490
1491 std::vector<MInt> cellIdShifts(noTotalWallPoints + 1, 0);
1492 for(
MInt globalWallId = 0; globalWallId < noTotalWallPoints; ++globalWallId) {
1493 Point<3> a(wallDistSurfCoordsAll[0][globalWallId], wallDistSurfCoordsAll[1][globalWallId], 0, globalWallId);
1495 cellIdShifts[globalWallId + 1] = cellIdShifts[globalWallId] - 1 * (isStartEndPointAll[globalWallId] == -1);
1496 }
1497
1499
1500 auto getDomainId = [&r_displs, noRanks](
const MInt id,
const MInt hint = 0) {
1501 for(
MInt rank = hint; rank < (signed)r_displs.size() - 1; ++rank) {
1502 if(r_displs[rank + 1] > id) return rank;
1503 }
1504 return noRanks - 1;
1505 };
1506
1507 static constexpr MFloat radius = std::numeric_limits<MFloat>::max();
1508 static constexpr MFloat eps = 1e-16;
1509
1510
1515 MBool overflow =
false;
1516 MInt nfound = tree.locatenearest(pt, radius, results, dists, 3, overflow);
1517 if(nfound != 3)
mTerm(1,
"Come on, your mesh should have at least 3 wall grid points!");
1518 MInt globalWallId1 = results[0];
1519 MInt globalWallId1_ = results[1];
1520 MInt globalWallId1__ = results[2];
1521
1522
1523 nfound = 1;
1524 const MFloat r2 =
POW2(wallDistSurfCoordsAll[0][globalWallId1] - wallDistSurfCoordsAll[0][globalWallId1_])
1525 +
POW2(wallDistSurfCoordsAll[1][globalWallId1] - wallDistSurfCoordsAll[1][globalWallId1_]);
1526 const MFloat r3 =
POW2(wallDistSurfCoordsAll[0][globalWallId1] - wallDistSurfCoordsAll[0][globalWallId1__])
1527 +
POW2(wallDistSurfCoordsAll[1][globalWallId1] - wallDistSurfCoordsAll[1][globalWallId1__]);
1528 nfound += r2 < eps;
1529 nfound += r3 < eps;
1530
1531
1532 if(nfound == 2 && r3 < r2) {
1533 const MInt temp = globalWallId1_;
1534 globalWallId1_ = globalWallId1__;
1535 globalWallId1__ = temp;
1536 }
1537
1538
1539 if(nfound == 2) {
1540 if(isStartEndPointAll[globalWallId1] == 3 && isStartEndPointAll[globalWallId1_] == 3)
mTerm(1,
"");
1541 if(isStartEndPointAll[globalWallId1] == 3) {
1542 globalWallId1 = globalWallId1_;
1543 nfound = 1;
1544 }
1545 if(isStartEndPointAll[globalWallId1_] == 3) {
1546 nfound = 1;
1547 }
1548 }
1549
1553
1554
1555
1556 MInt globalCellId1 = -1;
1557 MInt globalCellId2 = -1;
1559 if(nfound == 1 && abs(isStartEndPointAll[globalWallId1]) == 1) {
1560
1561 const MInt globalWallId2 = globalWallId1 + isStartEndPointAll[globalWallId1];
1562 globalCellId1 = (isStartEndPointAll[globalWallId1] == -1) ? globalWallId1 - 1 : globalWallId1;
1563 globalCellId1 += cellIdShifts[globalWallId1];
1564 const MFloat p1[
nDim] = {wallDistSurfCoordsAll[0][globalWallId1], wallDistSurfCoordsAll[1][globalWallId1]};
1565 const MFloat p2[
nDim] = {wallDistSurfCoordsAll[0][globalWallId2], wallDistSurfCoordsAll[1][globalWallId2]};
1569
1570 if(fraction > 0.5 + 1e-8) {
1571 stringstream msg;
1572 msg << "ERROR: p1=" << p1[0] << "|" << p1[1] << " p2=" << p2[0] << "|" << p2[1] << " pTarget=" << pTarget[0]
1573 <<
"|" << pTarget[1] <<
" distance=" <<
distance <<
" fraction=" << fraction << endl;
1574 cout << msg.str();
1575 mTerm(1,
"Fraction is >0.5, so nearest grid point is supposed to be p2 and not p1!");
1576 }
1577 weight = 1.0;
1578 } else {
1579
1580
1581
1584 if(nfound == 1 ) {
1585
1586 globalWallId2 = globalWallId1 - 1;
1587 globalWallId3 = globalWallId1 + 1;
1588 globalCellId1 = globalWallId2;
1589 globalCellId1 += cellIdShifts[globalWallId2];
1590 globalCellId2 = globalWallId1;
1591 globalCellId2 += cellIdShifts[globalWallId1];
1592 } else if(nfound == 2) {
1593
1594 if(abs(isStartEndPointAll[globalWallId1]) + abs(isStartEndPointAll[globalWallId1_]) != 2) {
1595
1596 const MInt blockId1 = blockIds[getDomainId(globalWallId1)];
1597 const MInt blockId1_ = blockIds[getDomainId(globalWallId1_)];
1598 if(blockId1 == blockId1_) {
1602 << wallDistSurfCoordsAll[1][globalWallId1]
1603 << "; wallCoords1_=" << wallDistSurfCoordsAll[0][globalWallId1_] << "|"
1604 << wallDistSurfCoordsAll[1][globalWallId1_]
1605 << "; wallCoords1__=" << wallDistSurfCoordsAll[0][globalWallId1__] << "|"
1606 << wallDistSurfCoordsAll[1][globalWallId1__] << endl;
1607
1608 cout << "ERROR: (x|y)_1=" << setprecision(12) << wallDistSurfCoordsAll[0][globalWallId1] << "|"
1609 << wallDistSurfCoordsAll[1][globalWallId1] << " (x|y)_2=" << wallDistSurfCoordsAll[0][globalWallId1_]
1610 << "|" << wallDistSurfCoordsAll[1][globalWallId1_] << endl;
1611 mTerm(1,
"One grid point found twice. Both grid points have neighbors to both sides, which is unexpected!");
1612 }
1613 if(blockId1 != myBlockId && blockId1_ != myBlockId)
mTerm(1,
"This case is not implemented yet!");
1614 if(blockId1_ == myBlockId) globalWallId1 = globalWallId1_;
1615
1616 globalWallId2 = globalWallId1 - 1;
1617 globalWallId3 = globalWallId1 + 1;
1618 globalCellId1 = globalWallId2;
1619 globalCellId1 += cellIdShifts[globalWallId2];
1620 globalCellId2 = globalWallId1;
1621 globalCellId2 += cellIdShifts[globalWallId1];
1622 } else {
1623 globalWallId2 = globalWallId1 + isStartEndPointAll[globalWallId1];
1624 globalWallId3 = globalWallId1_ + isStartEndPointAll[globalWallId1_];
1625 globalCellId1 = (isStartEndPointAll[globalWallId1] == -1) ? globalWallId1 - 1 : globalWallId1;
1626 globalCellId1 += cellIdShifts[globalWallId1];
1627 globalCellId2 = (isStartEndPointAll[globalWallId1_] == -1) ? globalWallId1_ - 1 : globalWallId1_;
1628 globalCellId2 += cellIdShifts[globalWallId1_];
1629 }
1630 } else {
1631
1632 stringstream msg;
1633 msg << setprecision(12) << "p1=" << wallDistSurfCoordsAll[0][globalWallId1] << "|"
1634 << wallDistSurfCoordsAll[1][globalWallId1] << ", p2=" << wallDistSurfCoordsAll[0][globalWallId1_] << "|"
1635 << wallDistSurfCoordsAll[1][globalWallId1_] << ", p3=" << wallDistSurfCoordsAll[0][globalWallId1__] << "|"
1636 << wallDistSurfCoordsAll[1][globalWallId1__] << endl;
1637 cout << msg.str();
1638 mTerm(1,
"Three wall grid points coincide. This situation is unknown!");
1639 }
1640
1641
1645 const MFloat p1[
nDim] = {wallDistSurfCoordsAll[0][globalWallId1], wallDistSurfCoordsAll[1][globalWallId1]};
1646 const MFloat p2[
nDim] = {wallDistSurfCoordsAll[0][globalWallId2], wallDistSurfCoordsAll[1][globalWallId2]};
1647 const MFloat p3[
nDim] = {wallDistSurfCoordsAll[0][globalWallId3], wallDistSurfCoordsAll[1][globalWallId3]};
1651 const MInt i = distances[1] < distances[0];
1652
1653 if(fractions[i] > 0.5 + 1e-8) {
1654 stringstream msg;
1655 msg << "Error p1=" << p1[0] << "|" << p1[1] << " p2=" << p2[0] << "|" << p2[1] << " p3=" << p3[0] << "|"
1656 << p3[1] <<
" pTarget=" << pTarget[0] <<
"|" << pTarget[1] <<
" distance=" <<
distance
1657 << " fraction=" << fractions[i] << " " << fractions[1 - i] << endl;
1658 cout << msg.str();
1659 mTerm(1,
"Fraction >0.5, so nearest grid point can not be p1!");
1660 }
1661
1662 weight = (fractions[i] * lineLengths[i] + 0.5 * lineLengths[1 - i]) / (0.5 * (lineLengths[0] + lineLengths[1]));
1664 if(i == 1) {
1665
1666 const MInt temp = globalCellId1;
1667 globalCellId1 = globalCellId2;
1668 globalCellId2 = temp;
1669 }
1670 }
1671
1672 if(distance < r_cells_fq_distance[cellId]) {
1673 ASSERT(globalCellId1 != -1, "");
1674
1675
1676 globalCellId2 = (globalCellId2 == -1) ? globalCellId1 : globalCellId2;
1677 r_cellId2globalWallId[
cellId] = std::make_pair(globalCellId1, globalCellId2);
1678 r_weighting[
cellId] = weight;
1680
1681
1682
1683 }
1684 }
1685
1686
1687 for(
MInt i = 1; i < (signed)r_displs.size(); ++i) {
1688 r_displs[i] = r_displs[i] + cellIdShifts[r_displs[i]];
1689 }
1690
1691
1692#ifndef NDEBUG
1693 MInt noNearWallCells = 0;
1694
1695
1696 std::set<MInt> globalWallIds;
1698 if(r_cellId2globalWallId[cellId].first != -1) {
1699 ++noNearWallCells;
1700 globalWallIds.insert(r_cellId2globalWallId[cellId].first);
1701 }
1702 if(r_cellId2globalWallId[cellId].second != -1) {
1703 globalWallIds.insert(r_cellId2globalWallId[cellId].second);
1704 }
1705 }
1706
1707 cout <<
"::computeDistance2Map: rank=" <<
m_solver->
domainId() <<
" cellmemSize=" << cellmemSize
1708 << " noTotalWallPoints=" << noTotalWallPoints << " #cells near wall=" << noNearWallCells
1709 << " #globalWallIds=" << globalWallIds.size() << endl;
1710#endif
1711}
MPI_Comm m_StructuredComm
MFloat shortestDistanceToLineElement(const MFloat(&)[nDim], const MFloat(&)[nDim], const MFloat(&)[nDim], MFloat &, MFloat &)
int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgatherv
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
MFloat distance(const MFloat *a, const MFloat *b)