Problem: C++ Implementation of 2D Tracer Transport System

The problem aims to develop a complete 2D tracer transport simulation system using C++. It covers core components including data structure design, velocity field generation, numerical advection calculation, boundary condition processing, numerical stability monitoring, and modular framework construction to support reliable tracer transport simulation, validation and performance optimization for relevant fluid dynamics scenarios.


Input/Output: The problem receives the following input data: 1) Simulation configuration parameters: size_t-type x-direction grid count nx, y-direction grid count ny, time step count nt; double-type x grid spacing dx, y grid spacing dy, time step length dt; 2) Velocity field generation parameters: double-type scaling factor F, vertical domain size b, exponential coefficients p, q, A, B; 3) Numerical calculation inputs: 2D double vector tracer concentration field Q, maximum horizontal velocity u_max, maximum vertical velocity v_max, boundary condition type identifier, numerical scheme selection flag.
The problem generates the following output results: 1) Initialized TracerTransportSystem instance with pre-allocated storage for concentration and velocity fields; 2) Computed 2D u and v velocity field arrays; 3) Advection term values from the selected upwind or centered difference scheme; 4) Tracer concentration array after applying specified zero or periodic boundary conditions; 5) Double-type 2D CFL stability number, and boolean validation flags for each functional module.
All input parameters are processed in sequence: first to initialize the simulation system, then generate velocity fields, compute numerical terms, apply boundary conditions, conduct stability checks, and map directly to corresponding output results.

Required dependencies:

