非饱和渗流问题
关键词:非饱和 渗流 瞬态 非线性 向后差分 迭代 变时间步长
许多岩土工程问题会涉及到非饱和渗流过程,如降雨入渗或地下水变化时土质边坡与堤坝的稳定性评价;垃圾填埋场内部污染物质的运移模拟;冻土中相变发生时的渗流过程分析;高放核废料的地质深埋处理等。因此,有效地模拟和分析非饱和渗流过程有着重要的实际意义,一直是岩土工程、水利工程、环境工程中的一项热门课题。
控制方程
微分形式
Richards 方程是非饱和渗流理论的基本方程。以孔隙水压力水头 $h$ 作为基本变量,$h =p/γ_w$,$p$ 为孔隙水压力,$γ_w$ 为水的容重。以 $z$ 表示竖直方向的坐标。如果考虑重力作用,则 $z$ 还代表了位置水头。此时,总水头为 $h+z$。二维坐标系下的 Richards 方程可表示为 \(n\frac{\partial S_{r}}{\partial h} \frac{\partial h}{\partial t}-\frac{\partial}{\partial x}\left(K \frac{\partial h}{\partial x}\right)-\frac{\partial}{\partial z}\left(K \frac{\partial h}{\partial z}\right)-\frac{\partial K}{\partial z}=0 \ \left(\text{in } \Omega\right) \tag{1}\label{eq1}\) 式中,$n$ 为多孔介质的孔隙率,$S_r$ 为饱和度,$K$ 为渗透系数,$x$ 为水平方向的坐标,$t$ 为时间。如果不考虑重力作用,则上式左侧最后一项 ${\partial K}/{\partial z}$ 为 $0$。
在初始时刻,压力水头为 $h_0$,即初始条件为 \(h=h_0 \ \left(\text{in } \Omega\right)\)
在边界 $\Gamma_h$ 上压力水头为定值 $\bar{h}$,在边界 $\Gamma_q$ 上流量为定值 $\bar{q}$ (流入为正),则边界条件可表示为:
- 强制边界条件 \(h=\bar{h}\ \left(\text{on } \Gamma_{h}\right)\)
- 自然边界条件 \(-K\frac{\partial(h+z)}{\partial \mathbf{n}} \cdot \mathbf{n}=-\bar{q} \ \left(\text {on } \Gamma_q\right)\)
其中,$\mathbf{n}$ 为多孔介质表面的单位法向量。
弱形式
运用变分原理,由方程 $\eqref{eq1}$ 得 \(\int_{\Omega}\left[n\frac{\partial S_{r}}{\partial h} \frac{\partial h}{\partial t}-\frac{\partial}{\partial x}\left(K \frac{\partial h}{\partial x}\right)-\frac{\partial}{\partial z}\left(K \frac{\partial h}{\partial z}\right)-\frac{\partial K}{\partial z}\right] \delta u d \Omega=0\) 将其转化为弱形式,可得 \(\int_{\Omega} n\frac{\partial S_{r}}{\partial h} \frac{\partial h}{\partial t} \delta h d \Omega+\int_{\Omega}\left(K \frac{\partial h}{\partial x} \frac{\partial \delta h}{\partial x}+K \frac{\partial h}{\partial z} \frac{\partial \delta h}{\partial z}\right) d \Omega \\=-\int_{\Omega} K \frac{\partial \delta h}{\partial z} d \Omega+\int_{\Gamma} K \frac{\partial (h+z)}{\partial \mathbf{n}}\cdot \mathbf{n} \delta h d \Gamma\) 代入边界条件,可得 \(\int_{\Omega} n\frac{\partial S_{r}}{\partial h} \frac{\partial h}{\partial t} \delta h d \Omega+\int_{\Omega}\left(K \frac{\partial h}{\partial x} \frac{\partial \delta h}{\partial x}+K \frac{\partial h}{\partial z} \frac{\partial \delta h}{\partial z}\right) d \Omega \\=-\int_{\Omega}K \frac{\partial \delta h}{\partial z} d \Omega+\int_{\Gamma_q} \bar{q} \delta h d \Gamma \tag{2}\label{eq2}\)
离散化
对式 $\eqref{eq2}$ 进行空间离散化后,可写成矩阵形式 \(M(U) \dot{U}+S(U)U=F\) 其中 $U$ 为压力水头向量,$\dot{U}$ 为压力水头对时间的导数向量,$M(U)$ 为质量矩阵, $S(U)$ 为刚度矩阵,$F$ 为载荷向量。采用向后差分法进行时域离散,可将上式改写为 \(M(U) \frac{U^{t+\Delta t}-U^{t}}{\Delta t}+S(U) U^{t+\Delta t}=F^{t+\Delta t}\) 整理得 \(\left(M(U)+S(U) \Delta t\right) U^{t+\Delta t}=F^{t+\Delta t} \Delta t+M(U) U^{t}\) 其中,上标 $t+\Delta t$ 代表当前时间步,$t$ 代表上一时间步。$M(U)$ 和 $S(U)$ 均为 $U$ 的函数,因此,上式是一个非线性方程组,无法直接求解,需要引入迭代过程。
最常用的处理方法是采用直接迭代法(也称 Picard 法),进行线性化,得到 \(\left(M(U^i)+S(U^i) \Delta t\right) U^{i+1,t+\Delta t}=F^{t+\Delta t} \Delta t+M(U^i) U^{t}\)
其中,上标 $i$ 表示 $t+\Delta t$ 时间步下的迭代步数。上式在每个时间步下都需要反复地迭代计算,直至误差 $\Vert U^{i+1}-U^i\Vert$ 小于某一设定的阈值。直接迭代法可以通过使用松弛因子,大幅提高收敛速度。松弛迭代法已被写入 NFE 算法模板库, 是 FEtch 系统默认的非线性迭代算法。
材料本构模型
非线性问题远比线性问题要复杂。由于非线性参数的函数形式千变万化,所以通常需要针对具体的问题专门地设计程序。对于 FEtch 系统而言,由于脚本文件是完全自主可控的,只要基本框架搭好,后面需要改动的地方极少。
孔隙水压力和相对渗透系数是饱和度的函数,它们之间的关系通常需要根据试验数据进行拟合,目前已有多种通用模型可以描述,如广泛使用的 van Genuchten 模型、Brooks-Corey 模型等。为了后续算例的计算需要,这里考虑以下两种模型。
1.自然指数模型
\[S_{r}(h)=S_{r}^{irr}+\left(1-S_{r}^{irr}\right) e^{\beta h} \tag{3a}\label{eq3a}\] \[K(h) = K_s e^{\beta h} \tag{3b}\label{eq3b}\]这里将持水特征曲线和渗透系数函数假设为压力水头 $h$ 的自然指数形式,主要应用于求解析解。式中,$S_{r}^{irr}$ 为残余饱和度,$\beta$ 为与土性相关的模型参数,$K_s$ 为饱和渗透系数。
2.van Genuchten 模型
\[S_{r}(h)=S_{r}^{irr}+\left(1-S_{r}^{i r r}\right)\left[1+\left(-\alpha_{v} h\right)^{n_{v}}\right]^{-m_{v}} \tag{4a}\label{eq4a}\] \[K(h)=K_s \sqrt{S_{e}}\left[1-\left(1-S_{e}^{1 / m_{v}}\right)^{m_{v}}\right]^{2} \tag{4b}\label{eq4b}\]式中,有效饱和度 $S_{e}=\left(S_{r}-S_{r}^{irr}\right) /\left(1-S_{r}^{irr}\right)$,$\alpha_v$ 、$n_v$ 和 $m_v$是与土性相关的模型参数,通常取 $m_v=1-1/n_v$。
后续程序开发的重点是定义和使用函数 $S_r(h)$ 和 $K(h)$ 。用户需认真体会有限元语言是如何实现的。
脚本编写
一个具体问题的有限元语言表述,通常需要包含 5 种类型的文件:PDE、FBC、MDI、GCN 和 NFE。下面依次给出详细介绍。
PDE 和 FBC 文件
在这个例子中,只有一个物理场,需要给出孔压场对应的 PDE 文件和 FBC 文件。根据有限元语言的语法规则,将方程 $\eqref{eq2}$ 的体积分项写入 PDE 文件如下。
seep.pde | 说明 |
---|---|
defi disp h coor x,z shap %1 %2 gaus %3 mass %1 cap coef hn mate en flg itag eks ea eb ec \ 0.3 0.0 1 1d-11 0.15 1d-3 0.0 stif $cv hn0 = hn $c6 if (hn0.gt.0) hn0 = 0 $c6 select case (itag) $c6 case (1) $c6 dsr = deri1(hn0,ea,eb) $c6 ek = eks*seep1(hn0,eb) $c6 case (2) $c6 ed = 1.0-1.0/ec $c6 dsr = deri2(hn0,ea,eb,ec,ed) $c6 ek = eks*seep2(hn0,ea,eb,ec,ed) $c6 end select $c6 cap = en*dsr dist = +[h/x;h/x]*ek+[h/z;h/z]*ek load = -[h/z]*ek*flg end |
系统段落关键字(信息定义) 定义未知量 定义坐标分量 定义采用的形函数 定义采用的积分方式 定义单元的集中质量矩阵 定义非线性变量,引入上一迭代步的压力水头值 定义用到的材料参数(续行) 参数值 (空行) 系统段落关键字(单元刚度矩阵表达式定义) 定义 hn0,用于传递非线性迭代参数给自定义函数 饱和时 hn0 取 0 调用自定义函数,计算非线性系数 自然指数模型 调用 deri1 函数 调用 seep1 函数 van Genuchten 模型 计算模型参数 调用 deri2 函数 调用 seep2 函数 计算质量矩阵的系数 刚度矩阵,对应式 $\eqref{eq2}$ 左侧第 2 项 (空行) 荷载向量,对应式 $\eqref{eq2}$ 右侧第 1 项 (空行) 系统关键字(文件结束) |
这里将 shap 行和 gaus 行的参数设为待定,参数值 %1、%2 和 %3 将从 MDI 文件中取得。
flg 参数用来标记是否考虑重力场。考虑时 flg 取值为1.0, 否则为 0.0。
文件中调用的自定义函数,由另外创建的 Fortran 源代码文件 swcc.f90 给出,具体文件内容如下。
! swcc.f90
! Exp model
real*8 function sat1(h,sir,beta)
implicit real*8 (a-h,o-z)
sat1=sir+(1.0-sir)*dexp(beta*h)
end
real*8 function deri1(h,sir,beta)
implicit real*8 (a-h,o-z)
deri1 = (1.0-sir)*beta*dexp(beta*h)
end
real*8 function seep1(h,beta)
implicit real*8 (a-h,o-z)
seep1 = dexp(beta*h)
end
! VG model
real*8 function sat2(h,sir,ea,en,em)
implicit real*8 (a-h,o-z)
sat2=sir+(1.0-sir)*(1.0+(-ea*h)**en)**(-em)
end
real*8 function deri2(h,sir,ea,en,em)
implicit real*8 (a-h,o-z)
deri = em*en*ea*(1.0-sir)*(-ea*h)**(en-1)
deri2 = deri*(1.0+(-ea*h)**en)**(-em-1)
end
real*8 function seep2(h,sir,ea,en,em)
implicit real*8 (a-h,o-z)
sr = sat2(h,sir,ea,en,em)
se = (sr-sir)/(1.0-sir)
seep2 = se**0.5*(1.0-(1.0-se**(1.0/em))**em)**2
end
类似 PDE 文件的填写,将方程 $\eqref{eq2}$ 的边界积分项写入 FBC 文件如下。
seep.fbc | 说明 |
---|---|
defi disp h coor x shap %1 %2 gaus %3 mate eq 0.0 stif dist = +[h;h]*0.0 load = +[h]*eq end |
系统段落关键字(信息定义) 定义未知量 定义坐标分量 定义采用的形函数 定义采用的积分方式 定义用到的材料参数和参数值 (空行) 系统段落关键字(单元刚度矩阵表达式定义) 刚度矩阵项,取零矩阵 (空行) 荷载向量项,对应式 $\eqref{eq2}$ 右侧第 2 项 (空行) 系统关键字(文件结束) |
MDI 文件
MDI 文件负责组织 PDE 和 FBC 文件,声明程序具体使用的坐标系统、单元类型和积分方法。这里文件命名为 unsat.mdi,具体内容如下。
unsat.mdi | 说明 |
---|---|
2dxy #a 1 1 h pde seep q4g2 fbc seep l2g2 f90 swcc # |
在二维直角坐标系下求解 a场,1个初值,1个自由度,自由度名称为 h 调用 heat.pde,采用 4 节点四边形单元,2点高斯积分 调用 heat.fbc,采用 2 节点线单元,2点高斯积分 调用 swcc.f90 (文件结束符,可留空) |
注意,同一个场的 PDE 和 FBC 的单元类型和积分方法需要保证匹配,否则会导致计算精度降低,甚至计算失败的情况发生。MDI 文件声明的单元类型和积分方式将以参数的形式传递给 PDE 和 FBC 文件中的的 %1、%2 和 %3。如果后续想要使用其他的单元类型或者积分方法,只需修改 MDI 文件即可。
GCN 文件
GCN 文件给出计算流程信息,系统规定其文件名字要与 MDI 文件一致。非线性抛物方程的计算流程较为复杂,包含两大循环过程,时间步循环和迭代步循环。时间步长可以根据非线性迭代的收敛速度进行动态调整。对应的 GCN 文件和说明如下。
unsat.gcn | 说明 |
---|---|
defi a nparb cc = 1.0 errb = 1.0e-8 itnmax = 30 open(1,file='time.dat') read(1,*) dt,tmax close(1) time = 0.0 it = 1 #startsin a do while (time <= tmax-1e-8) time = time + dt if (time > tmax) then dt = dt-(time-tmax) time = tmax endif iend=0 itn = 1 do while(iend==0) #solvsin a itn = itn+1 enddo it = it+1 if(itn .lt. 5) dt = dt*2.0 enddo |
算法引入段 场 a,采用线性抛物问题的算法 nparb.nfe 空行,开始命令流段 迭代变量赋值 误差阈值 最大迭代次数 从 time.dat 文件读取时间步参数 对时间 time 赋初始值 对时间步数 it 赋初始值 初始化场 a 时间步循环开始 更新 time 越界修正 迭代结束标志赋初值 迭代步数赋初值 迭代步循环开始 求解 a 场 更新 itn 迭代步循环结束 更新 it 变更时间步长 时间步循环结束 |
NFE 文件
GCN 文件使用了 nparb 算法,系统会基于模板文件自动生成以下的 npa.nfe 文件。如果用户有其他需要,可以在此基础上进一步地修改。
nparb.nfe | 说明 |
---|---|
defi stif s mass m load f coef u equation vect u1,u,du read(s,unod) u1,u,du matrix = [s]*dt+[m] forc = [f]*dt+[m]*[u1] solution v vect ue [ue] = [v]-[u] $c6 aa = 0.0 $c6 ab = 0.0 $c6 bb = 0.0 %nod %dof aa = aa+[ue]*[ue] ab = ab+[ue]*[du] bb = bb+[du]*[du] %dof %nod $c6 if (itn.eq.1 .or. cc.le.0) then $c6 cc = 1.0 $c6 else $c6 rab = sqrt(aa)*sqrt(bb) $c6 if (ab.gt.0.707*rab) cc = cc*sqrt(2.0) $c6 if (ab.lt.0.0) cc = cc/sqrt(2.0) $c6 endif $c6 if (cc.gt.1.0) cc = 1.0 $c6 err = aa $c6 ul = 0.0 [u] = [u]+[ue]*cc %nod %dof ul = ul + [u]*[u] %dof %nod $c6 write(*,"('itn,cc,err=',i3,2e12.3)") itn,cc,err $c6 if (err.lt.errb .or. err.lt.errb*ul & $c6 .or. itn.ge.itnmax) then $c6 if (cc .ne. 1.0) then $c6 cc = -1 $c6 else $c6 open(17,file='err.txt',position='append') $c6 if(it.eq.1) rewind(17) $c6 write(17,"(2i3,1e12.3)") it,itn,err $c6 close(17) $c6 iend=1 gidpost("h",time) u(1) [u1]=[u] [ue]=0.0 $c6 endif $c6 endif write(s,unod) u1,u,ue end |
DEFI段 定义刚度矩阵名为 s 定义质量矩阵名为 m 定义载荷向量名为 f (空行) 耦合的场向量 (空行) EQUATION段 定义场向量 读入上一时间步、上一迭代步的结果 方程组左端矩阵,对应式 $\eqref{eq4}$ 左侧 方程组右端向量,对应式 $\eqref{eq4}$ 右侧 (空行) SOLUTION段 定义求解的场向量 计算当前迭代步增量 ue 循环所有节点上的所有自由度 计算 ue 的模的平方和 aa 计算 ue 与 du 的广义内积 ab 计算 du 的模的平方和 bb 依据当前迭代步增量 ue与 上一迭代步增量 du 之间的夹角, 来调整松弛因子 当夹角为锐角时,适当放大 cc 当夹角为钝角时,则适当缩小 cc 用松弛因子调整计算结果 收敛判断 继续迭代标记,保证收敛时的 cc = 1 记录每个时间步的迭代收敛情况 迭代结束标志更新 将计算结果写入 GiD 后处理文件 临时存储当前的结果,供下一迭代步读取 (空行) 结束标记 |
算例1
一维均质土的非饱和渗流
考虑无限长的均质土层,设其厚度为 $L = 1.0\ \mathrm{m}$,底部对应地下水位($ h=0$),顶部为入渗边界,以入渗流量为 0 时的稳定状态为初始状态,时间 $t>0$ 时入渗流量变为 $q_A$。持水特征曲线和渗透系数函数采用自然指数模型 $\eqref{eq3a}$ 和 $\eqref{eq3b}$ 来描述。模拟过程中的具体参数取值如下表所示。
参数 | $n$ | $K_s/(m/h)$ | $\beta/m^{-1}$ | $S^{irr}_r$ | $q_A/(m/h)$ |
---|---|---|---|---|---|
取值 | $0.40$ | $3.60\times10^{-3}$ | $10.00$ | $0.15$ | $3.60\times10^{-3}$ |
前处理
建模
进入 GiD 前处理,建立一个 $0.1\ \mathrm{m}\times1.0\ \mathrm{m}$ 的长方形,它的两个对角的角点坐标分别为(0, 0)和(0.1, 1)。
填写材料参数文件
系统自动生成了unsat.mat 文件,用于设置材料参数。参数初始值全部为 PDE 和 FBC 文件给出的默认值。可根据具体问题进行修改。对于本算例,修改完成后的文件内容如下。
unsat.mat | 说明 |
---|---|
1 8 aeq4g2 num en flg itag eks ea eb ec 1 0.4 1.0 1 3.6d-3 0.15 10.0 0.0 # 1 2 all2g2 num ep 1 3.6d-3 # |
4节点四边形面单元 材料参数 参数值 分隔符 2节点线形边界单元 材料参数 参数值 分隔符 |
填写时间步长文件
由 unsat.gcn 文件可知,用户自定义了时间步长文件 time.dat,给出时间步长和终止时间。mat 文件中与时间相关的参数以小时 $\mathrm{h}$ 为单位, time.dat 与其保持一致。文件内容如下:
0.001 32
可知, 初始时间步长为 $0.01\ \mathrm{h}$,结束时间为 $32\ \mathrm{h}$。
赋单元材料
赋初始条件
注意,初始条件与几何模型的位置是直接相关的。这里的长方形的底边(同时也是水位线位置)在 x 轴上,因此初始压力水头按 -y 来分布。如果模型位置发生变化,初始压力水头要做相应的换算后,再进行施加。
施加第一类边界条件
其中:
u-I 为边界类型,-1 表示约束,1 表示自由
u-D 为相应的约束值或施加节点流量
施加第二类边界条件
第二类边界条件以线单元的形式施加
网格剖分
根据所开发程序的计算要求,网格剖分采用 4 节点等参单元。为了在保证计算精度的同时尽量减少网格数量,从下到上按 1.1:1 的比例进行网格局部加密,共使用了 40 个单元,82 个节点。
计算结果
通过自动改变时间步长,变化范围从 $0.001\ \mathrm{h}$ 到 $0.512\ \mathrm{h}$,总共使用了 183 个时间步。对计算结果稍加整理,效果如下。
压力水头的演化过程
不同时刻压力水头的空间分布
不同高度处压力水头随时间的变化
可以看到与解析解符合得很好。同时无论在时间和空间域内,模拟结果都没有震荡现象发生,充分证明了算法和程序的有效性。
算例2
二维砂槽的非饱和渗流
Vauclin 等进行的二维室内渗流试验也是检验算法的典型算例。流动区域为 $6.00\ \mathrm{m}\times2.00\ \mathrm{m}$ 的厚 $0.05\ \mathrm{m}$ 的砂土,底部为不透水边界,两侧为自由排水边界。土体为颗粒分布很规则的河砂。初始水位为 $0.65\ \mathrm{m}$,试验开始后在土槽顶部中间 $1.00\ \mathrm{m}$ 的范围均匀施加 $0.148\ \mathrm{m/h}$ 的降雨强度,共 $8\ \mathrm{h}$。试验中对流动域内自由水面位置的变化等数据进行了测量。该类砂土的孔隙水压力水头和渗透系数与饱和度之间的关系由 van Genuchten 模型 $\eqref{eq4a}$ 和 $\eqref{eq4b}$ 来描述。模拟过程中的具体参数取值如下表所示。根据对称性,从中线截取区域的右半部分进行计算。
参数 | $n$ | $K_s/(m/h)$ | $\alpha_v/m$ | $n_v$ | $S^{irr}_r$ |
---|---|---|---|---|---|
取值 | $0.30$ | $3.50\times10^{-1}$ | $3.30$ | $4.10$ | $0.033$ |
前处理
填写材料参数文件
对于本算例,材料参数文件 unsat.mat 的内容如下。
unsat.mat | 说明 |
---|---|
1 8 aeq4g2 num en flg itag eks ea eb ec 1 0.3 1.0 2 3.5d-1 3.3d-2 3.3 4.1 # 1 2 all2g2 num ep 1 0.148 # |
4节点四边形面单元 材料参数 参数值 分隔符 2节点线形边界单元 材料参数 参数值 分隔符 |
填写时间步长文件
由 unsat.gcn 文件可知,用户自定义了时间步长文件 time.dat,给出时间步长和终止时间。mat 文件中与时间相关的参数以小时 $\mathrm{h}$ 为单位, time.dat 与其保持一致。文件内容如下:
0.001 8
可知, 初始时间步长为 $0.01\ \mathrm{h}$,结束时间为 $8\ \mathrm{h}$。
赋单元材料
赋初始条件
施加第一类边界条件
其中:
u-I 为边界类型,-1 表示约束,1 表示自由
u-D 为相应的约束值或施加节点流量
施加第二类边界条件
第二类边界条件以线单元的形式施加
网格剖分
剖分为 750 个双线性四边形等参单元,共 806 个结点。
计算结果
通过自动改变时间步长,变化范围从 $0.001\ \mathrm{h}$ 到 $0.256\ \mathrm{h}$,总共使用了 202 个时间步。对计算结果稍加整理,效果如下。
压力水头的演化过程
部分等值线的演化过程
不同时刻地下水位位置模拟结果与试验结果对比
通过不同时刻地下水位位置($h =0$ 处)模拟结果与试验结果的对比,可以看出两者吻合较好。
不同观察点的压力水头随时间的变化
选取入渗前沿的点 A (0, 2.0)、B (0,1.6)、C (0, 1.2)、D (0.5, 1.6)、E (0.5, 1.2) 和 F (1.0,1.2) 作为观察点,压力水头随时间变化的情况如下图所示。
可以看到随着入渗的进行,孔隙水压力逐渐上升,向正孔压发展,且整个变化过程是平滑和稳定的,进一步证明了算法和程序的有效性。