Problem: C++ Implementation of CFD Scheme Stability and Convergence Analysis

The problem requires implementing a series of C++ utility functions for computational fluid dynamics numerical scheme analysis, covering CFL calculation, stability judgment, error metrics computation, von Neumann stability verification for leap-frog and Lax-Wendroff schemes, error prediction and convergence verification, packaged as structs holding corresponding function pointers to support CFD numerical scheme performance evaluation.


Input/Output: The problem receives as input double-precision floating-point values for advection velocity c, time step dt, spatial step dx, CFL number, wavenumber k, maximum wavenumber k_max, initial error scalar, expected convergence order, and integer number of time steps. It also accepts standard string inputs specifying the numerical scheme (either "leap_frog" or "lax_wendroff"), and double-precision vector inputs for numerical solution arrays, analytical solution arrays, initial error arrays, spatial step size arrays, and error magnitude arrays.
The problem outputs a struct containing 12 type-matched function pointers that implement core CFD numerical analysis utilities: CFL calculation, explicit stability judgment, L2 and maximum error calculation, leap-frog and Lax-Wendroff amplification factor computation, von Neumann stability verification, error growth calculation, long-term error prediction, convergence order calculation, and convergence verification. Each function pointer maps to corresponding input parameters to return the specified computed result or perform the required analysis operation.

Required dependencies:

