From 19db8aefccba163209fefb135c0ec2b631ba6fd4 Mon Sep 17 00:00:00 2001 From: mckay Date: Fri, 25 Jul 2025 15:56:19 +0800 Subject: [PATCH] refactor newton method and introduce test with googleTest --- .../interface/SurfaceIntegrator.hpp | 10 +++-- surface_integral/src/SurfaceIntegrator.cpp | 37 ++++++++++--------- .../test/SurfaceIntegrator_test.cpp | 24 ++++++++++++ surface_integral/xmake.lua | 8 +++- 4 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 surface_integral/test/SurfaceIntegrator_test.cpp diff --git a/surface_integral/interface/SurfaceIntegrator.hpp b/surface_integral/interface/SurfaceIntegrator.hpp index 3640899..5c5587c 100644 --- a/surface_integral/interface/SurfaceIntegrator.hpp +++ b/surface_integral/interface/SurfaceIntegrator.hpp @@ -52,11 +52,13 @@ private: std::vector find_vertical_intersections(double u_val); bool is_point_inside_domain(double u, double v); - double newton_method(const std::function& F, - double v_initial, - double tolerance = 1e-8, - int max_iterations = 100); + void sort_and_unique_with_tol(std::vector& vec, double epsilon = 1e-8); }; +double newton_method(const std::function& F, + double v_initial, + double tolerance = 1e-8, + int max_iterations = 100); + } // namespace internal \ No newline at end of file diff --git a/surface_integral/src/SurfaceIntegrator.cpp b/surface_integral/src/SurfaceIntegrator.cpp index 865df03..ac35e8f 100644 --- a/surface_integral/src/SurfaceIntegrator.cpp +++ b/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 } + +void SurfaceAreaCalculator::sort_and_unique_with_tol(std::vector& 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& F, +double newton_method(const std::function& F, double v_initial, double tolerance, int max_iterations) @@ -264,22 +282,5 @@ double SurfaceAreaCalculator::newton_method(const std::function& 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 \ No newline at end of file diff --git a/surface_integral/test/SurfaceIntegrator_test.cpp b/surface_integral/test/SurfaceIntegrator_test.cpp new file mode 100644 index 0000000..3784140 --- /dev/null +++ b/surface_integral/test/SurfaceIntegrator_test.cpp @@ -0,0 +1,24 @@ +#include +#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); +} \ No newline at end of file diff --git a/surface_integral/xmake.lua b/surface_integral/xmake.lua index fd919bd..ef18ade 100644 --- a/surface_integral/xmake.lua +++ b/surface_integral/xmake.lua @@ -4,4 +4,10 @@ internal_library("surface_integral", "SI", os.scriptdir()) add_rules("config.indirect_predicates.flags") 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() \ No newline at end of file