完成函数double phi

请完成函数double phi(double z),该函数计算并返回给定z时,z+z^3/3+z^5/(3*5)+…+z^1001/(3*5*7…*1001)的值。公式中“z^3”表示z的三次方。例如, phi(0.3)=0.309164.
提示:如果直接求算式中各项的分子和分母,其值将会很快溢出。
输入样例
0.3
输出样例
0.309164

#include<iostream>
#include<stdio.h>
#include<cmath>
using namespace std;
double phi(double a)
{
 double sum1=0;
 double sum=a;
 for(int i=3;i<=1001;i=i+2)
 {
  sum1=sum1+sum;
  sum=sum*(pow(a,2)/i);
 }
 printf("%.6f",sum1);
}
int main()
{
 double a;
 cin>>a;
 phi(a);
}
参考上述的建议,重新修改下面的代码:#include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <fftw3.h> // 结构体定义 typedef struct { int iterations; double time; double energy; double* phi; } LBResult; // 函数声明 double compute_energy(double* phi, fftw_complex* phi_fft, double* k2, int N, double tau, double gamma); LBResult solve_LB_C2C(int N, double tau, double gamma, double dt, double tol, int maxiter); LBResult solve_LB_C2R(int N, double tau, double gamma, double dt, double tol, int maxiter); void cleanup_result(LBResult* result); // 计算能量函数 double compute_energy(double* phi, fftw_complex* phi_fft, double* k2, int N, double tau, double gamma) { // 分配内存 fftw_complex* A_phi_fft = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* A_phi_temp = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); double* A_phi = (double*)fftw_malloc(N * N * sizeof(double)); // 创建IFFT计划 fftw_plan plan_ifft = fftw_plan_dft_2d(N, N, A_phi_fft, A_phi_temp, FFTW_BACKWARD, FFTW_ESTIMATE); // 计算 A_phi_fft = (1 - k2) .* phi_fft for (int i = 0; i < N * N; i++) { double factor = 1.0 - k2[i]; A_phi_fft[i][0] = factor * phi_fft[i][0]; A_phi_fft[i][1] = factor * phi_fft[i][1]; } // A_phi = ifft2(A_phi_fft, 'symmetric') * N^2 fftw_execute(plan_ifft); // 提取实部并归一化(对应MATLAB的 * N^2) for (int i = 0; i < N * N; i++) { A_phi[i] = A_phi_temp[i][0]; // FFTW的IFFT已经包含了正确的缩放 } // 计算各项能量 double E1 = 0.0, E2 = 0.0, E3 = 0.0, E4 = 0.0; for (int i = 0; i < N * N; i++) { double A_phi_sq = A_phi[i] * A_phi[i]; double phi_sq = phi[i] * phi[i]; double phi_cu = phi[i] * phi[i] * phi[i]; double phi_qu = phi[i] * phi[i] * phi[i] * phi[i]; E1 += A_phi_sq; E2 += phi_sq; E3 += phi_cu; E4 += phi_qu; } // 计算平均值(对应MATLAB的mean函数double norm = 1.0 / (N * N); E1 = 0.5 * E1 * norm; // 0.5 * mean(A_phi_sq(:)) E2 = (tau / 2.0) * E2 * norm; // (tau/2) * mean(phi_sq(:)) E3 = (-gamma / 6.0) * E3 * norm; // (-gamma/6) * mean(phi_cu(:)) E4 = (1.0 / 24.0) * E4 * norm; // (1/24) * mean(phi_qu(:)) double energy = E1 + E2 + E3 + E4; // 清理内存 fftw_destroy_plan(plan_ifft); fftw_free(A_phi_fft); fftw_free(A_phi_temp); fftw_free(A_phi); return energy; } // C2C方法求解 LBResult solve_LB_C2C(int N, double tau, double gamma, double dt, double tol, int maxiter) { LBResult result; clock_t start_time = clock(); // 分配内存 fftw_complex* phi_fft = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* phi_old_fft = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* phi_sq_fft = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* phi_cu_fft = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* phi_temp = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* phi_sq_temp = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); fftw_complex* phi_cu_temp = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); double* phi = (double*)fftw_malloc(N * N * sizeof(double)); double* phi_old = (double*)fftw_malloc(N * N * sizeof(double)); double* phi_sq = (double*)fftw_malloc(N * N * sizeof(double)); double* phi_cu = (double*)fftw_malloc(N * N * sizeof(double)); double* k2 = (double*)malloc(N * N * sizeof(double)); // 生成波数 - 严格按照MATLAB代码 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { double kx, ky; // MATLAB: if i <= N/2, k(i) = i - 1; else k(i) = i - N - 1; end if (i + 1 <= N / 2) { // MATLAB索引从1开始 kx = (double)i; } else { kx = (double)(i - N); } if (j + 1 <= N / 2) { ky = (double)j; } else { ky = (double)(j - N); } k2[i * N + j] = kx * kx + ky * ky; } } // 创建FFTW计划 fftw_plan plan_ifft = fftw_plan_dft_2d(N, N, phi_fft, phi_temp, FFTW_BACKWARD, FFTW_ESTIMATE); fftw_plan plan_fft_sq = fftw_plan_dft_2d(N, N, phi_sq_temp, phi_sq_fft, FFTW_FORWARD, FFTW_ESTIMATE); fftw_plan plan_fft_cu = fftw_plan_dft_2d(N, N, phi_cu_temp, phi_cu_fft, FFTW_FORWARD, FFTW_ESTIMATE); // 初始化 phi_fft = zeros(N, N) for (int i = 0; i < N * N; i++) { phi_fft[i][0] = 0.0; phi_fft[i][1] = 0.0; } // 设置初始条件 // MATLAB: phi_fft(2, 1) = 0.3; phi_fft(N, 1) = 0.3; // 转换为C索引: (2,1) -> [1][0], (N,1) -> [N-1][0] phi_fft[1 * N + 0][0] = 0.3; // phi_fft(2, 1) = 0.3 phi_fft[1 * N + 0][1] = 0.0; phi_fft[(N - 1) * N + 0][0] = 0.3; // phi_fft(N, 1) = 0.3 phi_fft[(N - 1) * N + 0][1] = 0.0; // 迭代求解 int iter; for (iter = 0; iter < maxiter; iter++) { // 保存旧值 phi_old_fft = phi_fft for (int i = 0; i < N * N; i++) { phi_old_fft[i][0] = phi_fft[i][0]; phi_old_fft[i][1] = phi_fft[i][1]; } // phi_old = ifft2(phi_old_fft, 'symmetric') * N^2 fftw_execute(plan_ifft); for (int i = 0; i < N * N; i++) { phi_old[i] = phi_temp[i][0]; // 提取实部,FFTW已经正确缩放 } // 计算非线性项 for (int i = 0; i < N * N; i++) { phi_sq[i] = phi_old[i] * phi_old[i]; phi_cu[i] = phi_old[i] * phi_old[i] * phi_old[i]; // 准备复数数组用于FFT phi_sq_temp[i][0] = phi_sq[i]; phi_sq_temp[i][1] = 0.0; phi_cu_temp[i][0] = phi_cu[i]; phi_cu_temp[i][1] = 0.0; } // phi_sq_fft = fft2(phi_sq) / N^2 // phi_cu_fft = fft2(phi_cu) / N^2 fftw_execute(plan_fft_sq); fftw_execute(plan_fft_cu); // 归一化 (除以 N^2) for (int i = 0; i < N * N; i++) { phi_sq_fft[i][0] /= (N * N); phi_sq_fft[i][1] /= (N * N); phi_cu_fft[i][0] /= (N * N); phi_cu_fft[i][1] /= (N * N); } // 更新 // numerator = (1 - dt*tau) * phi_old_fft + dt * (gamma/2 * phi_sq_fft - 1/6 * phi_cu_fft) // denominator = 1 + dt*(1 - k2).^2 // phi_fft = numerator ./ denominator for (int i = 0; i < N * N; i++) { double k2_val = k2[i]; double numerator_real = (1.0 - dt * tau) * phi_old_fft[i][0] + dt * (gamma / 2.0 * phi_sq_fft[i][0] - 1.0 / 6.0 * phi_cu_fft[i][0]); double numerator_imag = (1.0 - dt * tau) * phi_old_fft[i][1] + dt * (gamma / 2.0 * phi_sq_fft[i][1] - 1.0 / 6.0 * phi_cu_fft[i][1]); double denominator = 1.0 + dt * pow(1.0 - k2_val, 2.0); phi_fft[i][0] = numerator_real / denominator; phi_fft[i][1] = numerator_imag / denominator; } // 保持零均值约束 phi_fft(1, 1) = 0 phi_fft[0][0] = 0.0; phi_fft[0][1] = 0.0; // 计算新的phi phi = ifft2(phi_fft, 'symmetric') * N^2 fftw_execute(plan_ifft); for (int i = 0; i < N * N; i++) { phi[i] = phi_temp[i][0]; } // 检查收敛 diff = max(abs(phi(:) - phi_old(:))) / dt double max_diff = 0.0; for (int i = 0; i < N * N; i++) { double diff = fabs(phi[i] - phi_old[i]) / dt; if (diff > max_diff) { max_diff = diff; } } if (max_diff < tol) { break; } } clock_t end_time = clock(); double elapsed_time = ((double)(end_time - start_time)) / CLOCKS_PER_SEC; // 计算能量 double energy = compute_energy(phi, phi_fft, k2, N, tau, gamma); // 设置结果 result.iterations = iter + 1; result.time = elapsed_time; result.energy = energy; result.phi = (double*)malloc(N * N * sizeof(double)); for (int i = 0; i < N * N; i++) { result.phi[i] = phi[i]; } // 清理内存 fftw_destroy_plan(plan_ifft); fftw_destroy_plan(plan_fft_sq); fftw_destroy_plan(plan_fft_cu); fftw_free(phi_fft); fftw_free(phi_old_fft); fftw_free(phi_sq_fft); fftw_free(phi_cu_fft); fftw_free(phi_temp); fftw_free(phi_sq_temp); fftw_free(phi_cu_temp); fftw_free(phi); fftw_free(phi_old); fftw_free(phi_sq); fftw_free(phi_cu); free(k2); return result; } // C2R方法求解 - 修正后的版本 LBResult solve_LB_C2R(int N, double tau, double gamma, double dt, double tol, int maxiter) { LBResult result; clock_t start_time = clock(); // C2R变换的输出大小 int fft_size = N * (N / 2 + 1); // 分配内存 fftw_complex* phi_fft = (fftw_complex*)fftw_malloc(fft_size * sizeof(fftw_complex)); fftw_complex* phi_old_fft = (fftw_complex*)fftw_malloc(fft_size * sizeof(fftw_complex)); fftw_complex* phi_sq_fft = (fftw_complex*)fftw_malloc(fft_size * sizeof(fftw_complex)); fftw_complex* phi_cu_fft = (fftw_complex*)fftw_malloc(fft_size * sizeof(fftw_complex)); double* phi = (double*)fftw_malloc(N * N * sizeof(double)); double* phi_old = (double*)fftw_malloc(N * N * sizeof(double)); double* phi_sq = (double*)fftw_malloc(N * N * sizeof(double)); double* phi_cu = (double*)fftw_malloc(N * N * sizeof(double)); double* k2 = (double*)malloc(fft_size * sizeof(double)); // 生成波数(C2R格式) for (int i = 0; i < N; i++) { for (int j = 0; j <= N / 2; j++) { double kx, ky; if (i + 1 <= N / 2) { kx = (double)i; } else { kx = (double)(i - N); } ky = (double)j; k2[i * (N / 2 + 1) + j] = kx * kx + ky * ky; } } // 创建FFTW计划 fftw_plan plan_c2r = fftw_plan_dft_c2r_2d(N, N, phi_fft, phi, FFTW_ESTIMATE); fftw_plan plan_r2c_sq = fftw_plan_dft_r2c_2d(N, N, phi_sq, phi_sq_fft, FFTW_ESTIMATE); fftw_plan plan_r2c_cu = fftw_plan_dft_r2c_2d(N, N, phi_cu, phi_cu_fft, FFTW_ESTIMATE); // 初始化 for (int i = 0; i < fft_size; i++) { phi_fft[i][0] = 0.0; phi_fft[i][1] = 0.0; } // 设置初始条件 - 修正版本 // 原来的C2C初始条件:phi_fft(2, 1) = 0.3; phi_fft(N, 1) = 0.3; // 对应波数 k = (1, 0) 和 k = (-1, 0) // 在C2R格式中: // k = (1, 0) 对应 phi_fft[1 * (N/2 + 1) + 0] = 0.3 // k = (-1, 0) 由于共轭对称性,需要特殊处理 // 设置 k = (1, 0) 对应的值 phi_fft[1 * (N / 2 + 1) + 0][0] = 0.3; phi_fft[1 * (N / 2 + 1) + 0][1] = 0.0; // 设置 k = (-1, 0) 对应的值 // 在C2R中,负频率通过共轭对称性隐含表示 // k = (-1, 0) 对应 phi_fft[(N-1) * (N/2 + 1) + 0] = 0.3 phi_fft[(N - 1) * (N / 2 + 1) + 0][0] = 0.3; phi_fft[(N - 1) * (N / 2 + 1) + 0][1] = 0.0; // 迭代求解 int iter; for (iter = 0; iter < maxiter; iter++) { // 保存旧值 for (int i = 0; i < fft_size; i++) { phi_old_fft[i][0] = phi_fft[i][0]; phi_old_fft[i][1] = phi_fft[i][1]; } // 执行逆FFT到实空间 fftw_execute(plan_c2r); // FFTW的C2R变换不归一化,需要手动归一化 for (int i = 0; i < N * N; i++) { phi_old[i] = phi[i] / (N * N); } // 计算非线性项 for (int i = 0; i < N * N; i++) { phi_sq[i] = phi_old[i] * phi_old[i]; phi_cu[i] = phi_old[i] * phi_old[i] * phi_old[i]; } // 将非线性项FFT到频域 fftw_execute(plan_r2c_sq); fftw_execute(plan_r2c_cu); // 注意:FFTW的R2C变换不归一化,所以结果已经是正确的 // 更新频域值 for (int i = 0; i < fft_size; i++) { double k2_val = k2[i]; double numerator_real = (1.0 - dt * tau) * phi_old_fft[i][0] + dt * (gamma / 2.0 * phi_sq_fft[i][0] - 1.0 / 6.0 * phi_cu_fft[i][0]); double numerator_imag = (1.0 - dt * tau) * phi_old_fft[i][1] + dt * (gamma / 2.0 * phi_sq_fft[i][1] - 1.0 / 6.0 * phi_cu_fft[i][1]); double denominator = 1.0 + dt * pow(1.0 - k2_val, 2.0); phi_fft[i][0] = numerator_real / denominator; phi_fft[i][1] = numerator_imag / denominator; } // 保持零均值约束 phi_fft[0][0] = 0.0; phi_fft[0][1] = 0.0; // 计算新的phi用于收敛检查 fftw_execute(plan_c2r); // 归一化 for (int i = 0; i < N * N; i++) { phi[i] = phi[i] / (N * N); } // 检查收敛 double max_diff = 0.0; for (int i = 0; i < N * N; i++) { double diff = fabs(phi[i] - phi_old[i]) / dt; if (diff > max_diff) { max_diff = diff; } } if (max_diff < tol) { break; } } clock_t end_time = clock(); double elapsed_time = ((double)(end_time - start_time)) / CLOCKS_PER_SEC; // 为了计算能量,需要将C2R结果转换为完整的C2C格式 fftw_complex* phi_fft_full = (fftw_complex*)fftw_malloc(N * N * sizeof(fftw_complex)); double* k2_full = (double*)malloc(N * N * sizeof(double)); // 展开C2R结果到完整格式 - 修正版本 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { double kx, ky; if (i + 1 <= N / 2) kx = (double)i; else kx = (double)(i - N); if (j + 1 <= N / 2) ky = (double)j; else ky = (double)(j - N); k2_full[i * N + j] = kx * kx + ky * ky; if (j <= N / 2) { // 直接复制 int idx = i * (N / 2 + 1) + j; phi_fft_full[i * N + j][0] = phi_fft[idx][0]; phi_fft_full[i * N + j][1] = phi_fft[idx][1]; } else { // 利用共轭对称性:F[i][N-j] = conj(F[N-i][j]) int i_sym = (i == 0) ? 0 : (N - i); int j_sym = N - j; int idx = i_sym * (N / 2 + 1) + j_sym; phi_fft_full[i * N + j][0] = phi_fft[idx][0]; phi_fft_full[i * N + j][1] = -phi_fft[idx][1]; } } } double energy = compute_energy(phi, phi_fft_full, k2_full, N, tau, gamma); // 设置结果 result.iterations = iter + 1; result.time = elapsed_time; result.energy = energy; result.phi = (double*)malloc(N * N * sizeof(double)); for (int i = 0; i < N * N; i++) { result.phi[i] = phi[i]; } // 清理内存 fftw_destroy_plan(plan_c2r); fftw_destroy_plan(plan_r2c_sq); fftw_destroy_plan(plan_r2c_cu); fftw_free(phi_fft); fftw_free(phi_old_fft); fftw_free(phi_sq_fft); fftw_free(phi_cu_fft); fftw_free(phi); fftw_free(phi_old); fftw_free(phi_sq); fftw_free(phi_cu); fftw_free(phi_fft_full); free(k2); free(k2_full); return result; } // 清理结果内存 void cleanup_result(LBResult* result) { if (result->phi) { free(result->phi); result->phi = NULL; } } // 主函数 int main() { // 参数设置 double tau = -0.2; double gamma = 0.1; double dt = 0.1; double tol = 1e-6; int maxiter = 10000; // 测试不同的网格尺寸 int N_values[] = { 4, 8, 16, 32, 64, 128, 256 }; int num_N = sizeof(N_values) / sizeof(N_values[0]); printf("使用 C2C 方式计算:\n"); printf("N\t迭代次数\t时间 (s)\t能量\n"); for (int idx = 0; idx < num_N; idx++) { int N = N_values[idx]; LBResult result = solve_LB_C2C(N, tau, gamma, dt, tol, maxiter); printf("%d\t%d\t\t%.6f\t%.6e\n", N, result.iterations, result.time, result.energy); cleanup_result(&result); } printf("\n使用 C2R 方式计算:\n"); printf("N\t迭代次数\t时间 (s)\t能量\n"); for (int idx = 0; idx < num_N; idx++) { int N = N_values[idx]; LBResult result = solve_LB_C2R(N, tau, gamma, dt, tol, maxiter); printf("%d\t%d\t\t%.6f\t%.6e\n", N, result.iterations, result.time, result.energy); cleanup_result(&result); } return 0; }
07-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

【执珪】瑕瑜·夕环玦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值