⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test.cpp

📁 汪德灌教授那本 计算水力学书后的 perisiman 隐式差分法源代码的 c++版本
💻 CPP
字号:

// test.cpp : 定义控制台应用程序的入口点。
//
#include <errno.h> //读文件用的
#include "stdafx.h"
#include<stdio.h>
#include<math.h>
#define N1 150	//断面数
#define N2 20	//断面的分层数
#define N3 50	//计算次数
#define G 9.8f
int IZ;
	float A1[N1],B1[N1],C1[N1],D1[N1],E1[N1],A2[N1];
	float B2[N1],DKDZJ[N1];
	float C2[N1],D2[N1],E2[N1],H1[N1],H2[N1],H3[N1];
	float DKDZS[N1][N2],DBDZS[N1][N2],DBDZJ[N1];
	float TT;//后加上去的
	int JS,JE,IK[2];//断数的起始个数

//*********************************共享去了*****************************************
	float Z0[N1],Q0[N1];			//初始水深和流量
	float DZ[N1],DQ[N1];			//水深和流量的增量
	float BCUP[N2][2],BCDN[N2][2];	//上下游边界条件
	float FJ[N1],GJ[N1];
//**********************************************************************************

//计算水面积
//*****************************************************************
//					各段面分层水深	AS对应过水面积	Z0初始水深	过水面积(要求的量)	断面起始 结束	每个断面的层数
void SufaceArea(	float A[][N2],	float B[][N2],	float C[N1],	float D[N1],	int JS,	int JE,	int IZJ[N1])
{
	//int N1=150,N2=20,N3=50;
//	float A[N1][N2],
//	float B[N1][N2],C[N1],D[N1],IZJ[N1];
	int LevelNum,j;
	float InitWaterHigh;
	for(j=JS;j<=JE;j++)				//求每个断面的过水面积,断面循环
	{
		LevelNum=IZJ[j];			//每个断面的层数
		InitWaterHigh=C[j];			//断面初始水位高度
		for(int i=1;i<LevelNum;i++)	//求每层的过水面积
		{
			if(InitWaterHigh<=A[j][i])	//当前水位低于该层水位时,计算该层过水面积
				break;
		}
		D[j]=B[j][i-1]+(B[j][i]-B[j][i-1])*(InitWaterHigh-A[j][i-1])/(A[j][i]-A[j][i-1]);//求过水面积
		//计算理论参见PPT
	}
}
//计算水位流量
//*****************************************************************
//					上游边界条件			要求的量	实际分层数
void WaterHigh(	float A[][2],	float A1,	float* A2,	int IA)
{
	//float A[N2][2];
	for(int i=1;i<IA;i++)	//每一层的流量
	{
		if(A1<A[i][0])		//如果A1<上游边界流量条件
			break;
	}
	*A2=A[i-1][1]+(A[i][1]-A[i-1][1])*(A1-A[i-1][0])/(A[i][0]-A[i-1][0]);//计算流量
		//流量=上游入水流量+(本段流量-上段流量)*(当前-上)/(本断流量-)
}

