Upload
fumiya-nozaki
View
499
Download
4
Embed Size (px)
Citation preview
Fumiya Nozaki
最終更新日: 2015年6月6日
日本語版
Keywords: • Block Matrix • Coupled Solver
foam-extend-3.1 チュートリアル
blockCoupledSwirlTest
3
キーポイント
𝛻 ∙ 𝑼𝑇 − 𝛻 𝐷𝑇𝛻𝑇 = 𝛼 𝑇𝑠 − 𝑇 −𝛻 𝐷𝑇𝑠𝛻𝑇𝑠 = 𝛼 𝑇 − 𝑇𝑠
どのように解法があるでしょうか?
• 解法1 (Segregated):2つの方程式を別々に離散化し,順番に繰り返し解くことで,両方の方程式を満たす解を求める.
• 解法2 (Coupled):2つの方程式をまとめて1つの連立方程式に離散化し,これを解くことで,両方の方程式を満たす解を求める.
それぞれの方程式に,2つの未知変数 𝑇 と 𝑇𝑠 が含まれています.
blockCoupledScalarTransportFoam はこちらの解法
8
変数の定義|createFields.H
// Working coupled solution field Info<< "Creating field blockT¥n" << endl; volVector2Field blockT ( IOobject ( "blockT", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE ), mesh, dimensionedVector2("zero", dimless, vector2::zero) ); { vector2Field& blockX = blockT.internalField(); blockMatrixTools::blockInsert(0, T.internalField(), blockX); blockMatrixTools::blockInsert(1, Ts.internalField(), blockX); }
2つの温度場 T と Ts (volScalarField) から, これらをまとめたベクトル場 blockT (volVector2Field) を作成しています.
初期値の代入
9
変数の定義|createFields.H
template<class BlockType> void blockInsert ( const direction dir, const scalarField& x, Field<BlockType>& blockX ) { forAll (x, i) { blockX[i](dir) = x[i]; } }
変数 blockT への値の代入を行っている blockInsert は次のように定義されています.
src/VectorN/finiteVolume/ blockMatrixTools/blockMatrixTools.C
T[0] Ts[0]
T[1] Ts[1]
⋮ ⋮
T[i] Ts[i]
blockT
dir=0 dir=1
i=0
i=1 ⋮ i 第 i 成分
10
方程式の離散化|blockCoupledScalarTransportFoam.C
fvScalarMatrix TEqn ( fvm::div(phi, T) - fvm::laplacian(DT, T) == alpha*Ts - fvm::Sp(alpha, T) ); TEqn.relax(); fvScalarMatrix TsEqn ( - fvm::laplacian(DTs, Ts) == alpha*T - fvm::Sp(alpha, Ts) ); TsEqn.relax();
まず,2ページに記載した2つの方程式を別々に離散化しています.
𝛻 ∙ 𝑼𝑇 − 𝛻 𝐷𝑇𝛻𝑇= 𝛼 𝑇𝑠 − 𝑇
−𝛻 𝐷𝑇𝑠𝛻𝑇𝑠 = 𝛼 𝑇 − 𝑇𝑠
11
方程式の離散化|blockCoupledScalarTransportFoam.C
// Prepare block system BlockLduMatrix<vector2> blockM(mesh); //- Transfer the coupled interface list for processor/cyclic/etc. // boundaries blockM.interfaces() = blockT.boundaryField().blockInterfaces(); // Grab block diagonal and set it to zero Field<tensor2>& d = blockM.diag().asSquare(); d = tensor2::zero; // Grab linear off-diagonal and set it to zero Field<vector2>& l = blockM.lower().asLinear(); Field<vector2>& u = blockM.upper().asLinear(); u = vector2::zero; l = vector2::zero; vector2Field& blockX = blockT.internalField(); vector2Field blockB(mesh.nCells(), vector2::zero);
ブロック係数行列 blockM,解ベクトル blockX,右辺ベクトル blockB 等の変数を 定義して,初期化しています.
12
方程式の離散化|blockCoupledScalarTransportFoam.C
//- Inset equations into block Matrix blockMatrixTools::insertEquation(0, TEqn, blockM, blockX, blockB); blockMatrixTools::insertEquation(1, TsEqn, blockM, blockX, blockB); //- Add off-diagonal terms and remove from block source forAll(d, i) { d[i](0, 1) = -alpha.value()*mesh.V()[i]; d[i](1, 0) = -alpha.value()*mesh.V()[i]; blockB[i][0] -= alpha.value()*blockX[i][1]*mesh.V()[i]; blockB[i][1] -= alpha.value()*blockX[i][0]*mesh.V()[i]; }
2つの係数行列からブロック係数行列を構成しています.
もともとの離散化では,陽的にソース項として扱っていた 赤字の項をブロック係数行列に追加して陰的に扱っています.
𝛻 ∙ 𝑼𝑇 − 𝛻 𝐷𝑇𝛻𝑇 = 𝛼 𝑇𝑠 − 𝑇
−𝛻 𝐷𝑇𝑠𝛻𝑇𝑠 = 𝛼 𝑇 − 𝑇𝑠
カップルして 1つの行列で解くから可能!
13
方程式の解法|blockCoupledScalarTransportFoam.C
//- Block coupled solver call BlockSolverPerformance<vector2> solverPerf = BlockLduSolver<vector2>::New ( blockT.name(), blockM, mesh.solutionDict().solver(blockT.name()) )->solve(blockX, blockB); solverPerf.print();
連立方程式を解きます.
14
解の取得|blockCoupledScalarTransportFoam.C
// Retrieve solution blockMatrixTools::blockRetrieve(0, T.internalField(), blockX); blockMatrixTools::blockRetrieve(1, Ts.internalField(), blockX); T.correctBoundaryConditions(); Ts.correctBoundaryConditions();
template<class BlockType> void blockRetrieve ( const direction dir, scalarField& x, const Field<BlockType>& blockX ) { forAll (x, i) { x[i] = blockX[i](dir); } }
src/VectorN/finiteVolume/ blockMatrixTools/blockMatrixTools.C
解ベクトル blockX から,変数 T と Ts の値を取り出し,境界値を更新しています.
15
次回の更新では, insertEquation を詳しく調べて,
ブロック係数行列の正体に迫ります.
template<class blockType, class matrixType> void insertEquation ( const label loc, fvMatrix<matrixType>& matrix, BlockLduMatrix<blockType>& A, Field<blockType>& x, Field<blockType>& b ) { insertDiagSource(loc, matrix, A, b); insertUpperLower(loc, matrix, A); updateCouplingCoeffs(loc, matrix, A); insertSolutionVector(loc, matrix.psi().internalField(), x); }