Sub-steps:
step_number: 1
step_description_prompt: Please use C++ to implement a function named subproblem_8_1_functions. This function shall implement CFL number calculation, stability judgment, L2 and max error calculation, von Neumann stability verification for leap-frog and Lax-Wendroff schemes, error growth prediction and convergence order calculation, and return a struct holding corresponding function pointers.
function_header: auto subproblem_8_1_functions() {
    struct Result
test_cases: int main() {
    unsigned int seed = 12345;
    srand(seed);
    
    auto funcs = subproblem_8_1_functions();
    auto calculate_cfl = funcs.calculate_cfl;
    auto is_stable = funcs.is_stable;
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        std::vector<double> velocities = {1.0, -1.0, 2.5, -0.75, 10.0};
        std::vector<double> time_steps = {0.1, 0.5, 1.0, 0.25, 2.0};
        std::vector<double> spatial_steps = {0.5, 1.0, 2.0, 0.25, 5.0};
        
        int stable_count = 0, unstable_count = 0;
        int total_tests = 0;
        bool all_correct = true;
        
        for (size_t i = 0; i < velocities.size(); ++i) {
            for (size_t j = 0; j < time_steps.size(); ++j) {
                for (size_t k = 0; k < spatial_steps.size(); ++k) {
                    double c = velocities[i];
                    double dt = time_steps[j];
                    double dx = spatial_steps[k];
                    
                    if (dx < 1e-10) continue;
                    
                    total_tests++;
                    double cfl = calculate_cfl(c, dt, dx);
                    bool stable = is_stable(cfl);
                    
                    if (stable) stable_count++;
                    else unstable_count++;
                    
                    double expected_cfl = std::abs(c) * dt / dx;
                    bool correct = (std::abs(cfl - expected_cfl) < 1e-10);
                    if (!correct) all_correct = false;
                }
            }
        }
        
        test1_passed = (total_tests >= 50 && all_correct && stable_count > 0 && unstable_count > 0);
        std::cout << "Test 1: " << (test1_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> cfl_targets = {0.99, 0.999, 0.9999, 1.0, 1.0001, 1.001, 1.01};
        double c = 1.0;
        double dx = 1.0;
        
        int correct_count = 0;
        for (size_t i = 0; i < cfl_targets.size(); ++i) {
            double target_cfl = cfl_targets[i];
            double dt = target_cfl * dx / c;
            
            double calculated_cfl = calculate_cfl(c, dt, dx);
            bool stable = is_stable(calculated_cfl);
            bool expected_stable = (target_cfl <= 1.0);
            
            bool correct = (stable == expected_stable) && (std::abs(calculated_cfl - target_cfl) < 1e-6);
            if (correct) correct_count++;
        }
        
        test2_passed = (correct_count == cfl_targets.size());
        std::cout << "Test 2: " << (test2_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        double c1 = 100.0, dx1 = 0.01;
        std::vector<double> dt1_values = {1e-5, 5e-5, 1e-4, 2e-4};
        int scenario1_correct = 0;
        for (double dt : dt1_values) {
            double cfl = calculate_cfl(c1, dt, dx1);
            bool stable = is_stable(cfl);
            bool expected = (cfl <= 1.0);
            if (stable == expected) scenario1_correct++;
        }
        
        double c2 = 0.1, dx2 = 10.0;
        std::vector<double> dt2_values = {10.0, 50.0, 100.0, 150.0};
        int scenario2_correct = 0;
        for (double dt : dt2_values) {
            double cfl = calculate_cfl(c2, dt, dx2);
            bool stable = is_stable(cfl);
            bool expected = (cfl <= 1.0);
            if (stable == expected) scenario2_correct++;
        }
        
        std::vector<double> c3_values = {0.5, 1.0, 2.0, 3.0, 4.0, 5.0};
        double dt3 = 0.1, dx3 = 1.0;
        int scenario3_correct = 0;
        for (double c : c3_values) {
            double cfl = calculate_cfl(c, dt3, dx3);
            bool stable = is_stable(cfl);
            bool expected = (cfl <= 1.0);
            if (stable == expected) scenario3_correct++;
        }
        
        test3_passed = (scenario1_correct == dt1_values.size() && 
                       scenario2_correct == dt2_values.size() && 
                       scenario3_correct == c3_values.size());
        std::cout << "Test 3: " << (test3_passed ? "correct" : "wrong") << "\n";
    }
    
    return 0;
}

step_number: 2
step_description_prompt: Please use C++ to write a function named subproblem_8_2_functions. This function returns a struct holding multiple function pointers for computational fluid dynamics numerical scheme analysis, including CFL calculation, stability judgment, error computation, von Neumann stability analysis, and convergence verification for leapfrog and Lax-Wendroff schemes.
function_header: auto subproblem_8_2_functions() {
    struct Result
test_cases: int main() {
    unsigned int seed = 12345;
    srand(seed);
    
    auto funcs = subproblem_8_2_functions();
    auto calculate_cfl = funcs.calculate_cfl;
    auto is_stable = funcs.is_stable;
    auto calculate_l2_error = funcs.calculate_l2_error;
    auto calculate_max_error = funcs.calculate_max_error;
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        size_t n = 1000;
        std::vector<double> numerical(n), analytical(n);
        
        for (size_t i = 0; i < n; ++i) {
            double x = 2.0 * PI * i / n;
            analytical[i] = sin(x);
            numerical[i] = analytical[i] + 0.01 * sin(10.0 * x);
        }
        double l2_1 = calculate_l2_error(numerical, analytical);
        double max_1 = calculate_max_error(numerical, analytical);
        
        for (size_t i = 0; i < n; ++i) {
            analytical[i] = i * 0.001;
            double error = 0.001 * (1.0 + 0.1 * sin(i * 0.1));
            if (i % 100 == 0) error *= 10.0;
            numerical[i] = analytical[i] + error;
        }
        double l2_2 = calculate_l2_error(numerical, analytical);
        double max_2 = calculate_max_error(numerical, analytical);
        
        for (size_t i = 0; i < n; ++i) {
            analytical[i] = exp(-0.001 * i);
            double small_error = 1e-6 * (1.0 + 0.5 * sin(i * 0.01));
            double large_error = (i % 200 == 0) ? 0.1 : 0.0;
            numerical[i] = analytical[i] + small_error + large_error;
        }
        double l2_3 = calculate_l2_error(numerical, analytical);
        double max_3 = calculate_max_error(numerical, analytical);
        
        bool pattern1_ok = (l2_1 > 0 && l2_1 < 0.1 && max_1 > 0 && max_1 < 0.1);
        bool pattern2_ok = (l2_2 > 0 && max_2 > 0.01);
        bool pattern3_ok = (l2_3 > 0 && max_3 >= 0.1);
        
        test1_passed = (pattern1_ok && pattern2_ok && pattern3_ok);
        std::cout << "Test 1: " << (test1_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        size_t n = 500;
        std::vector<double> numerical(n), analytical(n);
        
        for (size_t i = 0; i < n; ++i) {
            analytical[i] = 1.0;
            double boundary_factor = std::min(i, n - 1 - i) / double(n / 10);
            double error = 0.1 * exp(-boundary_factor);
            numerical[i] = analytical[i] + error;
        }
        double l2_boundary = calculate_l2_error(numerical, analytical);
        double max_boundary = calculate_max_error(numerical, analytical);
        
        size_t discontinuity = n / 2;
        for (size_t i = 0; i < n; ++i) {
            analytical[i] = (i < discontinuity) ? 0.0 : 1.0;
            double error = (std::abs(int(i) - int(discontinuity)) < 10) ? 0.5 : 0.001;
            numerical[i] = analytical[i] + error;
        }
        double l2_disc = calculate_l2_error(numerical, analytical);
        double max_disc = calculate_max_error(numerical, analytical);
        
        for (size_t i = 0; i < n; ++i) {
            analytical[i] = i * 0.01;
            double error = 0.01 * ((i % 2 == 0) ? 1.0 : -1.0);
            numerical[i] = analytical[i] + error;
        }
        double l2_osc = calculate_l2_error(numerical, analytical);
        double max_osc = calculate_max_error(numerical, analytical);
        
        bool case1_ok = (l2_boundary > 0 && max_boundary > 0.05);
        bool case2_ok = (l2_disc > 0 && max_disc >= 0.5);
        bool case3_ok = (l2_osc > 0 && max_osc >= 0.01);
        
        test2_passed = (case1_ok && case2_ok && case3_ok);
        std::cout << "Test 2: " << (test2_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        size_t n1 = 100;
        std::vector<double> num1(n1), ana1(n1);
        for (size_t i = 0; i < n1; ++i) {
            ana1[i] = i * 1e-10;
            num1[i] = ana1[i] + 1e-12 * (i % 10);
        }
        double l2_scale1 = calculate_l2_error(num1, ana1);
        double max_scale1 = calculate_max_error(num1, ana1);
        
        size_t n2 = 500;
        std::vector<double> num2(n2), ana2(n2);
        for (size_t i = 0; i < n2; ++i) {
            ana2[i] = sin(2.0 * PI * i / n2);
            num2[i] = ana2[i] + 0.001 * (1.0 + 0.1 * sin(10.0 * PI * i / n2));
        }
        double l2_scale2 = calculate_l2_error(num2, ana2);
        double max_scale2 = calculate_max_error(num2, ana2);
        
        size_t n3 = 200;
        std::vector<double> num3(n3), ana3(n3);
        for (size_t i = 0; i < n3; ++i) {
            ana3[i] = i * 0.1;
            num3[i] = ana3[i] + 0.1 * (1.0 + 0.5 * sin(i * 0.1));
        }
        double l2_scale3 = calculate_l2_error(num3, ana3);
        double max_scale3 = calculate_max_error(num3, ana3);
        
        bool scale1_ok = (l2_scale1 < 1e-10 && max_scale1 < 1e-10);
        bool scale2_ok = (l2_scale2 > 1e-4 && l2_scale2 < 1e-2 && max_scale2 > 0.001);
        bool scale3_ok = (l2_scale3 > 0.01 && max_scale3 > 0.1);
        
        test3_passed = (scale1_ok && scale2_ok && scale3_ok);
        std::cout << "Test 3: " << (test3_passed ? "correct" : "wrong") << "\n";
    }
    
    return 0;
}

step_number: 3
step_description_prompt: Please write C++ code to generate a function named subproblem_8_3_functions. The function returns a struct containing function pointers for common CFD numerical analysis utilities, covering CFL calculation, stability check, error computation, amplification factor calculation for leap-frog and Lax-Wendroff schemes, von Neumann stability analysis, error prediction and convergence verification.
function_header: auto subproblem_8_3_functions() {
    struct Result
test_cases: int main() {
    unsigned int seed = 12345;
    srand(seed);
    
    auto funcs = subproblem_8_3_functions();
    auto calculate_cfl = funcs.calculate_cfl;
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        std::vector<double> dx_values = {2.0, 1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625};
        std::vector<double> cfl_targets = {0.1, 0.3, 0.5, 0.7, 0.9, 0.99, 0.999, 1.0};
        std::vector<double> velocities = {0.5, 1.0, 2.0, 5.0, 10.0};
        
        int total_tests = 0;
        int correct_tests = 0;
        
        for (double c : velocities) {
            for (double target_cfl : cfl_targets) {
                for (double dx : dx_values) {
                    double dt = target_cfl * dx / c;
                    double calculated_cfl = calculate_cfl(c, dt, dx);
                    double error = std::abs(calculated_cfl - target_cfl);
                    
                    total_tests++;
                    if (error < 1e-8) correct_tests++;
                }
            }
        }
        
        double success_rate = 100.0 * correct_tests / total_tests;
        
        test1_passed = (success_rate > 99.9 && total_tests >= 200);
        std::cout << "Test 1: " << (test1_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        double c = 1.0;
        double initial_dx = 1.0;
        double max_cfl = 0.8;
        int refinement_levels = 6;
        
        std::vector<double> dx_sequence;
        std::vector<double> dt_sequence;
        std::vector<double> cfl_sequence;
        
        for (int level = 0; level < refinement_levels; ++level) {
            double dx = initial_dx / std::pow(2.0, level);
            double dt = max_cfl * dx / c;
            double cfl = calculate_cfl(c, dt, dx);
            
            dx_sequence.push_back(dx);
            dt_sequence.push_back(dt);
            cfl_sequence.push_back(cfl);
        }
        
        bool all_stable = true;
        bool all_consistent = true;
        for (size_t i = 0; i < cfl_sequence.size(); ++i) {
            if (cfl_sequence[i] > max_cfl + 1e-6) all_stable = false;
            if (std::abs(cfl_sequence[i] - max_cfl) > 1e-6) all_consistent = false;
        }
        
        test2_passed = (all_stable && all_consistent && dt_sequence[0] > dt_sequence.back());
        std::cout << "Test 2: " << (test2_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> c_range = {0.1, 0.5, 1.0, 2.0, 5.0, 10.0};
        std::vector<double> dx_range = {0.01, 0.1, 0.5, 1.0, 2.0, 5.0};
        std::vector<double> dt_range = {0.001, 0.01, 0.1, 0.5, 1.0, 2.0};
        
        int stable_count = 0;
        int unstable_count = 0;
        int total_combinations = 0;
        
        for (double c : c_range) {
            for (double dx : dx_range) {
                if (dx < 1e-10) continue;
                for (double dt : dt_range) {
                    total_combinations++;
                    double cfl = calculate_cfl(c, dt, dx);
                    bool stable = (cfl <= 1.0);
                    
                    if (stable) stable_count++;
                    else unstable_count++;
                }
            }
        }
        
        bool reasonable = (stable_count > 0 && unstable_count > 0 && total_combinations >= 100);
        
        test3_passed = reasonable;
        std::cout << "Test 3: " << (test3_passed ? "correct" : "wrong") << "\n";
    }
    
    return 0;
}

step_number: 4
step_description_prompt: Please use C++ code to implement a function named subproblem_8_4_functions. This function returns a struct holding function pointers for computational fluid dynamics related computations, including CFL number calculation, error metrics calculation, von Neumann stability check, amplification factor calculation for leap-frog and Lax-Wendroff schemes, and convergence analysis utilities.
function_header: auto subproblem_8_4_functions() {
    struct Result
test_cases: int main() {
    unsigned int seed = 12345;
    srand(seed);
    
    auto funcs = subproblem_8_4_functions();
    auto amplification_factor_leap_frog = funcs.amplification_factor_leap_frog;
    auto amplification_factor_lax_wendroff = funcs.amplification_factor_lax_wendroff;
    auto is_stable_von_neumann = funcs.is_stable_von_neumann;
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        std::vector<double> cfl_values = {0.1, 0.3, 0.5, 0.7, 0.9, 0.99, 1.0};
        std::vector<double> k_values = {0.1, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, PI};
        
        int leap_frog_stable = 0, leap_frog_unstable = 0;
        int lax_wendroff_stable = 0, lax_wendroff_unstable = 0;
        int total_tests = 0;
        
        for (double cfl : cfl_values) {
            for (double k : k_values) {
                total_tests++;
                std::complex<double> G = amplification_factor_leap_frog(k, cfl);
                double abs_G = std::abs(G);
                bool stable = (abs_G <= 1.0 + 1e-6);
                
                if (stable) leap_frog_stable++;
                else leap_frog_unstable++;
            }
        }
        
        int total_tests_lw = 0;
        for (double cfl : cfl_values) {
            for (double k : k_values) {
                total_tests_lw++;
                std::complex<double> G = amplification_factor_lax_wendroff(k, cfl);
                double abs_G = std::abs(G);
                bool stable = (abs_G <= 1.0 + STABILITY_TOLERANCE);
                
                if (stable) lax_wendroff_stable++;
                else lax_wendroff_unstable++;
            }
        }
        
        bool lf_ok = (leap_frog_stable > 0 && total_tests >= 50);
        bool lw_ok = (lax_wendroff_stable > 0 && total_tests_lw >= 50);
        
        int lw_stable_cfl_leq1 = 0, lw_total_cfl_leq1 = 0;
        for (double cfl : cfl_values) {
            if (cfl <= 1.0) {
                for (double k : k_values) {
                    lw_total_cfl_leq1++;
                    std::complex<double> G = amplification_factor_lax_wendroff(k, cfl);
                    if (std::abs(G) <= 1.0 + STABILITY_TOLERANCE) lw_stable_cfl_leq1++;
                }
            }
        }
        bool lw_stable_mostly = (lw_total_cfl_leq1 > 0 && lw_stable_cfl_leq1 * 100.0 / lw_total_cfl_leq1 > 95.0);
        
        test1_passed = (lf_ok && lw_ok && lw_stable_mostly);
        std::cout << "Test 1: " << (test1_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> critical_cfl = {0.99, 0.999, 0.9999, 1.0, 1.0001, 1.001, 1.01};
        std::vector<double> critical_k = {0.1, 1.0, PI/2, PI, 2*PI};
        
        int critical_tests = 0;
        int critical_correct = 0;
        
        for (double cfl : critical_cfl) {
            for (double k : critical_k) {
                critical_tests++;
                
                std::complex<double> G_lf = amplification_factor_leap_frog(k, cfl);
                std::complex<double> G_lw = amplification_factor_lax_wendroff(k, cfl);
                
                double abs_G_lf = std::abs(G_lf);
                double abs_G_lw = std::abs(G_lw);
                
                bool stable_lf = (abs_G_lf <= 1.0 + STABILITY_TOLERANCE);
                bool stable_lw = (abs_G_lw <= 1.0 + STABILITY_TOLERANCE);
                
                bool correct = false;
                if (cfl > 1.0) {
                    correct = (!stable_lw);
                } else {
                    correct = stable_lw;
                }
                if (correct) critical_correct++;
            }
        }
        
        double critical_success = 100.0 * critical_correct / critical_tests;
        
        test2_passed = (critical_success > 80.0 && critical_tests >= 30);
        std::cout << "Test 2: " << (test2_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> cfl_range = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 1.0, 1.1, 1.2};
        double k_max = 2.0 * PI;
        
        std::map<double, std::pair<bool, bool>> stability_map;
        
        for (double cfl : cfl_range) {
            bool lf_stable = is_stable_von_neumann("leap_frog", cfl, k_max);
            bool lw_stable = is_stable_von_neumann("lax_wendroff", cfl, k_max);
            stability_map[cfl] = {lf_stable, lw_stable};
        }
        
        int lf_stable_count = 0, lw_stable_count = 0;
        for (const auto& entry : stability_map) {
            if (entry.second.first) lf_stable_count++;
            if (entry.second.second) lw_stable_count++;
        }
        
        bool lw_correct = true;
        int lw_stable_cfl_leq1 = 0, lw_unstable_cfl_leq1 = 0;
        int lf_stable_cfl_leq1 = 0, lf_unstable_cfl_leq1 = 0;
        
        for (double cfl : cfl_range) {
            if (cfl <= 1.0) {
                if (stability_map[cfl].second) lw_stable_cfl_leq1++;
                else lw_unstable_cfl_leq1++;
                
                if (stability_map[cfl].first) lf_stable_cfl_leq1++;
                else lf_unstable_cfl_leq1++;
                
                if (!stability_map[cfl].second) lw_correct = false;
            }
        }
        
        test3_passed = (lw_correct && lf_stable_count > 0 && lw_stable_count > 0 && lw_stable_cfl_leq1 > 0);
        std::cout << "Test 3: " << (test3_passed ? "correct" : "wrong") << "\n";
    }
    
    return 0;
}

step_number: 5
step_description_prompt: Please use C++ code to generate a function named subproblem_8_5_functions. This function returns a struct holding 12 function pointers for common CFD numerical analysis utilities, covering CFL calculation, stability judgment, error calculation, amplification factor calculation for leap-frog and Lax-Wendroff schemes, von Neumann stability check, error growth prediction, and convergence order verification. Implement all required internal logic correctly.
function_header: auto subproblem_8_5_functions() {
    struct Result
test_cases: int main() {
    unsigned int seed = 12345;
    srand(seed);
    
    auto funcs = subproblem_8_5_functions();
    auto calculate_error_growth = funcs.calculate_error_growth;
    auto predict_long_term_error = funcs.predict_long_term_error;
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        std::vector<double> initial_errors = {1e-8, 1e-6, 1e-4, 1e-2, 0.1, 1.0};
        std::vector<double> cfl_values = {0.1, 0.3, 0.5, 0.7, 0.9, 0.99, 1.0, 1.1, 1.5};
        std::vector<int> step_counts = {10, 50, 100, 500, 1000};
        std::vector<std::string> schemes = {"leap_frog", "lax_wendroff"};
        
        int total_tests = 0;
        int valid_tests = 0;
        
        for (const std::string& scheme : schemes) {
            for (double error0 : initial_errors) {
                for (double cfl : cfl_values) {
                    for (int n_steps : step_counts) {
                        total_tests++;
                        
                        std::vector<double> error_vec = {error0};
                        double growth = calculate_error_growth(error_vec, cfl, n_steps, scheme);
                        double predicted = predict_long_term_error(error0, cfl, n_steps, scheme);
                        
                        bool valid = (growth >= 0.0 && predicted >= error0 && predicted < 1e10);
                        if (valid) valid_tests++;
                    }
                }
            }
        }
        
        double success_rate = 100.0 * valid_tests / total_tests;
        
        test1_passed = (success_rate > 95.0 && total_tests >= 200);
        std::cout << "Test 1: " << (test1_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> initial_errors = {1e-6, 1e-4, 1e-2, 0.1};
        std::vector<double> base_cfl = {0.3, 0.5, 0.7, 0.9};
        std::vector<int> time_horizons = {100, 500, 1000, 5000, 10000};
        
        int evolution_tests = 0;
        int evolution_correct = 0;
        
        for (double error0 : initial_errors) {
            for (double cfl : base_cfl) {
                for (int n_steps : time_horizons) {
                    evolution_tests++;
                    
                    double predicted = predict_long_term_error(error0, cfl, n_steps, "leap_frog");
                    
                    bool monotonic = true;
                    if (cfl > 1.0 && predicted < error0) monotonic = false;
                    
                    bool bounded = (predicted >= error0 && predicted < 1e15);
                    
                    if (monotonic && bounded) evolution_correct++;
                }
            }
        }
        
        double evolution_success = 100.0 * evolution_correct / evolution_tests;
        
        test2_passed = (evolution_success > 90.0 && evolution_tests >= 60);
        std::cout << "Test 2: " << (test2_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> error0_values = {1e-5, 1e-3, 0.01, 0.1};
        std::vector<double> cfl_values = {0.3, 0.5, 0.7, 0.9, 0.99};
        int n_steps = 1000;
        
        std::map<std::string, std::vector<double>> scheme_predictions;
        
        for (const std::string& scheme : {"leap_frog", "lax_wendroff"}) {
            scheme_predictions[scheme] = std::vector<double>();
            
            for (double error0 : error0_values) {
                for (double cfl : cfl_values) {
                    double predicted = predict_long_term_error(error0, cfl, n_steps, scheme);
                    scheme_predictions[scheme].push_back(predicted);
                }
            }
        }
        
        bool schemes_different = false;
        if (scheme_predictions["leap_frog"].size() == scheme_predictions["lax_wendroff"].size()) {
            for (size_t i = 0; i < scheme_predictions["leap_frog"].size(); ++i) {
                double diff = std::abs(scheme_predictions["leap_frog"][i] - scheme_predictions["lax_wendroff"][i]);
                if (diff > 1e-10) schemes_different = true;
            }
        }
        
        bool all_reasonable = true;
        for (const auto& entry : scheme_predictions) {
            for (double pred : entry.second) {
                if (pred < 0 || pred > 1e15) all_reasonable = false;
            }
        }
        
        test3_passed = (all_reasonable && scheme_predictions["leap_frog"].size() >= 15);
        std::cout << "Test 3: " << (test3_passed ? "correct" : "wrong") << "\n";
    }
    
    return 0;
}

step_number: 6
step_description_prompt: Please write C++ code to implement a function named subproblem_8_6_functions. The function returns a struct holding function pointers for CFD numerical analysis utilities, covering CFL calculation, stability check, error computation, von Neumann analysis, and convergence verification for leap-frog and Lax-Wendroff schemes.
function_header: auto subproblem_8_6_functions() {
    struct Result
test_cases: int main() {
    unsigned int seed = 12345;
    srand(seed);
    
    auto funcs = subproblem_8_6_functions();
    auto calculate_order_of_accuracy = funcs.calculate_order_of_accuracy;
    auto verify_convergence = funcs.verify_convergence;
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        std::vector<double> dx1 = {2.0, 1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625};
        std::vector<double> errors1;
        for (double dx : dx1) {
            errors1.push_back(1.0 * dx * dx);
        }
        
        double order1 = calculate_order_of_accuracy(dx1, errors1);
        bool verified1 = verify_convergence(dx1, errors1, 2.0);
        
        std::vector<double> dx2 = {1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125};
        std::vector<double> errors2;
        for (double dx : dx2) {
            errors2.push_back(0.5 * dx);
        }
        
        double order2 = calculate_order_of_accuracy(dx2, errors2);
        bool verified2 = verify_convergence(dx2, errors2, 1.0);
        
        std::vector<double> dx3 = {1.0, 0.5, 0.25, 0.125, 0.0625};
        std::vector<double> errors3;
        for (double dx : dx3) {
            errors3.push_back(0.1 * dx * dx * dx * dx);
        }
        
        double order3 = calculate_order_of_accuracy(dx3, errors3);
        bool verified3 = verify_convergence(dx3, errors3, 4.0);
        
        bool case1_ok = (order1 > 1.8 && order1 < 2.2 && verified1);
        bool case2_ok = (order2 > 0.8 && order2 < 1.2 && verified2);
        bool case3_ok = (order3 > 3.5 && order3 < 4.5 && verified3);
        
        test1_passed = (case1_ok && case2_ok && case3_ok);
        std::cout << "Test 1: " << (test1_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> dx_base = {1.0, 0.5, 0.25, 0.125, 0.0625};
        
        std::vector<double> errors_upwind;
        for (double dx : dx_base) {
            errors_upwind.push_back(2.0 * dx);
        }
        double order_upwind = calculate_order_of_accuracy(dx_base, errors_upwind);
        
        std::vector<double> errors_centered;
        for (double dx : dx_base) {
            errors_centered.push_back(1.5 * dx * dx);
        }
        double order_centered = calculate_order_of_accuracy(dx_base, errors_centered);
        
        std::vector<double> errors_compact;
        for (double dx : dx_base) {
            errors_compact.push_back(0.5 * dx * dx * dx * dx);
        }
        double order_compact = calculate_order_of_accuracy(dx_base, errors_compact);
        
        bool orders_correct = (order_upwind < order_centered && order_centered < order_compact);
        
        bool upwind_ok = (order_upwind > 0.8 && order_upwind < 1.2);
        bool centered_ok = (order_centered > 1.8 && order_centered < 2.2);
        bool compact_ok = (order_compact > 3.5 && order_compact < 4.5);
        
        test2_passed = (upwind_ok && centered_ok && compact_ok && orders_correct);
        std::cout << "Test 2: " << (test2_passed ? "correct" : "wrong") << "\n";
    }
    
    {
        std::vector<double> dx_ideal = {1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125};
        std::vector<double> errors_ideal;
        for (double dx : dx_ideal) {
            errors_ideal.push_back(1.0 * dx * dx);
        }
        double order_ideal = calculate_order_of_accuracy(dx_ideal, errors_ideal);
        
        std::vector<double> errors_noisy;
        for (size_t i = 0; i < dx_ideal.size(); ++i) {
            double base_error = 1.0 * dx_ideal[i] * dx_ideal[i];
            double noise = 0.01 * base_error * (1.0 + 0.1 * sin(i));
            errors_noisy.push_back(base_error + noise);
        }
        double order_noisy = calculate_order_of_accuracy(dx_ideal, errors_noisy);
        
        std::vector<double> dx_irregular = {1.0, 0.6, 0.3, 0.15, 0.08, 0.04};
        std::vector<double> errors_irregular;
        for (size_t i = 0; i < dx_irregular.size(); ++i) {
            double order_mix = (i < 3) ? 1.0 : 2.0;
            errors_irregular.push_back(0.5 * std::pow(dx_irregular[i], order_mix));
        }
        double order_irregular = calculate_order_of_accuracy(dx_irregular, errors_irregular);
        
        std::vector<double> errors_saturated;
        for (size_t i = 0; i < dx_ideal.size(); ++i) {
            double base = 1.0 * dx_ideal[i] * dx_ideal[i];
            double saturation = (i >= 5) ? 1e-10 : 0.0;
            errors_saturated.push_back(std::max(base, saturation));
        }
        double order_saturated = calculate_order_of_accuracy(dx_ideal, errors_saturated);
        
        bool ideal_ok = (order_ideal > 1.9 && order_ideal < 2.1);
        bool noisy_ok = (order_noisy > 1.5 && order_noisy < 2.5);
        bool irregular_ok = (order_irregular > 0.5 && order_irregular < 3.0);
        bool saturated_ok = (order_saturated > -1.0 && order_saturated < 5.0 && !std::isnan(order_saturated) && !std::isinf(order_saturated));
        
        test3_passed = (ideal_ok && noisy_ok && irregular_ok && saturated_ok);
        std::cout << "Test 3: " << (test3_passed ? "correct" : "wrong") << "\n";
    }
    
    return 0;
}

General solution:

General tests: