1 * <lisp>(setq Title "elsa开发手册")</lisp>
4 * 1 空间离散后为ODE,采用(伪)unsteady时间积分求解器,进入(伪)时间循环
16 - elsA kernel 采用C++的OOP设计,只有很费cpu时间的计算采用Fortran,并且在不影响OO设计的情况下
26 - Python脚本,复杂仿真的首选,用法在elsA用户手册上
27 elsA可以被看为一个标准的Python模块,elsA.py . 将c++代码转换的Python 工具为swig.
30 - 采用MPI库,使用coarse-grained并行策略.
36 - Opt模块实现了离散Adjoint方法.用来嵌入气动外形自动优化过程.
45 - 构建方程组:计算空间离散项(flux,source terms)和边界条件
49 elsA kernel包括400个class,分配到26个modules.这些模块又归于6个layer,上层只依赖下层,单向职责.
53 - Space Discretization
58 - Fld: 数据存储类,封装了存储任何计算数据所需要的动态数据管理,提供了monitoring 方法,优化了array-like的语义(类似fortran 90语法),并提供于fortran的交互方法.Fld提供最有效率的cpu和内存.STL的容器没法与其效率相比.
59 - Pcm: 并行实现,封装了消息传递界面(目前只有MPI)
61 *** 9.2.2 Geometry Layer
62 - Blk: 定义了block概念,block为一个定义了网格的离散了的物理区域,包括边界条件和初始数据.考虑了grid motion,ALE,chimera和HMR.
63 - Geo: 定义了抽象的计算网格,提供了所有的FV需要的geometry要素.
64 - Metris: cell的体积,surface of cell interface
65 - Topological relations: cells, interfaces和nodes分别的关系.ghost cells 减少了计算循环的indirections.提高了cpu效率
66 - Dtw: 保存说有的distance和边界层积分厚度
67 - Mask: 定义用在Chimera 技术里的概念
68 - Join: 处理multi-block计算.可以为1-1连接,1-n连接或者mismatched.
70 *** 9.2.3 Physical model层
71 - Eos: 计算p,t,层流年星系数等变量
76 - Fxc: convective fluxes
77 - Fxd: diffusive fluxes
81 *** 9.2.5 Solve layer, kernel最复杂的部分,
82 - Rhs: 计算方程组的Right Hand side
83 - Lhs: 汇总implicit方法: 每种方法都要从线性化方程组中构建和转折矩阵
86 *** 9.2.6 Factory (elsA 顶层layer)
87 - 负责动态创建说有的kernel对象,从用户的输入构建说有的相应对象
92 Fields是elsA最基本的操作对象,作为real,integer,boolean的容器.用后缀表示版本,F代表Float,I,B.
93 - FldArray: 保存数值,没有任何的位置信息
94 - FldField: 保存在grid上的数值信息.有FldNode,FldCell,FldInt三种.可以用如下详细指定
96 typedef FldFieldF FldCellF
101 - 一个为节点的个数 0 ~ _size-1
102 - 一个为节点内保存的变量个数 1 ~ _nfld
104 ***** 10.1.2.1. Construction of a field which stores the unknowns of the CFD problem (ro, rou, rov, row, roE):
107 FldCellF wCons(ncell, nfld);
108 Construction of a field which stores fluxes:
109 FldIntF flux(3*ncell, nfld);
111 ***** 10.1.2.2. Construction of a field which stores mesh coordinates:
112 FldNodeF x(ncell, 3);
113 FldNodeF y(ncell, 3);
114 FldNodeF z(ncell, 3);
116 ***** 10.1.2.3. FldArray or FldField can be used to store values without geometric links, such as:
117 FldArrayF TurKO::getModConst() const
119 FldArrayF modConst (7);
120 modConst[0] = _kappa;
121 modConst[1] = _sigma1;
122 modConst[2] = _sigmae1;
123 modConst[3] = _beta1;
124 modConst[4] = _wsig1;
125 modConst[5] = _betae;
130 ***** 10.1.2.4. To access individual elements, a syntax similar to Fortran is used:
132 f(3,2)=3.14159; // assigns pi to the fourth element of component 2
141 *** 10.1.4 传递field数据给Fortran
142 传递数据给Fortran77函数.通过给FldField动态分配的内存地址
143 **** 10.1.4.1 FldArray 内部结构
144 FldArray在一个连续的内存空间存储数据,为动态分配的.我们可以认为它是c 指针管理内存的wrapper._data指向这块内存.这种1D的布局和传统的Fortran和c代码一致.
147 //返回第fld物理变量的第l个节点数据,按_nfld存
149 FldArrayF::operator()(E_Int l, E_Int fld) const
151 return (_data[l + (fld-1)*_size]);
154 //We would have the transpose (or swapped) implementation:
157 FldArrayF::operator()(E_Int l, E_Int fld) const
159 return (_data[fld-1 + l*_nfld]);
171 denconvec_(const E_Int& ncell, const E_Int& neqtot, const E_Int& neq,
172 const E_Int& ro, const E_Int& rou, const E_Int& roe,
173 const E_Int& rog, const E_Int& roug, const E_Int& roeg,
174 const E_Float* consvar, const E_Float* press,
175 E_Float* fdx, E_Float* fdy, E_Float* fdz);
182 denconvec_(ncell, neqTot, nbEqMoyComp,
183 rho, mom, ene, rhoG, momG, eneG,
184 wCons.begin(), press.begin(),
185 fdx.begin(), fdy.begin(), fdz.begin() );
188 - 我们使用第一个index先增长方式,即c方式,按行存储,先o行,再1行
189 <source lang="shell">
190 fdX( 0,1), fdX(0,2), fdX(0,3),..., fdX( 0,neq),
192 fdX(ncell-1,1), ..., fdX(ncell-1,neq)
195 <source lang="shell">
196 fdX(0, 1), fdX(1,1),fdX(2,1),..., fdX(ncell-1, 1),
198 fdX(0,neq),..., fdX(ncell-1,neq)
202 <source lang="fortran">
203 SUBROUTINE denconvec(ncell, neqtot, neq,
210 INTEGER_E ncell, neqtot, neq
211 REAL_E w(0:ncell-1,neqtot) ! Conservative Variables
212 REAL_E p(0:ncell-1) ! Pressure
214 REAL_E fdx(0:ncell-1,neq) ! Convective Flux X-Component
215 REAL_E fdy(0:ncell-1,neq) ! Convective Flux Y-Component
216 REAL_E fdz(0:ncell-1,neq) ! Convective Flux Z-Component
218 DO icell = 0, ncell-1
219 roi = ONE / w(icell,rog)
220 fdx(icell,ro) = w(icell,roug)
221 fdy(icell,ro) = w(icell,rovg)
222 fdz(icell,ro) = w(icell,rowg)
227 GeoGrid在kernel中广泛使用,因为很多的CFD类需要一个指向GeoGrid的指针.GeoGrid为GeoGridMetrics和GeoConnect的组合.他们负责
228 - metrics, : GeoGridMetrics
229 - index counting 和position(connectivity) : GeoConnect
231 **** 10.2.1 Ghost 几何元素
233 - GHOST_I1 and GHOST_I2 in the "I" direction,
234 - GHOST_J1 and GHOST_J2 in the "J" direction,
235 - GHOST_K1 and GHOST_K2 in the "K" direction.
237 ***** 10.2.1.1 Ghost cell numbering
238 • GHOST_I1 ghost cells in IMIN(代表i的最小index), GHOST_I2 ghost cells in IMAX(代表i的最大index),
239 • GHOST_J1 ghost cells in JMIN, GHOST_J2 ghost cells in JMAX,
240 • GHOST_K1 ghost cells in KMIN, GHOST_K2 ghost cells in KMAX.
242 ***** 10.2.1.2 Ghost interface numbering
243 • GHOST_I1 ghost interfaces in IMIN, GHOST_I2-1 ghost interface in IMAX,
244 • GHOST_J1 ghost interfaces in JMIN, GHOST_J2-1 ghost interface in JMAX,
245 • GHOST_K1 ghost interfaces in KMIN, GHOST_K2-1 ghost interface in KMAX.
247 ***** 10.2.1.3 Ghost node (mesh points) numbering
248 • GHOST_I1 ghost nodes in IMIN, GHOST_I2-1 ghost node in IMAX,
249 • GHOST_J1 ghost nodes in JMIN, GHOST_J2-1 ghost node in JMAX,
250 • GHOST_K1 ghost nodes in KMIN, GHOST_K2-1 ghost node in KMAX.
252 ***** 10.2.1.4 Ghost defaultvalues
253 The default values are:
254 GHOST_I1 = 2; GHOST_I2 = 2;
255 GHOST_J1 = 2; GHOST_J2 = 2;
256 GHOST_K1 = 2; GHOST_K2 = 2;
258 ***** 10.2.1.5 cell/interface/node的分辨
259 上述定义的好处就是我们在cell,interface和node的index之间关系简化,使得我们在他们中循环很方便.我们在i,j,k方向上的cells,nodes和interface数目完全相同.
260 <source lang="fortran">
261 DO n=n0cell, nfcell ! loop on cells
262 ni1 = n ! "i" interface (left)
263 nj1 = n + ncell ! "j" interface (down),ncell是所有的cell个数,因为先存i,后存j,再存k
264 nk1 = n + 2*ncell ! "k" interface (back)
266 ni2 = n + inccell(1,0,0) ! "i" interface (right
267 nj2 = n + ncell + inccell(0,1,0) ! "j" interface (up)
268 nk2 = n + 2*ncell + inccell(0,0,1) ! "k" interface (front)
272 - 所以所有的interfaces的数目为cells的3倍.
275 GeoConnect::getNbCell() const
277 return ((_im - 1 + GHOST_I1 + GHOST_I2)*
278 (_jm - 1 + GHOST_J1 + GHOST_J2)*
279 (_km - 1 + GHOST_K1 + GHOST_K2));
282 GeoConnect::getNbInti() const
292 - 2 计算总应力张量(viscosity tensor+Reynolds tensor)
298 - 基于算术方程: 计算渦黏性系数只需要守恒变量和壁面距离
299 - 基于输运方程: 需要积分一个方程组.要计算source term,turbulent diffusive flux coefficients
302 Operator的类主要为空间离散.每一个operator都必须计算一个定义在特殊几何体(cell或者interface)上的Fld-FieldF对象.
304 - Fxc: 对流fluxes(中心差分,迎风格式,人工耗散)
305 - Fxd: 扩散fluxes(层流,平均流,湍流)
306 - Sou: 源项(湍流封闭关系,moving frame,dual time stepping method)
310 OperBase为抽象类.比较重要的属性:
311 - _geoEntity: 计算几何体的类型
312 - _borderDepth: 边界区域的宽度.需要特殊计算的区域
313 - _elemSysOper: 控制方程的id
314 - EosSysEq* _sysEq: 描述目前的问题
315 - EosIdealGas* _eos: 目前的状态方程
316 - GeoGridBase* _grid: 目前的计算网格
319 virtual void prepare(const EosSysEq&, EosElemSysType,EosIdealGas* eos, const GeoGridBase* grid);
325 - Utility 用于附属的计算,OperTerm调用这些类,只实现了两个,OperGrad和OperGradInt.
329 - OperGrad 用于在cell center计算梯度
330 - OperGradInt 用于在interface center计算梯度
335 // compute the gradient of the conservative variables
336 void compute( FldCellF& fldOut,
337 const list<BndPhys*>& listBnd,
338 const list<JoinBase*>& listJoin,
339 AuxField identOfField = MISC);
341 // compute the gradient of non conservative variables (?)
342 virtual void compute( FldCellF& fldOut,
343 const list<BndPhys*>& listBnd,
344 const list<JoinBase*>& listJoin,
345 const FldCellF& fldIn,
346 AuxField identOfField);
348 梯度和flux计算在所有的cell和interfaces上使用相同的数值算法计算.但是标准的计算公式会在border区域给出错误的结果.所以operator对象需要和boundary对象协作.
349 - 策略1: 分两步计算,先在所有的cell或interfaces进行计算,然后再在border上修正,OperGrad使用这个策略
350 - 策略2: 一步计算:通过boundary 将Ghost cell填充在border区域周围,然后用标准算法就会得到正确的结果.OperGradInt使用这个策略.
354 1. 计算所有需要的附属场值(通过守恒变量)
355 2. 计算fluxes和source term(使用第一步计算的数值)
357 OperTerm::_setOfIdent为list<AuxField>类型,用于识别什么样的附属计算需要进行.computeAllField调用computeFiled()函数计算所有的注册过的附属场.
359 virtual void computeAllField(const list<BndPhys*>* listBnd = E_NULLPTR,
360 const list<JoinBase*>* listJoin = E_NULLPTR);
362 virtual void computeField(AuxField identOfField,
363 const list<BndPhys*>* listBnd = E_NULLPTR,
364 const list<JoinBase*>* listJoin = E_NULLPTR);
367 Flus和source在这一个阶段还没有计算,下一节介绍.
370 继承自OperTerm,使用上面介绍的策略1实现了主要的compute()方法.
373 void OperFlux::compute( FldIntF& fldOut,
374 const list<BndPhys*>& listBnd,
375 const list<JoinBase*>* listJoin )
378 computeAllBorders(...);
383 定义了flux类最重要的抽象方法compFlx.知道了cell center上的守恒变量,这个方法提供了interfaces上的flux.
386 virtual void compFlux(const FldCellF& fldIn,FldIntF& fldOut) = 0;
389 OperFlux还定义了另外一个重要的方法:computeAllBorders(),这个方法用于计算边界区域的flux,并且考虑边界条件.所有的物理边界,使用下述的思想:
390 1. 定义在边界interfaces上的vector wb1的计算代理给了BndPhys* 对象,它负责处理边界
391 2. wb1 然后被用来修正边界interface的flux计算.具体的实现由特定的flux类决定.
394 OperSou是source term的抽象类.这个类继承自OperTerm类.