1 引言
这个系列笔记根据2020年6月4日Itasca公司发布的Webinar视频改写和扩展而成,主要介绍了FLAC3D 7.0的新特性。我用笔记的型式记录下这个视频所讲的内容,同时穿插了我自己的观点和部分功能的使用方法,仅作为学术研究参考使用。因为这是个公开展示的视频,不是内部培训资料,没有版权保护的限制,所以这个笔记断续地插入了视频中的一些截图。这个系列笔记的第一部分《FLAC3D 7.0 新特性简介(P1)---速度提升》,介绍了FLAC3D 7.0在速度方面的提升性能。由于篇幅和时间所限,这个部分还没有写完,今天接着上一篇继续介绍速度提升方面的新特性。
2. 速度提升
FLAC3D声称,由于使用了多栈处理技术和改进的算法,导致FLAC3D的运行速度大幅提升。在第一部分(P1)中介绍了力学(Mechanical),流体(Fluid Flow),热(Thermal),边界条件(Boundary Conditions)四个方面的速度提升性能。下面继续介绍在其它方面的速度提升。
2.1 Attach算法改进(Attach)
FLAC3D 7.0版本改进了attach logic的算法,在下面图示的这个测试中,7.0版本的运行速度比6.0版本快1.8倍。当进行数值模拟时,为了节省计算时间和提高计算进度,通常需要对开挖区域周围的网格设置的密一些,在远离开挖边界的地方网格设置的稀疏一些。当大尺寸的单元与小尺寸的单元相互衔接的时候需要用到attach logic。此外,断层的模拟(下图中红色的线)也需要划分成非常小的单元,特别是在早期的数值模拟时期,无论是FLAC3D还是其它有限元软件都必须这样做。另一种情形是通过子网格(subgrid)在模型中产生不同形状的区域,例如一个大坝的子网格放置在一个地基子网格上面, 然后通过连接面(attached faces)把分离的子网格的网格面连接在一起,不同单元密度的子网格连接在一起。事实上,FLAC3D 7.0之前的版本,已经在attach方面做了大量工作,以后将会单独讨论网格之间的连接。
zone attach by-face
zone validate
2.2 界面算法改进(Interfaces)
现代数值模拟技术模拟断层或节理的另一种方法是使用interface, 界面表示一种物理上的不连续,例如断层,接触面,或者两种不同材料的界面。使用interface模拟大的节理或断层比划分细小网格的方法更有效。计算过程中子网格能够通过interface发生滑动或分离。FLAC3D 7.0 使用了多栈技术改进了interface的算法,从而提高了运算速度。
2.3 基于多线程的FISH(Multi-threaded FISH-Splittling)
原来的FISH不是多线程运行的,只使用一个CPU来循环任何list(单元zone,网格点gridpoint等),FLAC3D 7.0中的FISH语言引入了多栈技术。具体地说,通过任何list的循环可以把它分配到计算机上所有可得到的处理器来并行运算。比如我使用的计算机CPU是12核的, 对于大的模型来说,使用新的算**把这个循环split成不同的块,在这12个CPU上分配运行,因而增加了整体的运行速度。
如上图所示的例子,新的方法使用了如下格式:
[zone.prop(::zone.list, 'shear') *=0.5]
这行代码与上面使用loop循环语句的作用是相同的,意思是对zone.list内的每一个单元的‘shear'值在原来值的基础上乘以0.5。这行代码中出现了两个操作符,一个是"::", 另一个是"*=" 。这两个符号均来自于Python语言。有时我想,将来FLAC3D的版本会不会彻底不用FISH, FISH的主要作用是从链表中提取数据,因而从理论上来说FISH能做的事情Python也完全能做,不过这个太遥远了,暂时不考虑。两个并列冒号的操作符"::"在Python语言中称为“切片”,前一个冒号表示“开始”,后一个冒号表示“结尾”,在Python编程中,我在两个应用方面使用了这个功能,一个是文档的二次处理,比如要把某个字符前面或后面的字符串删除;另一个是对于较长的文档,需要只显示部分字符。比如下面这个代码,只让它输出整个文档的前500个字符。
output.write(each['c1text'][:500] '\n\n')
下面这段代码显示了"::"的实际功能。在一个range(10),也就是[0,9]的值域内,从开始值0到结束值9以步长2取值,这段代码的运行结果为0, 2, 4, 6, 8
x = range(10)[::2]
for each in x:
print(each)
"*= 0.5"是Python的乘法运算符,意思是把原来的值乘以0.5然后赋值给新的变量。
下面用一个例子演示这个新功能的用法。在这个例子中,我首先给出了模型的材料参数值,包括剪切模量“shear”, 接着使用旧的FISH语言改变模型的剪切模量值,最后使用新的FISH语言再次改变模型的剪切模量值。我把整个过程封装在Python中,代码如下所示。
# Testing FISH new function
# Created by GeotechWu
# 6/06/2020
import itasca as it
it.command ("python-reset-state false")
it.command("""
model new
model large-strain off
zone create brick size 10 10 10
zone cmodel assign mohr-coulomb
zone property bulk 65000 shear 30000 density 2.0
zone property cohesion 10 friction 34 tension 1.0
""")
z = it.zone.find(1)
print( '模型初始的剪切模量:' str(z.props()['shear']))
# 使用旧的FISH编程
it.command("""
define old_way
loop foreach zp zone.list
zone.prop(zp,'shear') = zone.prop(zp,'shear')*0.5
end_loop
end
[old_way]
"""
print('模型第一次改变剪切模量:' str(z.props()['shear']))
# 使用新的FISH编程
it.command("""
[zone.prop(::zone.list, 'shear') *=0.5]
""")
print('模型第二次改变剪切模量:' str(z.props()['shear']))
上述代码的运行结果就象我们期望的那样:
模型初始的剪切模量:30000.0
模型第一次改变剪切模量:15000.0
模型第二次改变剪切模量:7500.0
2.4 多线程FISH运算器(Multi-threaded FISH - Operators)
it.command("""
fish operator labeldata(data,xmin)
local x = data.scalar.pos(data)->x
if x > xmin
data.scalar.group(data) = 'right_side'
return true
endif
data.scalar.group(data) = 'left_side'
return false
end
[labeldata(::data.scalar.list,4.0)
""")
上一节使用了[zone.prop(::zone.list, 'shear') *=0.5] 这样的格式,zone.prop是FLAC3D内置的函数。新的改进引入了命令fish operator,用户可以自定义一个函数,然后这个函数就可以使用多线程的优点,从概念上讲没有什么好解释的。FISH的这个功能也来源于Python。Python语言有一个模块就叫operator。在Python中,operator模块输出一系列对应Python内部操作符的函数。例如:operator.add(x, y)等价于表达式x y。FLAC3D借用了Python的operator概念。
import operator
a = operator.add(1, 3)
print(a)
# 3
顺便说一下上面代码中local x = data.scalar.pos(data)->x的“->”这个符号,这也是从Python借用过来的,它是一个返回值注解的符号,常常出现在python函数定义的函数名后面,为函数添加元数据,描述函数的返回类型。例如:
def add(x, y) -> int:
return x y
这里,元数据表明了函数的返回值为int类型。这样做可以使用预期的类型来注释参数,然后在函数返回值验证时检验参数的类型或者将其强制转换成预期的类型。
最后演示一个地层冻结的例子,在这个例子中,使用了fish operator命令进行多线程计算,从而提高了计算速度。
program call 'freeze_zone'
fish operator ground_freezing(zone)
if zone.isgroup(zone,'frozen','state') then return 0
if zone.temp(zone) > 0.0 then return 0
freeze_zone(zone)
end
fish operator freeze_zone(zone)
local porosity = zone.fluid.prop(zone,'porosity') ; Note: Assuming fully saturated
local expansion = porosity * 0.09 * 1.0; Porosity * water expansion * saturation
local bulk = zone.prop(zone,'bulk')
local stress_inc = bulk * expansion ; Amount to increment stress
local bulk_inc = (8.96/2.16) * porosity ; Ratio of ice/water bulk * porosity
zone.prop(zone,'bulk') = bulk bulk_inc
zone.stress.xx(zone) -= stress_inc ; Compressive negative!
zone.stress.yy(zone) -= stress_inc
zone.stress.zz(zone) -= stress_inc
zone.group(zone,'state') = 'frozen'
end
4. 结束语
根据Itasca发布的最新视频,改编和扩展介绍了FLAC3D 7.0的新特性。本文作为本系列的第二部分(P2),主要介绍了7.0版本在attach, interface以及FISH算法上的改进,这些改进显著提升了程序的运行速度。至此,FLAC3D 7.0的速度提升性能介绍完毕,下个笔记将介绍FLAC3D 7.0版本新引入的本构模型。(19:11)
本文相关文档: