Skip to content

Commit

Permalink
GRIDEDIT-704 Added setting of nodes outside a box to invalid.
Browse files Browse the repository at this point in the history
  • Loading branch information
BillSenior committed Oct 9, 2023
1 parent 19af3c4 commit 57f68d4
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ namespace meshkernel
/// @note If any index is the null value or is out of range a ConstraintError will be thrown
void DeleteInterior(const CurvilinearGridNodeIndices& firstNode, const CurvilinearGridNodeIndices& secondNode);

/// @brief Set all the nodes oustide of the block to be invalid.

Check failure on line 213 in libs/MeshKernel/include/MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp

View workflow job for this annotation

GitHub Actions / check

oustide ==> outside
/// @note If any index is the null value or is out of range a ConstraintError will be thrown
void DeleteExterior(const CurvilinearGridNodeIndices& firstNode, const CurvilinearGridNodeIndices& secondNode);

/// @brief Moves a node from one position to another
/// @param[in] fromPoint The input position, the closest node will be used
/// @param[in] toPoint The coordinates of the new position
Expand Down
63 changes: 63 additions & 0 deletions libs/MeshKernel/src/CurvilinearGrid/CurvilinearGrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,69 @@ void CurvilinearGrid::DeleteInterior(const CurvilinearGridNodeIndices& firstNode
}
}

void CurvilinearGrid::DeleteExterior(const CurvilinearGridNodeIndices& firstNode, const CurvilinearGridNodeIndices& secondNode)
{

if (!firstNode.IsValid() || !secondNode.IsValid())
{
throw ConstraintError("Invalid index: first index - {{{}, {}}}, second index - {{{}, {}}}", firstNode.m_m, firstNode.m_n, secondNode.m_m, secondNode.m_n);
}

if (firstNode.m_m >= m_numM || firstNode.m_n >= m_numN)
{
throw ConstraintError("Invalid index: first index {{{}, {}}} not in mesh limits {{{}, {}}}", firstNode.m_m, firstNode.m_n, m_numM, m_numN);
}

if (secondNode.m_m >= m_numM || secondNode.m_n >= m_numN)
{
throw ConstraintError("Invalid index: second index {{{}, {}}} not in mesh limits {{{}, {}}}", secondNode.m_m, secondNode.m_n, m_numM, m_numN);
}

UInt lowerLimitI = std::min(firstNode.m_n, secondNode.m_n);
UInt upperLimitI = std::max(firstNode.m_n, secondNode.m_n);

UInt lowerLimitJ = std::min(firstNode.m_m, secondNode.m_m);
UInt upperLimitJ = std::max(firstNode.m_m, secondNode.m_m);

// Split into 4 regions, setting the nodes in each region to invalid
//
// First region: all nodes "south" the designated box
for (UInt n = 0; n < m_numN; ++n)
{
for (UInt m = 0; m < lowerLimitJ; ++m)
{
m_gridNodes(n, m).SetInvalid();
}
}

// Second region: all nodes "directly west of" the designated box
for (UInt n = 0; n < lowerLimitI; ++n)
{
for (UInt m = lowerLimitJ; m <= upperLimitJ; ++m)
{
m_gridNodes(n, m).SetInvalid();
}
}

// Third region: all nodes "directly east of" the designated box
for (UInt n = upperLimitI + 1; n < m_numN; ++n)
{
for (UInt m = lowerLimitJ; m <= upperLimitJ; ++m)
{
m_gridNodes(n, m).SetInvalid();
}
}

// Fourth region: all nodes "north" the designated box
for (UInt n = 0; n < m_numN; ++n)
{
for (UInt m = upperLimitJ + 1; m < m_numM; ++m)
{
m_gridNodes(n, m).SetInvalid();
}
}
}

void CurvilinearGrid::MoveNode(Point const& fromPoint, Point const& toPoint)
{
// Get the node indices of fromPoint
Expand Down
110 changes: 110 additions & 0 deletions libs/MeshKernel/tests/src/CurvilinearUniformTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,113 @@ TEST(CurvilinearGridUniform, DeleteInteriorNodesFailureTest)
EXPECT_THROW(curvilinearGrid->DeleteInterior({1, 1}, {nx, ny}), meshkernel::ConstraintError);
EXPECT_THROW(curvilinearGrid->DeleteInterior({nx, 1}, {4, 4}), meshkernel::ConstraintError);
}

void TestDeleteExteriorNodes(std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid,
const meshkernel::CurvilinearGridNodeIndices first,
const meshkernel::CurvilinearGridNodeIndices second)
{
// Check first, that all nodes are valid
for (meshkernel::UInt i = 0; i < curvilinearGrid->m_numN; ++i)
{
for (meshkernel::UInt j = 0; j < curvilinearGrid->m_numM; ++j)
{
EXPECT_TRUE(curvilinearGrid->GetNode(i, j).IsValid());
}
}

meshkernel::UInt lowerLimitI = std::min(first.m_n, second.m_n);
meshkernel::UInt upperLimitI = std::max(first.m_n, second.m_n);

meshkernel::UInt lowerLimitJ = std::min(first.m_m, second.m_m);
meshkernel::UInt upperLimitJ = std::max(first.m_m, second.m_m);

meshkernel::UInt expectedValid = (upperLimitI - lowerLimitI + 1) * (upperLimitJ - lowerLimitJ + 1);

// Delete the nodes outside of a block
curvilinearGrid->DeleteExterior(first, second);

auto inRange = [](const meshkernel::UInt v, const meshkernel::UInt l, const meshkernel::UInt u)
{ return l <= v && v <= u; };

EXPECT_EQ(expectedValid, CurvilinearGridCountValidNodes(curvilinearGrid));

// Check that these exterior nodes have been set to invalid.
for (meshkernel::UInt i = 0; i < curvilinearGrid->m_numN; ++i)
{
for (meshkernel::UInt j = 0; j < curvilinearGrid->m_numM; ++j)
{
if (inRange(i, lowerLimitI, upperLimitI) && inRange(j, lowerLimitJ, upperLimitJ))
{
EXPECT_TRUE(curvilinearGrid->GetNode(i, j).IsValid()) << "node should be true: " << i << " " << j;
}
else
{
EXPECT_FALSE(curvilinearGrid->GetNode(i, j).IsValid()) << "node should be false: " << i << " " << j;
}
}
}
}

TEST(CurvilinearGridUniform, DeleteExteriorNodesTest)
{
// Basic, testing of setting nodes inside a box to invalid
meshkernel::UInt nx = 10;
meshkernel::UInt ny = 10;
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {1, 1}, {4, 4});

// Reset the mesh
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {2, 1}, {5, 4});

// Reset the mesh
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {4, 3}, {7, 8});
}

TEST(CurvilinearGridUniform, DeleteExteriorNodesReverseTest)
{
// testing of setting nodes inside a box to invalid, with lower and upper reversed

meshkernel::UInt nx = 10;
meshkernel::UInt ny = 10;

// Prepare
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {5, 6}, {1, 2});

// Reset the mesh
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {5, 6}, {0, 4});
}

TEST(CurvilinearGridUniform, DeleteExteriorNodesMixedTest)
{
// testing of setting nodes inside a box to invalid, with lower and upper reversed for any of i and j index

meshkernel::UInt nx = 100;
meshkernel::UInt ny = 100;

std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {5, 1}, {1, 6});

// Reset grid
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
TestDeleteExteriorNodes(curvilinearGrid, {1, 6}, {5, 2});
}

TEST(CurvilinearGridUniform, DeleteExteriorNodesFailureTest)
{
// testing of setting nodes inside a box to invalid with invalid or out of range indices.

meshkernel::UInt nx = 10;
meshkernel::UInt ny = 10;

// Prepare
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);

EXPECT_THROW(curvilinearGrid->DeleteExterior({1, meshkernel::constants::missing::uintValue}, {nx, ny}), meshkernel::ConstraintError);
EXPECT_THROW(curvilinearGrid->DeleteExterior({1, 1}, {meshkernel::constants::missing::uintValue, ny}), meshkernel::ConstraintError);
EXPECT_THROW(curvilinearGrid->DeleteExterior({1, 1}, {nx, ny}), meshkernel::ConstraintError);
EXPECT_THROW(curvilinearGrid->DeleteExterior({nx, 1}, {4, 4}), meshkernel::ConstraintError);
}

0 comments on commit 57f68d4

Please sign in to comment.