Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4ecd1b9
Added evaluate_integral.hpp, changed CMake file, add optional dependa…
jcs15c Jun 21, 2022
3aa6a04
Added test for evaluate_integral methods, changed CMake file
jcs15c Jun 21, 2022
52a24a7
Added copyright info
jcs15c Jun 21, 2022
ff23aad
Corrected style
jcs15c Jun 21, 2022
2095c3e
Fixed style, slic logging
jcs15c Jun 21, 2022
b5496b1
Fixed lambda function warning
jcs15c Jun 21, 2022
67212d7
Fixed dependency of primal::evaluate_integral on mfem in build system
jcs15c Jun 21, 2022
5a43055
Add implementation file to minimize interface, change CMake
jcs15c Jun 22, 2022
64c9dc3
Minimize interface, add static quadrature rules library
jcs15c Jun 22, 2022
b9d0005
Add comments, increase readability
jcs15c Jun 22, 2022
3b57151
Update primal/CMakeLists.txt formatting
jcs15c Jun 22, 2022
1d61386
Added tests for CurvedPolygon interface.
jcs15c Jun 22, 2022
4995da1
Updated style/formatting, compilation optimization
jcs15c Jun 22, 2022
6c02447
update release notes
jcs15c Jun 23, 2022
f4935d9
Updated comments
jcs15c Jun 23, 2022
b4bef28
Added CurvedPolygon overload to evaluate_line_integral
jcs15c Jun 23, 2022
0534920
Updated to r-value reference for lambda functions
jcs15c Jun 23, 2022
b6b1b5b
Merge branch 'develop' into feature/spainhour/bezier_quadrature
jcs15c Jun 23, 2022
ddc9791
Changed quadrature rule pointers to references
jcs15c Jun 24, 2022
4d0d9e1
Changed quadrature rule pointers to references
jcs15c Jun 24, 2022
39d5cb7
Merge branch 'feature/spainhour/bezier_quadrature' of https://github.…
jcs15c Jun 24, 2022
702de76
Temporarily removed R-value references
jcs15c Jun 24, 2022
de51f54
Add tests for line integrals on disconnected curves
jcs15c Jun 24, 2022
8f75254
Added extra dependencies for Primal
jcs15c Jun 27, 2022
218eac7
Merge branch 'develop' into feature/spainhour/bezier_quadrature
jcs15c Jun 27, 2022
1c3c99d
Merge changes from develop
jcs15c Jun 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/
in quest's signed_distance C API.
- Adds utility function for linear interpolation (`lerp`) of two numbers
- Adds utility function to compute binomial coefficients
- Adds a `CurvedPolygon` class to primal representing a polygon with `BezierCurves` as edges
- Adds a `CurvedPolygon` class to primal representing a polygon with `BezierCurve`s as edges
- Adds functions to compute the moments (area, centroid) of a `CurvedPolygon`
- Adds functions to evaluate integrals over `BezierCurve` and `CurvedPolygon` objects

### Changed
- Axom now requires C++14 and will default to that if not specified via `BLT_CXX_STD`.
Expand Down
8 changes: 8 additions & 0 deletions src/axom/primal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ set( primal_sources
operators/detail/intersect_impl.cpp
)

blt_list_append(
TO primal_headers
ELEMENTS operators/evaluate_integral.hpp
operators/detail/evaluate_integral_impl.hpp
IF MFEM_FOUND
)