//输入边界
//*****************************************************************
void BOUND(float DATA[][2], float A1, int IA,int J,int IGG,int KD)
{
	float ZT=0.0f;
	float QT,QZD,HIQ,DFQ,QIQ;
//	J=J-1;
	if(IGG==1)
	{
		WaterHigh(DATA,A1,&ZT,IA);
		DZ[J]=ZT-Z0[J];
		if(KD==1)
		{
			FJ[J]=1000000.0;
			GJ[J]=-FJ[J]*DZ[J];
		}
		else
			DQ[J]=FJ[J]*DZ[J]+GJ[J];
	}
	if(IGG==2)
	{
		WaterHigh(DATA,A1,&QT,IA);
		DQ[J]=QT-Q0[J];
		if(KD==1)
		{
			FJ[J]=0.0;
			GJ[J]=DQ[J];
		}
		else
			DZ[J]=(DQ[J]-GJ[J])/FJ[J];
	}
	if(IGG==3)
	{
		WaterHigh(DATA,Z0[J],&QZD,IA);
		HIQ=Z0[J]+0.1f;
		WaterHigh(DATA,HIQ,&QIQ,IA);
		DFQ=(QIQ-QZD)/0.1f;
		if(KD==1)
		{
			FJ[J]=DFQ;
			GJ[J]=QZD-Q0[J];
		}
		else
		{
			DZ[J]=(QZD-GJ[J]-Q0[J])/(FJ[J]-DFQ);
			DQ[J]=FJ[J]*DZ[J]+GJ[J];
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{

	float ZN[N3][N1],QN[N3][N1];	//计算的水深和流量
	float T,temp,DZS,DBS;	//
	//	 AS面积,  BS面宽,  	PS湿周  	各断面分层水深 流量模数
	float AS[N1][N2],BS[N1][N2],	PS[N1][N2],	ZS[N1][N2],		RKS[N1][N2];
	//对应ZJ[]的过水面面积,水面宽度,湿周和流量模数,用于计算流量模数,断面坐标值
	float AJ[N1],BJ[N1],RKJ[N1],RNJ[N1],XL[N1];
	int IZJ[N1];	//各断面对应ZS[][]的分层数
	float ZETA,DT;
	int NX;
	FILE * fp1;
	if(NULL==(fp1=fopen("E:\\WangStu\\Water Simulation\\N当前成果代码\\test\\test\\input.txt","rb+")))
	{
		printf("Open file 1 error:\n");
		return 1;
	}
	printf("Open file(s) successfull!\n");
	printf("Get data from file 1 : \n");
	fscanf(fp1,"%f %d %f %f", &TT, &NX, &DT, &ZETA);//时间间隔,段数,时间间隔,代表权值,应该>0且<1 一般取0.5
	printf("\n时间长度(HOURS)\t河道段数\t时间间隔(HOURS)\t代表权值\n%f\t%f\t%f\t%f\t\n",TT,NX,DT,ZETA);
	float NT,RS;	//后加上去的,未声明的标识符
	int IBU,IBD;	//后加上去的,未声明的标识符
	NT=int(TT/DT)+1.001f;
	JS=0;
	JE=NX;
	fscanf(fp1,"%f %f %f %f %f %f %f %f %f %f %f", &XL[0],&XL[1],&XL[2],&XL[3],&XL[4],&XL[5],&XL[6],&XL[7],&XL[8],&XL[9],&XL[10]);				//READ(1,*) (XL(J),J=JS,JE);//各断面坐标值
	fscanf(fp1,"%f %f %f %f %f %f %f %f %f %f %f", &RNJ[0],&RNJ[1],&RNJ[2],&RNJ[3],&RNJ[4],&RNJ[5],&RNJ[6],&RNJ[7],&RNJ[8],&RNJ[9],&RNJ[10]);	//READ(1,*) (RNJ(J),J=JS,JE);
	fscanf(fp1,"%d %d %d %d %d %d %d %d %d %d %d", &IZJ[0],&IZJ[1],&IZJ[2],&IZJ[3],&IZJ[4],&IZJ[5],&IZJ[6],&IZJ[7],&IZJ[8],&IZJ[9],&IZJ[10]);	//READ(1,*) (IZJ(J),J=JS,JE);各断面对应zs分层数
	int i;
	printf("\n各断面分层水深值,水面宽度 一层 二层\n");

	for(i=JS;i<JE;i++)//段循环
	{
		IZ=IZJ[i];//各段的分层数
		fscanf(fp1,"%f %f %f %f",&ZS[i][0],&BS[i][0],&ZS[i][1],&BS[i][1]);//各断面分层水深值,水面宽度
		printf("%d:\t%f\t%f\t%f\t%f\t\n",i+1,ZS[i][0],BS[i][0],ZS[i][1],BS[i][1]);
	}

	fscanf(fp1,"%d %d",	&IK[0],	&IK[1]);//READ(1,*) (IK(I),I=1,2);//边界条件指示数,IK[1]上游边界条件IK[2]下游边界条件,IK[*]=1给定水位时间过程Z(t) =2给定流量时间过程Q(t) =3给定流量水位关系Q(Z)
	fscanf(fp1,"%d %d",	&IBU, &IBD);	//READ(1,*) IBU,IBD;上下游分层数
	printf("\n边界条件类型值\n[%d]\t\t[%d]\t\t\n上下游条件的个数\n[%d]\t\t[%d]\t\t\n",IK[0],IK[1],IBU,IBD);
	printf("\n读取  上  游各层的边界条件(水位时间过程) 一层\t二层\n");

	for(i=0;i<IBU;i++)//读取  上  游各层的边界条件//以列表形式给出时,数据的个数
	{
		fscanf(fp1,"%f %f",	&BCUP[i][0],&BCUP[i][1]	);//READ(1,*) ((BCUP(J,I),I=1,2),J=1,IBU);	//上游边界条件
		printf("[%f]\t[%f]\t\n",BCUP[i][0],BCUP[i][1]);
	}

	printf("\n读取  下  游各层的边界条件(水位时间过程) 一层\t二层\n");
	for(i=0;i<IBD;i++)//读取  下  游各层的边界条件
	{
		fscanf(fp1,"%f %f",	&BCDN[i][0],&BCDN[i][1]	);//下游边界条件
		printf("[%f]\t[%f]\t\n",BCDN[i][0],BCDN[i][1]);
	}

	fscanf(fp1,"%f %f %f %f %f %f %f %f %f %f %f",&Q0[0], &Q0[1], &Q0[2], &Q0[3], &Q0[4], &Q0[5], &Q0[6], &Q0[7], &Q0[8], &Q0[9], &Q0[10]);//READ(1,*) (Q0(J),J=JS,JE);	//各断面初识流量
	fscanf(fp1,"%f %f %f %f %f %f %f %f %f %f %f",&Z0[0], &Z0[1], &Z0[2], &Z0[3], &Z0[4], &Z0[5], &Z0[6], &Z0[7], &Z0[8], &Z0[9], &Z0[10]);//READ(1,*) (Z0(J),J=JS,JE);	//各断面初识水深
	printf("\n各断面初始流量\n%f\t%f\t%f\t%f\t%f\t%f\t\n",Q0[0], Q0[1], Q0[2], Q0[3], Q0[4], Q0[5]);
	printf("\n各断面初始水深\n%f\t%f\t%f\t%f\t%f\t%f\t\n",Z0[0], Z0[1], Z0[2], Z0[3], Z0[4], Z0[5]);
	printf("--------------------文件读取结束-----------------\n");
	fclose(fp1);
	int j;

	//未知变量赋初值
	for(j=JS;j<JE;j++)//DO 30 J=JS,JE
	{
		AS[j][0]=0.0;	//过水面积
		PS[j][0]=0.0;	//湿周
		RKS[j][0]=0.0;	//流量模数
		DQ[j]=0.0;		//水深增量
		DZ[j]=0.0;		//流量增量
	}

	
	//计算过水面面积,水面宽,流量模数 dbdz dkdz 与z的关系
	for(j=JS;j<JE;j++)
	{
		IZ=IZJ[j];
		for(int i=1;i<IZ;i++)//DO 20 i=2,IZ  
		{
			DZS=ZS[j][i]-ZS[j][i-1];			//各断分层水深
			DBS=(BS[j][i]-BS[j][i-1])/2.0f;		//水面宽
			AS[j][i]=AS[j][i-1]+(BS[j][i-1]+BS[j][i])*DZS/2.0f;	//计算面积=下面的面积+(上底+下底)*高/2
			PS[j][i]=PS[j][i-1]+2.0f*sqrtf(DBS*DBS+DZS*DZS);		//计算湿周=可以理解为水与土壤的接触长度
			RS=AS[j][i]/PS[j][i];				//面积/湿周
			RKS[j][i]=AS[j][i]*powf(float(RS),float(2.0/3.0))/RNJ[j];//流量模数
			DKDZS[j][i]=(RKS[j][i]-RKS[j][i-1])/DZS;
			DBDZS[j][i]=(BS[j][i]-BS[j][i-1])/DZS;
		}
		DKDZS[j][0]=DKDZS[j][1];
		DBDZS[j][0]=DBDZS[j][1];
	}


	//计算系数 A,B,C,D,E
	float DX,CR1,BJM,AJM,DQJ,DZJ;	//后加上去的,未声明的标识符
	int JEM1,JSP1;

	JEM1=JE-1;//断面数-1
	JSP1=JS+1;//断面数起始+1
	NT=(TT/DT)+1;//TT为读进来的值.DT为读进来的值 时间间隔,TT可以假设是时间总长度
	for(int N=0;N<NT;N++)//模拟次数循环
	{
		T=float(N+1)*DT;
		//Z0初始水深,AJ=对应ZJ过水断面积,JS=0,JE=最大断面数,IZJ=各断面对应ZS的分层数
			SufaceArea(ZS,AS,Z0,AJ,JS,JE,IZJ);		//ZS=各段面分层水深值,AS=对应ZS过水断面积,求对应ZJ过水断面积AJ
			SufaceArea(ZS,BS,Z0,BJ,JS,JE,IZJ);		//BS=对应ZS过水面宽度,BJ=对应ZJ水面宽度,求对应ZJ过水面宽度BJ
			SufaceArea(ZS,RKS,Z0,RKJ,JS,JE,IZJ);	//RKS=对应ZS流量模数,RKJ=对应ZJ流量模数,求对应ZJ流量模数RKJ
			SufaceArea(ZS,DKDZS,Z0,DKDZJ,JS,JE,IZJ);//DKDZS=各断对应不同水深的dk/dz值,DKDZJ=(dk/dz)f值,求对应ZJ(dk/dz)f值DKDZJ
			SufaceArea(ZS,DBDZS,Z0,DBDZJ,JS,JE,IZJ);//DBDZS=各断对应不同水深的db/dz值,DKDZJ=(db/dz)f值,求对应ZJ(db/dz)f值DBDZJ
		for(int o=0;o<5;o++)
//			printf("##### AJ=%.2f,BJ=%.2f,RKJ=%.2f,DKDZJ=%.2f,DBDZJ=%.2f\n",AJ[o],BJ[o],RKJ[o],DKDZJ[o],DBDZJ[o]);

		for(j=JS;j<JEM1;j++)//断数-1个循环
		{
			DX = XL[j+1]-XL[j];//各断面坐标值,这里理解为段河道的长度
			CR1 = ZETA*DT/DX;//ZETA读进来的
			BJM = BJ[j]+BJ[j+1];//水面宽度
			AJM = AJ[j]+AJ[j+1];//水断面面积
			DQJ = Q0[j+1]-Q0[j];
			DZJ = Z0[j+1]-Z0[j];

//计算各个参数或系数
			A1[j] = -4.0f*CR1/BJM;
			B1[j] = 1.0f-4.0f*CR1*ZETA*DQJ*DBDZJ[j]/BJM/BJM;
			C1[j] = 4.0f/BJM*CR1;
			D1[j] = 1.0f-4.0f*CR1*DQJ*DBDZJ[j+1]/BJM/BJM;
			E1[j] = -4*CR1*DQJ/BJM;
			A2[j] = 1.0f-4.0f*CR1*Q0[j]/AJ[j]+2.0f*CR1*DX*G*AJ[j]*fabsf(Q0[j])/RKJ[j]/RKJ[j];
			B2[j] = CR1*(2.0f*Q0[j]*Q0[j]*BJ[j]/AJ[j]/AJ[j]-G*AJM+G*DZJ*BJ[j]);
			temp = G*CR1*DX*Q0[j]*fabsf(Q0[j])/RKJ[j]/RKJ[j]*(BJ[j]-2*AJ[j]*DKDZJ[j]/RKJ[j]);
			B2[j] = B2[j]+temp;
			C2[j] = 1.0f+4.0f*CR1*Q0[j+1]/AJ[j+1]+2.0f*G*CR1*DX*AJ[j+1]*fabsf(Q0[j+1])/RKJ[j+1]/RKJ[j+1];
			temp = -2.0f*Q0[j+1]*Q0[j+1]*BJ[j+1]/AJ[j+1]/AJ[j+1]+G*AJM+G*DZJ*BJ[j+1];
			D2[j] = CR1*temp;
			temp = BJ[j+1]-2.0f*AJ[j+1]*DKDZJ[j+1]/RKJ[j+1];
			D2[j] = D2[j]+G*CR1*DX*Q0[j+1]*fabsf(Q0[j+1])/RKJ[j+1]/RKJ[j+1]*temp;
			E2[j] = DT/DX*(-2.0f*Q0[j+1]*Q0[j+1]/AJ[j+1]+2.0f*Q0[j]*Q0[j]/AJ[j]-G*AJM*DZJ);
			E2[j]=E2[j]-G*DT*(AJ[j+1]*Q0[j+1]*fabsf(Q0[j+1])/RKJ[j+1]/RKJ[j+1]+Q0[j]*fabsf(Q0[j])*AJ[j]/RKJ[j]/RKJ[j]);
		}

		float AFB1,AFB2,AHC2;
		int JR,IGG;
//输入边界条件 上游
		IGG=IK[0];
 		BOUND(BCUP,T,IBU,JS,IGG,1);
		//THE FIRST SWEEP
		for(j=JS;j<JEM1;j++)
		{
			AFB1=A1[j]*FJ[j]+B1[j];
			H1[j]=-C1[j]/AFB1;
			H2[j]=-D1[j]/AFB1;
			H3[j]=(E1[j]-A1[j]*GJ[j])/AFB1;
			AFB2=A2[j]*FJ[j]+B2[j];
			AHC2=AFB2*H1[j]+C2[j];
			FJ[j+1]=-(AFB2*H2[j]+D2[j])/AHC2;
			GJ[j+1]=(E2[j]-AFB2*H3[j]-A2[j]*GJ[j])/AHC2;
		}

//输入边界条件 下游
		IGG=IK[1];
		BOUND(BCDN,T,IBD,JE-1,IGG,2);
		//THE SECOND SWEEP
		for(j=JS;j<JEM1;j++)
		{
			JR=JE-j-2;
			DZ[JR]=H1[JR]*DQ[JR+1]+H2[JR]*DZ[JR+1]+H3[JR];	//水深的增量
			DQ[JR]=FJ[JR]*DZ[JR]+GJ[JR];					//流量的增量
		}

//JE个断数循环,重置参数
		for(j=JS;j<JE;j++)	//RESET INITIAL CONDITION
		{
			Q0[j]=Q0[j]+DQ[j];	//初识流量+流量增量
			Z0[j]=Z0[j]+DZ[j];	//初始水深+水深增量
			QN[N][j]=Q0[j];		//计算的流量
			ZN[N][j]=Z0[j];		//计算的水深
		}
	}
	//输出 计算次数,时间点,水深,流量
	for(N=0;N<NT;N++)
	{
		float TIME=float(N+1)*DT;
		printf("\n%d\t%f\t\n\t\t",N+1,TIME);
		for(i=0;i<JE;i++)
		{
			printf("断面%d     ",i);
		}
		printf("\n计算的流量\t");
		for(i=0;i<JE;i++)
		{
			printf("%.3f    ",QN[N][i]);
		}
		printf("\n计算的水深\t");
		for(i=0;i<JE;i++)
		{
			printf("%.3f    ",ZN[N][i]);
		}
		printf("\n");
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -