1
This commit is contained in:
commit
a024039f05
74
Controllers/FortranController.cs
Normal file
74
Controllers/FortranController.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using FortranWebApi.Models;
|
||||
using FortranWebApi.Services;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace FortranWebApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class FortranCalculateController : ControllerBase
|
||||
{
|
||||
private readonly FortranInteropService _fortranService;
|
||||
private readonly ILogger<FortranCalculateController> _logger;
|
||||
|
||||
public FortranCalculateController(FortranInteropService fortranService, ILogger<FortranCalculateController> logger)
|
||||
{
|
||||
_fortranService = fortranService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Post([FromBody] FortranRequestWrapper wrapper)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(wrapper.Text))
|
||||
{
|
||||
return BadRequest(new
|
||||
{
|
||||
message = "请求文本不能为空",
|
||||
success = false,
|
||||
data = (object)null
|
||||
});
|
||||
}
|
||||
|
||||
string result = _fortranService.ProcessFortranRequest(wrapper.Text);
|
||||
|
||||
// 使用驼峰命名法解析结果
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
var resultObj = JsonSerializer.Deserialize<FortranRequest>(result, options);
|
||||
|
||||
// 返回新的格式
|
||||
var response = new ApiResponse<FortranRequest>
|
||||
{
|
||||
Message = "Success",
|
||||
Success = true,
|
||||
Data = new ApiResponseData<FortranRequest>
|
||||
{
|
||||
Value = resultObj
|
||||
}
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "处理Fortran请求时发生错误");
|
||||
return StatusCode(500, new
|
||||
{
|
||||
message = ex.Message,
|
||||
success = false,
|
||||
data = (object)null
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
88
Dockerfile
Normal file
88
Dockerfile
Normal file
@ -0,0 +1,88 @@
|
||||
# ===== 第一阶段:构建阶段 =====
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
|
||||
# 配置 NuGet 使用国内镜像源
|
||||
RUN dotnet nuget add source https://mirrors.cloud.tencent.com/nuget/ \
|
||||
&& dotnet nuget disable source nuget.org
|
||||
|
||||
# 配置 apt-get 使用 apt-cacher-ng 作为代理
|
||||
RUN echo 'Acquire::http::Proxy "http://192.168.1.140:3142";' > /etc/apt/apt.conf.d/01proxy
|
||||
|
||||
# 创建并配置 Debian 镜像源
|
||||
RUN echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list
|
||||
|
||||
# 允许使用不安全的软件源
|
||||
RUN echo 'Acquire::AllowInsecureRepositories "true";' > /etc/apt/apt.conf.d/99allow-insecure && \
|
||||
echo 'Acquire::AllowDowngradeToInsecureRepositories "true";' >> /etc/apt/apt.conf.d/99allow-insecure
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
# 安装 Fortran 编译器
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gfortran \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 复制 Fortran 源文件并编译
|
||||
COPY Fortran/*.f90 /src/Fortran/
|
||||
WORKDIR /src/Fortran
|
||||
|
||||
# 编译所有 .f90 文件为 .o 文件
|
||||
RUN for file in *.f90; do gfortran -fPIC -c "$file" -o "${file%.f90}.o"; done
|
||||
|
||||
# 链接所有 .o 文件为共享库
|
||||
RUN gfortran -shared *.o -o libMAIN_UFRN.so
|
||||
|
||||
# 回到主工作目录
|
||||
WORKDIR /src
|
||||
|
||||
# 只复制项目文件
|
||||
COPY ["FortranWebApi.csproj", "./"]
|
||||
RUN dotnet restore
|
||||
|
||||
# 复制源代码
|
||||
COPY . .
|
||||
|
||||
# 合并 build 和 publish 命令
|
||||
RUN dotnet publish -c Release -o /app/publish
|
||||
|
||||
# 复制编译好的 .so 文件到发布目录
|
||||
RUN mkdir -p /app/publish && \
|
||||
cp /src/Fortran/libMAIN_UFRN.so /app/publish/
|
||||
|
||||
# ===== 第二阶段:运行阶段 =====
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
||||
|
||||
# 配置 apt-get 使用 apt-cacher-ng 作为代理
|
||||
RUN echo 'Acquire::http::Proxy "http://192.168.1.140:3142";' > /etc/apt/apt.conf.d/01proxy
|
||||
|
||||
# 创建并配置 Debian 镜像源
|
||||
RUN echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \
|
||||
echo "deb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list
|
||||
|
||||
# 允许使用不安全的软件源
|
||||
RUN echo 'Acquire::AllowInsecureRepositories "true";' > /etc/apt/apt.conf.d/99allow-insecure && \
|
||||
echo 'Acquire::AllowDowngradeToInsecureRepositories "true";' >> /etc/apt/apt.conf.d/99allow-insecure
|
||||
|
||||
# 安装运行时依赖
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libc6-dev \
|
||||
libgfortran5 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/publish .
|
||||
|
||||
# 确保 .so 文件的权限正确
|
||||
RUN chmod 755 /app/libMAIN_UFRN.so
|
||||
|
||||
# 设置 LD_LIBRARY_PATH
|
||||
ENV LD_LIBRARY_PATH=/app
|
||||
|
||||
# 设置端口和监听地址
|
||||
ENV ASPNETCORE_URLS=http://+:5000
|
||||
EXPOSE 5000
|
||||
|
||||
ENTRYPOINT ["dotnet", "FortranWebApi.dll"]
|
329
Fortran/1.json
Normal file
329
Fortran/1.json
Normal file
@ -0,0 +1,329 @@
|
||||
{
|
||||
"fortranSourceFile": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\dll\\\u591A\u6CB3\u9053\u4E00\u7EF4\u6C34\u52A8\u529B\u6A21\u578B\\MAIN_UFRN\\MAIN_UFRN\\MAIN_UFRN - \u526F\u672C.f90",
|
||||
"fortranFunctionName": "MAIN_UFRN",
|
||||
"projectName": "FortranWebApi",
|
||||
"outputDirectory": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\\u8F93\u51FA\u5E93\\\u591A\u6CB3\u9053\u4E00\u7EF4\u6C34\u52A8\u529B\u6A21\u578B",
|
||||
"cmbLanguage": "Fortran",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "nriver",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "nsect",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "krc",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "ndata",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Ns",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Pc",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Nrc",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Lc",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Dric",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "XJ",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Asave",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "ds",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "bd",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "zd",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "sm",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "rough",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "ZZ0",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Zctr",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Qp",
|
||||
"dataType": "Float",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "UB1",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "UB2",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "DB1",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "DB2",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "OneDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "UBV",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "NUB",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "DBV",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Gate",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "NDB",
|
||||
"dataType": "Integer",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Aphi",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "period",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "dt",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "sita",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "sorz",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "sorq",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "epsz",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "epsq",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Bsor1",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Bsor2",
|
||||
"dataType": "Float",
|
||||
"arrayType": "Scalar",
|
||||
"direction": "Input",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Z",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Output",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
},
|
||||
{
|
||||
"name": "Q",
|
||||
"dataType": "Float",
|
||||
"arrayType": "TwoDimensional",
|
||||
"direction": "Output",
|
||||
"description": "",
|
||||
"isSelected": true
|
||||
}
|
||||
]
|
||||
}
|
BIN
Fortran/1.xlsx
Normal file
BIN
Fortran/1.xlsx
Normal file
Binary file not shown.
350
Fortran/MAIN_UFRN.f90
Normal file
350
Fortran/MAIN_UFRN.f90
Normal file
@ -0,0 +1,350 @@
|
||||
SUBROUTINE MAIN_UFRN(nriver ,& !河道数量
|
||||
nsect ,& !河道计算断面数最大值
|
||||
krc ,& !河道汊点数最大值
|
||||
ndata ,& !计算时刻数
|
||||
Ns ,& !河道断面数
|
||||
Pc ,& !河道汊点数
|
||||
Nrc ,& !河道汊点微段号
|
||||
Lc ,& !汊点类型
|
||||
Dric ,& !流动方向
|
||||
XJ ,& !流量过程
|
||||
Asave ,& !水库面积
|
||||
ds ,& !河道几何数据
|
||||
bd ,& !梯形断面底宽
|
||||
zd ,& !梯形断面底高程
|
||||
sm ,& !梯形断面边坡系数
|
||||
rough ,& !梯形断面糙率
|
||||
ZZ0 ,& !计算区域初始水位
|
||||
Zctr ,& !河道末端挡潮闸运行控制水位
|
||||
Qp ,& !计算区域入河流量过程
|
||||
UB1 ,& !上游边界条件类型1(1——水位边界,2——流量边界,3——水位流量关系)
|
||||
UB2 ,& !上游边界条件类型2(1——河网外边界,2——河网内边界)
|
||||
DB1 ,& !下游边界条件类型1(1——水位边界,2——流量边界,3——水位流量关系)
|
||||
DB2 ,& !下游边界条件类型2(1——河网外边界,2——河网内边界)
|
||||
UBV ,& !上游外边界断面处的水位,或流量过程
|
||||
NUB ,& !上游内边界断面所连接的河道编号、微段编号
|
||||
DBV ,& !下游外边界断面处的水位,或流量,或闸下潮位过程
|
||||
Gate ,& !Gate(1,i) = 闸净宽;Gate(2,i) = 最大过流量;Gate(3,i) = 流量公式C1;Gate(4,i) = 流量公式C2 (流量公式Q=C1*B*e*dZ^C2中的C1和C2)
|
||||
NDB ,& !下游内边界断面所连接的河道编号、微段编号
|
||||
Aphi ,& !下游流量内边界(管涵)的过流断面面积、流速系数
|
||||
period ,& !计算小时数
|
||||
dt ,& !计算时间步长
|
||||
sita ,& !水量隐格式权系数
|
||||
sorz ,& !水位迭代松弛因子
|
||||
sorq ,& !流量迭代松弛因子
|
||||
epsz ,& !水位迭代控制精度
|
||||
epsq ,& !流量迭代控制精度
|
||||
Bsor1 ,& !水闸外边界计算中的松弛因子
|
||||
Bsor2 ,& !管涵内边界计算中的松弛因子
|
||||
Z ,& !输出河道水位
|
||||
Q )& !输出河道流量
|
||||
BIND(C, NAME="MAIN_UFRN")
|
||||
|
||||
!DEC$ ATTRIBUTES DLLEXPORT::MAIN_UFRN
|
||||
|
||||
IMPLICIT NONE
|
||||
|
||||
INTEGER::nriver ! 河道数量
|
||||
INTEGER::nsect ! 河道计算断面数最大值
|
||||
INTEGER::krc ! 河道汊点数最大值
|
||||
INTEGER::ndata ! 计算时刻数(时间步数据点数量)
|
||||
INTEGER::MRIVER
|
||||
integer River,tstep
|
||||
INTEGER::I
|
||||
INTEGER::II
|
||||
|
||||
! 河道组态数据
|
||||
INTEGER::Ns(nriver) ! 各河道断面数(维度: NRIVER)
|
||||
INTEGER::Pc(nriver) ! 各河道汊点数(维度: NRIVER)
|
||||
INTEGER::Nrc(krc,nriver) ! 汊点类型(1-普通,2-集中入流,3-调蓄水库)(维度: KRC, NRIVER)
|
||||
INTEGER::Lc(krc,nriver) ! 汊点连接的微段编号(维度: KRC, NRIVER)
|
||||
|
||||
!边界条件
|
||||
INTEGER::UB1(nriver) ! 上游边界类型(1-水位,2-流量,3-水位流量关系)(维度: NRIVER)
|
||||
INTEGER::UB2(nriver) ! 上游边界位置(1-外边界,2-内边界)(维度: NRIVER)
|
||||
INTEGER::DB1(nriver) ! 下游边界类型(同上)(维度: NRIVER)
|
||||
INTEGER::DB2(nriver) ! 下游边界位置(同上)(维度: NRIVER)
|
||||
INTEGER::NUB(2,nriver) ! 上游内边界连接的河道和微段(维度: 2, NRIVER)
|
||||
INTEGER::NDB(2,nriver) ! 下游内边界连接的河道和微段(维度: 2, NRIVER)
|
||||
|
||||
REAL::ZZ0 ! 计算区域初始水位(m)
|
||||
REAL::Zctr ! 河道末端挡潮闸控制水位(m)
|
||||
REAL::period ! 计算总时长(小时)
|
||||
REAL::dt ! 计算时间步长(秒)
|
||||
REAL::sita ! 隐格式权系数(0.5~1.0)
|
||||
REAL::sorz ! 水位迭代松弛因子(0~1)
|
||||
REAL::sorq ! 流量迭代松弛因子(0~1)
|
||||
REAL::epsz ! 水位迭代收敛精度(m)
|
||||
REAL::epsq ! 流量迭代收敛精度(m?/s)
|
||||
REAL::Bsor1 ! 水闸边界松弛因子
|
||||
REAL::Bsor2 ! 管涵边界松弛因子
|
||||
REAL::ql
|
||||
REAL::condu,condd(3)
|
||||
REAL::Bs,As,Rs,Cs
|
||||
|
||||
!河道汊点数据
|
||||
REAL::Dric(krc,nriver) ! 汊点流动方向(流入1,流出-1)(维度: KRC, NRIVER)
|
||||
REAL::Qj(ndata,krc,nriver) ! 集中入流流量过程(维度: NDATA, KRC, NRIVER)
|
||||
REAL::Asave(krc,nriver) ! 调蓄水库面积(m?)(维度: KRC, NRIVER)
|
||||
|
||||
!河道几何数据
|
||||
REAL::ds(nsect - 1,nriver) ! 微段长度(m)(维度: nsect - 1, NRIVER)
|
||||
REAL::bd(nsect,nriver) ! 断面底宽(m)(维度: NSECT, NRIVER)
|
||||
REAL::zd(nsect,nriver) ! 断面底高程(m)(维度: NSECT, NRIVER)
|
||||
REAL::sm(nsect,nriver) ! 边坡系数(-)(维度: NSECT, NRIVER)
|
||||
REAL::rough(nsect,nriver) ! 糙率(曼宁系数)(维度: NSECT, NRIVER)
|
||||
|
||||
!边界过程数据
|
||||
REAL::UBV(ndata,nriver) ! 上游外边界水位/流量过程(维度: NDATA, NRIVER)
|
||||
REAL::DBV(ndata,nriver) ! 下游外边界水位/流量过程(维度: NDATA, NRIVER)
|
||||
REAL::Gate(4,nriver) ! 闸门参数(净宽、最大流量、C1、C2)(维度: 4, NRIVER)
|
||||
REAL::Aphi(2,nriver) ! 管涵过流参数(面积、流速系数)(维度: 2, NRIVER)
|
||||
REAL::Qp(ndata) ! 计算区域入河总流量过程(m?/s)(维度: NDATA)
|
||||
|
||||
REAL::Z0(nsect,nriver)
|
||||
REAL::Q0(nsect,nriver)
|
||||
REAL::Z(nsect,nriver)
|
||||
REAL::Q(nsect,nriver)
|
||||
REAL::V(nsect,nriver)
|
||||
REAL::Zc(nsect,nriver),Qc(nsect,nriver)
|
||||
REAL::XJ(ndata,nriver*krc)
|
||||
|
||||
REAL::maxtstep
|
||||
REAL::maxiter
|
||||
REAL::ttime
|
||||
REAL::fc
|
||||
REAL::Scanal
|
||||
REAL::dzmax
|
||||
REAL::dqmax
|
||||
REAL::dz
|
||||
REAL::dq
|
||||
REAL::maxz_r
|
||||
REAL::maxz_s
|
||||
REAL::maxq_r
|
||||
REAL::maxq_s
|
||||
|
||||
INTEGER::Is
|
||||
INTEGER::iter
|
||||
INTEGER::J,K
|
||||
|
||||
MRIVER = nsect - 1
|
||||
|
||||
Scanal = 0.0 ! Scanal——河网所有河道的合计长度,用于计算旁侧入流量ql
|
||||
|
||||
DO I = 1,ndata
|
||||
DO J = 1,KRC
|
||||
DO K = 1,NRIVER
|
||||
Qj(i,j,k) = xj(i,j*k)
|
||||
end do
|
||||
end do
|
||||
end do
|
||||
|
||||
DO J = 1,nriver
|
||||
DO I = 1,Ns(j)-1
|
||||
Scanal = Scanal + ds(i,j) ! 每条河道各微段的长度,普通汊点、集中入流微段及调蓄水库的长度取0,每条河道的首末微段长度必须取一个非零值。
|
||||
END DO
|
||||
END DO
|
||||
|
||||
! 计算时间步长
|
||||
maxtstep=period*3600/dt
|
||||
maxiter=1000 ! 仿真模拟步数
|
||||
|
||||
! 给河道水位、流量赋初值
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
Z0(Is,river)=ZZ0
|
||||
Q0(Is,river)=0.0
|
||||
END DO
|
||||
END DO
|
||||
|
||||
DO tstep=1,maxtstep ! 步数累加器
|
||||
|
||||
ttime=dt*tstep/3600.0 ! 真实时刻
|
||||
|
||||
iter=0
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
Z(Is,river)=Z0(Is,river)
|
||||
Q(Is,river)=Q0(Is,river)
|
||||
END DO
|
||||
END DO
|
||||
|
||||
! 计算当前时刻入河流量大小
|
||||
call int_a( ttime ,& ! 真实时刻 // 输入参数
|
||||
ndata ,& ! 入河流量变化过程时段数
|
||||
Qp ,& ! 入河流量变化过程线
|
||||
fc ) ! 当前时刻入河流量大小 // 输出参数
|
||||
|
||||
ql=fc/Scanal
|
||||
|
||||
25 iter=iter+1
|
||||
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
Zc(Is,river)=Z(Is,river)
|
||||
Qc(Is,river)=Q(Is,river)
|
||||
END DO
|
||||
END DO
|
||||
|
||||
DO river=1,nriver
|
||||
! 确定计算时刻河段上下游边界条件值
|
||||
call sub_bound( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river ,&
|
||||
tstep ,&
|
||||
Ns ,&
|
||||
Pc ,&
|
||||
Nrc ,&
|
||||
Lc ,&
|
||||
Dric ,&
|
||||
Qj ,&
|
||||
Asave ,&
|
||||
UB1 ,&
|
||||
UB2 ,&
|
||||
DB1 ,&
|
||||
DB2 ,&
|
||||
NUB ,&
|
||||
NDB ,&
|
||||
UBV ,&
|
||||
Aphi ,&
|
||||
DBV ,&
|
||||
Gate ,&
|
||||
ql ,&
|
||||
Zctr ,&
|
||||
dt ,&
|
||||
sita ,&
|
||||
Bsor1 ,&
|
||||
Bsor2 ,&
|
||||
Z0 ,&
|
||||
Q0 ,&
|
||||
Z ,&
|
||||
Q ,&
|
||||
V ,&
|
||||
condu ,&
|
||||
condd )
|
||||
|
||||
! 用四点隐格式计算未知时层水位Z和流量Q
|
||||
call sub_QZ( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river ,&
|
||||
tstep ,&
|
||||
Ns ,&
|
||||
Pc ,&
|
||||
Nrc ,&
|
||||
Lc ,&
|
||||
Dric ,&
|
||||
Qj ,&
|
||||
Asave ,&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
UB1 ,&
|
||||
UB2 ,&
|
||||
DB1 ,&
|
||||
DB2 ,&
|
||||
NUB ,&
|
||||
NDB ,&
|
||||
UBV ,&
|
||||
Aphi ,&
|
||||
DBV ,&
|
||||
Gate ,&
|
||||
ql ,&
|
||||
Zctr ,&
|
||||
dt ,&
|
||||
sita ,&
|
||||
Bsor1 ,&
|
||||
Bsor2 ,&
|
||||
Z0 ,&
|
||||
Q0 ,&
|
||||
Z ,&
|
||||
Q ,&
|
||||
V ,&
|
||||
condu ,&
|
||||
condd ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
|
||||
END DO
|
||||
|
||||
dzmax=0.0
|
||||
dqmax=0.0
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
dz=abs(Z(Is,river)-Zc(Is,river))
|
||||
dq=abs(Q(Is,river)-Qc(Is,river))
|
||||
if(dz.gt.dzmax)then
|
||||
dzmax=dz
|
||||
maxz_r=river
|
||||
maxz_s=Is
|
||||
end if
|
||||
if(dq.gt.dqmax)then
|
||||
dqmax=dq
|
||||
maxq_r=river
|
||||
maxq_s=Is
|
||||
end if
|
||||
END DO
|
||||
END DO
|
||||
|
||||
if(dzmax.gt.epsz.or.dqmax.gt.epsq)then
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
Z(Is,river)=(1.0-sorz)*Zc(Is,river)&
|
||||
+sorz*Z(Is,river)
|
||||
Q(Is,river)=(1.0-sorq)*Qc(Is,river)&
|
||||
+sorq*Q(Is,river)
|
||||
END DO
|
||||
END DO
|
||||
|
||||
if(iter.le.maxiter)then
|
||||
goto 25
|
||||
else
|
||||
exit
|
||||
end if
|
||||
|
||||
else
|
||||
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
! 计算断面几何要素
|
||||
call sub_sect(NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,Is,Z(Is,river),&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
|
||||
V(Is,river)=Q(Is,river)/As
|
||||
END DO
|
||||
END DO
|
||||
|
||||
DO river=1,nriver
|
||||
DO Is=1,Ns(river)
|
||||
Z0(Is,river)=Z(Is,river)
|
||||
Q0(Is,river)=Q(Is,river)
|
||||
END DO
|
||||
END DO
|
||||
|
||||
end if
|
||||
|
||||
end do
|
||||
|
||||
END SUBROUTINE MAIN_UFRN
|
164
Fortran/SUB_BOUND.f90
Normal file
164
Fortran/SUB_BOUND.f90
Normal file
@ -0,0 +1,164 @@
|
||||
! ==================================================================================
|
||||
! 确定计算时刻河段上下游边界条件值的子程序
|
||||
! ==================================================================================
|
||||
!
|
||||
! 说明:下游外边界条件都给定一个过程,有ndata个数据点(1小时间隔),水位边界即为水位过程,
|
||||
! 流量边界即为流量过程,水位流量关系边界只限挡潮闸情况,给出闸下潮位过程。
|
||||
! 河道末端挡潮闸水位流量关系简化成Q=C1*B*e*dZ^C2。Z>Ztide且Z>Zctr时开闸,
|
||||
! 否则关闸,Zctr是挡潮闸运行控制水位,保证内河不会过低。
|
||||
! ----------------------------------------------------------------------------------
|
||||
SUBROUTINE SUB_BOUND( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river ,&
|
||||
tstep ,&
|
||||
Ns ,&
|
||||
Pc ,&
|
||||
Nrc ,&
|
||||
Lc ,&
|
||||
Dric ,&
|
||||
Qj ,&
|
||||
Asave ,&
|
||||
UB1 ,&
|
||||
UB2 ,&
|
||||
DB1 ,&
|
||||
DB2 ,&
|
||||
NUB ,&
|
||||
NDB ,&
|
||||
UBV ,&
|
||||
Aphi ,&
|
||||
DBV ,&
|
||||
Gate ,&
|
||||
ql ,&
|
||||
Zctr ,&
|
||||
dt ,&
|
||||
sita ,&
|
||||
Bsor1 ,&
|
||||
Bsor2 ,&
|
||||
Z0 ,&
|
||||
Q0 ,&
|
||||
Z ,&
|
||||
Q ,&
|
||||
V ,&
|
||||
condu ,&
|
||||
condd )
|
||||
|
||||
INTEGER::NRIVER
|
||||
INTEGER::NSECT
|
||||
INTEGER::MRIVER
|
||||
INTEGER::KRC
|
||||
INTEGER::NDATA
|
||||
|
||||
INTEGER RIVER,TSTEP
|
||||
|
||||
! node
|
||||
INTEGER::Ns(nriver),Pc(nriver),Nrc(krc,nriver),Lc(krc,nriver)
|
||||
REAL::Dric(krc,nriver),Qj(ndata,krc,nriver),Asave(krc,nriver)
|
||||
! boundary
|
||||
INTEGER::UB1(nriver),UB2(nriver),DB1(nriver)
|
||||
INTEGER::DB2(nriver),NUB(2,nriver),NDB(2,nriver)
|
||||
REAL::UBV(ndata,nriver),Aphi(2,nriver),DBV(ndata,nriver)
|
||||
REAL::Gate(4,nriver),ql,Zctr
|
||||
! calcu
|
||||
REAL::dt,sita,Bsor1,Bsor2
|
||||
! zzqq
|
||||
REAL::Z0(nsect,nriver),Q0(nsect,nriver),Z(nsect,nriver)
|
||||
REAL::Q(nsect,nriver),V(nsect,nriver)
|
||||
! r_bv
|
||||
REAL::condu,condd(3)
|
||||
|
||||
REAL:: ZQ(NDATA)
|
||||
|
||||
|
||||
|
||||
TC=DT*FLOAT(TSTEP)/3600.0
|
||||
|
||||
! 上游边界处理
|
||||
IF(UB2(RIVER).EQ.1)THEN ! 外
|
||||
DO II=1,NDATA
|
||||
ZQ(II)=UBV(II,RIVER)
|
||||
END DO
|
||||
CALL INT_A(TC,NDATA,ZQ,FC)
|
||||
CONDU=FC
|
||||
ELSEIF(UB2(RIVER).EQ.2)THEN ! 内
|
||||
IR=NUB(1,RIVER)
|
||||
IS=NUB(2,RIVER)
|
||||
IF(UB1(RIVER).EQ.1)THEN
|
||||
CONDU=Z(IS,IR)
|
||||
END IF
|
||||
IF(UB1(RIVER).EQ.2)THEN
|
||||
CONDU=Q(IS+1,IR)
|
||||
END IF
|
||||
END IF
|
||||
|
||||
! 下游边界处理
|
||||
IF(DB2(RIVER).EQ.1)THEN
|
||||
DO II=1,NDATA
|
||||
ZQ(II)=DBV(II,RIVER)
|
||||
END DO
|
||||
CALL INT_A(TC,NDATA,ZQ,FC)
|
||||
IF(DB1(RIVER).EQ.1)THEN
|
||||
CONDD(1)=1.0
|
||||
CONDD(2)=0.0
|
||||
CONDD(3)=FC
|
||||
ELSE IF(DB1(RIVER).EQ.2)THEN
|
||||
CONDD(1)=0.0
|
||||
CONDD(2)=1.0
|
||||
CONDD(3)=FC
|
||||
ELSE IF(DB1(RIVER).EQ.3)THEN
|
||||
ZU0=Z0(NS(RIVER)-1,RIVER)
|
||||
ZU=Z0(NS(RIVER)-1,RIVER)
|
||||
ZU=(1-BSOR1)*ZU0+BSOR1*ZU
|
||||
B=GATE(1,RIVER)
|
||||
QMAX=GATE(2,RIVER)
|
||||
C1=GATE(3,RIVER)
|
||||
C2=GATE(4,RIVER)
|
||||
IF(ZU>FC.AND.ZU>=ZCTR)THEN
|
||||
DZ=ZU-FC
|
||||
EK=5.0*DZ
|
||||
IF(DZ<0.15)THEN
|
||||
E=0.0
|
||||
END IF
|
||||
QQ=C1*B*EK*DZ**C2
|
||||
QQ=(1-BSOR1)*Q0(NS(RIVER),RIVER)+BSOR1*QQ
|
||||
IF(QQ>QMAX)THEN
|
||||
QQ=QMAX
|
||||
END IF
|
||||
CONDD(1)=0.0
|
||||
CONDD(2)=1.0
|
||||
CONDD(3)=QQ
|
||||
ELSE
|
||||
CONDD(1)=0.0
|
||||
CONDD(2)=1.0
|
||||
CONDD(3)=0.0
|
||||
END IF
|
||||
END IF
|
||||
ELSEIF(DB2(RIVER).EQ.2)THEN
|
||||
IR=NDB(1,RIVER)
|
||||
IS=NDB(2,RIVER)
|
||||
IF(DB1(RIVER).EQ.1)THEN
|
||||
CONDD(1)=1.0
|
||||
CONDD(2)=0.0
|
||||
CONDD(3)=Z(IS,IR)
|
||||
ELSE
|
||||
AH=APHI(1,RIVER)
|
||||
PHI=APHI(2,RIVER)
|
||||
IF(Z(NS(RIVER),RIVER)>=Z(IS,IR))THEN
|
||||
QQ=AH*PHI*SQRT(2*9.8*(Z(NS(RIVER),RIVER)-Z(IS,IR)))
|
||||
ELSE
|
||||
QQ=-AH*PHI*SQRT(2*9.8*(Z(IS,IR)-Z(NS(RIVER),RIVER)))
|
||||
END IF
|
||||
QQ=(1-BSOR2)*Q0(NS(RIVER),RIVER)+BSOR2*QQ
|
||||
CONDD(1)=0.0
|
||||
CONDD(2)=1.0
|
||||
CONDD(3)=QQ
|
||||
END IF
|
||||
END IF
|
||||
|
||||
END SUBROUTINE SUB_BOUND
|
||||
|
||||
|
||||
|
||||
|
42
Fortran/SUB_INT_A.f90
Normal file
42
Fortran/SUB_INT_A.f90
Normal file
@ -0,0 +1,42 @@
|
||||
! 根据区域入河流量过程,计算当时时刻的流量大小
|
||||
|
||||
SUBROUTINE INT_A( TC ,& ! 真实时刻 // 输入参数
|
||||
N ,& ! 入河流量变化过程时段数
|
||||
F ,& ! 入河流量变化过程线
|
||||
FC ) ! 当前时刻入河流量大小 // 输出参数
|
||||
|
||||
IMPLICIT NONE
|
||||
|
||||
! 输入参数
|
||||
REAL::TC
|
||||
INTEGER::N
|
||||
REAL::F(N)
|
||||
|
||||
! 输出参数
|
||||
REAL::FC
|
||||
|
||||
! 中间参数
|
||||
INTEGER::I
|
||||
REAL::T
|
||||
REAL::T1
|
||||
REAL::T2
|
||||
|
||||
! 当前时间刚好和入河流量过程时刻值相同
|
||||
DO I=1,N
|
||||
T=1.0*FLOAT(I-1)
|
||||
IF(TC.EQ.T)THEN
|
||||
FC=F(I)
|
||||
END IF
|
||||
END DO
|
||||
|
||||
! 当前时间和入河流量过程时刻值不同,做线性插值
|
||||
DO I=1,N-1
|
||||
T1=1.0*FLOAT(I-1)
|
||||
T2=1.0*FLOAT(I)
|
||||
IF(TC.GT.T1.AND.TC.LT.T2)THEN
|
||||
FC=F(I)+(TC-T1)*(F(I+1)-F(I))/(T2-T1)
|
||||
EXIT
|
||||
END IF
|
||||
END DO
|
||||
|
||||
END SUBROUTINE INT_A
|
350
Fortran/SUB_QZ.f90
Normal file
350
Fortran/SUB_QZ.f90
Normal file
@ -0,0 +1,350 @@
|
||||
! ==================================================================================
|
||||
! 用四点隐格式计算未知时层水位Z和流量Q的子程序
|
||||
! ==================================================================================
|
||||
subroutine sub_QZ( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river ,&
|
||||
tstep ,&
|
||||
Ns ,&
|
||||
Pc ,&
|
||||
Nrc ,&
|
||||
Lc ,&
|
||||
Dric ,&
|
||||
Qj ,&
|
||||
Asave ,&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
UB1 ,&
|
||||
UB2 ,&
|
||||
DB1 ,&
|
||||
DB2 ,&
|
||||
NUB ,&
|
||||
NDB ,&
|
||||
UBV ,&
|
||||
Aphi ,&
|
||||
DBV ,&
|
||||
Gate ,&
|
||||
ql ,&
|
||||
Zctr ,&
|
||||
dt ,&
|
||||
sita ,&
|
||||
Bsor1 ,&
|
||||
Bsor2 ,&
|
||||
Z0 ,&
|
||||
Q0 ,&
|
||||
Z ,&
|
||||
Q ,&
|
||||
V ,&
|
||||
condu ,&
|
||||
condd ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
|
||||
|
||||
INTEGER::NRIVER
|
||||
INTEGER::NSECT
|
||||
INTEGER::MRIVER
|
||||
INTEGER::KRC
|
||||
INTEGER::NDATA
|
||||
integer River,tstep
|
||||
REAL Qjj(ndata)
|
||||
real L(nsect),M(nsect),P(nsect),R(nsect)
|
||||
|
||||
! node
|
||||
INTEGER::Ns(nriver),Pc(nriver),Nrc(krc,nriver),Lc(krc,nriver)
|
||||
REAL::Dric(krc,nriver),Qj(ndata,krc,nriver),Asave(krc,nriver)
|
||||
! section
|
||||
REAL::ds(mriver,nriver),bd(nsect,nriver),zd(nsect,nriver)
|
||||
REAL::sm(nsect,nriver), rough(nsect,nriver)
|
||||
! boundary
|
||||
INTEGER::UB1(nriver),UB2(nriver),DB1(nriver),DB2(nriver)
|
||||
INTEGER::NUB(2,nriver),NDB(2,nriver)
|
||||
REAL::UBV(ndata,nriver),Aphi(2,nriver),DBV(ndata,nriver)
|
||||
REAL::Gate(4,nriver),ql,Zctr
|
||||
! calcu
|
||||
REAL::dt,sita,Bsor1,Bsor2
|
||||
! zzqq
|
||||
REAL::Z0(nsect,nriver),Q0(nsect,nriver),Z(nsect,nriver)
|
||||
REAL::Q(nsect,nriver),V(nsect,nriver)
|
||||
! r_bv
|
||||
REAL::condu,condd(3)
|
||||
! BARC
|
||||
REAL::Bs,As,Rs,Cs
|
||||
|
||||
|
||||
f(t10,t1,t20,t2)=0.5*(sita*(t2+t1)+(1.0-sita)*(t20+t10))
|
||||
tc=dt*float(tstep)/3600.0
|
||||
|
||||
if(UB1(river).eq.1)Z(1,river)=condu
|
||||
if(UB1(river).eq.2)Q(1,river)=condu
|
||||
|
||||
! ----------------------------------------------------------------------------------
|
||||
! 计算递推公式系数L、M、P、R
|
||||
! ----------------------------------------------------------------------------------
|
||||
P(1)=condu
|
||||
R(1)=0.0
|
||||
|
||||
call sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,1,Z0(1,river),&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
BB10=Bs
|
||||
AA10=As
|
||||
RR10=Rs
|
||||
CC10=Cs
|
||||
call sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,1,Z(1,river),&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
BB1=Bs
|
||||
AA1=As
|
||||
RR1=Rs
|
||||
CC1=Cs
|
||||
do 100 k=1,Ns(river)-1
|
||||
Ik=0
|
||||
do 20 i=1,Pc(river)
|
||||
if(Nrc(i,river).eq.k)then
|
||||
Ic=i
|
||||
Ik=1
|
||||
end if
|
||||
20 continue
|
||||
|
||||
if(Ik.ne.1)then
|
||||
! ------------------------------------------------------
|
||||
! 非汊点河段计算
|
||||
!
|
||||
! 计算河段M点处的水面宽B、面积A、水力半径R、流量Q和水位Z
|
||||
! ------------------------------------------------------
|
||||
call sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,k+1,Z0(k+1,river),&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
BB20=Bs
|
||||
AA20=As
|
||||
RR20=Rs
|
||||
CC20=Cs
|
||||
call sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,k+1,Z(k+1,river),&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
BB2=Bs
|
||||
AA2=As
|
||||
RR2=Rs
|
||||
CC2=Cs
|
||||
Bm=f(BB10,BB1,BB20,BB2)
|
||||
Am=f(AA10,AA1,AA20,AA2)
|
||||
Rm=f(RR10,RR1,RR20,RR2)
|
||||
Cm=f(CC10,CC1,CC20,CC2)
|
||||
Qm=f(Q0(k,river),Q(k,river),Q0(k+1,river),Q(k+1,river))
|
||||
Zm=f(Z0(k,river),Z(k,river),Z0(k+1,river),Z(k+1,river))
|
||||
|
||||
! ------------------------------------------------------
|
||||
! 计算河段方程中的系数
|
||||
! ------------------------------------------------------
|
||||
a1=1.0
|
||||
c1=2.0*sita*dt/(ds(k,river)*Bm)
|
||||
e1=Z0(k,river)+Z0(k+1,river)+(1.0-sita)/sita*c1*(Q0(k,river)&
|
||||
-Q0(k+1,river))+2.0*dt*ql/Bm
|
||||
a2=2.0*sita*dt/ds(k,river)*((Qm/Am)**2.0*Bm-9.8*Am)
|
||||
c2=1.0-4.0*sita*dt/ds(k,river)*Qm/Am
|
||||
d2=1.0+4.0*sita*dt/ds(k,river)*Qm/Am
|
||||
call sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,k,Zm,&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
AZm1=As
|
||||
call sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river,k+1,Zm,&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
AZm2=As
|
||||
e2=(1.0-sita)/sita*a2*(Z0(k+1,river)-Z0(k,river))+(1.0-4.0*&
|
||||
(1.0-sita)*dt/ds(k,river)*Qm/Am)*Q0(k+1,river)+(1.0+4.0*&
|
||||
(1.0-sita)*dt/ds(k,river)*Qm/Am)*Q0(k,river)+2.0*dt*&
|
||||
(Qm/Am)**2.0*(AZm2-AZm1)/ds(k,river)-2.0*dt*9.8*abs(Qm)*Qm&
|
||||
/(Am*Cm*Cm*Rm)
|
||||
else
|
||||
|
||||
! --------------------------------------------------------
|
||||
! 汊点计算处理(普通汊点Lc=1,集中入流Lc=2,调蓄水库Lc=3)
|
||||
! --------------------------------------------------------
|
||||
if(Lc(Ic,river).eq.1)then
|
||||
do 35 j=1,nriver
|
||||
if(NUB(1,j).eq.river.and.NUB(2,j).eq.Nrc(Ic,river))then
|
||||
a1=0.0
|
||||
c1=1.0
|
||||
e1=Dric(Ic,river)*Q(1,j)
|
||||
a2=1.0
|
||||
c2=0.0
|
||||
d2=0.0
|
||||
e2=0.0
|
||||
elseif(NDB(1,j).eq.river.and.NDB(2,j).eq.Nrc(Ic,river))then
|
||||
a1=0.0
|
||||
c1=1.0
|
||||
e1=Dric(Ic,river)*Q(Ns(j),j)
|
||||
a2=1.0
|
||||
c2=0.0
|
||||
d2=0.0
|
||||
e2=0.0
|
||||
end if
|
||||
35 continue
|
||||
elseif(Lc(Ic,river).eq.2)then
|
||||
do 55 ii=1,ndata
|
||||
Qjj(ii)=Qj(ii,Ic,river)
|
||||
55 continue
|
||||
call int_a(tc,ndata,Qjj,fc)
|
||||
a1=0.0
|
||||
c1=1.0
|
||||
e1=Dric(Ic,river)*fc
|
||||
a2=1.0
|
||||
c2=0.0
|
||||
d2=0.0
|
||||
e2=0.0
|
||||
elseif(Lc(Ic,river).eq.3)then
|
||||
a1=0.5*Asave(Ic,river)/dt
|
||||
c1=1.0
|
||||
e1=Asave(Ic,river)*Z0(k,river)/dt
|
||||
a2=1.0
|
||||
c2=0.0
|
||||
d2=0.0
|
||||
e2=0.0
|
||||
end if
|
||||
|
||||
|
||||
end if
|
||||
|
||||
! ------------------------------------------------------
|
||||
! 求上游边界条件为水位过程线的递推系数
|
||||
! ------------------------------------------------------
|
||||
if(UB1(river).eq.1)then
|
||||
Y1=a1*R(k)-c1
|
||||
Y2=a2*R(k)+c2
|
||||
Y3=e1-a1*P(k)
|
||||
Y4=e2-a2*P(k)
|
||||
Y5=a1*Y2+a2*Y1
|
||||
L(k+1)=(a2*Y3+a1*Y4)/Y5
|
||||
M(k+1)=-(a1*d2+a2*c1)/Y5
|
||||
P(k+1)=(Y2*Y3-Y1*Y4)/Y5
|
||||
R(k+1)=(d2*Y1-c1*Y2)/Y5
|
||||
end if
|
||||
! ------------------------------------------------------
|
||||
! 求上游边界条件为流量过程线的递推系数
|
||||
! ------------------------------------------------------
|
||||
if(UB1(river).eq.2)then
|
||||
Y1=a1-c1*R(k)
|
||||
Y2=a2+c2*R(k)
|
||||
Y3=e1+c1*P(k)
|
||||
Y4=e2-c2*P(k)
|
||||
Y5=d2*Y1-c1*Y2
|
||||
L(k+1)=(d2*Y3-c1*Y4)/Y5
|
||||
M(k+1)=-(a1*d2+a2*c1)/Y5
|
||||
P(k+1)=(Y1*Y4-Y2*Y3)/Y5
|
||||
R(k+1)=(a1*Y2+a2*Y1)/Y5
|
||||
end if
|
||||
|
||||
BB10=BB20
|
||||
AA10=AA20
|
||||
RR10=RR20
|
||||
CC10=CC20
|
||||
BB1=BB2
|
||||
AA1=AA2
|
||||
RR1=RR2
|
||||
CC1=CC2
|
||||
100 continue
|
||||
! ----------------------------------------------------------------------------------
|
||||
! 回代求出流量Q和水位Z
|
||||
! ----------------------------------------------------------------------------------
|
||||
if(UB1(river).eq.1)then
|
||||
Q(Ns(river),river)=(condd(3)-condd(1)*P(Ns(river)))&
|
||||
/(condd(1)*R(Ns(river))+condd(2))
|
||||
do 120 i=Ns(river),2,-1
|
||||
Z(i,river)=P(i)+R(i)*Q(i,river)
|
||||
Q(i-1,river)=L(i)+M(i)*Q(i,river)
|
||||
120 continue
|
||||
end if
|
||||
|
||||
if(UB1(river).eq.2)then
|
||||
Z(Ns(river),river)=(condd(3)-condd(2)*P(Ns(river)))&
|
||||
/(condd(2)*R(Ns(river))+condd(1))
|
||||
do 130 i=Ns(river),2,-1
|
||||
Q(i,river)=P(i)+R(i)*Z(i,river)
|
||||
Z(i-1,river)=L(i)+M(i)*Z(i,river)
|
||||
130 continue
|
||||
end if
|
||||
|
||||
return
|
||||
end
|
46
Fortran/SUB_SECT.f90
Normal file
46
Fortran/SUB_SECT.f90
Normal file
@ -0,0 +1,46 @@
|
||||
! ==================================================================================
|
||||
! 计算断面几何要素的子程序
|
||||
! ==================================================================================
|
||||
subroutine sub_sect( NRIVER ,&
|
||||
NSECT ,&
|
||||
MRIVER ,&
|
||||
KRC ,&
|
||||
NDATA ,&
|
||||
river ,&
|
||||
Is ,&
|
||||
Zs ,&
|
||||
ds ,&
|
||||
bd ,&
|
||||
zd ,&
|
||||
sm ,&
|
||||
rough ,&
|
||||
Bs ,&
|
||||
As ,&
|
||||
Rs ,&
|
||||
Cs )
|
||||
|
||||
INTEGER::NRIVER
|
||||
INTEGER::NSECT
|
||||
INTEGER::MRIVER
|
||||
INTEGER::KRC
|
||||
INTEGER::NDATA
|
||||
|
||||
integer River
|
||||
! section
|
||||
REAL::ds(mriver,nriver),bd(nsect,nriver),zd(nsect,nriver)
|
||||
REAL::sm(nsect,nriver), rough(nsect,nriver)
|
||||
! BARC
|
||||
REAL::Bs,As,Rs,Cs
|
||||
|
||||
! ----------------------------------------------------------------------------------
|
||||
! Bs、As、Rs、Cs——相应于水位Zs的断面要素(梯形断面)
|
||||
! ----------------------------------------------------------------------------------
|
||||
h=Zs-zd(Is,river)
|
||||
Bs=bd(Is,river)+2.0*sm(Is,river)*h
|
||||
As=(bd(Is,river)+sm(Is,river)*h)*h
|
||||
Sl=bd(Is,river)+2*h*sqrt(1+sm(Is,river)**2.0)
|
||||
Rs=As/Sl
|
||||
Cs=Rs**(1.0/6.0)/rough(Is,river)
|
||||
return
|
||||
end
|
||||
|
0
Fortran/~$1.xlsx
Normal file
0
Fortran/~$1.xlsx
Normal file
27
FortranWebApi.csproj
Normal file
27
FortranWebApi.csproj
Normal file
@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="lib{{FortranFunctionName}}.so">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
49
HttpRequests/fortranwebapi.http
Normal file
49
HttpRequests/fortranwebapi.http
Normal file
@ -0,0 +1,49 @@
|
||||
@FortranWebApi_HostAddress = http://localhost:5000
|
||||
|
||||
### 测试Fortran请求
|
||||
|
||||
POST {{FortranWebApi_HostAddress}}/FortranCalculate
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"text": "{\"FuncName\":\"calculate_main\",\"ClassName\":\"\",\"Par\":[ {"Name":"nriver","DataType":"0","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"nsect","DataType":"0","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"krc","DataType":"0","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"ndata","DataType":"0","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"Ns","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Pc","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Nrc","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Lc","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Dric","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"XJ","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Asave","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"ds","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"bd","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"zd","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"sm","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"rough","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"ZZ0","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"Zctr","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"Qp","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"UB1","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"UB2","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"DB1","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"DB2","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"UBV","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"NUB","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"DBV","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Gate","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"NDB","DataType":"0","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"Aphi","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]},
|
||||
{"Name":"period","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"dt","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"sita","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"sorz","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"sorq","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"epsz","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"epsq","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"Bsor1","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"Bsor2","DataType":"1","ArrayType":"0","IsOut":"2","Data":0},
|
||||
{"Name":"Z","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]},
|
||||
{"Name":"Q","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}]}"
|
||||
}
|
31
Models/ApiResponse.cs
Normal file
31
Models/ApiResponse.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FortranWebApi.Models
|
||||
{
|
||||
public class ApiResponse<T>
|
||||
{
|
||||
[JsonPropertyName("message")]
|
||||
public string Message { get; set; } = "Success";
|
||||
|
||||
[JsonPropertyName("success")]
|
||||
public bool Success { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public ApiResponseData<T>? Data { get; set; }
|
||||
}
|
||||
|
||||
public class ApiResponseData<T>
|
||||
{
|
||||
[JsonPropertyName("contentType")]
|
||||
public string? ContentType { get; set; }
|
||||
|
||||
[JsonPropertyName("serializerSettings")]
|
||||
public object? SerializerSettings { get; set; }
|
||||
|
||||
[JsonPropertyName("statusCode")]
|
||||
public int? StatusCode { get; set; }
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public T? Value { get; set; }
|
||||
}
|
||||
}
|
22
Models/FortranParameter.cs
Normal file
22
Models/FortranParameter.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FortranWebApi.Models
|
||||
{
|
||||
public class FortranParameter
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("dataType")]
|
||||
public string DataType { get; set; } = "0";
|
||||
|
||||
[JsonPropertyName("arrayType")]
|
||||
public string ArrayType { get; set; } = "0";
|
||||
|
||||
[JsonPropertyName("isOut")]
|
||||
public string IsOut { get; set; } = "2";
|
||||
|
||||
[JsonPropertyName("data")]
|
||||
public object? Data { get; set; }
|
||||
}
|
||||
}
|
13
Models/FortranRequest.cs
Normal file
13
Models/FortranRequest.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FortranWebApi.Models
|
||||
{
|
||||
public class FortranRequest
|
||||
{
|
||||
public string FuncName { get; set; } = string.Empty;
|
||||
public string ClassName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("par")]
|
||||
public List<FortranParameter> Parameters { get; set; } = new List<FortranParameter>();
|
||||
}
|
||||
}
|
7
Models/FortranRequestWrapper.cs
Normal file
7
Models/FortranRequestWrapper.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace FortranWebApi.Models
|
||||
{
|
||||
public class FortranRequestWrapper
|
||||
{
|
||||
public string Text { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
80
Program.cs
Normal file
80
Program.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using Serilog;
|
||||
using FortranWebApi.Services;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
// 设置库搜索路径
|
||||
string currentDir = Directory.GetCurrentDirectory();
|
||||
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH",
|
||||
$"{Environment.GetEnvironmentVariable("LD_LIBRARY_PATH")}:{currentDir}");
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// 添加健康检查服务
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
// 配置Serilog
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.Console(outputTemplate:
|
||||
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
.WriteTo.File("logs/log-.txt",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
outputTemplate:
|
||||
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
|
||||
.CreateLogger();
|
||||
|
||||
builder.Host.UseSerilog(); // 将Serilog添加到Host
|
||||
|
||||
// 配置JSON序列化选项,使用驼峰命名法
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
|
||||
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
|
||||
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
|
||||
});
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddSingleton<FortranInteropService>();
|
||||
|
||||
// 配置CORS
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddDefaultPolicy(policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseCors();
|
||||
app.UseAuthorization();
|
||||
// 映射健康检查端点
|
||||
app.MapHealthChecks("/health");
|
||||
app.MapControllers();
|
||||
|
||||
try
|
||||
{
|
||||
Log.Information("启动应用程序...");
|
||||
app.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "应用程序启动失败");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
14
Properties/launchSettings.json
Normal file
14
Properties/launchSettings.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"profiles": {
|
||||
"FortranWebApi": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://0.0.0.0:5000"
|
||||
}
|
||||
}
|
||||
}
|
627
Services/FortranInteropService.cs
Normal file
627
Services/FortranInteropService.cs
Normal file
@ -0,0 +1,627 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using FortranWebApi.Models;
|
||||
using System.Text.Json;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
using System.IO;
|
||||
|
||||
namespace FortranWebApi.Services
|
||||
{
|
||||
public class FortranInteropService
|
||||
{
|
||||
// 静态构造函数设置DLL导入解析器
|
||||
static FortranInteropService()
|
||||
{
|
||||
// 添加当前目录到库搜索路径
|
||||
NativeLibrary.SetDllImportResolver(typeof(FortranInteropService).Assembly, (name, assembly, path) =>
|
||||
{
|
||||
if (name == "libMAIN_UFRN.so")
|
||||
{
|
||||
// 尝试从当前目录加载
|
||||
string currentDir = Directory.GetCurrentDirectory();
|
||||
string libraryPath = Path.Combine(currentDir, "libMAIN_UFRN.so");
|
||||
|
||||
if (File.Exists(libraryPath))
|
||||
{
|
||||
return NativeLibrary.Load(libraryPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 回退到默认加载行为
|
||||
return IntPtr.Zero;
|
||||
});
|
||||
}
|
||||
|
||||
// DllImport声明
|
||||
[DllImport("libMAIN_UFRN.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "MAIN_UFRN")]
|
||||
private static extern void MAIN_UFRN(
|
||||
ref int nriver,
|
||||
ref int nsect,
|
||||
ref int krc,
|
||||
ref int ndata,
|
||||
int[] Ns,
|
||||
int[] Pc,
|
||||
int[] Nrc,
|
||||
int[] Lc,
|
||||
float[] Dric,
|
||||
float[] XJ,
|
||||
float[] Asave,
|
||||
float[] ds,
|
||||
float[] bd,
|
||||
float[] zd,
|
||||
float[] sm,
|
||||
float[] rough,
|
||||
ref float ZZ0,
|
||||
ref float Zctr,
|
||||
float[] Qp,
|
||||
int[] UB1,
|
||||
int[] UB2,
|
||||
int[] DB1,
|
||||
int[] DB2,
|
||||
float[] UBV,
|
||||
int[] NUB,
|
||||
float[] DBV,
|
||||
float[] Gate,
|
||||
int[] NDB,
|
||||
float[] Aphi,
|
||||
ref float period,
|
||||
ref float dt,
|
||||
ref float sita,
|
||||
ref float sorz,
|
||||
ref float sorq,
|
||||
ref float epsz,
|
||||
ref float epsq,
|
||||
ref float Bsor1,
|
||||
ref float Bsor2,
|
||||
float[] Z,
|
||||
float[] Q
|
||||
);
|
||||
|
||||
public string ProcessFortranRequest(string requestText)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 解析请求
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
var request = JsonSerializer.Deserialize<FortranRequest>(requestText, options);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentException("无效的请求格式");
|
||||
}
|
||||
|
||||
// 准备输入参数
|
||||
var parameters = request.Parameters;
|
||||
|
||||
// 提取参数
|
||||
int nriver = GetIntParameter(parameters, "nriver");
|
||||
int nsect = GetIntParameter(parameters, "nsect");
|
||||
int krc = GetIntParameter(parameters, "krc");
|
||||
int ndata = GetIntParameter(parameters, "ndata");
|
||||
int[] Ns = GetIntArrayParameter(parameters, "Ns");
|
||||
int[] Pc = GetIntArrayParameter(parameters, "Pc");
|
||||
int[] Nrc = GetIntArrayParameter(parameters, "Nrc");
|
||||
int[] Lc = GetIntArrayParameter(parameters, "Lc");
|
||||
float[] Dric = GetFloatArrayParameter(parameters, "Dric");
|
||||
float[] XJ = GetFloatArrayParameter(parameters, "XJ");
|
||||
float[] Asave = GetFloatArrayParameter(parameters, "Asave");
|
||||
float[] ds = GetFloatArrayParameter(parameters, "ds");
|
||||
float[] bd = GetFloatArrayParameter(parameters, "bd");
|
||||
float[] zd = GetFloatArrayParameter(parameters, "zd");
|
||||
float[] sm = GetFloatArrayParameter(parameters, "sm");
|
||||
float[] rough = GetFloatArrayParameter(parameters, "rough");
|
||||
float ZZ0 = GetFloatParameter(parameters, "ZZ0");
|
||||
float Zctr = GetFloatParameter(parameters, "Zctr");
|
||||
float[] Qp = GetFloatArrayParameter(parameters, "Qp");
|
||||
int[] UB1 = GetIntArrayParameter(parameters, "UB1");
|
||||
int[] UB2 = GetIntArrayParameter(parameters, "UB2");
|
||||
int[] DB1 = GetIntArrayParameter(parameters, "DB1");
|
||||
int[] DB2 = GetIntArrayParameter(parameters, "DB2");
|
||||
float[] UBV = GetFloatArrayParameter(parameters, "UBV");
|
||||
int[] NUB = GetIntArrayParameter(parameters, "NUB");
|
||||
float[] DBV = GetFloatArrayParameter(parameters, "DBV");
|
||||
float[] Gate = GetFloatArrayParameter(parameters, "Gate");
|
||||
int[] NDB = GetIntArrayParameter(parameters, "NDB");
|
||||
float[] Aphi = GetFloatArrayParameter(parameters, "Aphi");
|
||||
float period = GetFloatParameter(parameters, "period");
|
||||
float dt = GetFloatParameter(parameters, "dt");
|
||||
float sita = GetFloatParameter(parameters, "sita");
|
||||
float sorz = GetFloatParameter(parameters, "sorz");
|
||||
float sorq = GetFloatParameter(parameters, "sorq");
|
||||
float epsz = GetFloatParameter(parameters, "epsz");
|
||||
float epsq = GetFloatParameter(parameters, "epsq");
|
||||
float Bsor1 = GetFloatParameter(parameters, "Bsor1");
|
||||
float Bsor2 = GetFloatParameter(parameters, "Bsor2");
|
||||
|
||||
|
||||
// 准备数组参数
|
||||
float[] Z = new float[10000]; // 输出数组,初始大小为10000
|
||||
float[] Q = new float[10000]; // 输出数组,初始大小为10000
|
||||
|
||||
|
||||
// 调用Fortran函数
|
||||
MAIN_UFRN(
|
||||
ref nriver,
|
||||
ref nsect,
|
||||
ref krc,
|
||||
ref ndata,
|
||||
Ns,
|
||||
Pc,
|
||||
Nrc,
|
||||
Lc,
|
||||
Dric,
|
||||
XJ,
|
||||
Asave,
|
||||
ds,
|
||||
bd,
|
||||
zd,
|
||||
sm,
|
||||
rough,
|
||||
ref ZZ0,
|
||||
ref Zctr,
|
||||
Qp,
|
||||
UB1,
|
||||
UB2,
|
||||
DB1,
|
||||
DB2,
|
||||
UBV,
|
||||
NUB,
|
||||
DBV,
|
||||
Gate,
|
||||
NDB,
|
||||
Aphi,
|
||||
ref period,
|
||||
ref dt,
|
||||
ref sita,
|
||||
ref sorz,
|
||||
ref sorq,
|
||||
ref epsz,
|
||||
ref epsq,
|
||||
ref Bsor1,
|
||||
ref Bsor2,
|
||||
Z,
|
||||
Q
|
||||
);
|
||||
|
||||
// 更新输出参数
|
||||
UpdateParameter(parameters, "Z", Z);
|
||||
UpdateParameter(parameters, "Q", Q);
|
||||
|
||||
|
||||
// 处理输出数组
|
||||
// 处理输出数组 Z
|
||||
// 注意:没有找到明确的长度参数,使用非零元素数量
|
||||
{
|
||||
int nonZeroCount = 0;
|
||||
for (int i = 0; i < Z.Length; i++)
|
||||
{
|
||||
if (Z[i] != 0) nonZeroCount = i + 1;
|
||||
}
|
||||
if (nonZeroCount > 0)
|
||||
{
|
||||
float[] resultArray = new float[nonZeroCount];
|
||||
Array.Copy(Z, resultArray, nonZeroCount);
|
||||
UpdateArrayParameter(parameters, "Z", resultArray);
|
||||
}
|
||||
}
|
||||
// 处理输出数组 Q
|
||||
// 注意:没有找到明确的长度参数,使用非零元素数量
|
||||
{
|
||||
int nonZeroCount = 0;
|
||||
for (int i = 0; i < Q.Length; i++)
|
||||
{
|
||||
if (Q[i] != 0) nonZeroCount = i + 1;
|
||||
}
|
||||
if (nonZeroCount > 0)
|
||||
{
|
||||
float[] resultArray = new float[nonZeroCount];
|
||||
Array.Copy(Q, resultArray, nonZeroCount);
|
||||
UpdateArrayParameter(parameters, "Q", resultArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 返回结果 - 只返回原始请求的结构,但包含更新后的参数
|
||||
var result = new FortranRequest
|
||||
{
|
||||
FuncName = request.FuncName,
|
||||
ClassName = request.ClassName,
|
||||
Parameters = parameters
|
||||
};
|
||||
|
||||
return JsonSerializer.Serialize(result, options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return JsonSerializer.Serialize(new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
private float GetFloatParameter(List<FortranParameter> parameters, string name)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (param.Data is JsonElement element)
|
||||
{
|
||||
if (element.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
return element.GetSingle();
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.ToSingle(param.Data);
|
||||
}
|
||||
private double GetDoubleParameter(List<FortranParameter> parameters, string name)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (param.Data is JsonElement element)
|
||||
{
|
||||
if (element.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
return element.GetSingle();
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.ToDouble(param.Data);
|
||||
}
|
||||
private int GetIntParameter(List<FortranParameter> parameters, string name)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param.Data is JsonElement element)
|
||||
{
|
||||
if (element.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
return element.GetInt32();
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.ToInt32(param.Data);
|
||||
}
|
||||
private int[] GetIntArrayParameter(List<FortranParameter> parameters, string name)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return Array.Empty<int>();
|
||||
}
|
||||
|
||||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var array = new List<int>();
|
||||
foreach (var item in element.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
array.Add(item.GetInt32());
|
||||
}
|
||||
}
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||||
{
|
||||
var array = new List<int>();
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
array.Add(Convert.ToInt32(item));
|
||||
}
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
return Array.Empty<int>();
|
||||
}
|
||||
private float[] GetFloatArrayParameter(List<FortranParameter> parameters, string name)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return Array.Empty<float>();
|
||||
}
|
||||
|
||||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var array = new List<float>();
|
||||
foreach (var item in element.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
array.Add(item.GetSingle());
|
||||
}
|
||||
}
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||||
{
|
||||
var array = new List<float>();
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
array.Add(Convert.ToSingle(item));
|
||||
}
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
return Array.Empty<float>();
|
||||
}
|
||||
private double[] GetDoubleArrayParameter(List<FortranParameter> parameters, string name)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return Array.Empty<double>();
|
||||
}
|
||||
|
||||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var array = new List<double>();
|
||||
foreach (var item in element.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
array.Add(item.GetSingle());
|
||||
}
|
||||
}
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||||
{
|
||||
var array = new List<double>();
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
array.Add(Convert.ToSingle(item));
|
||||
}
|
||||
return array.ToArray();
|
||||
}
|
||||
|
||||
return Array.Empty<double>();
|
||||
}
|
||||
private void UpdateParameter(List<FortranParameter> parameters, string name, object value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
param.Data = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateArrayParameter(List<FortranParameter> parameters, string name, float[] value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
param.Data = value;
|
||||
}
|
||||
}
|
||||
private void UpdateDoubleArrayParameter(List<FortranParameter> parameters, string name, double[] value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
param.Data = value;
|
||||
}
|
||||
}
|
||||
private void UpdateIntArrayParameter(List<FortranParameter> parameters, string name, int[] value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
param.Data = value;
|
||||
}
|
||||
}
|
||||
// 添加新的辅助方法来处理二维数组
|
||||
private double[,] GetDouble2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return new double[rows, cols];
|
||||
}
|
||||
|
||||
double[,] result = new double[rows, cols];
|
||||
|
||||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in element.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
int row = index / cols;
|
||||
int col = index % cols;
|
||||
if (row < rows && col < cols)
|
||||
{
|
||||
result[row, col] = item.GetDouble();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
int row = index / cols;
|
||||
int col = index % cols;
|
||||
if (row < rows && col < cols)
|
||||
{
|
||||
result[row, col] = Convert.ToDouble(item);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 添加更新二维数组参数的方法
|
||||
private void UpdateDouble2DArrayParameter(List<FortranParameter> parameters, string name, double[,] value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
// 将二维数组转换为一维数组以便于JSON序列化
|
||||
int rows = value.GetLength(0);
|
||||
int cols = value.GetLength(1);
|
||||
double[] flatArray = new double[rows * cols];
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
for (int j = 0; j < cols; j++)
|
||||
{
|
||||
flatArray[i * cols + j] = value[i, j];
|
||||
}
|
||||
}
|
||||
param.Data = flatArray;
|
||||
}
|
||||
}
|
||||
// float版本
|
||||
private float[,] GetFloat2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return new float[rows, cols];
|
||||
}
|
||||
|
||||
float[,] result = new float[rows, cols];
|
||||
|
||||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in element.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
int row = index / cols;
|
||||
int col = index % cols;
|
||||
if (row < rows && col < cols)
|
||||
{
|
||||
result[row, col] = item.GetSingle();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
int row = index / cols;
|
||||
int col = index % cols;
|
||||
if (row < rows && col < cols)
|
||||
{
|
||||
result[row, col] = Convert.ToSingle(item);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void UpdateFloat2DArrayParameter(List<FortranParameter> parameters, string name, float[,] value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
int rows = value.GetLength(0);
|
||||
int cols = value.GetLength(1);
|
||||
float[] flatArray = new float[rows * cols];
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
for (int j = 0; j < cols; j++)
|
||||
{
|
||||
flatArray[i * cols + j] = value[i, j];
|
||||
}
|
||||
}
|
||||
param.Data = flatArray;
|
||||
}
|
||||
}
|
||||
|
||||
// int版本
|
||||
private int[,] GetInt2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param == null || param.Data == null)
|
||||
{
|
||||
return new int[rows, cols];
|
||||
}
|
||||
|
||||
int[,] result = new int[rows, cols];
|
||||
|
||||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in element.EnumerateArray())
|
||||
{
|
||||
if (item.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
int row = index / cols;
|
||||
int col = index % cols;
|
||||
if (row < rows && col < cols)
|
||||
{
|
||||
result[row, col] = item.GetInt32();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
int row = index / cols;
|
||||
int col = index % cols;
|
||||
if (row < rows && col < cols)
|
||||
{
|
||||
result[row, col] = Convert.ToInt32(item);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void UpdateInt2DArrayParameter(List<FortranParameter> parameters, string name, int[,] value)
|
||||
{
|
||||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||||
if (param != null)
|
||||
{
|
||||
int rows = value.GetLength(0);
|
||||
int cols = value.GetLength(1);
|
||||
int[] flatArray = new int[rows * cols];
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
for (int j = 0; j < cols; j++)
|
||||
{
|
||||
flatArray[i * cols + j] = value[i, j];
|
||||
}
|
||||
}
|
||||
param.Data = flatArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
appsettings.json
Normal file
16
appsettings.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"Endpoints": {
|
||||
"Http": {
|
||||
"Url": "http://0.0.0.0:5000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user