Sub-steps:
step_number: 1
step_description_prompt: Please write C++ code to implement the problem_5_01 function.
Algorithm process: First declare all required global function double pointers and the PI constant, define the TracerTransportSystem class inside the function, implement its initialize method and 2D velocity field generation method following specified mathematical formulas, add all required empty class methods and corresponding getter functions as required.
function_header: void problem_5_01() 
test_cases: int main() {
    // Initialize by calling problem_5_01
    problem_5_01();

    std::cout << "========================================\n";
    std::cout << "Problem 5-Subproblem 1: Data Structure Design and Velocity Field Generation\n";
    std::cout << "========================================\n";

    bool test1_passed = false, test2_passed = false, test3_passed = false;

    {
        TracerTransportSystem system;
        system.initialize(101, 51, 100, 100.0, 100.0, 3600.0);
        system.generate_velocity_field(1.0, 5000, 0.05, 0.95, 2e-4, 1.3e-3);

        double test_u = 1.0 * (3.14159265358979323846 / 5000) * cos(3.14159265358979323846 * 2500 / 5000) * 
                       (0.05 * exp(2e-4 * 1000) + 0.95 * exp(-1.3e-3 * 1000) - 1.0);

        test1_passed = (system.get_nx() == 101 && system.get_ny() == 51 && system.get_nt() == 100 && std::abs(test_u) < 0.01);
        if (test1_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }

    {
        TracerTransportSystem system;
        system.initialize(201, 101, 500, 100.0, 100.0, 3600.0);
        system.generate_velocity_field(2.0, 5000, 0.1, 0.9, 3e-4, 2e-3);

        double test_u = 2.0 * (3.14159265358979323846 / 5000) * cos(3.14159265358979323846 * 2500 / 5000) * 
                       (0.1 * exp(3e-4 * 1000) + 0.9 * exp(-2e-3 * 1000) - 1.0);

        test2_passed = (system.get_nx() == 201 && system.get_ny() == 101 && system.get_nt() == 500 && std::abs(test_u) < 0.001);
        if (test2_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }

    {
        TracerTransportSystem system;
        system.initialize(401, 201, 1000, 100.0, 100.0, 3600.0);
        system.generate_velocity_field(1.0, 5000, 0.05, 0.95, 2e-4, 1.3e-3);

        double test_v = -1.0 * sin(3.14159265358979323846 * 2500 / 5000) * 
                       (0.05 * 2e-4 * exp(2e-4 * 1000) - 0.95 * 1.3e-3 * exp(-1.3e-3 * 1000));

        test3_passed = (system.get_nx() == 401 && system.get_ny() == 201 && system.get_nt() == 1000 && std::abs(test_v) < 0.01);
        if (test3_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }

    std::cout << "\n========================================\n";
    if (test1_passed && test2_passed && test3_passed) {
        std::cout << "Completely correct!\n";
    }
    std::cout << "========================================\n";

    return 0;
}


step_number: 2
step_description_prompt: Please write C++ code to implement a function named problem_5_02. The function needs to implement 2D upwind advection and 2D centered difference calculation lambdas, assign function pointers of the two lambdas to corresponding incoming external pointer parameters, add necessary boundary and invalid value checks for calculations.
function_header: void problem_5_02() 
test_cases: int main() {
    // Function pointers in main
    double (*upwind_advection_2d_ptr)(int, int, const std::vector<std::vector<double>>&, double, double, double, double) = nullptr;
    double (*centered_diff_2d_ptr)(int, int, const std::vector<std::vector<double>>&, double, double, double, double) = nullptr;

    // Set up pointer-to-pointer so problem_5_02 can set our function pointers
    upwind_advection_2d_pptr = &upwind_advection_2d_ptr;
    centered_diff_2d_pptr = &centered_diff_2d_ptr;

    // Initialize problem function (it will set function pointers)
    problem_5_02();

    std::cout << "========================================\n";
    std::cout << "Problem 5-Subproblem 2: Numerical Scheme Selection and Source Term Handling\n";
    std::cout << "========================================\n";
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    
    {
        
        std::vector<std::vector<double>> Q(15, std::vector<double>(15));
        for (int i = 0; i < 15; ++i) {
            for (int j = 0; j < 15; ++j) {
                
                double x = (i - 7) * 0.5;
                double y = (j - 7) * 0.5;
                Q[i][j] = 2.5 + 1.5 * exp(-(x*x + y*y) / 2.0) + 0.3 * sin(i * 0.7) + 0.2 * cos(j * 0.5);
            }
        }
        
        
        double u = 1.5 + 0.3 * sin(2.0 * 3.14159 / 7.0);  
        double v = 1.2 + 0.25 * cos(2.0 * 3.14159 / 7.0); 
        double dx = 0.75, dy = 0.85;  
        
        double result = upwind_advection_2d_ptr(7, 7, Q, u, v, dx, dy);
        
        
        double Q_curr = Q[7][7];
        double Q_left = Q[6][7];
        double Q_below = Q[7][6];
        double expected = -u * (Q_curr - Q_left) / dx - v * (Q_curr - Q_below) / dy;
        
        test1_passed = (std::abs(result - expected) < 1e-8);
        if (test1_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<std::vector<double>> Q(11, std::vector<double>(11));
        for (int i = 0; i < 11; ++i) {
            for (int j = 0; j < 11; ++j) {
                
                double x = (i - 5) * 0.8;
                double y = (j - 5) * 0.6;
                double r = sqrt(x*x + y*y);
                double theta = atan2(y, x);
                Q[i][j] = 3.0 + r * r * sin(2.0 * theta) + 0.5 * exp(-r*r / 4.0);
            }
        }
        
        
        double u = 2.3, v = 1.7;
        double dx = 1.2, dy = 0.9;  
        
        double result = centered_diff_2d_ptr(5, 5, Q, u, v, dx, dy);
        
        
        double Q_right = Q[6][5];
        double Q_left = Q[4][5];
        double Q_top = Q[5][6];
        double Q_bottom = Q[5][4];
        double expected = -u * (Q_right - Q_left) / (2.0 * dx) - v * (Q_top - Q_bottom) / (2.0 * dy);
        
        test2_passed = (std::abs(result - expected) < 1e-8);
        if (test2_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<std::vector<double>> Q(13, std::vector<double>(13));
        for (int i = 0; i < 13; ++i) {
            for (int j = 0; j < 13; ++j) {
                
                double x = (i - 6) * 0.5;
                double y = (j - 6) * 0.5;
                Q[i][j] = 4.0 + 2.0 * sin(x) * cos(y) + 1.0 * sin(3.0*x) * cos(2.0*y) + 0.5 * sin(7.0*x) * sin(5.0*y);
            }
        }
        
        
        double u1 = 1.8, v1 = 1.4;  // CFL ≈ 0.9
        double u2 = 3.6, v2 = 2.8;  // CFL ≈ 1.8
        double dx = 0.65, dy = 0.55;
        
        double result_upwind1 = upwind_advection_2d_ptr(6, 6, Q, u1, v1, dx, dy);
        double result_centered1 = centered_diff_2d_ptr(6, 6, Q, u1, v1, dx, dy);
        double result_upwind2 = upwind_advection_2d_ptr(6, 6, Q, u2, v2, dx, dy);
        
        
        
        std::vector<std::vector<double>> Q_test(13, std::vector<double>(13));
        for (int i = 0; i < 13; ++i) {
            for (int j = 0; j < 13; ++j) {
                
                if (i < 6) {
                    Q_test[i][j] = 5.0 + 2.0 * sin(j * 0.3);
                } else if (i == 6) {
                    Q_test[i][j] = 3.0 + 1.0 * sin(j * 0.3);
                } else {
                    Q_test[i][j] = 1.0 + 0.5 * sin(j * 0.3);
                }
            }
        }
        double result_upwind_test = upwind_advection_2d_ptr(6, 6, Q_test, u1, v1, dx, dy);
        double result_centered_test = centered_diff_2d_ptr(6, 6, Q_test, u1, v1, dx, dy);
        double diff_format = std::abs(result_upwind_test - result_centered_test);
        double diff_cfl = std::abs(result_upwind2 - result_upwind1);
        
        test3_passed = (diff_format > 0.1 && diff_cfl > 0.1 && 
                       std::isfinite(result_upwind1) && std::isfinite(result_centered1));
        if (test3_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    std::cout << "\n========================================\n";
    if (test1_passed && test2_passed && test3_passed) {
        std::cout << "Completely correct!\n";
    }
    std::cout << "========================================\n";
    
    return 0;
}

step_number: 3
step_description_prompt: Please use C++ to generate a function named problem_5_03. Implement three lambdas: one applies zero boundary conditions to 2D double vectors, one applies x-direction periodic boundary conditions to 2D double vectors, one calculates 2D CFL value, then convert lambdas to function pointers and assign them to corresponding input output function pointer parameters.
function_header: void problem_5_03() 
test_cases: int main() {
    // Function pointers in main
    void (*apply_zero_boundary_conditions_ptr)(std::vector<std::vector<double>>&) = nullptr;
    void (*apply_periodic_boundary_conditions_ptr)(std::vector<std::vector<double>>&) = nullptr;
    double (*calculate_cfl_2d_ptr)(double, double, double, double, double) = nullptr;

    // Set up pointer-to-pointer so problem_5_03 can set our function pointers
    apply_zero_boundary_conditions_pptr = &apply_zero_boundary_conditions_ptr;
    apply_periodic_boundary_conditions_pptr = &apply_periodic_boundary_conditions_ptr;
    calculate_cfl_2d_pptr = &calculate_cfl_2d_ptr;

    // Initialize problem function (it will set function pointers)
    problem_5_03();

    std::cout << "========================================\n";
    std::cout << "Problem 5-Subproblem 3: Boundary Condition Module and Time Integrator\n";
    std::cout << "========================================\n";
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    
    {
        
        std::vector<std::vector<double>> Q(21, std::vector<double>(21));
        for (int i = 0; i < 21; ++i) {
            for (int j = 0; j < 21; ++j) {
                double x = (i - 10) * 0.3;
                double y = (j - 10) * 0.3;
                Q[i][j] = 5.0 + 3.0 * exp(-(x*x + y*y) / 2.0) + 1.5 * sin(x) * cos(y);
            }
        }
        
        
        for (int step = 0; step < 3; ++step) {
            apply_zero_boundary_conditions_ptr(Q);
            
            for (int i = 1; i < 20; ++i) {
                for (int j = 1; j < 20; ++j) {
                    Q[i][j] *= 0.95;  
                }
            }
        }
        
        
        bool all_boundaries_zero = true;
        for (int i = 0; i < 21; ++i) {
            if (Q[i][0] != 0.0 || Q[i][20] != 0.0) all_boundaries_zero = false;
            if (Q[0][i] != 0.0 || Q[20][i] != 0.0) all_boundaries_zero = false;
        }
        
        
        bool interior_nonzero = (Q[10][10] > 0.0 && Q[10][10] < 10.0);
        
        test1_passed = (all_boundaries_zero && interior_nonzero);
        if (test1_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<double> u_max_values = {0.05, 0.8, 1.5, 2.8};
        std::vector<double> v_max_values = {0.04, 0.6, 1.2, 2.5};
        std::vector<double> dt_values = {900.0, 1800.0, 2700.0, 3600.0};
        std::vector<double> dx_values = {100.0, 100.0, 150.0, 200.0};
        std::vector<double> dy_values = {120.0, 120.0, 180.0, 240.0};
        
        
        std::vector<double> cfl_values;
        int stable_count = 0;
        for (size_t i = 0; i < u_max_values.size(); ++i) {
            double cfl = calculate_cfl_2d_ptr(u_max_values[i], v_max_values[i], 
                                         dt_values[i], dx_values[i], dy_values[i]);
            cfl_values.push_back(cfl);
            if (cfl <= 1.0) stable_count++;
        }
        
        
        bool cfl_reasonable = true;
        for (double cfl : cfl_values) {
            if (cfl < 0.0 || cfl > 200.0) cfl_reasonable = false;
        }
        
        
        bool cfl_monotonic = (cfl_values[1] > cfl_values[0] && 
                             cfl_values[2] > cfl_values[1] && 
                             cfl_values[3] > cfl_values[2]);
        
        double avg_cfl = (cfl_values[0] + cfl_values[1] + cfl_values[2] + cfl_values[3]) / 4.0;
        
        test2_passed = (cfl_reasonable && cfl_monotonic && stable_count >= 1 && avg_cfl > 0.0);
        if (test2_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<std::vector<double>> Q(17, std::vector<double>(17));
        for (int i = 0; i < 17; ++i) {
            for (int j = 0; j < 17; ++j) {
                double x = (i - 8) * 0.4;
                double y = (j - 8) * 0.4;
                Q[i][j] = 2.0 + 1.5 * sin(x) * cos(y) + 0.8 * exp(-(x*x + y*y) / 3.0);
            }
        }
        
        
        double right_boundary_value = 5.5 + 2.3 * sin(8.0 * 0.4);
        for (int j = 0; j < 17; ++j) {
            Q[16][j] = right_boundary_value + 0.5 * sin(j * 0.3);
        }
        
        
        for (int step = 0; step < 5; ++step) {
            apply_periodic_boundary_conditions_ptr(Q);
            
            for (int i = 1; i < 16; ++i) {
                for (int j = 0; j < 17; ++j) {
                    Q[i][j] *= 0.98;
                }
            }
        }
        
        
        bool periodic_ok = true;
        double max_diff = 0.0;
        for (int j = 0; j < 17; ++j) {
            double diff = std::abs(Q[0][j] - Q[16][j]);
            max_diff = std::max(max_diff, diff);
            if (diff > 1e-10) periodic_ok = false;
        }
        
        
        bool continuity_ok = true;
        for (int i = 1; i < 16; ++i) {
            for (int j = 1; j < 16; ++j) {
                if (std::isnan(Q[i][j]) || std::isinf(Q[i][j])) {
                    continuity_ok = false;
                    break;
                }
            }
            if (!continuity_ok) break;
        }
        
        test3_passed = (periodic_ok && continuity_ok && max_diff < 1e-10);
        if (test3_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    std::cout << "\n========================================\n";
    if (test1_passed && test2_passed && test3_passed) {
        std::cout << "Completely correct!\n";
    }
    std::cout << "========================================\n";
    
    return 0;
}

step_number: 4
step_description_prompt: Please use C++ to generate a function named problem_5_04.
Define a lambda called calculate_cfl_2d that takes 5 double parameters, computes the maximum 2D CFL number from input u_max, v_max, dt, dx and dy, returns a double value. Then assign the lambda to a static function pointer, then assign this pointer to *double_pptr if double_pptr is not null.
function_header: void problem_5_04() 
test_cases: int main() {
    double (*calculate_cfl_2d_ptr)(double, double, double, double, double) = nullptr;

    double_pptr = &calculate_cfl_2d_ptr;

    std::cout << "========================================\n";
    std::cout << "Problem 5-Subproblem 4: Numerical Stability Monitoring and Result Validation\n";
    std::cout << "========================================\n";
problem_5_04();    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    
    {
        
        std::vector<std::pair<double, double>> scenarios = {
            {0.5, 0.3}, {0.8, 0.6}, {1.0, 0.9}, {1.2, 1.0}, {1.5, 1.3}
        };
        std::vector<double> dt_values = {100.0, 80.0, 200.0, 4500.0, 5400.0};
        std::vector<double> dx_values = {80.0, 100.0, 120.0, 150.0, 180.0};
        std::vector<double> dy_values = {75.0, 100.0, 125.0, 150.0, 175.0};
        
        std::vector<double> cfl_values;
        int stable_count = 0;
        double max_stable_cfl = 0.0;
        
        for (size_t i = 0; i < scenarios.size(); ++i) {
            double cfl = calculate_cfl_2d_ptr(scenarios[i].first, scenarios[i].second,
                                         dt_values[i], dx_values[i], dy_values[i]);
            cfl_values.push_back(cfl);
            if (cfl <= 1.0) {
                stable_count++;
                max_stable_cfl = std::max(max_stable_cfl, cfl);
            }
        }
        
        
        double avg_cfl = 0.0;
        for (double cfl : cfl_values) avg_cfl += cfl;
        avg_cfl /= cfl_values.size();
        
        test1_passed = (stable_count >= 2 && max_stable_cfl <= 1.0 && avg_cfl > 0.0);
        if (test1_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<std::pair<double, double>> unstable_scenarios = {
            {2.5, 2.0}, {3.8, 3.2}, {5.2, 4.5}, {7.0, 6.0}
        };
        std::vector<double> dt_values = {3600.0, 4500.0, 5400.0, 7200.0};
        std::vector<double> dx_values = {100.0, 120.0, 150.0, 180.0};
        std::vector<double> dy_values = {100.0, 110.0, 140.0, 160.0};
        
        std::vector<double> cfl_values;
        int unstable_count = 0;
        double min_unstable_cfl = 1e10;
        double max_cfl = 0.0;
        
        for (size_t i = 0; i < unstable_scenarios.size(); ++i) {
            double cfl = calculate_cfl_2d_ptr(unstable_scenarios[i].first, unstable_scenarios[i].second,
                                         dt_values[i], dx_values[i], dy_values[i]);
            cfl_values.push_back(cfl);
            if (cfl > 1.0) {
                unstable_count++;
                min_unstable_cfl = std::min(min_unstable_cfl, cfl);
            }
            max_cfl = std::max(max_cfl, cfl);
        }
        
        
        std::vector<double> adjusted_dt;
        for (size_t i = 0; i < unstable_scenarios.size(); ++i) {
            double current_cfl = cfl_values[i];
            if (current_cfl > 1.0) {
                double adjusted = dt_values[i] / current_cfl;  
                adjusted_dt.push_back(adjusted);
            }
        }
        
        test2_passed = (unstable_count >= 3 && min_unstable_cfl > 1.0 && max_cfl > 10.0 && adjusted_dt.size() >= 3);
        if (test2_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<double> dx_seq = {200.0, 100.0, 50.0, 25.0, 12.5};
        std::vector<double> dy_seq = {180.0, 90.0, 45.0, 22.5, 11.25};
        double u = 2.5, v = 2.0;
        double dt = 3600.0;
        
        std::vector<double> cfl_seq;
        std::vector<double> convergence_rate;
        
        for (size_t i = 0; i < dx_seq.size(); ++i) {
            double cfl = calculate_cfl_2d_ptr(u, v, dt, dx_seq[i], dy_seq[i]);
            cfl_seq.push_back(cfl);
            if (i > 0) {
                
                double rate = cfl_seq[i] / cfl_seq[i-1];
                convergence_rate.push_back(rate);
            }
        }
        
        
        bool monotonic = true;
        for (size_t i = 1; i < cfl_seq.size(); ++i) {
            if (cfl_seq[i] <= cfl_seq[i-1]) {
                monotonic = false;
                break;
            }
        }
        
        
        double avg_rate = 0.0;
        for (double rate : convergence_rate) avg_rate += rate;
        avg_rate /= convergence_rate.size();
        
        test3_passed = (monotonic && avg_rate > 1.5 && avg_rate < 2.5 && cfl_seq.back() > cfl_seq.front());
        if (test3_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    std::cout << "\n========================================\n";
    if (test1_passed && test2_passed && test3_passed) {
        std::cout << "Completely correct!\n";
    }
    std::cout << "========================================\n";
    
    return 0;
}

step_number: 5
step_description_prompt: Please write C++ code to generate a function named problem_5_05.
It defines an internal TracerTransportSystem class for tracer transport simulation. The class owns private 3D tracer concentration storage Q, 2D velocity fields u/v, dimension and step parameters, a public initialize method, and five empty public methods for velocity field generation, simulation running, result output, validation and performance optimization.
function_header: void problem_05_05() 
test_cases: int main() {
    
    std::cout << "========================================\n";
    std::cout << "Problem 5-Subproblem 5: Performance Optimization\n";
    std::cout << "========================================\n";
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    {
        std::vector<std::tuple<size_t, size_t, size_t>> grid_configs = {
            {50, 50, 100}, {100, 75, 200}, {150, 100, 300}, {200, 150, 500}
        };
        
        std::vector<size_t> grid_points;
        std::vector<double> computational_complexity;  
        
        for (const auto& config : grid_configs) {
            size_t nx = std::get<0>(config);
            size_t ny = std::get<1>(config);
            size_t nt = std::get<2>(config);
            size_t points = nx * ny * nt;
            grid_points.push_back(points);
            computational_complexity.push_back(static_cast<double>(points) / 1000000.0);  
        }
        
        bool complexity_grows = true;
        for (size_t i = 1; i < grid_points.size(); ++i) {
            if (grid_points[i] <= grid_points[i-1]) {
                complexity_grows = false;
                break;
            }
        }
        
        size_t total_points = 0;
        for (size_t points : grid_points) total_points += points;
        
        size_t expected_total_points = 20000000;
        
        test1_passed = (complexity_grows && total_points > expected_total_points);
        if (test1_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    {
        std::vector<std::tuple<size_t, size_t, size_t>> grid_configs = {
            {100, 100, 100}, {150, 120, 150}, {200, 150, 200}, {250, 200, 300}
        };
        
        const size_t bytes_per_double = 8;
        std::vector<size_t> memory_before;  
        std::vector<size_t> memory_after;   
        
        for (const auto& config : grid_configs) {
            size_t nx = std::get<0>(config);
            size_t ny = std::get<1>(config);
            size_t nt = std::get<2>(config);
            
            size_t mem_before = nx * ny * nt * bytes_per_double;
            
            size_t mem_after = nx * ny * 2 * bytes_per_double;
            
            memory_before.push_back(mem_before);
            memory_after.push_back(mem_after);
        }
        
        std::vector<double> memory_savings;
        for (size_t i = 0; i < memory_before.size(); ++i) {
            double savings = 1.0 - static_cast<double>(memory_after[i]) / static_cast<double>(memory_before[i]);
            memory_savings.push_back(savings);
        }
        
        double avg_savings = 0.0;
        for (double savings : memory_savings) avg_savings += savings;
        avg_savings /= memory_savings.size();
        
        double expected_avg_savings = 0.98;
        
        test2_passed = (avg_savings > expected_avg_savings && memory_after.back() < memory_before.back() / 10);
        if (test2_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    {
        std::vector<std::tuple<size_t, size_t, size_t>> strategies = {
            {30, 30, 50},   
            {60, 60, 100},  
            {90, 90, 150},  
            {120, 120, 200} 
        };
        
        std::vector<size_t> grid_sizes;
        std::vector<double> efficiency_ratios;  
        
        for (const auto& strategy : strategies) {
            size_t nx = std::get<0>(strategy);
            size_t ny = std::get<1>(strategy);
            size_t nt = std::get<2>(strategy);
            size_t size = nx * ny * nt;
            grid_sizes.push_back(size);
        }
        
        double base_size = static_cast<double>(grid_sizes[0]);
        for (size_t i = 0; i < grid_sizes.size(); ++i) {
            double ratio = static_cast<double>(grid_sizes[i]) / base_size;
            
            double parallel_efficiency = 1.0 + 0.1 * i;  
            efficiency_ratios.push_back(ratio / parallel_efficiency);
        }
        
        bool efficiency_improves = true;
        for (size_t i = 1; i < efficiency_ratios.size(); ++i) {
            if (efficiency_ratios[i] <= efficiency_ratios[i-1]) {
                efficiency_improves = false;
                break;
            }
        }
        
        double total_efficiency = 0.0;
        for (double ratio : efficiency_ratios) total_efficiency += ratio;
        
        double expected_total_efficiency = 6.0;
        size_t expected_grid_ratio = grid_sizes.front() * 11;
        
        test3_passed = (efficiency_improves && total_efficiency > expected_total_efficiency && grid_sizes.back() > expected_grid_ratio);
        if (test3_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    std::cout << "\n========================================\n";
    if (test1_passed && test2_passed && test3_passed) {
        std::cout << "Completely correct!\n";
    }
    std::cout << "========================================\n";
    
    return 0;
}

step_number: 6
step_description_prompt: Please use C++ to generate a function named problem_5_06. Define a TracerTransportSystem class inside this function, with private 2D transient grid size and step parameters, two public methods: one to initialize all parameters, another to output dummy grid data in CSV format to a specified file.
function_header: void problem_05_06() 
test_cases: int main() {
    problem_5_06();
    
    std::cout << "========================================\n";
    std::cout << "Problem 5-Subproblem 6: Output and Visualization\n";
    std::cout << "========================================\n";
    
    bool test1_passed = false, test2_passed = false, test3_passed = false;
    
    
    {
        
        std::vector<std::tuple<size_t, size_t, size_t>> system_configs = {
            {20, 15, 25}, {40, 30, 50}, {60, 45, 75}, {80, 60, 100}
        };
        
        std::vector<size_t> total_points_list;
        std::vector<std::string> filenames = {"test_output1.csv", "test_output2.csv", 
                                              "test_output3.csv", "test_output4.csv"};
        
        class TracerTransportSystem {
        private:
            size_t nx_, ny_, nt_;
            double dx_, dy_, dt_;
        public:
            void initialize(size_t nx, size_t ny, size_t nt, double dx, double dy, double dt) {
                nx_ = nx; ny_ = ny; nt_ = nt; dx_ = dx; dy_ = dy; dt_ = dt;
            }
            void output_results(const std::string& filename) {
                std::ofstream file(filename);
                if (file.is_open()) {
                    for (size_t t = 0; t < nt_; ++t) {
                        for (size_t i = 0; i < nx_; ++i) {
                            for (size_t j = 0; j < ny_; ++j) {
                                file << t << "," << i << "," << j << ",0.0\n";
                            }
                        }
                    }
                    file.close();
                }
            }
        };
        
        for (size_t i = 0; i < system_configs.size(); ++i) {
            TracerTransportSystem system;
            size_t nx = std::get<0>(system_configs[i]);
            size_t ny = std::get<1>(system_configs[i]);
            size_t nt = std::get<2>(system_configs[i]);
            
            system.initialize(nx, ny, nt, 100.0 + i*10.0, 100.0 + i*10.0, 3600.0 + i*600.0);
            system.output_results(filenames[i]);
            
            size_t total_points = nx * ny * nt;
            total_points_list.push_back(total_points);
        }
        
        
        bool grows_monotonically = true;
        for (size_t i = 1; i < total_points_list.size(); ++i) {
            if (total_points_list[i] <= total_points_list[i-1]) {
                grows_monotonically = false;
                break;
            }
        }
        
        size_t total_all_points = 0;
        for (size_t points : total_points_list) total_all_points += points;
        
        size_t expected_total_points = 700000;
        
        test1_passed = (grows_monotonically && total_all_points > expected_total_points);
        if (test1_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<std::vector<double>> Q(25, std::vector<double>(25));
        for (int i = 0; i < 25; ++i) {
            for (int j = 0; j < 25; ++j) {
                double x = (i - 12) * 0.4;
                double y = (j - 12) * 0.4;
                
                Q[i][j] = 2.0 + 3.0 * exp(-(x*x + y*y) / 2.0) + 
                          1.5 * exp(-((x-2)*(x-2) + (y+2)*(y+2)) / 1.5) -
                          0.8 * exp(-((x+1.5)*(x+1.5) + (y-1.5)*(y-1.5)) / 1.0) +
                          0.3 * sin(x) * cos(y);
            }
        }
        
        
        double min_val = Q[0][0], max_val = Q[0][0];
        double sum = 0.0, sum_sq = 0.0;
        size_t count = 0;
        size_t nan_count = 0, inf_count = 0;
        
        for (const auto& row : Q) {
            for (double val : row) {
                if (std::isnan(val)) {
                    nan_count++;
                    continue;
                }
                if (std::isinf(val)) {
                    inf_count++;
                    continue;
                }
                min_val = std::min(min_val, val);
                max_val = std::max(max_val, val);
                sum += val;
                sum_sq += val * val;
                count++;
            }
        }
        
        double mean = sum / count;
        double variance = (sum_sq / count) - (mean * mean);
        double std_dev = sqrt(std::max(0.0, variance));
        
        double expected_mean_min = 1.5;
        double expected_mean_max = 4.5;
        double expected_std_dev_min = 0.5;
        
        bool range_ok = (min_val > -1.0 && max_val < 10.0);
        bool stats_ok = (mean >= expected_mean_min && mean <= expected_mean_max && std_dev > expected_std_dev_min);
        bool no_errors = (nan_count == 0 && inf_count == 0);
        
        test2_passed = (range_ok && stats_ok && no_errors);
        if (test2_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    
    {
        
        std::vector<std::vector<std::vector<double>>> Q_time(5);
        for (int t = 0; t < 5; ++t) {
            Q_time[t] = std::vector<std::vector<double>>(15, std::vector<double>(15));
            for (int i = 0; i < 15; ++i) {
                for (int j = 0; j < 15; ++j) {
                    double x = (i - 7) * 0.5;
                    double y = (j - 7) * 0.5;
                    
                    Q_time[t][i][j] = 2.0 + 1.5 * exp(-(x*x + y*y) / (2.0 + t*0.2)) + 
                                     0.5 * sin(t * 0.5) * cos(x) * sin(y);
                }
            }
        }
        
        
        std::vector<double> time_means;
        std::vector<double> time_maxs;
        std::vector<double> time_mins;
        
        for (int t = 0; t < 5; ++t) {
            double sum = 0.0, max_val = Q_time[t][0][0], min_val = Q_time[t][0][0];
            size_t count = 0;
            
            for (const auto& row : Q_time[t]) {
                for (double val : row) {
                    sum += val;
                    max_val = std::max(max_val, val);
                    min_val = std::min(min_val, val);
                    count++;
                }
            }
            
            time_means.push_back(sum / count);
            time_maxs.push_back(max_val);
            time_mins.push_back(min_val);
        }
        
        
        double mean_trend = (time_means.back() - time_means.front()) / time_means.front();
        double max_trend = (time_maxs.back() - time_maxs.front()) / time_maxs.front();
        
        
        bool means_reasonable = true;
        for (double mean : time_means) {
            if (mean < 1.5 || mean > 4.5) means_reasonable = false;
        }
        
        double overall_mean = 0.0;
        for (double mean : time_means) overall_mean += mean;
        overall_mean /= time_means.size();
        
        double expected_overall_mean_min = 2.0;
        double expected_overall_mean_max = 4.0;
        double expected_mean_trend_max = 0.3;
        double expected_max_trend_max = 0.4;
        
        test3_passed = (means_reasonable && overall_mean >= expected_overall_mean_min && overall_mean <= expected_overall_mean_max && 
                       std::abs(mean_trend) < expected_mean_trend_max && std::abs(max_trend) < expected_max_trend_max);
        if (test3_passed) {
            std::cout << "correct\n";
        } else {
            std::cout << "wrong\n";
        }
    }
    
    std::cout << "\n========================================\n";
    if (test1_passed && test2_passed && test3_passed) {
        std::cout << "Completely correct!\n";
    }
    std::cout << "========================================\n";
    
    return 0;
}


General solution:

General tests: