首先用DELPHI语言写成通用坦克计算过程的的DLL,然后用VB调用和拓展程序功能。
DLL的流程如下:开始—读流域参数文件—读模型参数文件—读洪号文件—计算初始水深—模型计算和写输出文件—结束。
在DLL中使用一个可输出的函数tank,其参数为一个全路径文件名(lujing:string),返回值为布尔型。代码:functiontank(lujing:string):boolean;stdcall;export;//声明DLL函数。Lujing文件的内容是所有输入文件的全路径名称,包括流域参数文件、模型参数文件、洪号文件、洪水雨量文件、洪水过程文件。其内容如下:
流域参数文件(liuyu.ses)内容包括水箱组数目、流域面积、各水箱组权重和传播时间。
模型参数文件(hhao.txt)内容包括各个水箱的孔口系数A和孔口高H。
洪号文件(hhao.txt)的首行为洪水场次,下面为各次洪水雨量文件的全路径名称。
洪水雨量文件(洪号.int)内容包括洪水的初始流量、基流、各上层水箱初始水深,雨量记录数,记录数应包括预见期在内。最后是雨量记录,间隔一小时,依次为时间、1组雨量、2组雨量…
洪水过程文件(洪号.guo)为便于方案的检验,对应于洪水雨量文件。
程序运行后生成输出文件(洪号.out)也保存在同目录下。
二、程序实现:
1、水箱组的数量及各自传播时间和权重取决于流域的特性,为提高程序的通用性,设置成不确定变量,分别保存在tanknum、quan[1..tanknum]和time[1..tanknum] 。
2、模型参数的命名应利于计算,每组15个参数,名称canshu[315]其中3代表第三组水箱,15是第15个参数,读取代码:
assignfile(f,fname[2]);reset(f);
for i:=1 to tanknum do
begin
x:=100*i;
for n:=1 to 15 do
begin
read(f,canshu[x+n]);
if canshu[x+n]<=0 then
showmessage('发现错误参数,在'+ inttostr(x+n) +'个!');
readln(f);
end;
end;
closefile(f);
3、初始水深的分析:
坦克模型所谓的基流是第三层水箱的出流量,存在一个极限上值。当起涨前流域干旱时,初始流量大部是基流,是第三层水箱出流,即深层地下径流,据以计算其初始水深Hx,初始流量和基流之差为第二层水箱出流,即地下径流,据以计算其初始水深Hz,第一层水箱的初始水深Hs低于其下孔高;起涨前流域湿润,初始流量较大,表示有壤中流; Hs与前期的降雨量和雨量的时间分布关系密切,雨量越大、时间越接近起涨,Hs就越大。Hx和Hz计算代码如下:
for m:=1 totanknum do
begin
qep:= jiliu*quan[m] * 3.6 / mianji*quan[m];
hx[m]:= (qep + canshu[100*m+12] * canshu[100*m+11] + canshu[100*m+14] *canshu[100*m+13]) / (canshu[100*m+11] + canshu[100*m+13]);
If hx[m] < canshu[100*m+12] Then
hx[m]:= (qep + canshu[100*m+14] * canshu[100*m+13]) / canshu[100*m+13] ;
hx[m]:= hx[m] - qep - canshu[100*m+15] * hx[m];
//showmessage('qep'+floattostr(qep));
qcp:= (chuliu - jiliu)*quan[m] * 3.6 / mianji*quan[m];
hz[m]:= (qcp + canshu[100*m+6] * canshu[100*m+7] + canshu[100*m+8] *canshu[100*m+9]) / (canshu[100*m+6] + canshu[100*m+8]) ;
If hz[m] <canshu[100*m+7] Then
hz[m]:= (qcp + canshu[100*m+8] * canshu[100*m+9]) / canshu[100*m+8] ;
hz[m]:= hz[m] - qcp - canshu[100*m+10] * hz[m];
//showmessage('qcp'+floattostr(qcp));
end; //计算HZ和HX
4、模型计算:
模型计算时读入不同水箱组的参数及其雨量,按雨量数值的多少和水箱组的多少循环计算,代码如下:
proceduretanking; //计算过程
var
i,m:integer;rs,rx,rz,r1,r2,r3,r:single;
begin
for i:=1 totanknum do //水箱组循环计算
begin
for m:=1to rainnum do //雨量循环计算
begin
hs[i] := hs[i] + rainval[i,m];//加入雨量
rs := 0 ;
If hs[i] > canshu[100*i+2] Then
rs := (hs[i] - canshu[100*i+2]) * canshu[100*i+1];//上孔出流
rx := 0 ;
If hs[i] > canshu[100*i+4] Then
rx := (hs[i] - canshu[100*i+4]) * canshu[100*i+3];//下孔出流
rz:= hs[i] * canshu[100*i+5] ;//底孔渗流
r1 := rs + rx ;//第一层水箱出流
hs[i]:= hs[i] - r1 - rz ;//计算后水深
hz[i] := hz[i] + rz ; rs:= 0 ;
If hz[i] > canshu[100*i+7] Then
rs:= ( hz[i] - canshu[100*i+7]) * canshu[100*i+6];
rx:= 0 ;
If hz[i] > canshu[100*i+9] Then
rx:= ( hz[i] - canshu[100*i+9]) * canshu[100*i+8];
rz:= hz[i] * canshu[100*i+10] ;
r2:= rs + rx ; {第二层水箱出流} hz[i]:= hz[i] - r2 - rz;
hx[i]:= hx[i] + rz ; rs := 0 ;
If hx[i] >canshu[100*i+12] Then
rs:= ( hx[i] - canshu[100*i+12]) * canshu[100*i+11];
rx:= 0 ;
If hx[i] > canshu[100*i+14] Then
rx:= ( hx[i] - canshu[100*i+14]) * canshu[100*i+13];
rz:= hx[i] * canshu[100*i+15] ;
r3:= rs + rx ; {第三层水箱出流} hx[i]:= hx[i] - r3 - rz;
r:= r1 + r2 + r3 ; //总出流
outq[m+time[i]]:= outq[m+time[i]] + r * mianji*quan[i] / 3.6 ;//流量迭加
end;{雨量循环}end;{模型组循环} end; //坦克计算过程
5、写输出文件
此过程相对简单,因为文件要用VB读取,所以在数据中间加入分割符号“,”代码如下:
//以下写输出文件
hhao[i]:=leftstr(hhao[i],length(hhao[i]) - 4)+ '.out';//输出文件的名称
assignfile(f, hhao[i]); //关联文件
rewrite(f);
for j:=1 to rainnum do
begin
if outq[j]<chuliu then outq[j]:=chuliu;
writeln(f,inttostr(no[j]),' ,',floattostr(int(outq[j]))); //时间,流量
end; //write
closefile(f);
6、VB调用和功能拓展
声明DLL:PrivateDeclare Function tank Lib " tank.dll" (ByVal a As String) AsBoolean
若将DLL和VB的EXE文件没有放在一个文件夹,则有下划线部分需要全路径。
调用DLL:Iftank("f:/tank/lujing.txt") Then Text1.Text = "DLL调用成功!生成输出文件"
功能拓展主要是根据实际方案制作需要,进行检验统计或图形显示,以便方案参数的调整和对比,在此不再赘述。