用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - c++代码库

一维仿真-1

2023-04-28 作者: 云代码会员举报

[c++]代码库

#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;

// 定义一些常数和参数
const double F = 96485.0; // 法拉第常数 (C/mol)
const double R = 8.314; // 通用气体常数 (J/mol/K)
const double T = 353.0; // 工作温度 (K)
const double i0 = 0.1; // 交换电流密度 (A/cm2)
const double alpha = 0.5; // 电荷转移系数
const double b = 0.05; // 质量传递系数 (cm/s)
const double Lm = 25e-4; // 膜厚度 (cm)
const double Lc = 10e-4; // 催化层厚度 (cm)
const double Lg = 200e-4; // 气体扩散层厚度 (cm)
const double sigma_m = 0.1; // 膜电导率 (S/cm)
const double sigma_c = 100.0; // 催化层电导率 (S/cm)
const double sigma_g = 10.0; // 气体扩散层电导率 (S/cm)
const double cH2 = 0.2; // 氢气浓度 (mol/cm3)
const double cO2 = 0.1; // 氧气浓度 (mol/cm3)

// 定义边界条件
const double phi_a = 0.0; // 阳极电势 (V)
const double phi_c = 0.6; // 阴极电势 (V)

// 定义网格大小和节点数
const int Nm = 5; // 膜中的节点数
const int Nc = 5; // 催化层中的节点数
const int Ng = 20; // 气体扩散层中的节点数
const int N = Nm + 2 * Nc + 2 * Ng + 1; // 总节点数
const double dxm = Lm / Nm; // 膜中的网格大小
const double dxc = Lc / Nc; // 催化层中的网格大小
const double dxg = Lg / Ng; // 气体扩散层中的网格大小

// 定义一个函数来计算某个节点处的过电势
double eta(int i, double phi, double c) {
    if (i <= Ng + Nc) { // 阳极侧
        return phi - log(cH2 / c) / (2 * alpha * F / R / T) - i0 / sigma_c / dxc;
    }
    else if (i >= Ng + Nc + Nm + Nc) { // 阴极侧
        return phi - log(cO2 / c) / (4 * alpha * F / R / T) - i0 / sigma_c / dxc;
    }
    else { // 膜或界面
        return 0.0;
    }
}

// 定义一个函数来计算某个节点处的电流密度
double current(int i, double phi, double c) {
    return i0 * (exp(2 * alpha * F * eta(i, phi, c) / R / T) - exp(-2 * (1 - alpha) * F * eta(i, phi, c) / R / T));
}

// 定义一个函数来计算某个节点处的浓度
double concentration(int i, double phi, double c) {
    if (i <= Ng + Nc) { // 阳极侧
        return cH2 * exp(-b * current(i, phi, c));
    }
 else if (i >= Ng + Nc + Nm + Nc) { // 阴极侧
        return cO2 * exp(-b * current(i, phi, c));
    }
    else { // 膜或界面
        return c;
    }
}

// 定义一个函数来计算某个节点处的电导率
double conductivity(int i) {
    if (i <= Ng) { // 阳极气体扩散层
        return sigma_g;
    }
    else if (i <= Ng + Nc) { // 阳极催化层
        return sigma_c;
    }
    else if (i <= Ng + Nc + Nm) { // 膜
        return sigma_m;
    }
    else if (i <= Ng + Nc + Nm + Nc) { // 阴极催化层
        return sigma_c;
    }
    else { // 阴极气体扩散层
        return sigma_g;
    }
}

// 定义一个函数来计算某个节点处的网格大小
double dx(int i) {
    if (i <= Ng) { // 阳极气体扩散层
        return dxg;
    }
    else if (i <= Ng + Nc) { // 阳极催化层
        return dxc;
    }
    else if (i <= Ng + Nc + Nm) { // 膜
        return dxm;
    }
    else if (i <= Ng + Nc + Nm + Nc) { // 阴极催化层
        return dxc;
    }
    else { // 阴极气体扩散层
        return dxg;
    }
}

