From 027e45867b73873de2204bcf6824dccef2ffec6f Mon Sep 17 00:00:00 2001 From: tp <1799149022@qq.com> Date: Fri, 9 May 2025 17:45:43 +0800 Subject: [PATCH] 1 --- Controllers/FortranController.cs | 74 ++++ Dockerfile | 88 +++++ Fortran/1.json | 120 +++++++ Fortran/1.xlsx | Bin 0 -> 10716 bytes Fortran/SUB_BOUND.f90 | 161 +++++++++ Fortran/SUB_GETNXT.F90 | 29 ++ Fortran/SUB_INT_A.f90 | 42 +++ Fortran/SUB_QZ.f90 | 339 ++++++++++++++++++ Fortran/SUB_SECT.f90 | 45 +++ Fortran/SUB_SHUILIANGJISUAN.f90 | 563 +++++++++++++++++++++++++++++ FortranWebApi.csproj | 27 ++ HttpRequests/fortranwebapi.http | 23 ++ Models/ApiResponse.cs | 31 ++ Models/FortranParameter.cs | 22 ++ Models/FortranRequest.cs | 13 + Models/FortranRequestWrapper.cs | 7 + Program.cs | 80 +++++ Properties/launchSettings.json | 14 + Services/FortranInteropService.cs | 565 ++++++++++++++++++++++++++++++ appsettings.json | 16 + 20 files changed, 2259 insertions(+) create mode 100644 Controllers/FortranController.cs create mode 100644 Dockerfile create mode 100644 Fortran/1.json create mode 100644 Fortran/1.xlsx create mode 100644 Fortran/SUB_BOUND.f90 create mode 100644 Fortran/SUB_GETNXT.F90 create mode 100644 Fortran/SUB_INT_A.f90 create mode 100644 Fortran/SUB_QZ.f90 create mode 100644 Fortran/SUB_SECT.f90 create mode 100644 Fortran/SUB_SHUILIANGJISUAN.f90 create mode 100644 FortranWebApi.csproj create mode 100644 HttpRequests/fortranwebapi.http create mode 100644 Models/ApiResponse.cs create mode 100644 Models/FortranParameter.cs create mode 100644 Models/FortranRequest.cs create mode 100644 Models/FortranRequestWrapper.cs create mode 100644 Program.cs create mode 100644 Properties/launchSettings.json create mode 100644 Services/FortranInteropService.cs create mode 100644 appsettings.json diff --git a/Controllers/FortranController.cs b/Controllers/FortranController.cs new file mode 100644 index 0000000..46a63e2 --- /dev/null +++ b/Controllers/FortranController.cs @@ -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 _logger; + + public FortranCalculateController(FortranInteropService fortranService, ILogger 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(result, options); + + // 返回新的格式 + var response = new ApiResponse + { + Message = "Success", + Success = true, + Data = new ApiResponseData + { + Value = resultObj + } + }; + + return Ok(response); + } + catch (Exception ex) + { + _logger.LogError(ex, "处理Fortran请求时发生错误"); + return StatusCode(500, new + { + message = ex.Message, + success = false, + data = (object)null + }); + } + } + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5af55a2 --- /dev/null +++ b/Dockerfile @@ -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 libSUB_SHUILIANGJISUAN.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/libSUB_SHUILIANGJISUAN.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/libSUB_SHUILIANGJISUAN.so + +# 设置 LD_LIBRARY_PATH +ENV LD_LIBRARY_PATH=/app + +# 设置端口和监听地址 +ENV ASPNETCORE_URLS=http://+:5000 +EXPOSE 5000 + +ENTRYPOINT ["dotnet", "FortranWebApi.dll"] \ No newline at end of file diff --git a/Fortran/1.json b/Fortran/1.json new file mode 100644 index 0000000..ed695a5 --- /dev/null +++ b/Fortran/1.json @@ -0,0 +1,120 @@ +{ + "fortranSourceFile": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\dll\\\u5355\u6CB3\u9053\u4E00\u7EF4\u6C34\u52A8\u529B\u6A21\u578B\\SUB_SHUILIANGJISUAN - \u526F\u672C.f90", + "fortranFunctionName": "SUB_SHUILIANGJISUAN", + "projectName": "FortranWebApi", + "outputDirectory": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\\u8F93\u51FA\u5E93\\\u5355\u6CB3\u9053\u4E00\u7EF4\u6C34\u52A8\u529B\u6A21\u578B", + "parameters": [ + { + "name": "NDATA", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "LONG", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "INbd", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "INzd", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "INsm", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "INrough", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "ZZ0", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "DB", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "UQ", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "DQH", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "dt", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "OUTT", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "OUTQ", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "OUTH", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Output", + "description": "", + "isSelected": true + } + ] +} \ No newline at end of file diff --git a/Fortran/1.xlsx b/Fortran/1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..71203692bdd685cb48f271431b8158564fcb69fc GIT binary patch literal 10716 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 RbB`bj2-GuO3+cZtideZ>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),DB2(nriver),NUB(2,nriver),NDB(2,nriver) + REAL::UBV(ndata,nriver),Aphi(2,nriver),DBV(ndata,nriver),Gate(4,nriver),ql,Zctr + ! calcu + REAL::dt,sita,Bsor1,Bsor2 + ! zzqq + REAL::Z0(nsect,nriver),Q0(nsect,nriver),Z(nsect,nriver),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 + + + + diff --git a/Fortran/SUB_GETNXT.F90 b/Fortran/SUB_GETNXT.F90 new file mode 100644 index 0000000..daf265a --- /dev/null +++ b/Fortran/SUB_GETNXT.F90 @@ -0,0 +1,29 @@ +SUBROUTINE SUB_GETNXT(IIN) + + IMPLICIT NONE + + INTEGER::IIN + INTEGER::I + CHARACTER*80 DATALN + CHARACTER*1 CH + +1 READ(IIN,'(A80)') DATALN + + DO I = 1, 80 + CH = DATALN(I:I) + IF ( CH .EQ. '|') GOTO 1 ! |ſͷݲֱ + IF ( CH .EQ. '*') GOTO 1 ! *ſͷݲֱ + IF ( CH .EQ. ' ') GOTO 10 !˴ΪTABո + IF ( CH .NE. ' ') GOTO 40 ! ǿеӳòȥ洢 +10 END DO + + GOTO 1 + +40 BACKSPACE IIN + RETURN + +END SUBROUTINE SUB_GETNXT + + + + diff --git a/Fortran/SUB_INT_A.f90 b/Fortran/SUB_INT_A.f90 new file mode 100644 index 0000000..ea1bf35 --- /dev/null +++ b/Fortran/SUB_INT_A.f90 @@ -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 diff --git a/Fortran/SUB_QZ.f90 b/Fortran/SUB_QZ.f90 new file mode 100644 index 0000000..45b7c1c --- /dev/null +++ b/Fortran/SUB_QZ.f90 @@ -0,0 +1,339 @@ +! ================================================================================== +! ĵʽδ֪ʱˮλZQӳ +! ================================================================================== + 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),sm(nsect,nriver), rough(nsect,nriver) + ! boundary + INTEGER::UB1(nriver),UB2(nriver),DB1(nriver),DB2(nriver),NUB(2,nriver),NDB(2,nriver) + REAL::UBV(ndata,nriver),Aphi(2,nriver),DBV(ndata,nriver),Gate(4,nriver),ql,Zctr + ! calcu + REAL::dt,sita,Bsor1,Bsor2 + ! zzqq + REAL::Z0(nsect,nriver),Q0(nsect,nriver),Z(nsect,nriver),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 + +! ---------------------------------------------------------------------------------- +! ƹʽϵLMPR +! ---------------------------------------------------------------------------------- + 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㴦ˮBAˮ뾶RQˮλ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=1Lc=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 \ No newline at end of file diff --git a/Fortran/SUB_SECT.f90 b/Fortran/SUB_SECT.f90 new file mode 100644 index 0000000..fffdd2a --- /dev/null +++ b/Fortran/SUB_SECT.f90 @@ -0,0 +1,45 @@ +! ================================================================================== +! 漸Ҫصӳ +! ================================================================================== + 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),sm(nsect,nriver), rough(nsect,nriver) + ! BARC + REAL::Bs,As,Rs,Cs + +! ---------------------------------------------------------------------------------- +! BsAsRsCsӦˮλ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 + diff --git a/Fortran/SUB_SHUILIANGJISUAN.f90 b/Fortran/SUB_SHUILIANGJISUAN.f90 new file mode 100644 index 0000000..5e64f72 --- /dev/null +++ b/Fortran/SUB_SHUILIANGJISUAN.f90 @@ -0,0 +1,563 @@ +! SUB_SHUILIANGJISUAN.f90 +! +! FUNCTIONS/SUBROUTINES exported from SUB_SHUILIANGJISUAN.dll: +! SUB_SHUILIANGJISUAN - subroutine +! +subroutine SUB_SHUILIANGJISUAN( NDATA ,& ! ʱ // + LONG ,& ! ӵ + INbd ,& ! ׿ + INzd ,& ! ׸߳ + INsm ,& ! ϵ + INrough ,& ! + ZZ0 ,& ! ʼˮλ + DB ,& ! α߽ 1.ˮλ߽ 2.߽ + UQ ,& ! + DQH ,& ! ˮλ/ + dt ,& ! 㲽 룩 + OUTT ,& ! ʱ + OUTQ ,& ! + OUTH ) ! ˮλ + + ! Expose subroutine SUB_SHUILIANGJISUAN to users of this DLL + ! + !DEC$ ATTRIBUTES DLLEXPORT::SUB_SHUILIANGJISUAN + + ! Variables + +INTEGER::FHD + + INTEGER::NRIVER + INTEGER::NSECT + INTEGER::MRIVER + INTEGER::KRC + INTEGER::NDATA + + REAL::ZZ0 + + INTEGER::DB + + REAL::UQ(NDATA) + REAL::DQH(NDATA) + + REAL::OUTQ(1000) + REAL::OUTH(1000) + REAL::OUTT(1000) + + REAL::DDGC ! ̶߳ + + REAL::MAXH + + INTEGER::MY ! 1. 2.δ + + integer River,tstep + ! node + INTEGER,ALLOCATABLE::Ns(:),Pc(:),Nrc(:,:),Lc(:,:) + REAL,ALLOCATABLE::Dric(:,:),Qj(:,:,:),Asave(:,:) + ! section + REAL,ALLOCATABLE::ds(:,:),bd(:,:),zd(:,:),sm(:,:), rough(:,:) + ! boundary + INTEGER,ALLOCATABLE::UB1(:),UB2(:),DB1(:),DB2(:),NUB(:,:),NDB(:,:) + REAL,ALLOCATABLE::UBV(:,:),Aphi(:,:),DBV(:,:),Gate(:,:) + REAL::ql,Zctr + ! calcu + REAL::dt,sita,Bsor1,Bsor2 + ! zzqq + REAL,ALLOCATABLE::Z0(:,:),Q0(:,:),Z(:,:),Q(:,:),V(:,:) + ! r_bv + REAL::condu,condd(3) + ! BARC + REAL::Bs,As,Rs,Cs + + REAL,ALLOCATABLE::Qp(:) + REAL,ALLOCATABLE::Zc(:,:),Qc(:,:) + + INTEGER::I + INTEGER::II + + REAL::LONG + + REAL::INbd + REAL::INzd + REAL::INsm + REAL::INrough + + INTEGER::TEMP + + !OPEN(1,FILE='OUTFHDL.TXT') + !WRITE(1,*)' ! ʱ ', NDATA ,& + ! ' ! ӵ ', LONG ,& + ! '! ׿ ', INbd ,& + ! '! ׸߳ ' , INzd ,& + ! '! ϵ ', INsm ,& + ! ' ! ' , INrough ,& + ! ' ! ʼˮλ ', ZZ0 ,& + ! ' ! α߽ 1.ˮλ߽ 2.߽ ', DB ,& + ! ' ! ' , UQ ,& + ! ' ! ˮλ/ ', DQH ,& + ! ' ! 㲽 룩 ', dt ,& + ! '! ̶߳ ', DDGC + FHD = 0 + TEMP = 0 + + ! 1.ӵ̬ + !open(1,file='ӵ̬.TXT') + + ! 룺1.ӵ 2.ӵֵ 3.ӵֵ 4.ʱ + !CALL SUB_GETNXT(1) + !read(1,*) + nriver = 1 + nsect = 6 + krc = 0 + + mriver=nsect - 1 ! дģ΢͵ڶ-1 + + ALLOCATE(Ns(nriver),Pc(nriver),Nrc(krc,nriver),Lc(krc,nriver)) + ALLOCATE(Dric(krc,nriver),Qj(ndata,krc,nriver),Asave(krc,nriver)) + ALLOCATE(ds(mriver,nriver),bd(nsect,nriver),zd(nsect,nriver),sm(nsect,nriver), rough(nsect,nriver)) + ALLOCATE(UB1(nriver),UB2(nriver),DB1(nriver),DB2(nriver),NUB(2,nriver),NDB(2,nriver)) + ALLOCATE(UBV(ndata,nriver),Aphi(2,nriver),DBV(ndata,nriver),Gate(4,nriver)) + ALLOCATE(Z0(nsect,nriver),Q0(nsect,nriver),Z(nsect,nriver),Q(nsect,nriver),V(nsect,nriver)) + ALLOCATE(Qp(ndata)) + ALLOCATE(Zc(nsect,nriver),Qc(nsect,nriver)) + + !룺 1.ӵ 2.ӵ 3.ӵ + ! ڴ + ! CALL SUB_GETNXT(1) + ! DO I = 1,nriver + !read(1,*)II,Ns(i),Pc(i) + ! END DO + Ns(1) = 6 + Pc(1) = 0 + + !룺! 1.ӵ 2.ӵ΢κ 3. 4. + ! ͣ1ͨ㣬23ˮ + ! ĺӵˮ㣺1㣺-1ˮ + Nrc = 0 + Lc = 0 + Dric = 0 + ! DO J = 1,nriver + ! DO I = 1,Pc(J) + ! CALL SUB_GETNXT(1) + !read(1,*)II,Nrc(i,j),Lc(i,j),Dric(i,j) + ! END DO + ! END DO + + ! + Qj = 0.0 + !DO k=1,nriver + ! DO j=1,Pc(k) + ! CALL SUB_GETNXT(1) + ! if(Lc(j,k).eq.2)then + ! read(1,*)II,II,(Qj(i,j,k),i=1,ndata) + ! end if + ! END DO + ! END DO + + ! ӵˮˮm2 + Asave = 0.0 + !DO k=1,nriver + ! DO j=1,Pc(k) + ! if(Lc(j,k).eq.3)then + ! CALL SUB_GETNXT(1) + ! read(1,*)Asave(j,k) + ! end if + ! END DO + ! END DO + + ! 2.ӵ + ! CALL SUB_GETNXT(1) + ! ds = 0.0 + ! DO J = 1,nriver + ! DO I = 1,Ns(j)-1 + !read(1,*)II,II,ds(i,j) ! ÿӵ΢εijȣͨ㡢΢μˮijȡ0ÿӵĩ΢γȱȡһֵ + ! END DO + ! END DO + + ds(:,1) = LONG/5 + + ! CALL SUB_GETNXT(1) + ! bd = 0.0 + ! zd = 0.0 + ! sm = 0.0 + ! rough = 0.0 + ! DO j=1,nriver + ! DO I =1,Ns(j) + !read(1,*)II,II,bd(i,j),zd(i,j),sm(i,j),rough(i,j) ! ζ׿׸̡߳ϵ + ! END DO + ! END DO + + bd = INbd + zd = INzd + sm = INsm + rough = INrough + + ! 3.ӵ߽ + ! CALL SUB_GETNXT(1) +! read(1,*)ZZ0,Zctr ! ZZ0ʼˮλ,Zctrӵĩ˵բпˮλ, + + Zctr = 0.0 + + Scanal = 0.0 ! ScanalкӵĺϼƳȣڼԲql + + DO J = 1,nriver + DO I = 1,Ns(j)-1 + Scanal = Scanal + ds(i,j) ! ÿӵ΢εijȣͨ㡢΢μˮijȡ0ÿӵĩ΢γȱȡһֵ + END DO + END DO + + !CALL SUB_GETNXT(1) + !DO I = 1,ndata + ! read(1,*)II,Qp(i) ! Qp + ! END DO + + Qp = 0.0 + + ! UB1α߽11ˮλ߽磬2߽,3ˮλϵ + ! UB2α߽21߽磬2ڱ߽磩 + ! DB1α߽11ˮλ߽磬2߽,3ˮλϵ + ! DB2α߽21߽磬2ڱ߽磩 + !CALL SUB_GETNXT(1) + ! DO I = 1,nriver + ! read(1,*)II,UB1(i),UB2(i),DB1(i),DB2(i) + !END DO + + + + UB1(1) = 2 + UB2(1) = 1 + + DB1(1) = DB + DB2(1) = 1 + + + !CALL SUB_GETNXT(1) + UBV = 0.0 + NUB = 0 + !DO i=1,nriver + ! if(UB2(i).eq.1)then ! κⲿ߽ + ! read(1,*)II,II,II,(UBV(j,i),j=1,ndata) ! ߽洦ˮλ + ! elseif(UB2(i).eq.2)then ! κڲ߽ + ! read(1,*)II,II,II,(NUB(j,i),j=1,2) ! ڱ߽ӵĺӵš΢α + ! endif + ! END DO + + DO I = 1,ndata + UBV(I,1) = UQ(I) + END DO + + !CALL SUB_GETNXT(1) + !DO i=1,nriver + ! if(DB2(i).eq.1)then ! ⲿ + ! if(DB1(i).eq.3)then ! բ³λ + ! read(1,*)II,II,II,(DBV(j,i),j=1,ndata),(Gate(j,i),j=1,4) ! Gate(1,i) = բGate(2,i) = Gate(3,i) = ʽC1Gate(4,i) = ʽC2 ʽQ=C1*B*e*dZ^C2еC1C2 + ! ELSE + ! read(1,*)II,II,II,(DBV(j,i),j=1,ndata) ! ߽洦ˮλբ³λ + ! end if + ! elseif(DB2(i).eq.2)then ! ڲ + ! if(DB1(i).eq.2)then + ! read(1,*)II,II,II,(NDB(j,i),j=1,2),(Aphi(j,i),j=1,2) ! ڱ߽磨ܺĹϵ ڱ߽һˮλһǹܺҪṩϵ + ! ELSE + ! read(1,*)II,II,II,(NDB(j,i),j=1,2) ! ڱ߽ӵĺӵš΢α + ! end if + ! endif + !END DO + + DO I = 1,ndata + DBV(I,1) = DQH(I) + END DO + + ! 4.ӵ + !CALL SUB_GETNXT(1) + !read(1,*)period,dt,sita ! periodСʱdtʱ䲽룩,sitaˮʽȨϵ + !CALL SUB_GETNXT(1) + !read(1,*)sorz,sorq,epsz,epsq ! sorzsorqˮλɳ,epszepsqˮλƾ + !CALL SUB_GETNXT(1) + !read(1,*)Bsor1,Bsor2 ! Bsor1Bsor2ˮբ߽硢ܺڱ߽еɳ + !close(1) + + period =REAL( NDATA - 1 ) + +! read(1,*)dt + + sita = 0.7 + + sorz = 0.3 + sorq = 0.3 + epsz = 0.01 + epsq = 0.1 + + Bsor1 = 0.3 + Bsor2 = 0.1 + + + ! ʱ䲽 + 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 + + ! ˮλ + !open(1,file='ӵ1ˮλ仯.TXT') + !open(2,file='ӵ2ˮλ仯.TXT') + !open(3,file='ӵ3ˮλ仯.TXT') + !open(4,file='ӵ4ˮλ仯.TXT') + ! + !open(11,file='ӵ1仯.TXT') + !open(12,file='ӵ2仯.TXT') + !open(13,file='ӵ3仯.TXT') + !open(14,file='ӵ4仯.TXT') + +! ---------------------------------------------------------------------------------- +! ÿʱ̵ˮλ +! ---------------------------------------------------------------------------------- + DO tstep=1,maxtstep ! ۼ + + TEMP = TEMP + 1 + ttime=dt*tstep/3600.0 ! ʵʱ + ! write(*,15)ttime + + 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 ) + + ! ĵʽδ֪ʱˮλZQ + 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 + ! write(*,50)iter,maxz_r,maxz_s,dzmax,maxq_r,maxq_s,dqmax + + 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 + ! write(*,55) + goto 600 + 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 jj=1,nriver + !write(jj,80)ttime,(Z(ii,jj),ii=1,Ns(jj)) + END DO + DO jj=1,nriver + jj1=jj+10 + !write(jj1,80)ttime,(Q(ii,jj),ii=1,Ns(jj)) + END DO + + IF(FHD==1)THEN + OUTQ(TEMP ) = Q(5,1)*0.9 + OUTH(TEMP ) = Z(5,1)*0.95 + ELSE + OUTQ(TEMP ) = Q(5,1) + OUTH(TEMP ) = Z(5,1) + END IF + + OUTT(TEMP ) = ttime + + 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 + +600 close(100) + close(2) + close(3) + close(4) + + close(11) + close(12) + close(13) + close(14) + +15 format(55x,'time=',f10.2) +50 format(55x,'iter=',i5/1x,'maxz_r=',i5,5x,'maxz_s=',i5,5x,'dzmax=',e10.4/1x,'maxq_r=',i5,5x,'maxq_s=',i5,5x,'dqmax=',e10.4) +55 format(1x,'ɢ') +80 format(1x,40f12.4) + + + !MAXH = MAXVAL(OUTH) + !IF(MAXH.GT.DDGC)THEN + ! MY = 1 + !ELSE + ! MY = 0 + !END IF + + !WRITE(1,*)' ! 1. 0.δ ' , MY ,& + ! '! ʱ ', OUTT ,& + ! '! ', OUTQ ,& + ! '! ˮλ ', OUTH + + CLOSE(1) + +END SUBROUTINE SUB_SHUILIANGJISUAN + diff --git a/FortranWebApi.csproj b/FortranWebApi.csproj new file mode 100644 index 0000000..6a4d551 --- /dev/null +++ b/FortranWebApi.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/HttpRequests/fortranwebapi.http b/HttpRequests/fortranwebapi.http new file mode 100644 index 0000000..031e93c --- /dev/null +++ b/HttpRequests/fortranwebapi.http @@ -0,0 +1,23 @@ +@FortranWebApi_HostAddress = http://localhost:5000 + +### 测试Fortran请求 + +POST {{FortranWebApi_HostAddress}}/FortranCalculate +Content-Type: application/json + +{ + "text": "{\"FuncName\":\"calculate_main\",\"ClassName\":\"\",\"Par\":[ {"Name":"NDATA","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"LONG","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"INbd","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"INzd","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"INsm","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"INrough","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"ZZ0","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"DB","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"UQ","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"DQH","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"dt","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"OUTT","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}, + {"Name":"OUTQ","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}, + {"Name":"OUTH","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}]}" +} \ No newline at end of file diff --git a/Models/ApiResponse.cs b/Models/ApiResponse.cs new file mode 100644 index 0000000..3845aa5 --- /dev/null +++ b/Models/ApiResponse.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace FortranWebApi.Models +{ + public class ApiResponse + { + [JsonPropertyName("message")] + public string Message { get; set; } = "Success"; + + [JsonPropertyName("success")] + public bool Success { get; set; } = true; + + [JsonPropertyName("data")] + public ApiResponseData? Data { get; set; } + } + + public class ApiResponseData + { + [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; } + } +} \ No newline at end of file diff --git a/Models/FortranParameter.cs b/Models/FortranParameter.cs new file mode 100644 index 0000000..78d68f0 --- /dev/null +++ b/Models/FortranParameter.cs @@ -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; } + } +} \ No newline at end of file diff --git a/Models/FortranRequest.cs b/Models/FortranRequest.cs new file mode 100644 index 0000000..e17fc88 --- /dev/null +++ b/Models/FortranRequest.cs @@ -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 Parameters { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/Models/FortranRequestWrapper.cs b/Models/FortranRequestWrapper.cs new file mode 100644 index 0000000..49c36c2 --- /dev/null +++ b/Models/FortranRequestWrapper.cs @@ -0,0 +1,7 @@ +namespace FortranWebApi.Models +{ + public class FortranRequestWrapper + { + public string Text { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..ac334f1 --- /dev/null +++ b/Program.cs @@ -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(); + +// 配置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(); +} \ No newline at end of file diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..295de27 --- /dev/null +++ b/Properties/launchSettings.json @@ -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" + } + } +} \ No newline at end of file diff --git a/Services/FortranInteropService.cs b/Services/FortranInteropService.cs new file mode 100644 index 0000000..3cfcd63 --- /dev/null +++ b/Services/FortranInteropService.cs @@ -0,0 +1,565 @@ +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 == "libSUB_SHUILIANGJISUAN.so") + { + // 尝试从当前目录加载 + string currentDir = Directory.GetCurrentDirectory(); + string libraryPath = Path.Combine(currentDir, "libSUB_SHUILIANGJISUAN.so"); + + if (File.Exists(libraryPath)) + { + return NativeLibrary.Load(libraryPath); + } + } + + // 回退到默认加载行为 + return IntPtr.Zero; + }); + } + + // DllImport声明 + [DllImport("libSUB_SHUILIANGJISUAN.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SUB_SHUILIANGJISUAN")] + private static extern void SUB_SHUILIANGJISUAN( + ref int NDATA, + ref float LONG, + ref int INbd, + ref int INzd, + ref int INsm, + ref int INrough, + ref float ZZ0, + ref int DB, + float[] UQ, + float[] DQH, + ref float dt, + float[] OUTT, + float[] OUTQ, + float[] OUTH + ); + + public string ProcessFortranRequest(string requestText) + { + try + { + // 解析请求 + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + WriteIndented = true + }; + + var request = JsonSerializer.Deserialize(requestText, options); + if (request == null) + { + throw new ArgumentException("无效的请求格式"); + } + + // 准备输入参数 + var parameters = request.Parameters; + + // 提取参数 + int NDATA = GetIntParameter(parameters, "NDATA"); + float LONG = GetFloatParameter(parameters, "LONG"); + int INbd = GetIntParameter(parameters, "INbd"); + int INzd = GetIntParameter(parameters, "INzd"); + int INsm = GetIntParameter(parameters, "INsm"); + int INrough = GetIntParameter(parameters, "INrough"); + float ZZ0 = GetFloatParameter(parameters, "ZZ0"); + int DB = GetIntParameter(parameters, "DB"); + float[] UQ = GetFloatArrayParameter(parameters, "UQ"); + float[] DQH = GetFloatArrayParameter(parameters, "DQH"); + float dt = GetFloatParameter(parameters, "dt"); + + + // 准备数组参数 + float[] OUTT = new float[10000]; // 输出数组,初始大小为10000 + float[] OUTQ = new float[10000]; // 输出数组,初始大小为10000 + float[] OUTH = new float[10000]; // 输出数组,初始大小为10000 + + + // 调用Fortran函数 + SUB_SHUILIANGJISUAN( + ref NDATA, + ref LONG, + ref INbd, + ref INzd, + ref INsm, + ref INrough, + ref ZZ0, + ref DB, + UQ, + DQH, + ref dt, + OUTT, + OUTQ, + OUTH + ); + + // 更新输出参数 + UpdateArrayParameter(parameters, "OUTT", OUTT); + UpdateArrayParameter(parameters, "OUTQ", OUTQ); + UpdateArrayParameter(parameters, "OUTH", OUTH); + + + // 处理输出数组 + // 处理输出数组 OUTT + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < OUTT.Length; i++) + { + if (OUTT[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + float[] resultArray = new float[nonZeroCount]; + Array.Copy(OUTT, resultArray, nonZeroCount); + UpdateArrayParameter(parameters, "OUTT", resultArray); + } + } + // 处理输出数组 OUTQ + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < OUTQ.Length; i++) + { + if (OUTQ[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + float[] resultArray = new float[nonZeroCount]; + Array.Copy(OUTQ, resultArray, nonZeroCount); + UpdateArrayParameter(parameters, "OUTQ", resultArray); + } + } + // 处理输出数组 OUTH + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < OUTH.Length; i++) + { + if (OUTH[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + float[] resultArray = new float[nonZeroCount]; + Array.Copy(OUTH, resultArray, nonZeroCount); + UpdateArrayParameter(parameters, "OUTH", 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 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 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 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 parameters, string name) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param == null || param.Data == null) + { + return Array.Empty(); + } + + if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array) + { + var array = new List(); + 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(); + foreach (var item in enumerable) + { + array.Add(Convert.ToInt32(item)); + } + return array.ToArray(); + } + + return Array.Empty(); + } + private float[] GetFloatArrayParameter(List parameters, string name) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param == null || param.Data == null) + { + return Array.Empty(); + } + + if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array) + { + var array = new List(); + 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(); + foreach (var item in enumerable) + { + array.Add(Convert.ToSingle(item)); + } + return array.ToArray(); + } + + return Array.Empty(); + } + private double[] GetDoubleArrayParameter(List parameters, string name) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param == null || param.Data == null) + { + return Array.Empty(); + } + + if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array) + { + var array = new List(); + 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(); + foreach (var item in enumerable) + { + array.Add(Convert.ToSingle(item)); + } + return array.ToArray(); + } + + return Array.Empty(); + } + private void UpdateParameter(List parameters, string name, object value) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param != null) + { + param.Data = value; + } + } + + private void UpdateArrayParameter(List parameters, string name, float[] value) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param != null) + { + param.Data = value; + } + } + private void UpdateDoubleArrayParameter(List parameters, string name, double[] value) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param != null) + { + param.Data = value; + } + } + private void UpdateIntArrayParameter(List parameters, string name, int[] value) + { + var param = parameters.FirstOrDefault(p => p.Name == name); + if (param != null) + { + param.Data = value; + } + } + // 添加新的辅助方法来处理二维数组 + private double[,] GetDouble2DArrayParameter(List 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 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 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 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 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 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; + } + } + } +} \ No newline at end of file diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..dcb0750 --- /dev/null +++ b/appsettings.json @@ -0,0 +1,16 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Kestrel": { + "Endpoints": { + "Http": { + "Url": "http://0.0.0.0:5000" + } + } + } +} \ No newline at end of file