From 97b97cc17acc42903c4be1c53ce541ed3b7ee2ae Mon Sep 17 00:00:00 2001 From: tp <1799149022@qq.com> Date: Fri, 9 May 2025 14:01:19 +0800 Subject: [PATCH] 1 --- Controllers/FortranController.cs | 74 ++++ Dockerfile | 88 +++++ Fortran/1.json | 192 ++++++++++ Fortran/1.xlsx | Bin 0 -> 10888 bytes Fortran/MSJGMX.f90 | 90 +++++ Fortran/Mc_method.f90 | 64 ++++ Fortran/XAJ.f90 | 111 ++++++ Fortran/XAJMX.f90 | 412 ++++++++++++++++++++++ FortranWebApi.csproj | 27 ++ HttpRequests/fortranwebapi.http | 32 ++ 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 | 563 ++++++++++++++++++++++++++++++ appsettings.json | 16 + 18 files changed, 1836 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/MSJGMX.f90 create mode 100644 Fortran/Mc_method.f90 create mode 100644 Fortran/XAJ.f90 create mode 100644 Fortran/XAJMX.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..79fbcfe --- /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 libMSJGMX.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/libMSJGMX.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/libMSJGMX.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..fcc71f9 --- /dev/null +++ b/Fortran/1.json @@ -0,0 +1,192 @@ +{ + "fortranSourceFile": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\dll\\\u9A6C\u65AF\u4EAC\u8DDF\u6A21\u578B\\MSJGMX\\MSJGMX\\MSJGMX - \u526F\u672C.f90", + "fortranFunctionName": "MSJGMX", + "projectName": "FortranWebApi", + "outputDirectory": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\\u8F93\u51FA\u5E93\\\u9A6C\u65AF\u4EAC\u8DDF\u6A21\u578B", + "parameters": [ + { + "name": "FILELEN", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "NODE", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "M", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "PAR", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "NAREA", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "AREA", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "UH", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "DT", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "P", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "EP", + "dataType": "Float", + "arrayType": "TwoDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "W", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "FR", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "S", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "QRSS0", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "QRG0", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "Q20", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "X", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "K", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "DETAT", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "C0", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "C1", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "C2", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "QOUT", + "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..16e8bf82dba8ec778197f14b054be04e280834ad GIT binary patch literal 10888 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 literal 0 HcmV?d00001 diff --git a/Fortran/MSJGMX.f90 b/Fortran/MSJGMX.f90 new file mode 100644 index 0000000..d10cba9 --- /dev/null +++ b/Fortran/MSJGMX.f90 @@ -0,0 +1,90 @@ +subroutine MSJGMX( FILELEN ,& + NODE ,& ! ԪС // + M ,& ! ελС // + PAR ,& ! // + NAREA ,& ! Ԫ // + AREA ,& ! Ԫ // + UH ,& ! ελ // + DT ,& ! ʱβ // + P ,& ! ϵ // + EP ,& ! // + W ,& ! ˮ 1.ϲ 2.² 3. // + FR ,& ! ʼ // + S ,& ! ʼˮ // + QRSS0 ,& ! ʼ // + QRG0 ,& ! ʼˮ // + Q20 ,& ! ʼֵ // + X ,& ! // + K ,& ! ģ // + DETAT ,& ! ʱ䲽 Сʱ // + C0 ,& ! ϵ // + C1 ,& ! // + C2 ,& ! // + QOUT ) ! // + + ! Expose subroutine MSJGMX to users of this DLL + + !DEC$ ATTRIBUTES DLLEXPORT::MSJGMX + + IMPLICIT NONE + + REAL::X + REAL::K + REAL::DETAT + + REAL::C0 + REAL::C1 + REAL::C2 + REAL::Q2(1000) + INTEGER::NFILENAME + CHARACTER(LEN = 10)::FILENAME + + INTEGER:: FILELEN + + INTEGER::NODE ! + INTEGER::M , I ! + REAL::PAR(13) ! 1.ϲˮwum 2.²ˮwl 3.ˮwdm + ! 4.ϵKC.ϵc 6.ˮˮϵb + ! 7.͸ˮimp1 8.ˮˮsm 9.ˮˮָex + !10.ˮϵkg 11.ϵkss 12.ˮϵkkg + !13.ϵkkss + + INTEGER::NAREA ! Ԫ + REAL::AREA(NAREA) ! Ԫ + REAL::UH(M) ! ελ + REAL::DT ! ʱβ + REAL::P(NAREA,NODE) ! ϵ + REAL::EP(NAREA,NODE) ! + REAL::W(3) ! ˮ 1.ϲ 2.² 3. + REAL::FR ! ʼ + REAL::S ! ʼˮ + REAL::QRSS0 ! ʼ + REAL::QRG0 ! ʼˮ + REAL::Q20(NAREA) + REAL::QOUT(NAREA) + + CALL XAJ( FILELEN ,& + NODE ,& ! ԪС // + M ,& ! ελС // + PAR ,& ! // + NAREA ,& ! Ԫ // + AREA ,& ! Ԫ // + UH ,& ! ελ // + DT ,& ! ʱβ // + P ,& ! ϵ // + EP ,& ! // + W ,& ! ˮ 1.ϲ 2.² 3. // + FR ,& ! ʼ // + S ,& ! ʼˮ // + QRSS0 ,& ! ʼ // + QRG0 ,& ! ʼˮ // + Q20 ,& ! ʼֵ // + X ,& ! // + K ,& ! ģ // + DETAT ,& ! ʱ䲽 Сʱ // + C0 ,& ! ϵ // + C1 ,& ! // + C2 ,& ! // + QOUT ) ! // + +end subroutine MSJGMX diff --git a/Fortran/Mc_method.f90 b/Fortran/Mc_method.f90 new file mode 100644 index 0000000..4f2d3c7 --- /dev/null +++ b/Fortran/Mc_method.f90 @@ -0,0 +1,64 @@ +! Mc_method.f90 +! +! FUNCTIONS: +! Mc_method - Entry point of console application. +! + +!**************************************************************************** +! +! PROGRAM: Mc_method +! +! PURPOSE: Entry point for the console application. +! +!**************************************************************************** +SUBROUTINE Mc_method( NFILENAME ,& ! ļֳ // + FILENAME ,& ! ļ ַ // + N ,& ! ݵ // + Q1 ,& ! // + Q20 ,& ! ʼֵ // + X ,& ! // + K ,& ! ģ // + DETAT ,& ! ʱ䲽 Сʱ // + C0 ,& ! ϵ // + C1 ,& ! // + C2 ,& ! // + Q2 ) ! // + + INTEGER::NFILENAME + CHARACTER(LEN = NFILENAME)::FILENAME + + INTEGER::N + REAL::Q1(1000) + REAL::Q20 + REAL::Q2(1000) + REAL::I1 + REAL::I2 + REAL::C0 + REAL::C1 + REAL::C2 + + REAL::X + REAL::K + REAL::DETAT + + INTEGER::I + + C0 = (0.5*DETAT - K*X)/(0.5*DETAT + K - K*X) + C1 = (0.5*DETAT + K*X)/(0.5*DETAT + K - K*X) + C2 = (-0.5*DETAT +K - K*X)/(0.5*DETAT + K - K*X) + + Q2(1) =Q20 + + DO I = 2,N + + I2 = Q1(I) + + I1 = Q1(I-1) + + Q2(I) = C0*I2 + C1*I1 + C2*Q2(I-1) + + END DO + + +END SUBROUTINE Mc_method + diff --git a/Fortran/XAJ.f90 b/Fortran/XAJ.f90 new file mode 100644 index 0000000..8616058 --- /dev/null +++ b/Fortran/XAJ.f90 @@ -0,0 +1,111 @@ +SUBROUTINE XAJ(FILELEN ,& + NODE ,& ! ԪС // + M ,& ! ελС // + PAR ,& ! // + NAREA ,& ! Ԫ // + AREA ,& ! Ԫ // + UH ,& ! ελ // + DT ,& ! ʱβ // + P ,& ! ϵ // + EP ,& ! // + W ,& ! ˮ 1.ϲ 2.² 3. // + FR ,& ! ʼ // + S ,& ! ʼˮ // + QRSS0 ,& ! ʼ // + QRG0 ,& ! ʼˮ // + Q20 ,& ! ʼֵ // + X ,& ! // + K ,& ! ģ // + DETAT ,& ! ʱ䲽 Сʱ // + C0 ,& ! ϵ // + C1 ,& ! // + C2 ,& ! // + QOUT ) ! // + + IMPLICIT NONE + + INTEGER::NODE + + + REAL::X + REAL::K + REAL::DETAT + + REAL::C0 + REAL::C1 + REAL::C2 + + INTEGER:: FILELEN + INTEGER::M ! + REAL::PAR(13) ! 1.ϲˮwum 2.²ˮwl 3.ˮwdm + ! 4.ϵKC.ϵc 6.ˮˮϵb + ! 7.͸ˮimp1 8.ˮˮsm 9.ˮˮָex + !10.ˮϵkg 11.ϵkss 12.ˮϵkkg + !13.ϵkkss + integer::NAREA ! Ԫ // + REAL::AREA(NAREA) ! Ԫ + REAL::Q1(NAREA,NODE) + REAL::UH(M) ! ελ + REAL::DT ! ʱβ + REAL::P(NAREA,NODE) ! ϵ + REAL::EP(NAREA,NODE) ! + REAL::QR(NAREA,NODE) ! Ԫ + REAL::W(3) ! ˮ 1.ϲ 2.² 3. + REAL::FR ! ʼ + REAL::S ! ʼˮ + REAL::QRSS0 ! ʼ + REAL::QRG0 ! ʼˮ + REAL::Q2(NAREA,NODE) + INTEGER::I,J + REAL::QOUT(NODE) + REAL::Q20(NAREA) + + DO I = 1,NODE + QOUT(I) = 0.0 + END DO + + DO I =1,NAREA + + CALL XAJMX( FILELEN ,& + NODE ,& ! ԪС // + M ,& ! ελС // + PAR ,& ! // + AREA(I) ,& ! Ԫ // + UH ,& ! ελ // + DT ,& ! ʱβ // + P(I,:) ,& ! ϵ // + EP(I,:) ,& ! // + W ,& ! ˮ 1.ϲ 2.² 3. // + FR ,& ! ʼ // + S ,& ! ʼˮ // + QRSS0 ,& ! ʼ // + QRG0 ,& ! ʼˮ // + QR(I,:) ) ! Ԫ // + + DO J = 1,NAREA + + Q1(J,:)=QR(J,:) + + END DO + + CALL Mc_method( FILELEN ,& ! ļֳ // + NODE ,& ! ݵ // + Q1(I,:) ,& ! // + Q20(I) ,& ! ʼֵ // + X ,& ! // + K ,& ! ģ // + DETAT ,& ! ʱ䲽 Сʱ // + C0 ,& ! ϵ // + C1 ,& ! // + C2 ,& ! // + Q2(I,:) ) ! // + + END DO + + DO I = 1,NAREA + DO J = 1,NODE + QOUT(J)= Q2(I,J) + QOUT(J) + END DO + END DO + +END SUBROUTINE XAJ \ No newline at end of file diff --git a/Fortran/XAJMX.f90 b/Fortran/XAJMX.f90 new file mode 100644 index 0000000..ea84f14 --- /dev/null +++ b/Fortran/XAJMX.f90 @@ -0,0 +1,412 @@ +SUBROUTINE XAJMX( FILELEN ,& + N ,& ! ԪС // + M ,& ! ελС // + PAR ,& ! // + AREA ,& ! Ԫ // + UH ,& ! ελ // + DT ,& ! ʱβ // + P ,& ! ϵ // + EP ,& ! // + W ,& ! ˮ 1.ϲ 2.² 3. // + FR ,& ! ʼ // + S ,& ! ʼˮ // + QRSS0 ,& ! ʼ // + QRG0 ,& ! ʼˮ // + QR ) ! Ԫ // + + IMPLICIT NONE + +!///////////////////////////////////////////////////////////////////////////////////// + INTEGER::N ! + INTEGER::M ! + REAL::PAR(13) ! 1.ϲˮwum 2.²ˮwl 3.ˮwdm + ! 4.ϵKC.ϵc 6.ˮˮϵb + ! 7.͸ˮimp1 8.ˮˮsm 9.ˮˮָex + !10.ˮϵkg 11.ϵkss 12.ˮϵkkg + !13.ϵkkss + REAL::AREA ! Ԫ + REAL::UH(M) ! ελ + REAL::DT ! ʱβ + REAL::P(N) ! ϵ + REAL::EP(N) ! + REAL::QR(N) ! Ԫ + REAL::W(3) ! ˮ 1.ϲ 2.² 3. + REAL::FR ! ʼ + REAL::S ! ʼˮ + REAL::QRSS0 ! ʼ + REAL::QRG0 ! ʼˮ + + INTEGER::D + REAL::KSSD + REAL::KGD + REAL::E(3) + REAL::WM(3) + REAL::KC ! ϵ + REAL::C ! ϵ + REAL::B ! ˮˮϵ + REAL::IMP1 ! ͸ˮ + REAL::SM ! ˮˮ + REAL::EX ! ˮˮָ + REAL::KG ! ˮϵ + REAL::KSS ! ϵ + REAL::KKG ! ˮϵ + REAL::KKSS ! ϵ + +!±ԭvbδı + INTEGER::I ! //ʱ + INTEGER::J ! //ʱ + INTEGER::ICHECK ! жϼʱγǷʵʶ + INTEGER::NN + + REAL(KIND=8),PARAMETER::C5=5.000000000 + + REAL::U + REAL::CI + REAL::CG + REAL::WM0 + REAL::W0 + REAL::PE + REAL::R + REAL::RIMP + REAL::WMM + REAL::A + REAL::X + REAL::RS + REAL::RSS + REAL::RGD + REAL::RG + REAL::SS + REAL::Q + REAL::KSSDD + REAL::KGDD + REAL::SMM + REAL::SMMF + REAL::SMF + REAL::AU + REAL::RSD + REAL::RSSD + REAL::QRS + REAL::QRSS + REAL::QRG + REAL::QTR + + INTEGER:: FILELEN + + REAL::WTEMP(3) + REAL::FRTEMP + REAL::STEMP + REAL::QRSS0TEMP + REAL::QRG0TEMP + + +!///////////////////////////////////////////////////////////////////////////////////// + DO I = 1,3 + WTEMP(I) = W(I) + END DO + FRTEMP = FR + STEMP =S + QRSS0TEMP=QRSS0 + QRG0TEMP=QRG0 + +!///////////////////////////////////////////////////////////////////////////////////// + + D = 0 + KSSD = 0.0 + KGD = 0.0 + do i = 1,3 + E(I)=0.0 + WM(I) =0.0 + END DO + KC = 0.0 + C = 0.0 + B = 0.0 + IMP1 = 0.0 + SM = 0.0 + EX = 0.0 + KG = 0.0 + KSS = 0.0 + KKG = 0.0 + KKSS = 0.0 + U = 0.0 + CI = 0.0 + CG = 0.0 + WM0 = 0.0 + W0 = 0.0 + PE = 0.0 + R = 0.0 + RIMP = 0.0 + WMM = 0.0 + A = 0.0 + X = 0.0 + RS = 0.0 + RSS = 0.0 + RGD = 0.0 + RG = 0.0 + SS = 0.0 + Q = 0.0 + KSSDD = 0.0 + KGDD = 0.0 + SMM = 0.0 + SMMF = 0.0 + SMF = 0.0 + AU = 0.0 + RSD = 0.0 + RSSD = 0.0 + QRS = 0.0 + QRSS = 0.0 + QRG = 0.0 + QTR = 0.0 + + + ! ֵ + ICHECK = 1 + + DO I = 1, 3 + + WM(I) = PAR(I) + + END DO + + KC = PAR(4) + C = PAR(5) + B = PAR(6) + IMP1 = PAR(7) + SM = PAR(8) + EX = PAR(9) + KG = PAR(10) + KSS = PAR(11) + KKG = PAR(12) + KKSS = PAR(13) + + DO I = 1, N + + QR(I) = 0.0 + + END DO + + U = AREA / 3.6 / DT + + IF( DT.LE.24.0 )THEN + + D = 24 / DT + CI = KKSS ** (1.0 / D) + CG = KKG ** (1.0 / D) + KSSD = (1.0 - (1.0 - (KG + KSS)) ** (1.0 / D)) / (1.0 + & + KG / KSS) + KGD = KSSD * KG / KSS + + ELSE + ICHECK = 0 + END IF + + DO I = 1 , N + + IF (EP(I) .LT. 0.0)THEN + EP(I) = 0.0 + END IF + + IF (P(I) .LT. 0.0)THEN + P(I) = 0.0 + END IF + + EP(I) = EP(I) * KC + WM0 = WM(1) + WM(2) + WM(3) + W0 = W(1) + W(2) + W(3) + PE = P(I) - EP(I) + + ! ֵ + R = 0.0 + RIMP = 0.0 + + IF(PE.GT.0.0)THEN + + WMM = (1.0 + B) * WM0 / (1.0 - IMP1) + + IF ((WM0 - W0).LE.0.0001)THEN + + A = WMM + + ELSE + + A = WMM * (1.0 - (1.0 - W0 / WM0) ** (1.0 / (1.0 + B))) + + END IF + + IF ((PE + A) .LT. WMM) THEN + + R = PE - WM0 + W0 + WM0 * ((1.0 - (PE + A) / WMM) & + ** (1.0 + B)) + + ELSE + + R = PE - (WM0 - W0) + + END IF + + RIMP = PE * IMP1 + + END IF + + IF ((W(1) + P(I)) .GT. EP(I)) THEN + + E(1) = EP(I) + E(2) = 0.0 + E(3) = 0.0 + + ELSE + + E(1) = W(1) + P(I) + E(2) = (EP(I) - E(1)) * W(2) / WM(2) + + IF (W(2) .LE.( C * WM(2))) THEN + + E(2) = C * (EP(I) - E(1)) + E(3) = 0.0 + + IF (W(2) .GE. (C * (EP(I) - E(1)))) THEN + + E(2) = C * (EP(I) - E(1)) + E(3) = 0.0 + + ELSE + E(2) = W(2) + E(3) = C * (EP(I) - E(1) - E(2)) + + END IF + + END IF + + END IF + + W(1) = W(1) + P(I) - R - E(1) + W(2) = W(2) - E(2) + W(3) = W(3) - E(3) + + IF (W(1) .GT. WM(1)) THEN + + W(2) = W(1) - WM(1) + W(2) + W(1) = WM(1) + + IF (W(2) .GT. WM(2)) THEN + + W(3) = W(3) + W(2) - WM(2) + W(2) = WM(2) + + END IF + + END IF + + X = FR + + IF (PE .LE.0.0) THEN + + RS = 0.0 + RSS = S * KSSD * FR + RGD = S * FR * KGD + S = S - (RSS + RG) / FR + + ELSE + + FR = R / PE + S = X * S / FR + SS = S + Q = R / FR + NN = INT(Q / C5) + 1 ! vbC5˫ȳ5 + Q = Q / NN + KSSDD = (1.0 - (1.0 - (KGD + KSSD)) ** (1.0 / NN)) /& + (1.0 + KGD / KSSD) + KGDD = KSSDD * KGD / KSSD + RS = 0.0 + RSS = 0.0 + RG = 0.0 + SMM = (1 + EX) * SM + + IF (EX .LT. 0.001) THEN + + SMMF = SMM + + ELSE + + SMMF = SMM * (1.0 - (1.0 - FR) ** (1.0 / EX)) + + END IF + + SMF = SMMF / (1.0 + EX) + + DO J = 1 , NN + + IF (S .GT. SMF) THEN + + S = SMF + + END IF + + AU = SMMF * (1.0 - (1.0 - S / SMF) ** (1.0 /& + (1.0 + EX))) + + IF ((Q + AU) .LE. 0.0) THEN + + RSD = 0.0 + RSSD = 0.0 + RGD = 0.0 + S = 0.0 + + ELSE IF ((Q + AU) .GE. SMMF) THEN + + RSD = (Q + S - SMF) * FR + RSSD = SMF * KSSDD * FR + RGD = SMF * FR * KGDD + S = SMF - (KSSD + KGD) / FR + + ELSE IF ((Q + AU) .LT. SMMF) THEN + + RSD = (Q - SMF + S + SMF * (1.0 - (Q + AU)& + / SMMF) ** (1.0 + EX)) * FR + RSSD = (S + Q - RSD / FR) * KSSDD * FR + RGD = (S + Q - RSD / FR) * KGDD * FR + S = S + Q - (RSD + RSSD + RGD) / FR + + END IF + + RS = RS + RSD + RSS = RSS + RSSD + RG = RG + RGD + + END DO + + END IF + + RS = RS * (1.0 - IMP1) + RSS = RSS * (1.0 - IMP1) + RG = RG * (1.0 - IMP1) + QRS = (RS + RIMP) * U + QRSS = QRSS0 * CI + RSS * (1.0 - CI) * U + QRG = QRG0 * CG + RG * (1.0 - CG) * U + QTR = QRS + QRSS + QRG + + DO J = 1 , M + + IF ((I + J - 1) .LE. N) THEN + + QR(I + J - 1) = QR(I + J - 1) + QTR * UH(J) + + END IF + + END DO + + QRSS0 = QRSS + QRG0 = QRG + + END DO + + + DO I = 1,3 + W(I) = WTEMP(I) + END DO + FR = FRTEMP + S =STEMP + QRSS0=QRSS0TEMP + QRG0=QRG0TEMP + + +END SUBROUTINE XAJMX \ No newline at end of file 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..aa780ce --- /dev/null +++ b/HttpRequests/fortranwebapi.http @@ -0,0 +1,32 @@ +@FortranWebApi_HostAddress = http://localhost:5000 + +### 测试Fortran请求 + +POST {{FortranWebApi_HostAddress}}/FortranCalculate +Content-Type: application/json + +{ + "text": "{\"FuncName\":\"calculate_main\",\"ClassName\":\"\",\"Par\":[ {"Name":"FILELEN","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"NODE","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"M","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"PAR","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"NAREA","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"AREA","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"UH","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"DT","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"P","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"EP","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"W","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"FR","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"S","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"QRSS0","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"QRG0","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"Q20","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"X","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"K","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"DETAT","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"C0","DataType":"1","ArrayType":"0","IsOut":"1","Data":0}, + {"Name":"C1","DataType":"1","ArrayType":"0","IsOut":"1","Data":0}, + {"Name":"C2","DataType":"1","ArrayType":"0","IsOut":"1","Data":0}, + {"Name":"QOUT","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..f239995 --- /dev/null +++ b/Services/FortranInteropService.cs @@ -0,0 +1,563 @@ +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 == "libMSJGMX.so") + { + // 尝试从当前目录加载 + string currentDir = Directory.GetCurrentDirectory(); + string libraryPath = Path.Combine(currentDir, "libMSJGMX.so"); + + if (File.Exists(libraryPath)) + { + return NativeLibrary.Load(libraryPath); + } + } + + // 回退到默认加载行为 + return IntPtr.Zero; + }); + } + + // DllImport声明 + [DllImport("libMSJGMX.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "MSJGMX")] + private static extern void MSJGMX( + ref int FILELEN, + ref int NODE, + ref int M, + float[] PAR, + ref int NAREA, + float[] AREA, + float[] UH, + ref float DT, + float[] P, + [MarshalAs(UnmanagedType.LPArray, SizeConst = 0)] float[,] EP, + float[] W, + ref float FR, + ref float S, + ref float QRSS0, + ref float QRG0, + float[] Q20, + ref float X, + ref float K, + ref float DETAT, + out float C0, + out float C1, + out float C2, + float[] QOUT + ); + + 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 FILELEN = GetIntParameter(parameters, "FILELEN"); + int NODE = GetIntParameter(parameters, "NODE"); + int M = GetIntParameter(parameters, "M"); + float[] PAR = GetFloatArrayParameter(parameters, "PAR"); + int NAREA = GetIntParameter(parameters, "NAREA"); + float[] AREA = GetFloatArrayParameter(parameters, "AREA"); + float[] UH = GetFloatArrayParameter(parameters, "UH"); + float DT = GetFloatParameter(parameters, "DT"); + float[] P = GetFloatArrayParameter(parameters, "P"); + float[,] EP = GetFloatParameter(parameters, "EP"); + float[] W = GetFloatArrayParameter(parameters, "W"); + float FR = GetFloatParameter(parameters, "FR"); + float S = GetFloatParameter(parameters, "S"); + float QRSS0 = GetFloatParameter(parameters, "QRSS0"); + float QRG0 = GetFloatParameter(parameters, "QRG0"); + float[] Q20 = GetFloatArrayParameter(parameters, "Q20"); + float X = GetFloatParameter(parameters, "X"); + float K = GetFloatParameter(parameters, "K"); + float DETAT = GetFloatParameter(parameters, "DETAT"); + float C0; + float C1; + float C2; + + + // 准备数组参数 + float[] QOUT = new float[10000]; // 输出数组,初始大小为10000 + + + // 调用Fortran函数 + MSJGMX( + ref FILELEN, + ref NODE, + ref M, + PAR, + ref NAREA, + AREA, + UH, + ref DT, + P, + ref EP, + W, + ref FR, + ref S, + ref QRSS0, + ref QRG0, + Q20, + ref X, + ref K, + ref DETAT, + out C0, + out C1, + out C2, + QOUT + ); + + // 更新输出参数 + UpdateParameter(parameters, "C0", C0); + UpdateParameter(parameters, "C1", C1); + UpdateParameter(parameters, "C2", C2); + UpdateArrayParameter(parameters, "QOUT", QOUT); + + + // 处理输出数组 + // 处理输出数组 QOUT + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < QOUT.Length; i++) + { + if (QOUT[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + float[] resultArray = new float[nonZeroCount]; + Array.Copy(QOUT, resultArray, nonZeroCount); + UpdateArrayParameter(parameters, "QOUT", 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