Small Box FFT学习笔记(三):网格的数据结构

本文是SBFFT学习笔记的第三篇,这一篇中主要介绍在这一算法中用到的各种网格所使用的数据结构,以及与不同网格数据相互转换的子程序。

根据本系列第一篇中的相关理论,在计算中需要用到四种网格,全局的稠密网格(DGBX)、小块的稠密网格(DSBX)、全局的稀疏网格(SGBX)和小块的稀疏网格(SSBX)。在具体代码实现中定义了一个BOX数据类型(BOX.f90文件中的SetupBOX模块),来实现对于这四种网格的封装,具体的数据结构定义如下:

type :: BOX
	! 基本信息 
	character(len=4) 					id 					! 标记四种类型的网格,可能的值为"DGBX"、"DSBX"、"SGBX"、"SSBX"
	integer 							level 				! 标记是否使用:0表示未使用,1表示已初始化
	integer 							indbox 				! 当前小块的一维编号,用于 MPI_SPLIT
	integer, dimension( 3 ) 			indbox3d 			! 当前小块的在各个方向上的序号
	integer, dimension( 3 ) 			nbox 				! 每个方向上小块的数目
	integer, dimension( 3 ) 			buff 				! 各方向上缓冲区的格点数
	integer 							nproc 				! 当前小块使用的核数
	integer 							nproc_c 			! 当前小块核心区域使用的核数
	integer 							nptot 				! 计算使用的总核数
	! 核心区和缓冲区
	integer 							n1, n2, n3 			! 当前核使用的各方向格点数目
	integer 							n123 				! n123 = n1 * n2 * n3
	integer 							n1off, n2off, n3off ! 各方向上的位移值
	integer 							m1, m2, m3 			! 各方向上的总格点数
	! 倒空间 
	integer 							k1, k2, k3 			! 当前核使用的倒空间网格各方向格点数
	integer 							k123= 				! k123 = k1 * k2 * k3
	integer 							k3off 				! Gz方向上的位置
	! 核心区域
	integer 							c1, c2, c3 			! 当前核使用的各方向格点数目(核心区域)
	integer 							c123=0 				! c123 = c1 * c2 * c3
	integer 							c10, c11 			! 当前核的网格中核心区域格点在x方向的起始和结束位置
	integer 							c20, c21 			! 当前核的网格中核心区域格点在y方向的起始和结束位置
	integer 							c30, c31 			! 当前核的网格中核心区域格点在整个块中的起始和结束位置
	integer 							b1, b2, b3			! 当前小块中核心区域各方向格点数目
	integer 							b123 				! 核心区的总格点数
	integer 							b1off, b2off 		! 当前小块中核心区域在网格中下x,y方向的位置
	integer 							b3off 				! 当前小块中核心区域在网格中的位置
	! 稀疏度
	integer 							sparX, sparY, sparZ ! 各个方向的稀疏度,1表示是稠密网格
	! MPI
	integer 							MPI_INTRA_WORLD 	! 当前小块使用的MPI网络
	integer 							rankBox 			! 当前核在当前小块MPI网络中的编号
	integer 							rankBox0, rankBox1	! 核心区域使用核的编号的下界和上界
	integer 							MPI_CORE_WORLD 		! 所有计算核心区域的有核构成的MPI网络
	integer 							rankCore 			! 在上一网络中的编号
	type(FFT_CONFIG) 					FFT_STATE 			! FFT相关信息
	logical 							active_proc 		! 只有在第一个小块使用的核被标记为active
	logical 							buffer_proc 		! 为.TRUE.表示当前核处理缓冲区
	logical 							core_proc 			! 为.TRUE.表示当前核处理核心区
	! 电荷密度
	real*8, dimension( *, *, * ) 		rhoC 				! 核心区域的电荷密度 
	real*8, dimension( *, *, * ) 		qTable 				! q向量的长度
	real*8, dimension( *, *, * , * ) 	qVectors 			! 实际的q向量
	logical, dimension( *, * , * ) 		qMask 				! mask函数
	! 块的几何参数 
	real*8, dimension( 3, 3 ) 			cellReal 			! 当前块的格矢,以Bohr为单位
	real*8, dimension( 3, 3 ) 			cellRecip 			! 当前块的倒格矢
	real*8, dimension( 3 ) 				length 				! 当前块三个格矢的长度
	real*8, dimension( 3 ) 				ecut				! 各方向的截断能
end type BOX

在程序中使用了四个BOX类型的变量DGBX、DSBX、SGBX和SSBX,分别对应计算使用的四个网格。程序中首先使用Inputs中的ReadOptions子程序(Inputs.f90文件)读取输入参数后对这几个变量的网格大小等参数进行赋值(相关文件1244-1319),再调用SetupBOX模块中InitBOX子程序对这些变量进行初始化

call InitBOX(box, m1G, m2G, m3G, cellRealIn)

这里bx是需要初始化的BOX类型变量,m1G、m2G、m3G三个整数表示x、y、z三个方向全局网格长度,cellRealIn对应bx%cellReal表示格矢。关于具体的调用,可以参考SYS模块中SetupAllBoxes子程序(System.f90文件中)。

由于计算过程中涉及到涉及到不同类型网格的数据转换,在程序中用到了四种实空间中网格转换的子程序:

  • DGBX_2_DSBX
  • DSBX_2_DGBX
  • DSBX_2_SGBX
  • SGBX_2_SSBX

这些子程序对应计算流程中的赋值和拼合操作,只涉及到数据的传递(使用MPI_ISend和MPI_IRecv),因此没有从稀疏网格到稠密网格转换的子程序(对应插值操作)。这些子程序的调用方式是类似的,以DGBX_2_DSBX为例,其位于DataExchange_DG2DS.f90的同名模块中,其定义为:

subroutine DGBX_2_DSBX(
	real*8, dimension( *, *, * ) 	array_DG,
	real*8, dimension( *, *, * ) 	array_DS
	)

此外在DataExchange_SS2DS.f90文件的同名模块中定义的SSBX_2_DSBX子程序,对应的是在倒空间而非实空间中的数据转换,这里从稀疏网格到稠密网格的变换只是在高频部分加上0,其定义为:

subroutine SSBX_2_DSBX(
	complex*16, dimension( *, *, * ) 	array_SS,
	complex*16, dimension( *, *, * ) 	array_DS
	)

这些子程序的实现细节比较琐碎,还需要参考其源代码。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注