Skip to content

Commit

Permalink
levelset: micro-optimization in the evaluation of gradient
Browse files Browse the repository at this point in the history
  • Loading branch information
ksamouchos committed Jun 6, 2024
1 parent aac8cbd commit c6e9186
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
44 changes: 38 additions & 6 deletions src/levelset/levelSetSegmentationObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,20 +225,22 @@ bitpit::LevelSetSurfaceSmoothing LevelSetSegmentationSurfaceInfo::getSurfaceSmoo
* @param[in] point are the coordinates of point
* @param[in] segmentItr is an iterator pointing to the closest segment
* @param[in] signedDistance controls if the signed or unsigned distance will be evaluated
* @param[out] the distance function at the specified point
* @return The distance function at the specified point.
*/
double LevelSetSegmentationSurfaceInfo::evalDistance(const std::array<double, 3> &point,
const SegmentConstIterator &segmentItr,
bool signedDistance) const
bool signedDistance,
std::array<double, 3> *distanceVector) const
{
// Project the point on the surface and evaluate the point-projection vector
int nSegmentVertices = segmentItr->getVertexCount();
BITPIT_CREATE_WORKSPACE(lambda, double, nSegmentVertices, ReferenceElementInfo::MAX_ELEM_VERTICES);
std::array<double, 3> pointProjection = evalProjection(point, segmentItr, lambda);
std::array<double, 3> pointProjectionVector = point - pointProjection;
(*distanceVector) = point - pointProjection;

// Evaluate unsigned distance
double unsignedDistance = norm2(pointProjectionVector);
double unsignedDistance = norm2(*distanceVector);
if (!signedDistance) {
return unsignedDistance;
}
Expand All @@ -249,7 +251,7 @@ double LevelSetSegmentationSurfaceInfo::evalDistance(const std::array<double, 3>
// plane. This case is not supported, because it would require to evaluate the sign taking
// into account the the curvature of the surface.
std::array<double, 3> pseudoNormal = computePseudoNormal(segmentItr, lambda);
double pointProjectionNormalComponent = dotProduct(pointProjectionVector, pseudoNormal);
double pointProjectionNormalComponent = dotProduct(*distanceVector, pseudoNormal);

double distanceTolerance = m_surface->getTol();
if (utils::DoubleFloatingEqual()(pointProjectionNormalComponent, 0., distanceTolerance, distanceTolerance)) {
Expand All @@ -262,6 +264,22 @@ double LevelSetSegmentationSurfaceInfo::evalDistance(const std::array<double, 3>
return sign(pointProjectionNormalComponent) * unsignedDistance;
}

/*!
* Evaluate the distance function at the specified point.
*
* @param[in] point are the coordinates of point
* @param[in] segmentItr is an iterator pointing to the closest segment
* @param[in] signedDistance controls if the signed or unsigned distance will be evaluated
* @return The distance function at the specified point.
*/
double LevelSetSegmentationSurfaceInfo::evalDistance(const std::array<double, 3> &point,
const SegmentConstIterator &segmentItr,
bool signedDistance) const
{
std::array<double, 3> distanceVector;
return evalDistance(point, segmentItr, signedDistance, &distanceVector);
}

/*!
* Evaluate the distance vector function at the specified point.
*
Expand Down Expand Up @@ -297,6 +315,19 @@ std::array<double, 3> LevelSetSegmentationSurfaceInfo::evalNormal(const std::arr
return projectionNormal;
}

/*!
* Compute the pseudo-normal at specified point of the given segment.
*
* @param[in] segmentItr is an iterator pointing to the closest segment
* @param[in] lambda are the barycentric coordinates of the point
* @return the pseudo-normal at specified point of the given segment
*/
std::array<double,3> LevelSetSegmentationSurfaceInfo::evalPseudoNormal(const SegmentConstIterator &segmentItr,
const double *lambda ) const
{
return computePseudoNormal(segmentItr, lambda);
}

/*!
* Evaluate the projection of the given point on the surface created based on
* the points representing the specified segment. The surface passes from these
Expand Down Expand Up @@ -3036,7 +3067,8 @@ std::array<double,3> LevelSetSegmentationObject::_evalGradient(const std::array<

// Evaluate the distance of the point from the surface
LevelSetSegmentationSurfaceInfo::SegmentConstIterator supportItr = getSurface().getCellConstIterator(support);
double distance = m_surfaceInfo->evalDistance(point, supportItr, signedLevelSet);
std::array<double,3> distanceVector;
double distance = m_surfaceInfo->evalDistance(point, supportItr, signedLevelSet, &distanceVector);

// Early return if the point lies on the surface
if (evalValueSign(distance) == 0) {
Expand All @@ -3048,7 +3080,7 @@ std::array<double,3> LevelSetSegmentationObject::_evalGradient(const std::array<
}

// Evaluate levelset gradient
std::array<double,3> gradient = m_surfaceInfo->evalDistanceVector(point, supportItr) / distance;
std::array<double,3> gradient = distanceVector / distance;

return gradient;
}
Expand Down
2 changes: 2 additions & 0 deletions src/levelset/levelSetSegmentationObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ class LevelSetSegmentationSurfaceInfo {
double getFeatureAngle() const;
LevelSetSurfaceSmoothing getSurfaceSmoothing() const;

double evalDistance(const std::array<double, 3> &point, const SegmentConstIterator &segmentItr, bool signedDistance, std::array<double, 3> *distanceVector) const;
double evalDistance(const std::array<double, 3> &point, const SegmentConstIterator &segmentItr, bool signedDistance) const;
std::array<double, 3> evalDistanceVector(const std::array<double, 3> &point, const SegmentConstIterator &segmentItr) const;

std::array<double, 3> evalNormal(const std::array<double, 3> &point, const SegmentConstIterator &segmentItr) const;
std::array<double,3> evalPseudoNormal(const SurfUnstructured::CellConstIterator &segmentIterator, const double *lambda) const;

void evalProjection(const std::array<double, 3> &point, const SegmentConstIterator &segmentItr, std::array<double, 3> *projectionPoint, std::array<double, 3> *projectionNormal) const;
void evalProjection(const std::array<double, 3> &point, const SegmentConstIterator &segmentItr, std::array<double, 3> *projectionPoint) const;
Expand Down

0 comments on commit c6e9186

Please sign in to comment.