compressibleFoam &求解器编写思路探讨
- 
							
							
							
							
							
							
各位: 
 最近在研究这个求解器:
 compressibleFoam,发现里面的求解思路和我之前采用fortran语言是一样的。思路就是按边来循环,分别对internalFace和boundaryFace进行处理,求得单元交界面上的通量。
 控制方程如下
  
 其中一些量如下
  
  
  
 下面这个是求内部面无粘通量的函数/// Loop over internal faces and get face flux from L and R cell center label leftCell , rightCell; forAll( mesh.owner() , iface ) { /// Get the left and right cell index leftCell = mesh.owner()[iface]; rightCell = mesh.neighbour()[iface]; /// Approximate Riemann solver at interface scalar lambda = (*fluxSolver)( &rho[leftCell] , &U[leftCell] , &p[leftCell] , /// Left &rho[rightCell] , &U[rightCell] , &p[rightCell] , /// Right &massFlux[iface] , &momFlux[iface] , &energyFlux[iface] , &nf[iface] ); /// Multiply with face area to get face flux massFlux[iface] *= mesh.magSf()[iface]; momFlux[iface] *= mesh.magSf()[iface]; energyFlux[iface] *= mesh.magSf()[iface]; localDt[ leftCell ] += lambda * mesh.magSf()[iface]; localDt[ rightCell ] += lambda * mesh.magSf()[iface]; }下面这个是求物面边界条件的边界面上的无粘通量的函数 \*---------------------------------------------------------------------------*/ ///////////////////////////////////////////////////////////////////////////////// /// Remember BC's for Gas Dynamics solvers /// are based on characteristics and cannot be applied /// to individual variables. Rather it should be applied /// to the state vector as a whole. OpenFOAM framework /// does not allow us to do this without breaking the /// convention. ///////////////////////////////////////////////////////////////////////////////// /// Loop over boundary patches and determine the /// type of boundary condition of the patch ///////////////////////////////////////////////////////////////////////////////// forAll ( mesh.boundaryMesh() , ipatch ) { scalar bflux[5]; word BCTypePhysical = mesh.boundaryMesh().physicalTypes()[ipatch]; word BCType = mesh.boundaryMesh().types()[ipatch]; word BCName = mesh.boundaryMesh().names()[ipatch]; const UList<label> &bfaceCells = mesh.boundaryMesh()[ipatch].faceCells(); ///////////////////////////////////////////////////////////////////////////////// /// Slip Wall BC /// ///////////////////////////////////////////////////////////////////////////////// if( BCTypePhysical == "slip" || BCTypePhysical == "symmetry" ) { forAll( bfaceCells , iface ) { /// Extrapolate wall pressure scalar p_e = p[ bfaceCells[iface] ]; vector normal = nf.boundaryField()[ipatch][iface]; scalar face_area = mesh.magSf().boundaryField()[ipatch][iface]; scalar lambda = std::fabs( U[ bfaceCells[iface] ] & normal ) + std::sqrt ( gama * p_e / rho[ bfaceCells[iface] ] ); momResidue[ bfaceCells[iface] ] += p_e * normal * face_area; localDt[ bfaceCells[iface] ] += lambda * face_area; } }之后我们将边界上的通量从owner单元减去,加到nighbour单元去 /// Clear all residues massResidue = dimensionedScalar( "", massResidue.dimensions() , 0.0 ); momResidue = dimensionedVector( "" , momResidue.dimensions() , vector( 0.0 , 0.0 , 0.0 ) ); energyResidue = dimensionedScalar( "" , energyResidue.dimensions() , 0.0 ); /// Loop over each face and add the flux to left and subtract from the right forAll( mesh.owner() , iface ) { /// Store left and right cell reference leftCell = mesh.owner()[iface]; rightCell = mesh.neighbour()[iface]; /// Note that the normal vector to a face will point /// from the owner cell to the neighbour cell (L to R) /// Add to left cell massResidue[leftCell] += massFlux[iface]; momResidue[leftCell] += momFlux[iface]; energyResidue[leftCell] += energyFlux[iface]; /// Subtract from right cell massResidue[rightCell] -= massFlux[iface]; momResidue[rightCell] -= momFlux[iface]; energyResidue[rightCell] -= energyFlux[iface]; }原来编程就是一直按照这种思路来的,可是转到OpenFOAM 下一时适应不过来。看到官方的求解器,根本摸不清楚边界条件和有限体积是如何交互的。有人能解释一下这和我上述思路的差别和联系吗? 
 大家编写自己的求解器的时候都是怎么实现的?希望看透这一切联系的牛人能给予一点提示和点拨。跪谢!
- 
							
							
							
							
							
							
看到官方的求解器,根本摸不清楚边界条件和有限体积是如何交互的。有人能解释一下这和我上述思路的差别和联系吗? 粗略看了下,这个求解器完全没用openfoam的思路来,采用的他自己的思路,就像你说的,他在开发这个求解器的时候,可能是有其他的代码(比如同组的Fortran)转过来的。并且完全是面向过程的思想。 如果你要用OpenFOAM求解的思路,还是看OpenFOAM的求解器比较好他这个就是把求解的过程自己实现了,然而没有使用OpenFOAM自带的方法。 他的main函数已经写的很清楚了: int main(int argc, char *argv[]) { #include "setRootCase.H" #include "createTime.H" #include "createMesh.H" #include "setInputValues.H" #include "createFields.H" #include "readFluxScheme.H" /// Time step loop /// Posts the non-blocking send/recv of fields long int iter = 0; while( runTime.loop() ) { /// 构造通量 #include "constructFaceFlux.H" /// 有限体积离散 #include "sumFlux.H" /// 边界通量修正 #include "boundaryFlux.H" Info << "Iteration = " << ++iter << " "; /// 矩阵计算 #include "stateUpdateLTS.H" Info << " Max residue = " << rhoResidMax << endl; /// 输出结果 runTime.write(); } return 0; }