#------------------------------------------------------------------------------
# Build and install the library
#------------------------------------------------------------------------------
Expand All @@ -78,6 +85,7 @@ set( primal_dependencies

blt_list_append( TO primal_dependencies ELEMENTS cuda IF ENABLE_CUDA )
blt_list_append( TO primal_dependencies ELEMENTS blt::hip_runtime IF ENABLE_HIP )
blt_list_append( TO primal_dependencies ELEMENTS mfem IF MFEM_FOUND )

blt_add_library(
NAME primal
Expand Down
150 changes: 150 additions & 0 deletions src/axom/primal/operators/detail/evaluate_integral_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and
// other Axom Project Developers. See the top-level LICENSE file for details.
//
// SPDX-License-Identifier: (BSD-3-Clause)

#ifndef PRIMAL_EVAL_INTEGRAL_IMPL_HPP_
#define PRIMAL_EVAL_INTEGRAL_IMPL_HPP_

// Axom includes
#include "axom/config.hpp" // for compile-time configuration options
#include "axom/primal.hpp"

// MFEM includes
#ifdef AXOM_USE_MFEM
#include "mfem.hpp"
#else
#error "Primal's integral evaluation functions require mfem library."
#endif

// C++ includes
#include <cmath>

namespace axom
{
namespace primal
{
namespace detail
{
/*!
* \brief Evaluate a scalar field line integral on a single Bezier curve.
*
* Evaluate the scalar field line integral with MFEM integration rule
*
* \param [in] c the Bezier curve object
* \param [in] integrand the lambda function representing the integrand.
* Must accept a 2D point as input and return a double
* \param [in] quad the mfem integration rule containing nodes and weights
* \return the value of the integral
*/
inline double evaluate_line_integral_component(
const primal::BezierCurve<double, 2>& c,
std::function<double(Point2D)> integrand,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the lambda should be passed by r-value ref (here and elsewhere):

Suggested change
std::function<double(Point2D)> integrand,
std::function<double(Point2D)>&& integrand,

(@kanye-quest -- could you please confirm?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very unclear on the details, but passing the std::function's by R-value reference is causing some issues with some to-be-implemented winding number code. Specifically, if we pass to evaluate_line_integral a lambda function that is the return value for some other function (see below), then evaluate_line_integral_component can no longer fit the argument to either overloaded definition. This doesn't happen when the std::function's are passed by constant reference, or when the lambda function is not the return value for another function, so I am unsure how to keep this as general as possible.

// An example of function that returns argument to evaluate_line_integral
std::function<Vector2D(Point2D)> get_vector_field(Point2D p) 
{
  return [p](Point2D x) -> Vector2D { return Vector2D({p[1], p[0]}); };
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks -- ok, sounds like something to think about and try to fix in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might have something to do with this function (and the one below) accepting an std::function instead of a Lambda&& like in the other methods. The latter is a universal reference, so it can bind to both lvalues and rvalues.

For what it's worth, I think accepting Lambda&& might be better from an inlineability perspective -- it would be much more difficult for the compiler to inline through a type-erased std::function.

const mfem::IntegrationRule& quad)
{
// Store/compute quadrature result
double full_quadrature = 0.0;
for(int q = 0; q < quad.GetNPoints(); q++)
{
// Get intermediate quadrature point
// at which to evaluate tangent vector
auto x_q = c.evaluate(quad.IntPoint(q).x);
auto dx_q = c.dt(quad.IntPoint(q).x);

full_quadrature += quad.IntPoint(q).weight * integrand(x_q) * dx_q.norm();
}

return full_quadrature;
}

/*!
* \brief Evaluate a vector field line integral on a single Bezier curve.
*
* Evaluate the vector field line integral with MFEM integration rule
*
* \param [in] c the Bezier curve object
* \param [in] integrand the lambda function representing the integrand.
* Must accept a 2D point as input and return a 2D axom vector object
* \param [in] quad the mfem integration rule containing nodes and weights
* \return the value of the integral
*/
inline double evaluate_line_integral_component(
const primal::BezierCurve<double, 2>& c,
std::function<Vector2D(Point2D)> vec_field,
const mfem::IntegrationRule& quad)
{
// Store/compute quadrature result
double full_quadrature = 0.0;
for(int q = 0; q < quad.GetNPoints(); q++)
{
// Get intermediate quadrature point
// on which to evaluate dot product
auto x_q = c.evaluate(quad.IntPoint(q).x);
auto dx_q = c.dt(quad.IntPoint(q).x);
auto func_val = vec_field(x_q);

full_quadrature +=
quad.IntPoint(q).weight * Vector2D::dot_product(func_val, dx_q);
}

return full_quadrature;
}

/*!
* \brief Evaluate the area integral across one component of the curved polygon.
*
* Intended to be called for each BezierCurve object in a curved polygon.
* Uses a Spectral Mesh-Free Quadrature derived from Green's theorem, evaluating
* the area integral as a line integral of the antiderivative over the curve.
* For algorithm details, see "Spectral Mesh-Free Quadrature for Planar
* Regions Bounded by Rational Parametric Curves" by David Gunderman et al.
*
* \param [in] cs the array of Bezier curve objects that bound the region
* \param [in] integrand the lambda function representing the integrand.
* Must accept a 2D point as input and return a double
* \param [in] The lower bound of integration for the antiderivatives
* \param [in] quad_Q the quadrature rule for the line integral
* \param [in] quad_P the quadrature rule for the antiderivative
* \return the value of the integral, which is mathematically meaningless.
*/
template <class Lambda>
double evaluate_area_integral_component(const primal::BezierCurve<double, 2>& c,
Lambda&& integrand,
double int_lb,
const mfem::IntegrationRule& quad_Q,
const mfem::IntegrationRule& quad_P)
{
// Store some intermediate values
double antiderivative = 0.0;

// Store/compute quadrature result
double full_quadrature = 0.0;
for(int q = 0; q < quad_Q.GetNPoints(); q++)
{
// Get intermediate quadrature point
// on which to evaluate antiderivative
auto x_q = c.evaluate(quad_Q.IntPoint(q).x);

// Evaluate the antiderivative at x_q, add it to full quadrature
for(int xi = 0; xi < quad_P.GetNPoints(); xi++)
{
// Define interior quadrature points
auto x_qxi =
Point2D({x_q[0], (x_q[1] - int_lb) * quad_P.IntPoint(xi).x + int_lb});

antiderivative =
quad_P.IntPoint(xi).weight * (x_q[1] - int_lb) * integrand(x_qxi);

full_quadrature += quad_Q.IntPoint(q).weight *
c.dt(quad_Q.IntPoint(q).x)[0] * -antiderivative;
}
}

return full_quadrature;
}

} // end namespace detail
} // end namespace primal
} // end namespace axom

#endif
Loading