Commit b1bbd50f authored by Mark Olesen's avatar Mark Olesen Committed by Andrew Heather
Browse files

ENH: additional constructor and methods for PDRblock (#1216)

- construct from positions

- reset positions, minEdgeLen, find grid index

ENH: add accessor for obtaining the size of a single i-j-k dimension

- eg, obtain the 'i' dimension with any of these methods:

      ijkAddr.size(vector::X)
      ijkAddr.sizes().x()
      ijkAddr.sizes()[0]
parent b319e058
......@@ -104,6 +104,12 @@ public:
//- Return i,j,k addressing sizes for modification
inline labelVector& sizes();
//- The field size
using Field<Type>::size;
//- The addressing dimension in the given direction
inline const label& size(const vector::components cmpt) const;
// Edit
......
......@@ -157,6 +157,16 @@ inline Foam::labelVector& Foam::IjkField<Type>::sizes()
}
template<class Type>
inline const Foam::label& Foam::IjkField<Type>::size
(
const vector::components cmpt
) const
{
return ijk_.size(cmpt);
}
template<class Type>
inline void Foam::IjkField<Type>::clear()
{
......
......@@ -36,6 +36,7 @@ SourceFiles
#define ijkAddressing_H
#include "labelVector.H"
#include "vector.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -72,17 +73,20 @@ public:
// Access
//- Return the i,j,k addressing sizes
//- Addressing is considered empty if any component is zero
inline bool empty() const;
//- The (i,j,k) addressing dimensions
inline const labelVector& sizes() const;
//- Return the i,j,k addressing sizes for modification
//- Return the (i,j,k) dimensions for modification
inline labelVector& sizes();
//- Return the total i*j*k size
inline label size() const;
//- Addressing is considered empty if any component is zero
inline bool empty() const;
//- The addressing dimension in the given direction
inline const label& size(const vector::components cmpt) const;
//- Reset to (0,0,0) sizing
inline void clear();
......@@ -93,13 +97,13 @@ public:
//- Change the sizing parameters
inline void reset(const labelVector& newSizes);
//- Linear addressing index (offset) for an i,j,k position.
//- Linear addressing index (offset) for an (i,j,k) position.
inline label index(const label i, const label j, const label k) const;
//- Linear addressing index (offset) for an i,j,k position.
//- Linear addressing index (offset) for an (i,j,k) position.
inline label index(const labelVector& ijk) const;
//- The i,j,k indexing from linear addressing.
//- The (i,j,k) indexing from linear addressing.
inline labelVector index(const label idx) const;
......
......@@ -58,6 +58,12 @@ inline Foam::ijkAddressing::ijkAddressing
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::ijkAddressing::empty() const
{
return (!sizes_.x() || !sizes_.y() || !sizes_.z());
}
inline const Foam::labelVector& Foam::ijkAddressing::sizes() const
{
return sizes_;
......@@ -77,9 +83,12 @@ inline Foam::label Foam::ijkAddressing::size() const
}
inline bool Foam::ijkAddressing::empty() const
inline const Foam::label& Foam::ijkAddressing::size
(
const vector::components cmpt
) const
{
return (!sizes_.x() || !sizes_.y() || !sizes_.z());
return sizes_[cmpt];
}
......
......@@ -143,13 +143,13 @@ inline Foam::label Foam::ijkMesh::nBoundaryFaces
return n.y()*n.z();
break;
// Face 2, 3 == y-min, y-max
// Face 2,3 == y-min, y-max
case 2:
case 3:
return n.z()*n.x();
break;
// Face 4, 5 == z-min, z-max
// Face 4,5 == z-min, z-max
case 4:
case 5:
return n.x()*n.y();
......
......@@ -41,5 +41,6 @@ blockMeshTools/blockMeshTools.C
PDRblockMesh/PDRblock.C
PDRblockMesh/PDRblockCreate.C
PDRblockMesh/PDRblockLocation.C
LIB = $(FOAM_LIBBIN)/libblockMesh
......@@ -39,8 +39,87 @@ namespace Foam
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
bool Foam::PDRblock::checkMonotonic
(
const direction cmpt,
const UList<scalar>& pts
)
{
const label len = pts.size();
if (!len)
{
return false;
}
const scalar& minVal = pts[0];
for (label i=1; i < len; ++i)
{
if (pts[i] <= minVal)
{
FatalErrorInFunction
<< "Points in " << vector::componentNames[cmpt]
<< " direction do not increase monotonically" << nl
<< flatOutput(pts) << nl << nl
<< exit(FatalError);
}
}
return true;
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::PDRblock::adjustSizes()
{
// Adjust i-j-k addressing
sizes().x() = grid_.x().nCells();
sizes().y() = grid_.y().nCells();
sizes().z() = grid_.z().nCells();
if (sizes().x() <= 0 || sizes().y() <= 0 || sizes().z() <= 0)
{
// Sanity check. Silently disallow bad sizing
ijkMesh::clear();
grid_.x().clear();
grid_.y().clear();
grid_.z().clear();
bounds_ = boundBox::invertedBox;
minEdgeLen_ = Zero;
return;
}
// Adjust boundBox
bounds_.min().x() = grid_.x().first();
bounds_.min().y() = grid_.y().first();
bounds_.min().z() = grid_.z().first();
bounds_.max().x() = grid_.x().last();
bounds_.max().y() = grid_.y().last();
bounds_.max().z() = grid_.z().last();
// Min edge length
minEdgeLen_ = GREAT;
for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
{
const label nEdge = grid_[cmpt].nCells();
for (label edgei=0; edgei < nEdge; ++edgei)
{
const scalar len = grid_[cmpt].width(edgei);
minEdgeLen_ = min(minEdgeLen_, len);
}
}
}
void Foam::PDRblock::readGridControl
(
const direction cmpt,
......@@ -89,22 +168,7 @@ void Foam::PDRblock::readGridControl
}
// Do points increase monotonically?
{
const scalar& minVal = knots.first();
for (label pointi = 1; pointi < knots.size(); ++pointi)
{
if (knots[pointi] <= minVal)
{
FatalIOErrorInFunction(dict)
<< "Points are not monotonically increasing:"
<< " in " << vector::componentNames[cmpt]
<< " direction" << nl
<< exit(FatalIOError);
}
}
}
checkMonotonic(cmpt, knots);
if (verbose_)
{
......@@ -394,6 +458,33 @@ void Foam::PDRblock::readBoundary(const dictionary& dict)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::PDRblock::PDRblock
(
const UList<scalar>& xgrid,
const UList<scalar>& ygrid,
const UList<scalar>& zgrid
)
:
PDRblock()
{
// Default boundaries with patchi == shapeFacei
patches_.resize(6);
for (label patchi=0; patchi < 6; ++patchi)
{
patches_.set(patchi, new boundaryEntry());
boundaryEntry& bentry = patches_[patchi];
bentry.name_ = "patch" + Foam::name(patchi);
bentry.type_ = "patch";
bentry.size_ = 0;
bentry.faces_ = labelList(one(), patchi);
}
reset(xgrid, ygrid, zgrid);
}
Foam::PDRblock::PDRblock(const dictionary& dict, bool verbose)
:
PDRblock()
......@@ -411,50 +502,124 @@ bool Foam::PDRblock::read(const dictionary& dict)
// Mark no scaling with invalid value
const scalar scaleFactor = dict.lookupOrDefault<scalar>("scale", -1);
// Grid controls
readGridControl(0, dict.subDict("x"), scaleFactor);
readGridControl(1, dict.subDict("y"), scaleFactor);
readGridControl(2, dict.subDict("z"), scaleFactor);
// Adjust i-j-k addressing
sizes().x() = grid_.x().nCells();
sizes().y() = grid_.y().nCells();
sizes().z() = grid_.z().nCells();
adjustSizes();
// Adjust boundBox
bounds_.min().x() = grid_.x().first();
bounds_.min().y() = grid_.y().first();
bounds_.min().z() = grid_.z().first();
readBoundary(dict);
bounds_.max().x() = grid_.x().last();
bounds_.max().y() = grid_.y().last();
bounds_.max().z() = grid_.z().last();
return true;
}
// Boundaries
readBoundary(dict);
void Foam::PDRblock::reset
(
const UList<scalar>& xgrid,
const UList<scalar>& ygrid,
const UList<scalar>& zgrid
)
{
static_cast<scalarList&>(grid_.x()) = xgrid;
static_cast<scalarList&>(grid_.y()) = ygrid;
static_cast<scalarList&>(grid_.z()) = zgrid;
return true;
#ifdef FULLDEBUG
for (direction cmpt=0; cmpt < vector::nComponents; ++cmpt)
{
checkMonotonic(cmpt, grid_[cmpt]);
}
#endif
adjustSizes();
// Adjust boundaries
for (boundaryEntry& bentry : patches_)
{
bentry.size_ = 0;
// Count patch faces
for (const label shapeFacei : bentry.faces_)
{
bentry.size_ += nBoundaryFaces(shapeFacei);
}
}
}
Foam::labelVector Foam::PDRblock::findCell(const point& pt) const
bool Foam::PDRblock::findCell(const point& pt, labelVector& pos) const
{
// Out-of-bounds is handled explicitly, for efficiency and consistency,
// but principally to ensure that findLower() returns a valid
// result when the point is to the right of the bounds.
labelVector pos(-1,-1,-1);
if (bounds_.contains(pt))
// Since findLower returns the lower index, it corresponds to the
// cell in which the point is found
if (!bounds_.contains(pt))
{
for (direction cmpt=0; cmpt < labelVector::nComponents; ++cmpt)
{
// Binary search
pos[cmpt] = findLower(grid_[cmpt], pt[cmpt]);
}
return false;
}
for (direction cmpt=0; cmpt < labelVector::nComponents; ++cmpt)
{
// Binary search
pos[cmpt] = findLower(grid_[cmpt], pt[cmpt]);
}
return true;
}
bool Foam::PDRblock::gridIndex
(
const point& pt,
labelVector& pos,
const scalar relTol
) const
{
const scalar tol = relTol * minEdgeLen_;
for (direction cmpt=0; cmpt < labelVector::nComponents; ++cmpt)
{
// Linear search
pos[cmpt] = grid_[cmpt].findIndex(pt[cmpt], tol);
if (pos[cmpt] < 0) return false;
}
return true;
}
Foam::labelVector Foam::PDRblock::findCell(const point& pt) const
{
labelVector pos;
if (findCell(pt, pos))
{
return pos;
}
return labelVector(-1,-1,-1);
}
Foam::labelVector Foam::PDRblock::gridIndex
(
const point& pt,
const scalar relTol
) const
{
labelVector pos;
if (gridIndex(pt, pos, relTol))
{
return pos;
}
return pos;
return labelVector(-1,-1,-1);
}
......
......@@ -44,10 +44,10 @@ Description
Grid coordinate controls
\table
Property| Description | Required | Default
points | Locations defining the mesh segment | yes |
nCells | Divisions per mesh segment | yes |
ratios | Expansion ratio (end/start) per segment | no | uniform
Property| Description | Required | Default
points | Locations defining the mesh segment | yes |
nCells | Divisions per mesh segment | yes |
ratios | Expansion ratio (end/start) per segment | no | uniform
\endtable
The expansion ratios are defined as per blockMesh and represent the ratio
......@@ -98,14 +98,20 @@ public:
:
public scalarList
{
//- The locations are valid if they contain 2 or more points
inline bool valid() const;
//- The number of cells in this direction.
inline label nCells() const;
//- The number of points in this direction.
inline label nPoints() const;
//- The number of divisions (nCells) in this direction.
inline label size() const;
//- True if the location is within the range
inline bool contains(const scalar p) const;
//- Mid-point location, zero for an empty list.
inline scalar centre() const;
//- Check that element index is within valid range.
inline void checkIndex(const label i) const;
......@@ -114,7 +120,22 @@ public:
inline scalar width(const label i) const;
//- Cell centre at element position.
// Treats -1 and nCells positions like a halo cell.
inline scalar C(const label i) const;
//- Find the cell index enclosing this location
// \return -1 for out-of-bounds
label findCell(const scalar p) const;
//- Find the grid index, within the given tolerance
// Return -1 for out-of-bounds and -2 for a point that is
// within bounds, but not aligned with a grid point.
label findIndex(const scalar p, const scalar tol) const;
//- If out of range, return the respective min/max limits,
//- otherwise return the value itself.
// If the range is invalid, always return the value.
inline const scalar& clip(const scalar& val) const;
};
......@@ -153,9 +174,18 @@ private:
//- The boundary patch information
PtrList<boundaryEntry> patches_;
//- The min edge length
scalar minEdgeLen_;
// Private Member Functions
//- Check that points increase monotonically
static bool checkMonotonic(const direction cmpt, const UList<scalar>& pts);
//- Adjust sizing for updated grid points
void adjustSizes();
//- Read and define grid points in given direction
void readGridControl
(
......@@ -167,7 +197,6 @@ private:
//- Read "boundary" information
void readBoundary(const dictionary& dict);
//- Populate point field for the block
void createPoints(pointField& pts) const;
......@@ -181,7 +210,6 @@ private:
labelList::iterator& neiIter
) const;
//- Add boundary faces for the shape face to lists
// Lists must be properly sized!
// \return the number of faces added
......@@ -192,6 +220,19 @@ private:
labelList::iterator& ownIter
) const;
//- Obtain i,j,k index for cell enclosing this location
// \return false for out-of-bounds
bool findCell(const point& pt, labelVector& pos) const;
//- Obtain i,j,k grid index for point location
// \return false for out-of-bounds and off-grid
bool gridIndex
(
const point& pt,
labelVector& pos,
const scalar tol
) const;
public:
......@@ -200,6 +241,14 @@ public:
//- Construct zero-size
inline PDRblock();
//- Construct from components
PDRblock
(
const UList<scalar>& xgrid,
const UList<scalar>& ygrid,
const UList<scalar>& zgrid
);
//- Construct from dictionary
explicit PDRblock(const dictionary& dict, bool verbose=false);
......@@ -209,6 +258,14 @@ public:
//- Read dictionary
bool read(const dictionary& dict);
//- Reset grid locations and mesh i-j-k sizing
void reset
(
const UList<scalar>& xgrid,
const UList<scalar>& ygrid,
const UList<scalar>& zgrid
);
// Access
......@@ -221,6 +278,9 @@ public:
//- The mesh bounding box
inline const boundBox& bounds() const;
//- The min edge length
inline const scalar& minEdgeLen() const;
//- Cell size in x-direction at i position.
inline scalar dx(const label i) const;
......@@ -272,6 +332,12 @@ public:
// The value (-1,-1,-1) is returned for out-of-bounds (not found).
labelVector findCell(const point& pt) const;
//- Obtain i,j,k grid index for point location within specified
// relative tolerance of the minEdgeLen.
// The value (-1,-1,-1) is returned for out-of-bounds (not found).
// and off-grid
labelVector gridIndex(const point& pt, const scalar relTol=0.01) const;
// Mesh generation
......
......@@ -31,12 +31,19 @@ inline Foam::PDRblock::PDRblock()
verbose_(false),
grid_(),
bounds_(),
patches_()
patches_(),
minEdgeLen_(Zero)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::PDRblock::location::valid() const
{
return (scalarList::size() > 1);
}
inline Foam::label Foam::PDRblock::location::nCells() const
{
return (scalarList::size()-1);
......@@ -49,19 +56,25 @@ inline Foam::label Foam::PDRblock::location::nPoints() const
}