// 定义一个函数来使用追赶法解线性方程组 Ax = b,其中 A 是三对角矩阵,x 和 b 是向量,n 是维数
void thomas(double* a, double* b, double* c, double* d, double* x, int n) {
    // a, b, c 是三对角矩阵 A 的对角线元素,d 是右端向量 b,x 是解向量 x
    // 使用一维数组存储三对角矩阵和向量,下标从 1 开始
    double* p = new double[n]; // 用于存储中间变量 p
    double* q = new double[n]; // 用于存储中间变量 q

    // 前向消元过程,得到 p 和 q
    p[1] = b[1];
    q[1] = d[1] / p[1];
    for (int i = 2; i < n; i++) {
        p[i] = b[i] - a[i] * c[i - 1] / p[i - 1];
        q[i] = (d[i] - a[i] * q[i - 1]) / p[i];
    }
    
    // 后向回代过程,得到 x
    x[n - 1] = q[n - 1];
    for (int i = n - 2; i >= 1; i--) {
        x[i] = q[i] - c[i] * x[i + 1] / p[i];
    }

    // 释放动态分配的内存空间
    delete[] p;
    delete[] q;
}

// 定义一个函数来求解燃料电池一维模型,并打印结果
void solve() {

    // 创建动态数组来存储电势、浓度、电流密度
    double* phi = new double[N]; // 电势
    double* c = new double[N]; // 浓度
    double* i = new double[N]; // 电流密度

    // 给定初始值
    for (int k = 0; k < N; k++) {
        phi[k] = 0.0;
        c[k] = 0.0;
        i[k] = 0.0;
    }

    // 设置边界条件
    phi[1] = phi_a;
    phi[N - 1] = phi_c;

    // 创建动态数组来存储线性方程组的系数矩阵和右端向量
    double* a = new double[N]; // 下对角线元素
    double* b = new double[N]; // 主对角线元素
    double* cc = new double[N]; // 上对角线元素
    double* d = new double[N]; // 右端向量

    // 给定初始值
    for (int k = 0; k < N; k++) {
        a[k] = 0.0;
        b[k] = 0.0;
        cc[k] = 0.0;
        d[k] = 0.0;
    }

    // 定义一个变量来存储误差
    double error = 1e-6;

    // 定义一个变量来存储迭代次数
    int iter = 0;

    // 定义一个变量来存储最大迭代次数
    int max_iter = 100;

    // 使用牛顿法迭代求解非线性方程组,直到收敛或达到最大迭代次数
    while (error > 1e-6 && iter < max_iter) {
        // 计算每个节点处的浓度和电流密度
        for (int k = 1; k < N - 1; k++) {
            c[k] = concentration(k, phi[k], c[k]);
            i[k] = current(k, phi[k], c[k]);
        }

        // 根据有限差分法建立线性方程组 Ax = b,其中 x 是电势,A 是系数矩阵,b 是右端向量
        for (int k = 2; k < N - 1; k++) {
            a[k] = -conductivity(k) / dx(k);
            b[k] = conductivity(k) / dx(k) + conductivity(k - 1) / dx(k - 1);
            cc[k] = -conductivity(k - 1) / dx(k - 1);
            d[k] = i[k - 1] - i[k];
        }

        // 处理边界条件,即电势已知的节点
        b[1] = 1.0;
        d[1] = phi_a;
        b[N - 1] = 1.0;
        d[N - 1] = phi_c;

        // 使用追赶法解线性方程组,得到新的电势
        thomas(a, b, cc, d, phi, N);

        // 计算误差,即电流密度在两端的差值的绝对值
        error = abs(i[1] - i[N - 1]);

        // 增加迭代次数
        iter++;
    }

    // 打印结果
    cout << "The simulation results are:" << endl;
    cout << "The iteration number is: " << iter << endl;
    cout << "The error is: " << error << endl;
    cout << "The current density is: " << i[1] << endl;
    cout << "The potential distribution is:" << endl;
    for (int k = 1; k < N; k++) {
        cout << phi[k] << " ";
    }
    cout << endl;

    // 释放动态分配的内存空间
    delete[] phi;
    delete[] c;

    delete[] i;
    delete[] a;
    delete[] b;
    delete[] cc;
    delete[] d;
}

// 定义主函数
int main() {
    // 调用 solve 函数
    solve();
    // 返回 0
    return 0;
}



网友评论    (发表评论)


发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...