package com.ruoyi.caltools.controller;


import com.ruoyi.caltools.model.FlowProps;
import com.ruoyi.caltools.model.GasProps;
import com.ruoyi.caltools.service.DetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

@RestController

public class NozellFlowCalcISO9300 {

    @Autowired
    private GasController gasController = new GasController();


    // 计算流出系数Cd、雷诺数Re及流量（示例中仅展示关键步骤）
    public void calculateFlowCoefficient(FlowProps flowProps, GasProps gasProps) {

        // 获取基本参数
        double dOrifice = flowProps.getdOrificeD();
        double dPipe = flowProps.getdPipeD();
        double PStatic = flowProps.getdPf();
        double TStatic = flowProps.getdTf();
        // 气体属性
        double R = DetailService.RGASKJ;
        double kappa = gasProps.getdKappa();
        double rhoRef = gasProps.getdRhob();
        double Cstar = gasProps.getdCstar();

        // 计算几何参数
        double AOrifice = Math.PI * Math.pow(dOrifice, 2) / 4;
        double APipe = Math.PI * Math.pow(dPipe / 2, 2);


// 初始参数
        double Cd = 0.99; // 初始猜测值
        double rho = gasProps.getdRhof(); // 基于静态条件的初始密度
        double mu = gasProps.getdMu(); // 初始粘度
        double Re;

        // 迭代控制
        double tolerance = 1e-6;
        int maxIterations = 100;
        boolean converged = false;

        for (int i = 0; i < maxIterations; i++) {
            // 计算质量流量
            double qm = Cd * AOrifice * Cstar * Math.sqrt(gasProps.getdZf() * rho * gasProps.getdPf());

            // 计算流速
            double velocity = qm / (rho * APipe);

            // 计算滞止参数
            double[] stagnation = calculateStagnationProperties(
                    PStatic, TStatic, velocity, kappa, R);
            double P0 = stagnation[0];
            double T0 = stagnation[1];

            // 更新物性参数
            gasProps.setdPf(P0);
            gasProps.setdTf(T0);
            gasController.ngCalc(flowProps);
            double newRho =gasProps.getdRhof();
            double newMu = gasProps.getdMu();

            // 计算雷诺数
            Re = (4 * qm) / (Math.PI * dOrifice * newMu);

            // 获取喷嘴系数
            double[] coeffs = getNozzleCoefficients(flowProps.getdNozzleType());
            double a = coeffs[0], b = coeffs[1], c = coeffs[2],
                    d = coeffs[3], e = coeffs[4], f = coeffs[5], n = coeffs[6];

            // 计算新的Cd
            double term1 = a - b * Math.pow(Re, -n);
            double term2 = (c - d * Math.pow(Re, -n)) / (1 + Math.exp(e - Re / f));
            double newCd = term1 - term2;

            // 检查收敛
            if (Math.abs(newCd - Cd) < tolerance &&
                    Math.abs(newRho - rho) < tolerance &&
                    Math.abs(newMu - mu) < tolerance) {
                converged = true;
                Cd = newCd;
                rho = newRho;
                mu = newMu;
                break;
            }

            // 更新参数
            Cd = newCd;
            rho = newRho;
            mu = newMu;
        }

        if (!converged) throw new RuntimeException("迭代未收敛");

        // 计算标况体积流量
        double qm = Cd * AOrifice * Cstar * Math.sqrt(gasProps.getdZf() * rho * gasProps.getdPf());

        // 保存结果
        flowProps.setdCd(Cd);
        flowProps.setdRnPipe(rho);
        flowProps.setdMFlowb(qm);
        flowProps.setdVFlowb(qm/gasProps.getdRhob());
    }

    private static double[] getNozzleCoefficients(int coreType) {
        // 返回喷嘴系数数组 [a, b, c, d, e, f, n]
        if (coreType == 0) { // 圆环形
            return new double[]{0.9990, 3.415, 0.0031, 0.690, 10, 120000, 0.5};
        } else { // 圆柱形
            return new double[]{1.0000, 6.341, 0.008, 3.000, 6, 170000, 0.5};
        }
    }


    public static double[] calculateStagnationProperties(
            double staticP, double staticT, double velocity,
            double kappa, double R) {

        double soundSpeed = Math.sqrt(kappa * R * staticT);
        double mach = velocity / soundSpeed;
        double T0 = staticT * (1 + 0.5 * (kappa - 1) * mach * mach);
        double P0 = staticP * Math.pow(T0 / staticT, kappa / (kappa - 1));
        return new double[]{P0, T0};
    }


}
