mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
132 lines
4 KiB
C++
132 lines
4 KiB
C++
|
|
#include <iostream>
|
|
#include <optional>
|
|
#include <stdexcept>
|
|
|
|
#include "StructuredMesh2D.hpp"
|
|
|
|
namespace spatial
|
|
{
|
|
|
|
StructuredMesh2D::StructuredMesh2D(double left, double right, double bottom, double top, int nx, int ny)
|
|
: Mesh2D(left, right, bottom, top)
|
|
{
|
|
if (nx <= 1 || ny <= 1) throw std::invalid_argument("Number of nodes must be positive and greater than 1.");
|
|
|
|
nx_ = nx;
|
|
ny_ = ny;
|
|
|
|
std::cout << "\nCreating StructuredMesh2D with domain [" << left << ", " << right << "] x [" << bottom << ", " << top << "] and " << nx_ << " x " << ny_ << " nodes...\n";
|
|
|
|
meshDomain();
|
|
|
|
std::cout << " -> StructuredMesh2D created with " << nodes_.size() << " nodes (" << inner_nodes_.size() << " inner, " << boundary_nodes_.size() << " boundary).\n";
|
|
};
|
|
|
|
StructuredMesh2D::StructuredMesh2D(const Domain2D& domain, int nx, int ny)
|
|
: StructuredMesh2D(domain.left_, domain.right_, domain.bottom_, domain.top_, nx, ny) {};
|
|
|
|
void StructuredMesh2D::meshDomain()
|
|
{
|
|
double dx = getDx(), dy = getDy();
|
|
|
|
nodes_.reserve(nx_ * ny_);
|
|
inner_nodes_.reserve((nx_ - 2) * (ny_ - 2));
|
|
boundary_nodes_.reserve(2 * (nx_ + ny_) - 4);
|
|
node_to_boundary_node_.resize(nx_ * ny_, -1);
|
|
|
|
boundaries_[sideToIndex(DomainSide::Left)].reserve(ny_);
|
|
boundaries_[sideToIndex(DomainSide::Right)].reserve(ny_);
|
|
boundaries_[sideToIndex(DomainSide::Bottom)].reserve(nx_);
|
|
boundaries_[sideToIndex(DomainSide::Top)].reserve(nx_);
|
|
|
|
int boundary_node = 0;
|
|
for (int row = 0; row < ny_; ++row)
|
|
{
|
|
for (int col = 0; col < nx_; ++col)
|
|
{
|
|
int nodeID = nx_ * row + col;
|
|
double x = domain_.left_ + col * dx;
|
|
double y = domain_.bottom_ + row * dy;
|
|
nodes_.push_back(Node2D{nodeID, x, y});
|
|
|
|
std::vector<DomainSide> sides;
|
|
|
|
if (col == 0)
|
|
{
|
|
boundaries_[sideToIndex(DomainSide::Left)].push_back(nodeID);
|
|
sides.push_back(DomainSide::Left);
|
|
}
|
|
if (col == nx_ - 1)
|
|
{
|
|
boundaries_[sideToIndex(DomainSide::Right)].push_back(nodeID);
|
|
sides.push_back(DomainSide::Right);
|
|
}
|
|
if (row == 0)
|
|
{
|
|
boundaries_[sideToIndex(DomainSide::Bottom)].push_back(nodeID);
|
|
sides.push_back(DomainSide::Bottom);
|
|
}
|
|
if (row == ny_ - 1)
|
|
{
|
|
boundaries_[sideToIndex(DomainSide::Top)].push_back(nodeID);
|
|
sides.push_back(DomainSide::Top);
|
|
}
|
|
|
|
if (sides.empty()) inner_nodes_.push_back(nodeID);
|
|
else
|
|
{
|
|
node_to_boundary_node_[nodeID] = boundary_node;
|
|
boundary_node++;
|
|
boundary_nodes_.push_back(BoundaryNode2D{nodeID, x, y, sides});
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < nodes_.size(); ++i)
|
|
{
|
|
if (nodes_[i].nodeID_ != i)
|
|
{
|
|
throw std::logic_error("Mesh2D invariant violated: nodeID_ must match nodes_ index.");
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
std::optional<int> StructuredMesh2D::getNodeID(int i, int j) const
|
|
{
|
|
if (i < 0 || i >= nx_ || j < 0 || j >= ny_) return std::nullopt;
|
|
return j * nx_ + i;
|
|
};
|
|
|
|
std::optional<int> StructuredMesh2D::getNeighbor(int nodeID, DomainSide side) const
|
|
{
|
|
switch (side)
|
|
{
|
|
case DomainSide::Left:
|
|
if (nodeID % nx_ == 0) return std::nullopt;
|
|
return nodeID - 1;
|
|
|
|
case DomainSide::Right:
|
|
if ((nodeID + 1) % nx_ == 0) return std::nullopt;
|
|
return nodeID + 1;
|
|
|
|
case DomainSide::Bottom:
|
|
if ((nodeID - nx_) < 0) return std::nullopt;
|
|
return nodeID - nx_;
|
|
|
|
case DomainSide::Top:
|
|
if ((nodeID + nx_) > nx_ * ny_ - 1) return std::nullopt;
|
|
return nodeID + nx_;
|
|
|
|
default:
|
|
return std::nullopt;
|
|
}
|
|
};
|
|
|
|
bool StructuredMesh2D::isCorner(int nodeID) const
|
|
{
|
|
return nodeID == 0 || nodeID == nx_ - 1 || nodeID == nx_ * (ny_ - 1) || nodeID == ny_ * nx_ - 1;
|
|
}
|
|
|
|
} // namespace
|