SUB_UNITHYDRO/Services/FortranInteropService.cs
2025-04-18 11:00:47 +08:00

562 lines
20 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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_UNITHYDRO.so")
{
// 尝试从当前目录加载
string currentDir = Directory.GetCurrentDirectory();
string libraryPath = Path.Combine(currentDir, "libSUB_UNITHYDRO.so");
if (File.Exists(libraryPath))
{
return NativeLibrary.Load(libraryPath);
}
}
// 回退到默认加载行为
return IntPtr.Zero;
});
}
// DllImport声明
[DllImport("libSUB_UNITHYDRO.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SUB_UNITHYDRO")]
private static extern void SUB_UNITHYDRO(
ref float S,
float[] QT,
ref int M,
float[] Q,
ref int N,
ref float IM,
ref float FC,
ref float QF,
ref float T,
ref float A,
float[] RUNOFF_U,
float[] RUNOFF_G,
float[] RUNOFF
);
public string ProcessFortranRequest(string requestText)
{
try
{
// 解析请求
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
WriteIndented = true
};
var request = JsonSerializer.Deserialize<FortranRequest>(requestText, options);
if (request == null)
{
throw new ArgumentException("无效的请求格式");
}
// 准备输入参数
var parameters = request.Parameters;
// 提取参数
float S = GetFloatParameter(parameters, "S");
float[] QT = GetFloatArrayParameter(parameters, "QT");
int M = GetIntParameter(parameters, "M");
float[] Q = GetFloatArrayParameter(parameters, "Q");
int N = GetIntParameter(parameters, "N");
float IM = GetFloatParameter(parameters, "IM");
float FC = GetFloatParameter(parameters, "FC");
float QF = GetFloatParameter(parameters, "QF");
float T = GetFloatParameter(parameters, "T");
float A = GetFloatParameter(parameters, "A");
// 准备数组参数
float[] RUNOFF_U = new float[10000]; // 输出数组初始大小为10000
float[] RUNOFF_G = new float[10000]; // 输出数组初始大小为10000
float[] RUNOFF = new float[10000]; // 输出数组初始大小为10000
// 调用Fortran函数
SUB_UNITHYDRO(
ref S,
QT,
ref M,
Q,
ref N,
ref IM,
ref FC,
ref QF,
ref T,
ref A,
RUNOFF_U,
RUNOFF_G,
RUNOFF
);
// 更新输出参数
UpdateArrayParameter(parameters, "RUNOFF_U", RUNOFF_U);
UpdateArrayParameter(parameters, "RUNOFF_G", RUNOFF_G);
UpdateArrayParameter(parameters, "RUNOFF", RUNOFF);
// 处理输出数组
// 处理输出数组 RUNOFF_U
// 注意:没有找到明确的长度参数,使用非零元素数量
{
int nonZeroCount = 0;
for (int i = 0; i < RUNOFF_U.Length; i++)
{
if (RUNOFF_U[i] != 0) nonZeroCount = i + 1;
}
if (nonZeroCount > 0)
{
float[] resultArray = new float[nonZeroCount];
Array.Copy(RUNOFF_U, resultArray, nonZeroCount);
UpdateArrayParameter(parameters, "RUNOFF_U", resultArray);
}
}
// 处理输出数组 RUNOFF_G
// 注意:没有找到明确的长度参数,使用非零元素数量
{
int nonZeroCount = 0;
for (int i = 0; i < RUNOFF_G.Length; i++)
{
if (RUNOFF_G[i] != 0) nonZeroCount = i + 1;
}
if (nonZeroCount > 0)
{
float[] resultArray = new float[nonZeroCount];
Array.Copy(RUNOFF_G, resultArray, nonZeroCount);
UpdateArrayParameter(parameters, "RUNOFF_G", resultArray);
}
}
// 处理输出数组 RUNOFF
// 注意:没有找到明确的长度参数,使用非零元素数量
{
int nonZeroCount = 0;
for (int i = 0; i < RUNOFF.Length; i++)
{
if (RUNOFF[i] != 0) nonZeroCount = i + 1;
}
if (nonZeroCount > 0)
{
float[] resultArray = new float[nonZeroCount];
Array.Copy(RUNOFF, resultArray, nonZeroCount);
UpdateArrayParameter(parameters, "RUNOFF", resultArray);
}
}
// 返回结果 - 只返回原始请求的结构,但包含更新后的参数
var result = new FortranRequest
{
FuncName = request.FuncName,
ClassName = request.ClassName,
Parameters = parameters
};
return JsonSerializer.Serialize(result, options);
}
catch (Exception ex)
{
return JsonSerializer.Serialize(new { error = ex.Message });
}
}
private float GetFloatParameter(List<FortranParameter> parameters, string name)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return 0.0f;
}
if (param.Data is JsonElement element)
{
if (element.ValueKind == JsonValueKind.Number)
{
return element.GetSingle();
}
}
return Convert.ToSingle(param.Data);
}
private double GetDoubleParameter(List<FortranParameter> parameters, string name)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return 0.0;
}
if (param.Data is JsonElement element)
{
if (element.ValueKind == JsonValueKind.Number)
{
return element.GetSingle();
}
}
return Convert.ToDouble(param.Data);
}
private int GetIntParameter(List<FortranParameter> parameters, string name)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return 0;
}
if (param.Data is JsonElement element)
{
if (element.ValueKind == JsonValueKind.Number)
{
return element.GetInt32();
}
}
return Convert.ToInt32(param.Data);
}
private int[] GetIntArrayParameter(List<FortranParameter> parameters, string name)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return Array.Empty<int>();
}
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
var array = new List<int>();
foreach (var item in element.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.Number)
{
array.Add(item.GetInt32());
}
}
return array.ToArray();
}
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
{
var array = new List<int>();
foreach (var item in enumerable)
{
array.Add(Convert.ToInt32(item));
}
return array.ToArray();
}
return Array.Empty<int>();
}
private float[] GetFloatArrayParameter(List<FortranParameter> parameters, string name)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return Array.Empty<float>();
}
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
var array = new List<float>();
foreach (var item in element.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.Number)
{
array.Add(item.GetSingle());
}
}
return array.ToArray();
}
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
{
var array = new List<float>();
foreach (var item in enumerable)
{
array.Add(Convert.ToSingle(item));
}
return array.ToArray();
}
return Array.Empty<float>();
}
private double[] GetDoubleArrayParameter(List<FortranParameter> parameters, string name)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return Array.Empty<double>();
}
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
var array = new List<double>();
foreach (var item in element.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.Number)
{
array.Add(item.GetSingle());
}
}
return array.ToArray();
}
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
{
var array = new List<double>();
foreach (var item in enumerable)
{
array.Add(Convert.ToSingle(item));
}
return array.ToArray();
}
return Array.Empty<double>();
}
private void UpdateParameter(List<FortranParameter> parameters, string name, object value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
param.Data = value;
}
}
private void UpdateArrayParameter(List<FortranParameter> parameters, string name, float[] value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
param.Data = value;
}
}
private void UpdateDoubleArrayParameter(List<FortranParameter> parameters, string name, double[] value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
param.Data = value;
}
}
private void UpdateIntArrayParameter(List<FortranParameter> parameters, string name, int[] value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
param.Data = value;
}
}
// 添加新的辅助方法来处理二维数组
private double[,] GetDouble2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return new double[rows, cols];
}
double[,] result = new double[rows, cols];
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
int index = 0;
foreach (var item in element.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.Number)
{
int row = index / cols;
int col = index % cols;
if (row < rows && col < cols)
{
result[row, col] = item.GetDouble();
}
index++;
}
}
}
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
{
int index = 0;
foreach (var item in enumerable)
{
int row = index / cols;
int col = index % cols;
if (row < rows && col < cols)
{
result[row, col] = Convert.ToDouble(item);
}
index++;
}
}
return result;
}
// 添加更新二维数组参数的方法
private void UpdateDouble2DArrayParameter(List<FortranParameter> parameters, string name, double[,] value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
// 将二维数组转换为一维数组以便于JSON序列化
int rows = value.GetLength(0);
int cols = value.GetLength(1);
double[] flatArray = new double[rows * cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
flatArray[i * cols + j] = value[i, j];
}
}
param.Data = flatArray;
}
}
// float版本
private float[,] GetFloat2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return new float[rows, cols];
}
float[,] result = new float[rows, cols];
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
int index = 0;
foreach (var item in element.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.Number)
{
int row = index / cols;
int col = index % cols;
if (row < rows && col < cols)
{
result[row, col] = item.GetSingle();
}
index++;
}
}
}
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
{
int index = 0;
foreach (var item in enumerable)
{
int row = index / cols;
int col = index % cols;
if (row < rows && col < cols)
{
result[row, col] = Convert.ToSingle(item);
}
index++;
}
}
return result;
}
private void UpdateFloat2DArrayParameter(List<FortranParameter> parameters, string name, float[,] value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
int rows = value.GetLength(0);
int cols = value.GetLength(1);
float[] flatArray = new float[rows * cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
flatArray[i * cols + j] = value[i, j];
}
}
param.Data = flatArray;
}
}
// int版本
private int[,] GetInt2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param == null || param.Data == null)
{
return new int[rows, cols];
}
int[,] result = new int[rows, cols];
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
int index = 0;
foreach (var item in element.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.Number)
{
int row = index / cols;
int col = index % cols;
if (row < rows && col < cols)
{
result[row, col] = item.GetInt32();
}
index++;
}
}
}
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
{
int index = 0;
foreach (var item in enumerable)
{
int row = index / cols;
int col = index % cols;
if (row < rows && col < cols)
{
result[row, col] = Convert.ToInt32(item);
}
index++;
}
}
return result;
}
private void UpdateInt2DArrayParameter(List<FortranParameter> parameters, string name, int[,] value)
{
var param = parameters.FirstOrDefault(p => p.Name == name);
if (param != null)
{
int rows = value.GetLength(0);
int cols = value.GetLength(1);
int[] flatArray = new int[rows * cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
flatArray[i * cols + j] = value[i, j];
}
}
param.Data = flatArray;
}
}
}
}