Browse Source

refactor newton method and introduce test with googleTest

wch
mckay 3 months ago
parent
commit
19db8aefcc
  1. 8
      surface_integral/interface/SurfaceIntegrator.hpp
  2. 37
      surface_integral/src/SurfaceIntegrator.cpp
  3. 24
      surface_integral/test/SurfaceIntegrator_test.cpp
  4. 8
      surface_integral/xmake.lua

8
surface_integral/interface/SurfaceIntegrator.hpp

@ -52,11 +52,13 @@ private:
std::vector<double> find_vertical_intersections(double u_val); std::vector<double> find_vertical_intersections(double u_val);
bool is_point_inside_domain(double u, double v); bool is_point_inside_domain(double u, double v);
double newton_method(const std::function<equation_intermediate_t(double)>& F,
void sort_and_unique_with_tol(std::vector<double>& vec, double epsilon = 1e-8);
};
double newton_method(const std::function<equation_intermediate_t(double)>& F,
double v_initial, double v_initial,
double tolerance = 1e-8, double tolerance = 1e-8,
int max_iterations = 100); int max_iterations = 100);
void sort_and_unique_with_tol(std::vector<double>& vec, double epsilon = 1e-8);
};
} // namespace internal } // namespace internal

37
surface_integral/src/SurfaceIntegrator.cpp

@ -232,8 +232,26 @@ bool is_point_inside_domain(double u, double v)
return intersection_count % 2 == 1; // in domain return intersection_count % 2 == 1; // in domain
} }
void SurfaceAreaCalculator::sort_and_unique_with_tol(std::vector<double>& vec, double epsilon)
{
if (vec.empty()) return;
std::sort(vec.begin(), vec.end());
size_t write_index = 0;
for (size_t read_index = 1; read_index < vec.size(); ++read_index) {
if (std::fabs(vec[read_index] - vec[write_index]) > epsilon) {
++write_index;
vec[write_index] = vec[read_index];
}
}
vec.resize(write_index + 1);
}
// 牛顿法求解器 // 牛顿法求解器
double SurfaceAreaCalculator::newton_method(const std::function<equation_intermediate_t(double)>& F, double newton_method(const std::function<equation_intermediate_t(double)>& F,
double v_initial, double v_initial,
double tolerance, double tolerance,
int max_iterations) int max_iterations)
@ -264,22 +282,5 @@ double SurfaceAreaCalculator::newton_method(const std::function<equation_interme
return v; return v;
} }
void SurfaceAreaCalculator::sort_and_unique_with_tol(std::vector<double>& vec, double epsilon)
{
if (vec.empty()) return;
std::sort(vec.begin(), vec.end());
size_t write_index = 0;
for (size_t read_index = 1; read_index < vec.size(); ++read_index) {
if (std::fabs(vec[read_index] - vec[write_index]) > epsilon) {
++write_index;
vec[write_index] = vec[read_index];
}
}
vec.resize(write_index + 1);
}
} // namespace internal } // namespace internal

24
surface_integral/test/SurfaceIntegrator_test.cpp

@ -0,0 +1,24 @@
#include <gtest/gtest.h>
#include "SurfaceIntegrator.hpp"
using namespace internal;
// 一个简单的方程:f(v) = v^2 - 2, df = 2v,根为 sqrt(2)
TEST(SurfaceAreaCalculatorTest, NewtonMethodConverges)
{
auto F = [](double v) -> equation_intermediate_t {
implicit_equation_intermediate iei;
iei.f = v * v - 2.0;
iei.df = 2.0 * v;
return equation_intermediate_t{iei};
};
double v_initial = 1.0;
double tolerance = 1e-8;
int max_iterations = 20;
double root = newton_method(F, v_initial, tolerance, max_iterations);
EXPECT_NEAR(root, std::sqrt(2.0), tolerance);
}

8
surface_integral/xmake.lua

@ -4,4 +4,10 @@ internal_library("surface_integral", "SI", os.scriptdir())
add_rules("config.indirect_predicates.flags") add_rules("config.indirect_predicates.flags")
add_deps("primitive_process", "shared_module") add_deps("primitive_process", "shared_module")
-- add Google Test target
target("newton_method_test")
set_kind("binary")
add_deps("surface_integral") -- depend on the internal library surface_integral
add_files("test/SurfaceIntegrator_test.cpp")
add_packages("gtest")
target_end()
Loading…
Cancel
Save