From 372da7c10aee57839d775b73a3be87671107b963 Mon Sep 17 00:00:00 2001 From: misaki <1018407731@qq.com> Date: Thu, 17 Apr 2025 17:50:06 +0800 Subject: [PATCH] 3 --- 1.xlsx | Bin 6542 -> 10671 bytes Fortran/SUB_appcoef.f90 | 62 ++- Fortran/SUB_wavedec.f90 | 36 +- .../Controllers/FortranController.cs | 74 +++ FortranWebApi/Dockerfile | 88 +++ FortranWebApi/FortranWebApi.csproj | 27 + FortranWebApi/HttpRequests/fortranwebapi.http | 13 + FortranWebApi/Models/ApiResponse.cs | 31 ++ FortranWebApi/Models/FortranParameter.cs | 22 + FortranWebApi/Models/FortranRequest.cs | 13 + FortranWebApi/Models/FortranRequestWrapper.cs | 7 + FortranWebApi/Program.cs | 80 +++ FortranWebApi/Properties/launchSettings.json | 14 + .../Services/FortranInteropService.cs | 519 ++++++++++++++++++ FortranWebApi/appsettings.json | 16 + HttpRequests/fortranwebapi.http | 5 +- Services/FortranInteropService.cs | 43 +- 17 files changed, 992 insertions(+), 58 deletions(-) create mode 100644 FortranWebApi/Controllers/FortranController.cs create mode 100644 FortranWebApi/Dockerfile create mode 100644 FortranWebApi/FortranWebApi.csproj create mode 100644 FortranWebApi/HttpRequests/fortranwebapi.http create mode 100644 FortranWebApi/Models/ApiResponse.cs create mode 100644 FortranWebApi/Models/FortranParameter.cs create mode 100644 FortranWebApi/Models/FortranRequest.cs create mode 100644 FortranWebApi/Models/FortranRequestWrapper.cs create mode 100644 FortranWebApi/Program.cs create mode 100644 FortranWebApi/Properties/launchSettings.json create mode 100644 FortranWebApi/Services/FortranInteropService.cs create mode 100644 FortranWebApi/appsettings.json diff --git a/1.xlsx b/1.xlsx index e6241e78b1f1f93e73d62dcfead3230acc63dd5c..342189be4b2558a28920bb6d1d50c1f79b26b258 100644 GIT binary patch literal 10671 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 s{2O)Y_b308y!5F1tJl*0L-%hglZrh2 zY-NiGAz3P9i!=0npK`wcxz71t|HJjpT;qM8`+eqq?%(r!pBu`6o`DMh0PF?)VI6N% z=PxmeNBcF!MWD8-non+(cG+j0O8 zwcHDGzuV}It#-qUB19Wn8k-Fcec|aP+_B6^UeBD{m))G+w4XN~Q z?-%yR-n;=BijCguSE{j5s1PO$g};R7V_c>5FXea4Lx`aMZnL%{{AN>0-4ayBA;l7e z({WJrhg5%8U&Ct6q5%N2&36GCClwN}bAwZ=N(<3#1UYy~OhS2xe2MjA8T;!9CXUpJ z2Z5cHY!i8b8rPSERPhRz7MRa!KdDu;Td?@rxu2XlntOT1YIf*c@KB9Uu|Q3xo%(8< zAx!+@vcA}eBWy}#Ry!{Lp-zffM38aqk@)usS3e6R=A@A*vi#&z8vxXA>~V4oK69fn zr$-L}aM0MpdSFl_4jwDN|(+e_%3x%%+V_tHO@vbMC7>kc=bK>@#X@8jb`t2^H1s7Zj0?V2rqe$8X(#< zZVfCwrk9Vun~uN7WX2dS{n2Fcy&pt_W1k3H*}_T5*D6$4n|Qx#2d|?IUrII^hK^&L z?e~9iKml(r)0ylnYl6CE2hb|WIOBXv_DF&uZ+8Q9eF(9Z8zKoxRZ$5<*1YDoQ?+}) z$4A10dC8%bacDudz2*U#?A33}_i!;U=uY|`kOwU9>|C=Ms#CN9HPt4ik0w|bqqO^^`9!b`FPBds9JoB)^qa;{X?LZyN664~<7`Z0Gn8it3 ziAdEP-lKiohp4h}6jZ9n*=kdJf${g!uryrsTBMc4eGdSzC3l*z$xdhz4r@js5!@Zg zTjeP&DQ<2x5jOxywza%2wSaZQQKlzb4cbnxwZ#J%1hhq;*VJ)Kk4vK8vFXt@S73 zQ>;P^UILOrg=8XG&H^P?sCtS89VL}xF~rp5gs85m#(bb)VPymRE(LEIpKd|WDAHpB z0NDPdiQ?yq+vewq#X!^mgyYAdtnc@(sT=I`O!SUMqx%xwS%PlNloZ{Q(dBc@__6v4 zubdWxx=w_NP=3V%5`Df141XFCJY)q## zvZ_~EMZQ!PlRtfkWS^t3DN;oS<{qScmWZ)TI)@xPmBbwkd~7k+tZi(7*B~<1MjA}X z)lGZtkpw*y$^(&YxbDmw*l}Ish?z?srjG3MNFMvZRpXl1`(Z}!vJgq=BZoXCWW5ir z4Jjl_>U|yQt~R`3d=Vf0#ZIpXeS7iak2B|hnj%z0nak1uNhhv5z03ysCFcMxvm3nn z+^A8~n#CzD)Z`@HMuF?;hu=lRD+VnZ)aMcTYc9TRNPKAixLiZ?ysp_$&wVjt()cSs z(eRg6f(_TcFPBz{Z}y&Tt4`JFsSwe%(nAMm_RC;FAz z$HQDaqWN|)&3Epr)Pr*;!(>+-6eiaE~govE5^zH+eU9cgvaU>bPy)j9UFf>wIb zv)qmvwi{eaHFUqP!`>Fvaw<(=OUwWO&rgAEZ7^gf9F9V!ElJuNbbF_<7%(2CY3)Yy zoI&UQu%eTkp#8Q4D?w|}Ytav1hIKtIq4K?N=@zaE@l`zU?pC&SKIu-=a;)Do7C*>2>zTS!YJYGna4^rKL%P;?`?LbZ0|Y zUm6>=IZyNxQv0*R!v~HJhSWLUK(P7nq*@f-(dQx-MBk$u??fjWnbIdH-*tECuqj6e zD2BF{Gx_qSI$=dzDp4&J+z%=m1-vG5QA8KufE=6rwBpIZ9P4tUcaat|n!*_w)PN*| ziy5mUB20zpwyb%tJTJJRY8V&1!TRf1{<7e&wclZmef%>UVRr*#ExfPegX;`)j`kP@!9DL+5LOfLX5zdiQsfUb=An3X9k>}cFvfSx9E zW;B10pue_fd}hNsaWW({A@lX(BymuLvR*a&h51nv7xxOZ?LdS~W5l#*)>w_Vo~Bst z>_SGF8zUM!E&kS)*JMLoKGtNuDY1B1 zOkV2ZW1!?`)HGVM_DHfihx8fkD02z+|7` zxTbuta<*oe6!-TMXurKV%YgpVa8j3z>kr9=qwuS0`jz92eYx!!QP(?`e5U=E4*V`{ zd&7v*GDZNP@(2KM@TasXPB=Flc>8r*)ibA0c?=-9HYG!6i$I$$z;2L3lY51zTb%DP z|6H7ngI44oJ+VbMr&xL>*6DCtrqAW|_lwl`f9?!Qbv;(jK55l^{DeU^sLVLc;Yi|9 zV8ZH??*W_3+EA-vwY|JbqMD}sUdO(Z1~o*!E{Ey{_oNg|QQ0O|%kKCZFp7xmeHQ<& z&Q=U1IaK&2m-&_TxsTAu;lAt998$?FH3-gShU=ks-{$uymvMA8YjCpb^;E$#Ok;1w zTTWqLGP4Hj=zn62jnpbiwFWXNE0Puk6qABP+o5<{W?#{DtTw+mGgSHza#G3b+vu(S zvO8slQ3Wg`A;azK(hO#iFHGw9vYb!XdsP4SPC|Jw&(lqKa+cOVrSzNtyn7#p*c46VH zW?*Kt5Wq08B%9OpTe4vZbEPVKQ;0+Tg^Im0Nc|pU)uX(rxCMq7i=Guo<9!WM%bf|e z$Nn2!Py9E=7Dh_DBGfWf{VA*Sw_z{R6uw3$fNR#)i#=2|&a3`d8XpBqF60)>NEZljIWjY8F8JV81SKjA-KHv;;H)kO0)gwUvsg)Dryvx z()1}|(PvXh-~XEBv3VRN6LOX5pfIkW{aDtMwlH_Jlgap@`%NFS*bYVU-_Z1dPUuXs zt9@ctxbkWy&jiJAUNH8S1GIml@EyDR9Ir}5=y1N$Hy;TT$9JCvOw`1|hksy258DoY zdMy-luIDaqn0rvi-K5k-#N*mtCD0?_vVdEQvhU%UgSPA3K`Yr{yM^(d&+}!~oN_`6&34-y~WvB3DeMSi|L(a~hR=2Z<>xSHkEns1%KT03# zA|9CXY3W2%RcP$K+on}32;;4#qGo?Df{RQ6lS%J`R;?>t9N!)yHduRPtP;WEeKFp~a z*~szkPJ|ognSCgTx)GSFIttfmKtmKYFo=W9JkmWn`}vLXL#^~M(2L6Q$2{SsYwC{# z5{rX7gF;Rp9e()7)J*D1@^GsHysm|1>5b%-^9FXQ6O+*vt()?8l$E+NEwY15>u{hT zq|>Y4s}e;Q5zNKheS}59ga-y;z2`mxZHEMf6~&xr3Ok%AuE%#%AfNuzagD6$0(FiD z#ipm;-)gm`G*bd{Q#-F-q@B_s z%%rdM#+jYqdrOsi%D^%g-s)5K;R<;8VL%ZFqJO&P0;WJQ6jMgEeJ z@`j1>cU2WZs(vl5hgf?3Av}* z)~KI0<82)#v@TCXV_eXVI4~JU@+M$#WUw2Kg2tjLXfVcugaZ+2^B;~xA<$09D$3&U z5C;fM7J`?>qhSs(v^+#!7UQ6ZM_}X;Fc~7*4T~YpRo5WZXw!(GH;zOmc(|(wLuDYs zf;e}K2bMOes0e#e@E`?YHC5!+4YuaXpZJ2b7m$yLUKyE zaA*n+D@aR7iQ-4ZsR;jd#tN>bZLTY<3WLDpKoD6FRNfo{SAxKlpmH)$2ox$Ot6+nq zQSlqj4zL@IT|D96LY9X>e?k5WNENxQfSm%V{w^e>+i8Y$+LQ3sv7aU+I}*;743^n? z{ohN#6z7Vj&_qIZA`rwwHVhWmXbNr{E{)akx;PEu|YkOe4wqyq0 zF6VE+;NPzh7Bokb9B~vCVel@GNmx)1t0HVFkHMp%4hX!00~RKWkb?;eg8$!A!}(Hh z?pPf5m(}`9e!E?qp9zxmu+V=$r{84%J5T?rfBcfsU(x@up7ST?4iH&99D_qRz;JL` z1Ol=B{lLHKf&90KfBJ>2?@pGE(!~3eCStyy&%8f%{HtrYt?9A^jVzEt1SN;k?*PqKH9J5i{H zQ4I0U{mz%C#@KD1ESL`#uY6;FHJ<%waNNx#rd=_>QP$JCDEkLpf!Tl(Jt74+42-P0 zP~JCf;5GmJfk?wbqmw>;l4`$k=D*&r>!0X6x7Ug1Yy*A=3wI z1^ronB)oLUS9fPVH43lpofd#=u1lijZ_c9Q`VPLCKaw0w^R4LiaBW+8|Lk1T#Q4k4 zt{$^Hc(-x86RAq8;O+*nJ9@XbxD(w+TNeN1H10;&ZM*Ft0BGvjLipQ++a0>wP}vDZ z(>%OCzxRK$S9YW9o?UlPko&e#c2BZ90RQ}0v;!ba`#-{eykYIW{qD_l=k_j~ziq8M zf&bjVb^;+Zo0vx5zi4N>adxlv9UOy00Kh-2eUt$stv&z%3+?wAO(vCxw?6$Bz#p(c diff --git a/Fortran/SUB_appcoef.f90 b/Fortran/SUB_appcoef.f90 index b356ccf..aa8d756 100644 --- a/Fortran/SUB_appcoef.f90 +++ b/Fortran/SUB_appcoef.f90 @@ -27,52 +27,60 @@ case('db3') lf = 6 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.332670552950957,0.806891509313339,0.459877502119331,-0.135011020010391,-0.0854412738822415,0.0352262918821007] - Hi_D = [0.0352262918821007,0.0854412738822415,-0.135011020010391,-0.459877502119331,0.806891509313339,-0.332670552950957] + Lo_D = [0.332670552950957,0.806891509313339,0.459877502119331,& + -0.135011020010391,-0.0854412738822415,0.0352262918821007] + Hi_D = [0.0352262918821007,0.0854412738822415,-0.135011020010391,& + -0.459877502119331,0.806891509313339,-0.332670552950957] case('db4') lf = 8 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.230377813308855,0.714846570552542,0.630880767929590,-0.0279837694169839,-0.187034811718881,0.0308413818359870,& - 0.0328830116669829,-0.0105974017849973] - Hi_D = [-0.0105974017849973,-0.0328830116669829,0.0308413818359870,0.187034811718881,-0.0279837694169839,-0.630880767929590,& - 0.714846570552542,-0.230377813308855] + Lo_D = [0.230377813308855,0.714846570552542,0.630880767929590,-0.0279837694169839,& + -0.187034811718881,0.0308413818359870,0.0328830116669829,-0.0105974017849973] + Hi_D = [-0.0105974017849973,-0.0328830116669829,0.0308413818359870,0.187034811718881,& + -0.0279837694169839,-0.630880767929590,0.714846570552542,-0.230377813308855] case('db5') lf = 10 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.160102397974125,0.603829269797473,0.724308528438574,0.138428145901103,-0.242294887066190,-0.0322448695850295,& - 0.0775714938400652,-0.00624149021301171,-0.0125807519990155,0.00333572528500155] - Hi_D = [0.00333572528500155,0.0125807519990155,-0.00624149021301171,-0.0775714938400652,-0.0322448695850295,0.242294887066190,& - 0.138428145901103,-0.724308528438574,0.603829269797473,-0.160102397974125] + Lo_D = [0.160102397974125,0.603829269797473,0.724308528438574,0.138428145901103,& + -0.242294887066190,-0.0322448695850295,0.0775714938400652,& + -0.00624149021301171,-0.0125807519990155,0.00333572528500155] + Hi_D = [0.00333572528500155,0.0125807519990155,-0.00624149021301171,& + -0.0775714938400652,-0.0322448695850295,0.242294887066190,0.138428145901103,& + -0.724308528438574,0.603829269797473,-0.160102397974125] case('db6') lf = 12 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.111540743350080,0.494623890398385,0.751133908021578,0.315250351709243,-0.226264693965169,-0.129766867567096,& - 0.0975016055870794,0.0275228655300163,-0.0315820393180312,0.000553842200993802,0.00477725751101065,-0.00107730108499558] + Lo_D = [0.111540743350080,0.494623890398385,0.751133908021578,0.315250351709243,& + -0.226264693965169,-0.129766867567096,0.0975016055870794,0.0275228655300163,& + -0.0315820393180312,0.000553842200993802,0.00477725751101065,-0.00107730108499558] Hi_D = [-0.00107730108499558,-0.00477725751101065,0.000553842200993802,0.0315820393180312,0.0275228655300163,-0.0975016055870794,& -0.129766867567096,0.226264693965169,0.315250351709243,-0.751133908021578,0.494623890398385,-0.111540743350080] case('db7') lf = 14 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.0778520540850624,0.396539319482306,0.729132090846555,0.469782287405359,-0.143906003929106,-0.224036184994166,& - 0.0713092192670500,0.0806126091510659,-0.0380299369350346,-0.0165745416310156,0.0125509985560138,0.000429577973004703,& - -0.00180164070399983,0.000353713800001040] - Hi_D = [0.000353713800001040,0.00180164070399983,0.000429577973004703,-0.0125509985560138,-0.0165745416310156,0.0380299369350346,& - 0.0806126091510659,-0.0713092192670500,-0.224036184994166,0.143906003929106,0.469782287405359,-0.729132090846555,& - 0.396539319482306,-0.0778520540850624] + Lo_D = [0.0778520540850624,0.396539319482306,0.729132090846555,0.469782287405359,-0.143906003929106,& + -0.224036184994166,0.0713092192670500,0.0806126091510659,-0.0380299369350346,& + -0.0165745416310156,0.0125509985560138,0.000429577973004703,-0.00180164070399983,0.000353713800001040] + Hi_D = [0.000353713800001040,0.00180164070399983,0.000429577973004703,-0.0125509985560138,& + -0.0165745416310156,0.0380299369350346,0.0806126091510659,-0.0713092192670500,& + -0.224036184994166,0.143906003929106,0.469782287405359,-0.729132090846555,0.396539319482306,-0.0778520540850624] case('db8') lf = 16 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.0544158422430816,0.312871590914466,0.675630736298013,0.585354683654869,-0.0158291052560239,-0.284015542962428,& - 0.000472484573997973,0.128747426620186,-0.0173693010020221,-0.0440882539310647,0.0139810279170155,0.00874609404701566,& + Lo_D = [0.0544158422430816,0.312871590914466,0.675630736298013,0.585354683654869,-0.0158291052560239,& + -0.284015542962428,0.000472484573997973,0.128747426620186,-0.0173693010020221,& + -0.0440882539310647,0.0139810279170155,0.00874609404701566,& -0.00487035299301066,-0.000391740372995977,0.000675449405998557,-0.000117476784002282] - Hi_D = [-0.000117476784002282,-0.000675449405998557,-0.000391740372995977,0.00487035299301066,0.00874609404701566,-0.0139810279170155,& - -0.0440882539310647,0.0173693010020221,0.128747426620186,-0.000472484573997973,-0.284015542962428,0.0158291052560239,& - 0.585354683654869,-0.675630736298013,0.312871590914466,-0.0544158422430816] + Hi_D = [-0.000117476784002282,-0.000675449405998557,& + -0.000391740372995977,0.00487035299301066,0.00874609404701566,-0.0139810279170155,& + -0.0440882539310647,0.0173693010020221,0.128747426620186,-0.000472484573997973,& + -0.284015542962428,0.0158291052560239,0.585354683654869,& + -0.675630736298013,0.312871590914466,-0.0544158422430816] case('fk4') lf = 4 @@ -89,10 +97,10 @@ case('fk8') lf = 8 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.349238111863800,0.782683620384065,0.475265135079471,-0.0996833284505732,-0.159978097434030,0.0431066681065162,& - 0.0425816316775818,-0.0190001788537359] - Hi_D = [-0.0190001788537359,-0.0425816316775818,0.0431066681065162,0.159978097434030,-0.0996833284505732,-0.475265135079471,& - 0.782683620384065,-0.349238111863800] + Lo_D = [0.349238111863800,0.782683620384065,0.475265135079471,-0.0996833284505732,& + -0.159978097434030,0.0431066681065162,0.0425816316775818,-0.0190001788537359] + Hi_D = [-0.0190001788537359,-0.0425816316775818,0.0431066681065162,0.159978097434030,& + -0.0996833284505732,-0.475265135079471,0.782683620384065,-0.349238111863800] end select diff --git a/Fortran/SUB_wavedec.f90 b/Fortran/SUB_wavedec.f90 index 7978b55..b910b2c 100644 --- a/Fortran/SUB_wavedec.f90 +++ b/Fortran/SUB_wavedec.f90 @@ -28,16 +28,16 @@ case('db4') lf = 8 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [-0.0105974017849973,0.0328830116669829,0.0308413818359870,-0.187034811718881,-0.0279837694169839,0.630880767929590,& - 0.714846570552542,0.230377813308855] + Lo_D = [-0.0105974017849973,0.0328830116669829,0.0308413818359870,-0.187034811718881,& + -0.0279837694169839,0.630880767929590,0.714846570552542,0.230377813308855] Hi_D = [-0.230377813308855,0.714846570552542,-0.630880767929590,-0.0279837694169839,0.187034811718881,0.0308413818359870,& -0.0328830116669829,-0.0105974017849973] case('db5') lf = 10 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.00333572528500155,-0.0125807519990155,-0.00624149021301171,0.0775714938400652,-0.0322448695850295,-0.242294887066190,& - 0.138428145901103,0.724308528438574,0.603829269797473,0.160102397974125] + Lo_D = [0.00333572528500155,-0.0125807519990155,-0.00624149021301171,0.0775714938400652,-0.0322448695850295,& + -0.242294887066190,0.138428145901103,0.724308528438574,0.603829269797473,0.160102397974125] Hi_D = [-0.160102397974125,0.603829269797473,-0.724308528438574,0.138428145901103,0.242294887066190,-0.0322448695850295,& -0.0775714938400652,-0.00624149021301171,0.0125807519990155,0.00333572528500155] @@ -52,22 +52,24 @@ case('db7') lf = 14 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [0.000353713800001040,-0.00180164070399983,0.000429577973004703,0.0125509985560138,-0.0165745416310156,-0.0380299369350346,& - 0.0806126091510659,0.0713092192670500,-0.224036184994166,-0.143906003929106,0.469782287405359,0.729132090846555,& - 0.396539319482306,0.0778520540850624] - Hi_D = [-0.0778520540850624,0.396539319482306,-0.729132090846555,0.469782287405359,0.143906003929106,-0.224036184994166,& - -0.0713092192670500,0.0806126091510659,0.0380299369350346,-0.0165745416310156,-0.0125509985560138,0.000429577973004703,& - 0.00180164070399983,0.000353713800001040] + Lo_D = [0.000353713800001040,-0.00180164070399983,0.000429577973004703,0.0125509985560138,-0.0165745416310156,& + -0.0380299369350346,0.0806126091510659,0.0713092192670500,-0.224036184994166,& + -0.143906003929106,0.469782287405359,0.729132090846555,0.396539319482306,0.0778520540850624] + Hi_D = [-0.0778520540850624,0.396539319482306,-0.729132090846555,0.469782287405359,0.143906003929106,& + -0.224036184994166,-0.0713092192670500,0.0806126091510659,0.0380299369350346,-0.0165745416310156,& + -0.0125509985560138,0.000429577973004703,0.00180164070399983,0.000353713800001040] case('db8') lf = 16 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [-0.000117476784002282,0.000675449405998557,-0.000391740372995977,-0.00487035299301066,0.00874609404701566,0.0139810279170155,& - -0.0440882539310647,-0.0173693010020221,0.128747426620186,0.000472484573997973,-0.284015542962428,-0.0158291052560239,& - 0.585354683654869,0.675630736298013,0.312871590914466,0.0544158422430816] + Lo_D = [-0.000117476784002282,0.000675449405998557,-0.000391740372995977,& + -0.00487035299301066,0.00874609404701566,0.0139810279170155,& + -0.0440882539310647,-0.0173693010020221,0.128747426620186,0.000472484573997973,& + -0.284015542962428,-0.0158291052560239,0.585354683654869,0.675630736298013,0.312871590914466,0.0544158422430816] Hi_D = [-0.0544158422430816,0.312871590914466,-0.675630736298013,0.585354683654869,0.0158291052560239,-0.284015542962428,& - -0.000472484573997973,0.128747426620186,0.0173693010020221,-0.0440882539310647,-0.0139810279170155,0.00874609404701566,& - 0.00487035299301066,-0.000391740372995977,-0.000675449405998557,-0.000117476784002282] + -0.000472484573997973,0.128747426620186,0.0173693010020221,-0.0440882539310647,& + -0.0139810279170155,0.00874609404701566,0.00487035299301066,-0.000391740372995977,& + -0.000675449405998557,-0.000117476784002282] case('fk4') lf = 4 @@ -84,8 +86,8 @@ case('fk8') lf = 8 allocate(Lo_D(lf),Hi_D(lf)) - Lo_D = [-0.0190001788537359,0.0425816316775818,0.0431066681065162,-0.159978097434030,-0.0996833284505732,0.475265135079471,& - 0.782683620384065,0.349238111863800] + Lo_D = [-0.0190001788537359,0.0425816316775818,0.0431066681065162,-0.159978097434030,& + -0.0996833284505732,0.475265135079471,0.782683620384065,0.349238111863800] Hi_D = [-0.349238111863800,0.782683620384065,-0.475265135079471,-0.0996833284505732,0.159978097434030,0.0431066681065162,& -0.0425816316775818,-0.0190001788537359] diff --git a/FortranWebApi/Controllers/FortranController.cs b/FortranWebApi/Controllers/FortranController.cs new file mode 100644 index 0000000..46a63e2 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Dockerfile b/FortranWebApi/Dockerfile new file mode 100644 index 0000000..4074a30 --- /dev/null +++ b/FortranWebApi/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_WAVELET.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_WAVELET.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_WAVELET.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/FortranWebApi/FortranWebApi.csproj b/FortranWebApi/FortranWebApi.csproj new file mode 100644 index 0000000..6a4d551 --- /dev/null +++ b/FortranWebApi/FortranWebApi.csproj @@ -0,0 +1,27 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + + PreserveNewest + + + + \ No newline at end of file diff --git a/FortranWebApi/HttpRequests/fortranwebapi.http b/FortranWebApi/HttpRequests/fortranwebapi.http new file mode 100644 index 0000000..1c35b49 --- /dev/null +++ b/FortranWebApi/HttpRequests/fortranwebapi.http @@ -0,0 +1,13 @@ +@FortranWebApi_HostAddress = http://localhost:5000 + +### 测试Fortran请求 + +POST {{FortranWebApi_HostAddress}}/FortranCalculate +Content-Type: application/json + +{ + "text": "{\"FuncName\":\"calculate_main\",\"ClassName\":\"\",\"Par\":[ {"Name":"n","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"Data_Error","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"Data_Re","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}, + {"Name":"Error","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}]}" +} \ No newline at end of file diff --git a/FortranWebApi/Models/ApiResponse.cs b/FortranWebApi/Models/ApiResponse.cs new file mode 100644 index 0000000..3845aa5 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Models/FortranParameter.cs b/FortranWebApi/Models/FortranParameter.cs new file mode 100644 index 0000000..78d68f0 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Models/FortranRequest.cs b/FortranWebApi/Models/FortranRequest.cs new file mode 100644 index 0000000..e17fc88 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Models/FortranRequestWrapper.cs b/FortranWebApi/Models/FortranRequestWrapper.cs new file mode 100644 index 0000000..49c36c2 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Program.cs b/FortranWebApi/Program.cs new file mode 100644 index 0000000..ac334f1 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Properties/launchSettings.json b/FortranWebApi/Properties/launchSettings.json new file mode 100644 index 0000000..295de27 --- /dev/null +++ b/FortranWebApi/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/FortranWebApi/Services/FortranInteropService.cs b/FortranWebApi/Services/FortranInteropService.cs new file mode 100644 index 0000000..4e9dd67 --- /dev/null +++ b/FortranWebApi/Services/FortranInteropService.cs @@ -0,0 +1,519 @@ +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_WAVELET.so") + { + // 尝试从当前目录加载 + string currentDir = Directory.GetCurrentDirectory(); + string libraryPath = Path.Combine(currentDir, "libSUB_WAVELET.so"); + + if (File.Exists(libraryPath)) + { + return NativeLibrary.Load(libraryPath); + } + } + + // 回退到默认加载行为 + return IntPtr.Zero; + }); + } + + // DllImport声明 + [DllImport("libSUB_WAVELET.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SUB_WAVELET")] + private static extern void SUB_WAVELET( + ref int n, + double[] Data_Error, + double[] Data_Re, + double[] Error + ); + + 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 n = GetIntParameter(parameters, "n"); + double[] Data_Error = GetDoubleArrayParameter(parameters, "Data_Error"); + + + // 准备数组参数 + double[] Data_Re = new double[10000]; // 输出数组,初始大小为10000 + double[] Error = new double[10000]; // 输出数组,初始大小为10000 + + + // 调用Fortran函数 + SUB_WAVELET( + ref n, + Data_Error, + Data_Re, + Error + ); + + // 更新输出参数 + UpdateDoubleArrayParameter(parameters, "Data_Re", Data_Re); + UpdateDoubleArrayParameter(parameters, "Error", Error); + + + // 处理输出数组 + // 处理输出数组 Data_Re + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < Data_Re.Length; i++) + { + if (Data_Re[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + double[] resultArray = new double[nonZeroCount]; + Array.Copy(Data_Re, resultArray, nonZeroCount); + UpdateDoubleArrayParameter(parameters, "Data_Re", resultArray); + } + } + // 处理输出数组 Error + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < Error.Length; i++) + { + if (Error[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + double[] resultArray = new double[nonZeroCount]; + Array.Copy(Error, resultArray, nonZeroCount); + UpdateDoubleArrayParameter(parameters, "Error", 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/FortranWebApi/appsettings.json b/FortranWebApi/appsettings.json new file mode 100644 index 0000000..dcb0750 --- /dev/null +++ b/FortranWebApi/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 diff --git a/HttpRequests/fortranwebapi.http b/HttpRequests/fortranwebapi.http index 6165a7f..1c35b49 100644 --- a/HttpRequests/fortranwebapi.http +++ b/HttpRequests/fortranwebapi.http @@ -7,6 +7,7 @@ Content-Type: application/json { "text": "{\"FuncName\":\"calculate_main\",\"ClassName\":\"\",\"Par\":[ {"Name":"n","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, - {"Name":"x","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, - {"Name":"xden","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}]}" + {"Name":"Data_Error","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"Data_Re","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}, + {"Name":"Error","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}]}" } \ No newline at end of file diff --git a/Services/FortranInteropService.cs b/Services/FortranInteropService.cs index 99a5632..4e9dd67 100644 --- a/Services/FortranInteropService.cs +++ b/Services/FortranInteropService.cs @@ -35,8 +35,9 @@ namespace FortranWebApi.Services [DllImport("libSUB_WAVELET.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SUB_WAVELET")] private static extern void SUB_WAVELET( ref int n, - double[] x, - double[] xden + double[] Data_Error, + double[] Data_Re, + double[] Error ); public string ProcessFortranRequest(string requestText) @@ -63,38 +64,56 @@ namespace FortranWebApi.Services // 提取参数 int n = GetIntParameter(parameters, "n"); - double[] x = GetDoubleArrayParameter(parameters, "x"); + double[] Data_Error = GetDoubleArrayParameter(parameters, "Data_Error"); // 准备数组参数 - double[] xden = new double[10000]; // 输出数组,初始大小为10000 + double[] Data_Re = new double[10000]; // 输出数组,初始大小为10000 + double[] Error = new double[10000]; // 输出数组,初始大小为10000 // 调用Fortran函数 SUB_WAVELET( ref n, - x, - xden + Data_Error, + Data_Re, + Error ); // 更新输出参数 - UpdateDoubleArrayParameter(parameters, "xden", xden); + UpdateDoubleArrayParameter(parameters, "Data_Re", Data_Re); + UpdateDoubleArrayParameter(parameters, "Error", Error); // 处理输出数组 - // 处理输出数组 xden + // 处理输出数组 Data_Re // 注意:没有找到明确的长度参数,使用非零元素数量 { int nonZeroCount = 0; - for (int i = 0; i < xden.Length; i++) + for (int i = 0; i < Data_Re.Length; i++) { - if (xden[i] != 0) nonZeroCount = i + 1; + if (Data_Re[i] != 0) nonZeroCount = i + 1; } if (nonZeroCount > 0) { double[] resultArray = new double[nonZeroCount]; - Array.Copy(xden, resultArray, nonZeroCount); - UpdateDoubleArrayParameter(parameters, "xden", resultArray); + Array.Copy(Data_Re, resultArray, nonZeroCount); + UpdateDoubleArrayParameter(parameters, "Data_Re", resultArray); + } + } + // 处理输出数组 Error + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < Error.Length; i++) + { + if (Error[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + double[] resultArray = new double[nonZeroCount]; + Array.Copy(Error, resultArray, nonZeroCount); + UpdateDoubleArrayParameter(parameters, "Error", resultArray); } }